From a2c280a53cf32bd104f35446890c11d48783d528 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 20 Jun 2012 10:00:08 +0200 Subject: [PATCH 01/13] Fix sphinx update (#574) --- lib/classes/record/adapter.class.php | 65 ++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/lib/classes/record/adapter.class.php b/lib/classes/record/adapter.class.php index b9d93f708d..795a632809 100644 --- a/lib/classes/record/adapter.class.php +++ b/lib/classes/record/adapter.class.php @@ -484,6 +484,71 @@ class record_adapter implements record_Interface, cache_cacheableInterface $this->base_id = $collection->get_base_id(); + try { + $sphinx_rt = sphinxrt::get_instance($appbox->get_registry()); + + $sbas_id = $this->get_sbas_id(); + $sbas_params = phrasea::sbas_params(); + + if (isset($sbas_params[$sbas_id])) { + $params = $sbas_params[$sbas_id]; + $sbas_crc = crc32( + str_replace( + array('.', '%') + , '_' + , sprintf('%s_%s_%s_%s', $params['host'], $params['port'], $params['user'], $params['dbname']) + ) + ); + + foreach ($this->get_caption()->get_fields(null, true) as $field) { + + if ( ! $field->is_indexable()) { + continue; + } + + $databox_field = $field->get_databox_field(); + + foreach ($field->get_values() as $value) { + + $sphinx_rt->delete(array("metadatas" . $sbas_crc, "metadatas" . $sbas_crc . "_stemmed_en", "metadatas" . $sbas_crc . "_stemmed_fr"), "metas_realtime" . $sbas_crc, $value->getId()); + + $sphinx_rt->replace_in_metas( + "metas_realtime" . $sbas_crc + , $value->getId() + , $databox_field->get_id() + , $this->get_record_id() + , $sbas_id + , phrasea::collFromBas($this->get_base_id()) + , ($this->is_grouping() ? '1' : '0') + , $this->get_type() + , $value->getValue() + , ($databox_field->isBusiness() ? '1' : '0') + , $this->get_creation_date() + ); + } + } + + $all_datas = array(); + + foreach ($this->get_caption()->get_fields(null, true) as $field) { + if ( ! $field->is_indexable()) { + continue; + } + + $all_datas[] = $field->get_serialized_values(); + } + + $all_datas = implode(' ', $all_datas); + $sphinx_rt->delete(array("documents" . $sbas_crc, "documents" . $sbas_crc . "_stemmed_fr", "documents" . $sbas_crc . "_stemmed_en"), "docs_realtime" . $sbas_crc, $this->get_record_id()); + + $sphinx_rt->replace_in_documents( + "docs_realtime" . $sbas_crc, $this->get_record_id(), $all_datas, $sbas_id, phrasea::collFromBas($this->get_base_id()), ($this->is_grouping() ? '1' : '0'), $this->get_type(), $this->get_creation_date() + ); + } + } catch (Exception $e) { + + } + $appbox->get_session()->get_logger($this->get_databox()) ->log($this, Session_Logger::EVENT_MOVE, $collection->get_coll_id(), ''); From 21eaa773c0b6a0cdecaf6e8adbf30745a049b221 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 20 Jun 2012 16:14:57 +0200 Subject: [PATCH 02/13] Add data migration commands --- .../Upgrade/DatasUpgraderInterface.php | 23 ++ .../Phrasea/Command/Upgrade/Step31.php | 152 +++++++++ .../Phrasea/Command/Upgrade/Step35.php | 306 ++++++++++++++++++ 3 files changed, 481 insertions(+) create mode 100644 lib/Alchemy/Phrasea/Command/Upgrade/DatasUpgraderInterface.php create mode 100644 lib/Alchemy/Phrasea/Command/Upgrade/Step31.php create mode 100644 lib/Alchemy/Phrasea/Command/Upgrade/Step35.php diff --git a/lib/Alchemy/Phrasea/Command/Upgrade/DatasUpgraderInterface.php b/lib/Alchemy/Phrasea/Command/Upgrade/DatasUpgraderInterface.php new file mode 100644 index 0000000000..38ca0fa96b --- /dev/null +++ b/lib/Alchemy/Phrasea/Command/Upgrade/DatasUpgraderInterface.php @@ -0,0 +1,23 @@ +core = $core; + $this->logger = $logger; + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $appbox = \appbox::get_instance($this->core); + + foreach ($appbox->get_databoxes() as $databox) { + do { + $records = $this->getNullUUIDs($databox); + + foreach ($records as $record) { + + $this->updateRecordUUID($databox, $record); + } + } while (count($records) > 0); + } + } + + /** + * {@inheritdoc} + */ + public function getTimeEstimation() + { + $appbox = \appbox::get_instance($this->core); + + $time = 0; + + foreach ($appbox->get_databoxes() as $databox) { + $time += $this->getDataboxTimeEstimation($databox); + } + + $time = $time / self::AVERAGE_PER_SECOND; + + return $time; + } + + /** + * Return the number of record which does not have a UUID + * + * @param \databox $databox + */ + protected function getDataboxTimeEstimation(\databox $databox) + { + $sql = 'SELECT r.coll_id, r.type, r.record_id, s.path, s.file, r.xml + FROM record r, subdef s + WHERE ISNULL(uuid) + AND s.record_id = r.record_id AND s.name="document" + AND parent_record_id = 0'; + + $stmt = $databox->get_connection()->prepare($sql); + $stmt->execute(); + $quantity = $stmt->rowCount(); + $stmt->closeCursor(); + + return $quantity; + } + + /** + * Return a maximum of 100 recods without UUIDs + * + * @param \databox $databox + * @return array + */ + protected function getNullUUIDs(\databox $databox) + { + $sql = 'SELECT r.coll_id, r.type, r.record_id, s.path, s.file, r.xml + FROM record r, subdef s + WHERE ISNULL(uuid) + AND s.record_id = r.record_id AND s.name="document" + AND parent_record_id = 0 LIMIT 100'; + + $stmt = $databox->get_connection()->prepare($sql); + $stmt->execute(); + $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); + $stmt->closeCursor(); + + return $rs; + } + + /** + * Update a record with a UUID + * + * @param \databox $databox + * @param array $record + */ + protected function updateRecordUUID(\databox $databox, array $record) + { + $pathfile = \p4string::addEndSlash($record['path']) . $record['file']; + + $uuid = \uuid::generate_v4(); + try { + $media = $this->core['mediavorus']->guess(new \SplFileInfo($pathfile)); + $collection = \collection::get_from_coll_id($databox, (int) $record['coll_id']); + + $file = new File($media, $collection); + $uuid = $file->getUUID(true, true); + $sha256 = $file->getSha256(); + + $this->logger->addInfo(sprintf("Upgrading record %d with uuid %s", $record['record_id'], $uuid)); + } catch (\Exception $e) { + $this->logger->addError(sprintf("Uuid upgrade for record %s failed", $record['record_id'])); + } + + $sql = 'UPDATE record SET uuid = :uuid, sha256 = :sha256 WHERE record_id = :record_id'; + + $params = array( + ':uuid' => $uuid, + 'sha256' => $sha256, + ':record_id' => $record['record_id'], + ); + $stmt = $databox->get_connection()->prepare($sql); + $stmt->execute($params); + $stmt->closeCursor(); + } +} diff --git a/lib/Alchemy/Phrasea/Command/Upgrade/Step35.php b/lib/Alchemy/Phrasea/Command/Upgrade/Step35.php new file mode 100644 index 0000000000..fe646cd9f0 --- /dev/null +++ b/lib/Alchemy/Phrasea/Command/Upgrade/Step35.php @@ -0,0 +1,306 @@ +core = $core; + $this->logger = $logger; + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $appbox = \appbox::get_instance($this->core); + + foreach ($appbox->get_databoxes() as $databox) { + + foreach ($databox->get_meta_structure()->get_elements() as $databox_field) { + if ($databox_field->is_on_error()) { + throw new \Exception(sprintf("Databox description field %s is on error, please fix it before continue", $databox_field->get_name())); + } + } + + $this->ensureMigrateColumn($databox); + + $sql = 'TRUNCATE metadatas'; + $stmt = $databox->get_connection()->prepare($sql); + $stmt->execute(); + $stmt->closeCursor(); + + do { + $rs = $this->getEmptyOriginalNameRecords($databox); + + $databox->get_connection()->beginTransaction(); + + foreach ($rs as $record) { + $this->setOriginalName($databox, $record); + } + + $databox->get_connection()->commit(); + } while (count($rs) > 0); + + do { + $rs = $this->getRecordsToMigrate($databox); + + $databox->get_connection()->beginTransaction(); + + $sql = 'UPDATE record SET migrate35=1 WHERE record_id = :record_id'; + $stmt = $databox->get_connection()->prepare($sql); + + foreach ($rs as $row) { + $stmt->execute(array(':record_id' => $row['record_id'])); + + try { + $record = new \record_adapter($databox->get_sbas_id(), $row['record_id']); + } catch (\Exception $e) { + $this->logger->addError(sprintf("Unable to load record %d on databox %d : %s", $record->get_record_id(), $record->get_sbas_id(), $record->get_sbas_id(), $e->getMessage())); + continue; + } + + try { + $this->updateMetadatas($record, $row['xml']); + } catch (Exception $e) { + $this->logger->addError(sprintf("Error while upgrading metadatas for record %d on databox %d : %s", $record->get_record_id(), $record->get_sbas_id(), $e->getMessage())); + } + + try { + $record->set_binary_status($row['status']); + } catch (Exception $e) { + $this->logger->addError(sprintf("Error while upgrading status for record %d on databox %d : %s", $record->get_record_id(), $record->get_sbas_id(), $e->getMessage())); + } + unset($record); + } + + $stmt->closeCursor(); + $databox->get_connection()->commit(); + } while (count($rs) > 0); + } + + + foreach ($appbox->get_databoxes() as $databox) { + $this->ensureDropMigrateColumn($databox); + } + } + + /** + * {@inheritdoc} + */ + public function getTimeEstimation() + { + + $appbox = \appbox::get_instance($this->core); + + $time = 0; + + foreach ($appbox->get_databoxes() as $databox) { + $sql = 'select record_id + FROM record'; + + $stmt = $databox->get_connection()->prepare($sql); + $stmt->execute(); + $time += $stmt->rowCount(); + $stmt->closeCursor(); + } + + $time = $time / self::AVERAGE_PER_SECOND; + + return $time; + } + + /** + * Update the metadatas of a record + * + * @param \record_adapter $record + * @param string $xml + */ + protected function updateMetadatas(\record_adapter $record, $xml) + { + $metas = $record->get_databox()->get_meta_structure(); + + $datas = $metadatas = array(); + + if (false !== $sxe = simplexml_load_string($xml)) { + $fields = $sxe->xpath('/record/description'); + if ($fields && is_array($fields)) { + foreach ($fields[0] as $fieldname => $value) { + $fieldname = trim($fieldname); + $value = trim($value); + + if (null === $databox_field = $metas->get_element_by_name($fieldname)) { + continue; + } + + if ($databox_field->is_multi()) { + + $new_value = \caption_field::get_multi_values($value, $databox_field->get_separator()); + if (isset($datas[$databox_field->get_id()])) { + $value = array_unique(array_merge($datas[$databox_field->get_id()], $new_value)); + } else { + $value = $new_value; + } + } else { + $new_value = $value; + if (isset($datas[$databox_field->get_id()])) { + $value = $datas[$databox_field->get_id()] . ' ' . $new_value; + } else { + $value = $new_value; + } + } + + $datas[$databox_field->get_id()] = $value; + } + } + } + + foreach ($datas as $meta_struct_id => $values) { + if (is_array($values)) { + foreach ($values as $value) { + $metadatas[$meta_struct_id] = array( + 'meta_struct_id' => $meta_struct_id + , 'meta_id' => null + , 'value' => $value + ); + } + } else { + $metadatas[$meta_struct_id] = array( + 'meta_struct_id' => $meta_struct_id + , 'meta_id' => null + , 'value' => $values + ); + } + } + + $record->set_metadatas($metadatas, true); + } + + /** + * Update the original name of a record + * + * @staticvar \PDO_statement $stmt + * @param \databox $databox + * @param array $record + */ + protected function setOriginalName(\databox $databox, array $record) + { + static $stmt; + + if ( ! $stmt) { + $sql = 'UPDATE record SET originalname = :originalname WHERE record_id = :record_id'; + $stmt = $databox->get_connection()->prepare($sql); + } + + $original = ''; + + if (false !== $sxe = simplexml_load_string($record['xml'])) { + foreach ($sxe->doc->attributes() as $key => $value) { + if (trim($key) != 'originalname') { + continue; + } + $original = basename(trim($value)); + break; + } + } + + $stmt->execute(array(':originalname' => $original, ':record_id' => $record['record_id'])); + } + + /** + * Returns an array of 500 records to update + * + * @return array + */ + protected function getRecordsToMigrate(\databox $databox) + { + $sql = 'select record_id, coll_id, xml, BIN(status) as status + FROM record + WHERE migrate35=0 + LIMIT 0, 500'; + + $stmt = $databox->get_connection()->prepare($sql); + $stmt->execute(); + $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); + $stmt->closeCursor(); + + return $rs; + } + + /** + * Returns an array of 500 records without original name + * + * @return array + */ + protected function getEmptyOriginalNameRecords(\databox $databox) + { + $sql = 'SELECT record_id, coll_id, xml, BIN(status) as status + FROM record + WHERE originalname IS NULL + LIMIT 0, 500'; + + $stmt = $databox->get_connection()->prepare($sql); + $stmt->execute(); + $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); + $stmt->closeCursor(); + + return $rs; + } + + /** + * Removes the migration column + * + * @param \databox $databox + */ + protected function ensureDropMigrateColumn(\databox $databox) + { + $sql = 'ALTER TABLE `record` DROP `migrate35` '; + $stmt = $databox->get_connection()->prepare($sql); + $stmt->execute(); + $stmt->closeCursor(); + } + + /** + * Add a migration column to the table + * + * @param \databox $databox + */ + protected function ensureMigrateColumn(\databox $databox) + { + try { + $sql = 'ALTER TABLE `record` + ADD `migrate35` TINYINT( 1 ) UNSIGNED NOT NULL , + ADD INDEX ( `migrate35` ) '; + $stmt = $databox->get_connection()->prepare($sql); + $stmt->execute(); + $stmt->closeCursor(); + } catch (\Exception $e) { + + } + } +} \ No newline at end of file From 5821b8fce1df6cf498bbf31dae74a9dd7390a5bd Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 20 Jun 2012 16:15:36 +0200 Subject: [PATCH 03/13] Add command to run data migration scripts --- .../Phrasea/Command/BuildMissingSubdefs.php | 19 --- lib/Alchemy/Phrasea/Command/Command.php | 23 +++ .../Phrasea/Command/RescanTechnicalDatas.php | 20 --- .../Phrasea/Command/UpgradeDBDatas.php | 136 ++++++++++++++++++ tests/Alchemy/Phrasea/Command/CommandTest.php | 52 +++++++ .../Phrasea/Command/UpgradeDBDatasTest.php | 78 ++++++++++ 6 files changed, 289 insertions(+), 39 deletions(-) create mode 100644 lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php create mode 100644 tests/Alchemy/Phrasea/Command/CommandTest.php create mode 100644 tests/Alchemy/Phrasea/Command/UpgradeDBDatasTest.php diff --git a/lib/Alchemy/Phrasea/Command/BuildMissingSubdefs.php b/lib/Alchemy/Phrasea/Command/BuildMissingSubdefs.php index beb746e982..ca34f5a96d 100644 --- a/lib/Alchemy/Phrasea/Command/BuildMissingSubdefs.php +++ b/lib/Alchemy/Phrasea/Command/BuildMissingSubdefs.php @@ -125,23 +125,4 @@ class BuildMissingSubdefs extends Command return; } - /** - * Format a duration in seconds to human readable - * - * @param type $seconds the time to format - * @return string - */ - public function getFormattedDuration($seconds) - { - $duration = round($seconds / 60) . ' minutes'; - - if ($duration > 60) { - $duration = round($duration / 60, 1) . ' hours'; - } - if ($duration > 24) { - $duration = round($duration / 24, 1) . ' days'; - } - - return $duration; - } } diff --git a/lib/Alchemy/Phrasea/Command/Command.php b/lib/Alchemy/Phrasea/Command/Command.php index bfdb414667..6c18d290b8 100644 --- a/lib/Alchemy/Phrasea/Command/Command.php +++ b/lib/Alchemy/Phrasea/Command/Command.php @@ -80,4 +80,27 @@ abstract class Command extends SymfoCommand } } } + + /** + * Format a duration in seconds to human readable + * + * @param type $seconds the time to format + * @return string + */ + public function getFormattedDuration($seconds) + { + $duration = ceil($seconds) . ' seconds'; + + if ($duration > 60) { + $duration = round($duration / 60 , 1) . ' minutes'; + } + elseif ($duration > 3600) { + $duration = round($duration / (60 * 60) , 1) . ' hours'; + } + elseif ($duration > (24 * 60 * 60)) { + $duration = round($duration / (24 * 60 * 60) , 1) . ' days'; + } + + return $duration; + } } diff --git a/lib/Alchemy/Phrasea/Command/RescanTechnicalDatas.php b/lib/Alchemy/Phrasea/Command/RescanTechnicalDatas.php index 0321684064..18ff1d8bb7 100644 --- a/lib/Alchemy/Phrasea/Command/RescanTechnicalDatas.php +++ b/lib/Alchemy/Phrasea/Command/RescanTechnicalDatas.php @@ -105,26 +105,6 @@ class RescanTechnicalDatas extends Command return; } - /** - * Format a duration in seconds to human readable - * - * @param type $seconds the time to format - * @return string - */ - public function getFormattedDuration($seconds) - { - $duration = round($seconds / (60 * self::AVG_SPEED)) . ' minutes'; - - if ($duration > 60) { - $duration = round($duration / (60 * self::AVG_SPEED), 1) . ' hours'; - } - if ($duration > 24) { - $duration = round($duration / (24 * self::AVG_SPEED), 1) . ' days'; - } - - return $duration; - } - /** * Return the total quantity of records to process * diff --git a/lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php b/lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php new file mode 100644 index 0000000000..ba395e64dc --- /dev/null +++ b/lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php @@ -0,0 +1,136 @@ +setDescription('Perform upgrade tasks on Phraseanet installs and older'); + + $this->addOption('from', 'f', null, 'The version where to start upgrade'); + $this->addOption('at-version', null, null, 'The version step to upgrade'); + + return $this; + } + + protected function generateUpgradesFromOption(InputInterface $input) + { + if (false === $input->getOption('from') && false === $input->getOption('at-version')) { + throw new \Exception('You MUST provide a `from` or `at-version` option'); + } + + if (false !== $input->getOption('from') && false !== $input->getOption('at-version')) { + throw new \Exception('You CAN NOT provide a `from` AND `at-version` option at the same time'); + } + $core = \bootstrap::getCore(); + + $versions = array( + 'Upgrade\\Step31' => '3.1', + 'Upgrade\\Step35' => '3.5', + ); + + if (null !== $input->getOption('from')) { + foreach ($versions as $classname => $version) { + if (version_compare($input->getOption('from'), $version) > 0) { + continue; + } + + $classname = __NAMESPACE__ . '\\' . $classname; + $this->upgrades[] = new $classname($core, $this->logger); + } + } + } + + /** + * {@inheritdoc} + */ + public function requireSetup() + { + return true; + } + + public function setUpgrades(array $upgrades) + { + $this->upgrades = array(); + + foreach ($upgrades as $upgrade) { + $this->addUpgrade($upgrade); + } + } + + public function addUpgrade(Upgrade\DatasUpgraderInterface $upgrade) + { + $this->upgrades[] = $upgrade; + } + + public function getUpgrades() + { + return $this->upgrades; + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $this->generateUpgradesFromOption($input); + + if ( ! $this->upgrades) { + throw new \Exception('No upgrade available'); + } + + $time = 0; + + foreach ($this->upgrades as $version) { + $time += $version->getTimeEstimation(); + } + + $question = sprintf("This process is estimated to %s", $this->getFormattedDuration($time)); + + $dialog = $this->getHelperSet()->get('dialog'); + + do { + $continue = strtolower($dialog->ask($output, $question. 'Continue ? (Y/n)', 'Y')); + } while ( ! in_array($continue, array('y', 'n'))); + + if (strtolower($continue) !== 'y') { + $output->writeln('Aborting !'); + + return; + } + + foreach ($this->upgrades as $version) { + $version->execute($input, $output); + } + + return; + } +} diff --git a/tests/Alchemy/Phrasea/Command/CommandTest.php b/tests/Alchemy/Phrasea/Command/CommandTest.php new file mode 100644 index 0000000000..a46e7b78b4 --- /dev/null +++ b/tests/Alchemy/Phrasea/Command/CommandTest.php @@ -0,0 +1,52 @@ +object = new AbstractCommandTester('name'); + $this->logger = new \Monolog\Logger('test'); + } + + /** + * @covers Alchemy\Phrasea\Command\Command::setLogger + * @covers Alchemy\Phrasea\Command\Command::getLogger + */ + public function testSetLogger() + { + $this->object->setLogger($this->logger); + $this->assertEquals($this->logger, $this->object->getLogger()); + } + + /** + * @covers Alchemy\Phrasea\Command\Command::checkSetup + */ + public function testCheckSetup() + { + $this->object->checkSetup(); + } + + /** + * @covers Alchemy\Phrasea\Command\Command::getFormattedDuration + */ + public function testGetFormattedDuration() + { + $this->assertRegExp('/50 \w+/', $this->object->getFormattedDuration(50)); + $this->assertRegExp('/1(\.|,)2 \w+/', $this->object->getFormattedDuration(70)); + } +} + +class AbstractCommandTester extends Command +{ + public function requireSetup() + { + return true; + } +} diff --git a/tests/Alchemy/Phrasea/Command/UpgradeDBDatasTest.php b/tests/Alchemy/Phrasea/Command/UpgradeDBDatasTest.php new file mode 100644 index 0000000000..64bd71df93 --- /dev/null +++ b/tests/Alchemy/Phrasea/Command/UpgradeDBDatasTest.php @@ -0,0 +1,78 @@ +object = new UpgradeDBDatas('commandname'); + } + + /** + * @covers Alchemy\Phrasea\Command\UpgradeDBDatas::requireSetup + */ + public function testRequireSetup() + { + $this->assertInternalType('boolean', $this->object->requireSetup()); + } + + /** + * @covers Alchemy\Phrasea\Command\UpgradeDBDatas::setUpgrades + * @covers Alchemy\Phrasea\Command\UpgradeDBDatas::addUpgrade + * @covers Alchemy\Phrasea\Command\UpgradeDBDatas::getUpgrades + */ + public function testSetUpgrades() + { + $this->object->setUpgrades(array()); + $this->assertEquals(array(), $this->object->getUpgrades()); + + $core = \bootstrap::getCore(); + + $upgrades = array( + new Upgrade\Step31($core, $core['monolog']) + ); + $this->object->setUpgrades($upgrades); + $this->assertEquals($upgrades, $this->object->getUpgrades()); + } + + /** + * @covers Alchemy\Phrasea\Command\UpgradeDBDatas::addUpgrade + */ + public function testAddUpgrade() + { + $this->assertEquals(array(), $this->object->getUpgrades()); + + $core = \bootstrap::getCore(); + + $step31 = new Upgrade\Step31($core, $core['monolog']); + $this->object->addUpgrade($step31); + + $this->assertEquals(array($step31), $this->object->getUpgrades()); + + $step35 = new Upgrade\Step35($core, $core['monolog']); + $this->object->addUpgrade($step35); + + $this->assertEquals(array($step31, $step35), $this->object->getUpgrades()); + } + + /** + * @covers Alchemy\Phrasea\Command\UpgradeDBDatas::execute + * @todo Implement testExecute(). + */ + public function testExecute() + { + // Remove the following lines when you implement this test. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } +} From 0801bb2c396ce272679f6516198c6755fe2e8030 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 20 Jun 2012 16:19:26 +0200 Subject: [PATCH 04/13] Fix truncation of tables --- lib/classes/patch/370a7.class.php | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/lib/classes/patch/370a7.class.php b/lib/classes/patch/370a7.class.php index 9ff999a83a..10cbdd4faf 100644 --- a/lib/classes/patch/370a7.class.php +++ b/lib/classes/patch/370a7.class.php @@ -157,19 +157,8 @@ class patch_370a7 implements patchInterface private function truncateTable(\Doctrine\ORM\EntityManager $em, $className) { - $cmd = $em->getClassMetadata($className); - $connection = $em->getConnection(); - $dbPlatform = $connection->getDatabasePlatform(); - $connection->beginTransaction(); - try { - $query = $dbPlatform->getTruncateTableSql($cmd->getTableName()); - $connection->executeUpdate($query); - $connection->commit(); - } catch (\Exception $e) { - $connection->rollback(); - // throw e to stop patch execution if one truncate failed - throw $e; - } + $query = $em->createQuery(sprintf('DELETE FROM %s', $className)); + $query->execute(); } } From 3e033845bbde23dd5430b0af1c7091431a7df1e9 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 20 Jun 2012 16:19:54 +0200 Subject: [PATCH 05/13] Remove upgrade tasks --- lib/classes/patch/3102.class.php | 91 ----- lib/classes/patch/320c.class.php | 11 - .../task/period/upgradetov31.class.php | 172 --------- .../task/period/upgradetov32.class.php | 347 ------------------ 4 files changed, 621 deletions(-) delete mode 100644 lib/classes/patch/3102.class.php delete mode 100644 lib/classes/task/period/upgradetov31.class.php delete mode 100644 lib/classes/task/period/upgradetov32.class.php diff --git a/lib/classes/patch/3102.class.php b/lib/classes/patch/3102.class.php deleted file mode 100644 index 01fa90e923..0000000000 --- a/lib/classes/patch/3102.class.php +++ /dev/null @@ -1,91 +0,0 @@ -release; - } - - public function require_all_upgrades() - { - return false; - } - - /** - * - * @return Array - */ - public function concern() - { - return $this->concern; - } - - public function apply(base &$base) - { - $conn = connection::getPDOConnection(); - - $sql = 'SELECT task_id FROM task2 WHERE `class` = "task_period_upgradetov31"'; - - $stmt = $conn->prepare($sql); - $stmt->execute(); - $rowcount = $stmt->rowCount(); - $stmt->closeCursor(); - - if ($rowcount == 0) { - $sql = 'INSERT INTO `task2` - (`task_id`, `usr_id_owner`, `pid`, `status`, `crashed`, - `active`, `name`, `last_exec_time`, `class`, `settings`, `completed`) - VALUES - (null, 0, 0, "stopped", 0, 1, "upgrade to v3.1", - "0000-00-00 00:00:00", "task_period_upgradetov31", - "' . - '", -1)'; - - $stmt = $conn->prepare($sql); - $stmt->execute(); - $stmt->closeCursor(); - } - - if ($base->get_base_type() == base::DATA_BOX) { - $sql = 'UPDATE record SET sha256 = "" - WHERE sha256 IS NULL AND parent_record_id = 0'; - $stmt = $base->get_connection()->prepare($sql); - $stmt->execute(); - $stmt->closeCursor(); - } - - return true; - } -} diff --git a/lib/classes/patch/320c.class.php b/lib/classes/patch/320c.class.php index 7fc019c8d7..d6de86d19d 100644 --- a/lib/classes/patch/320c.class.php +++ b/lib/classes/patch/320c.class.php @@ -117,17 +117,6 @@ class patch_320c implements patchInterface $databox->delete_data_from_cache(databox::CACHE_META_STRUCT); $conn = connection::getPDOConnection(); - $sql = 'INSERT INTO `task2` - (`task_id`, `usr_id_owner`, `pid`, `status`, `crashed`, - `active`, `name`, `last_exec_time`, `class`, `settings`, `completed`) - VALUES - (null, 0, 0, "stopped", 0, 1, "upgrade to v3.2 for sbas ' . $databox->get_sbas_id() . '", - "0000-00-00 00:00:00", "task_period_upgradetov32", - "' . - '' . $databox->get_sbas_id() . '", -1)'; - $stmt = $conn->prepare($sql); - $stmt->execute(); - $stmt->closeCursor(); $sql = 'DELETE FROM `task2` WHERE class="readmeta"'; $stmt = $conn->prepare($sql); diff --git a/lib/classes/task/period/upgradetov31.class.php b/lib/classes/task/period/upgradetov31.class.php deleted file mode 100644 index 8291c49a70..0000000000 --- a/lib/classes/task/period/upgradetov31.class.php +++ /dev/null @@ -1,172 +0,0 @@ -getID()); - // task can't be stopped here - $core = \bootstrap::getCore(); - $appbox = appbox::get_instance($core); - $conn = $appbox->get_connection(); - $running = true; - - $todo = $this->how_many_left(); - $done = 0; - - $appbox = appbox::get_instance(\bootstrap::getCore()); - $ret = 'stopped'; - - $this->setProgress($done, $todo); - - - while ($running) { - - foreach ($appbox->get_databoxes() as $databox) { - $connbas = $databox->get_connection(); - - $sql = 'SELECT r.coll_id, r.type, r.record_id, s.path, s.file, r.xml - FROM record r, subdef s - WHERE ISNULL(uuid) - AND s.record_id = r.record_id AND s.name="document" LIMIT 100'; - - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - foreach ($rs as $row) { - $pathfile = p4string::addEndSlash($row['path']) . $row['file']; - - $uuid = uuid::generate_v4(); - try { - $media = $core->guess(new \SplFileInfo($pathfile)); - $collection = \collection::get_from_coll_id($databox, $row['coll_id']); - - $file = new \Alchemy\Phrasea\Border\File($media, $collection); - $uuid = $file->getUUID(true, true); - } catch (\Exception $e) { - - } - - $sql = 'UPDATE record SET uuid = :uuid WHERE record_id = :record_id'; - - $params = array( - ':uuid' => $uuid - , ':record_id' => $row['record_id'] - ); - $stmt = $connbas->prepare($sql); - $stmt->execute($params); - $stmt->closeCursor(); - - $this->log("mise a jour du record " . $row['record_id'] . " avec uuid " . $uuid); - - $done ++; - $this->setProgress($done, $todo); - } - } - - $todo = $this->how_many_left() + $done; - - if ($done == $todo) { - $sql = 'UPDATE task2 SET status="tostop" WHERE task_id = :task_id'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':task_id' => $this->getID())); - $stmt->closeCursor(); - - $this->setProgress(0, 0); - $ret = 'todelete'; - } - - $sql = "SELECT status FROM task2 WHERE status='tostop' AND task_id=" . $this->getID(); - $stmt = $conn->prepare($sql); - $stmt->execute(array(':task_id' => $this->getID())); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - if ($row) { - $running = false; - } - - $conn->close(); - unset($conn); - sleep(1); - $conn = connection::getPDOConnection(); - } - printf("taskid %s ending." . PHP_EOL, $this->getID()); - - sleep(1); - - printf("good bye world I was task upgrade to version 3.1" . PHP_EOL); - - flush(); - - return $ret; - } - - private function how_many_left() - { - $todo = 0; - $appbox = appbox::get_instance(\bootstrap::getCore()); - - foreach ($appbox->get_databoxes() as $databox) { - try { - $connbas = $databox->get_connection(); - - $sql = 'SELECT count(r.record_id) as total FROM record r, subdef s' - . ' WHERE ISNULL(uuid)' - . ' AND s.record_id = r.record_id AND s.name="document"'; - - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - if ($row) { - $todo += (int) $row['total']; - } - } catch (Exception $e) { - - } - } - - return $todo; - } -} - diff --git a/lib/classes/task/period/upgradetov32.class.php b/lib/classes/task/period/upgradetov32.class.php deleted file mode 100644 index 500a2dc45a..0000000000 --- a/lib/classes/task/period/upgradetov32.class.php +++ /dev/null @@ -1,347 +0,0 @@ -sbas_id = (int) $sx_task_settings->sbas_id; - parent::loadSettings($sx_task_settings); - } - - protected function run2() - { - printf("taskid %s starting." . PHP_EOL, $this->getID()); - - $registry = registry::get_instance(); - - $registry->set('GV_sphinx', false, \registry::TYPE_BOOLEAN); - - if ( ! $this->sbas_id) { - printf("sbas_id '" . $this->sbas_id . "' invalide\n"); - $this->return_value = self::RETURNSTATUS_STOPPED; - - return; - } - - try { - $databox = databox::get_instance($this->sbas_id); - $connbas = connection::getPDOConnection($this->sbas_id); - } catch (Exception $e) { - $this->return_value = self::RETURNSTATUS_STOPPED; - - return; - } - - foreach ($databox->get_meta_structure()->get_elements() as $struct_el) { - if ($struct_el->is_on_error()) { - - printf("Please verify all your databox meta fields before migrating, It seems somes are wrong\n"); - $this->return_value = self::STATE_STOPPED; - - return self::STATE_STOPPED; - } - } - - $this->running = true; - - try { - $sql = 'ALTER TABLE `record` ADD `migrated` TINYINT( 1 ) UNSIGNED NOT NULL , ADD INDEX ( `migrated` ) '; - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $stmt->closeCursor(); - } catch (Exception $e) { - - } - - $n_done = 0; - - while ($this->running) { - try { - - $sql = 'SELECT COUNT(record_id) as total FROM record'; - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - $total = 0; - if ($row) { - $total = $row['total']; - } - - $sql = 'SELECT COUNT(record_id) as total FROM record WHERE migrated = 1'; - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - $done = 0; - if ($row) { - $done = $row['total']; - } - - $this->setProgress($done, $total); - - $this->running = false; - $sql = 'select record_id, coll_id, xml, BIN(status) as status - FROM record - WHERE originalname IS NULL - LIMIT 0, 500'; - - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - if (count($rs) > 0) { - $this->running = true; - } - - $sql = 'UPDATE record SET originalname = :originalname WHERE record_id = :record_id'; - $stmt_original = $connbas->prepare($sql); - $connbas->beginTransaction(); - foreach ($rs as $row) { - $original = ''; - $sxe = simplexml_load_string($row['xml']); - if ($sxe) { - foreach ($sxe->doc->attributes() as $key => $value) { - $key = trim($key); - $value = trim($value); - if ($key != 'originalname') { - continue; - } - $original = basename($value); - break; - } - } - try { - $stmt_original->execute(array(':originalname' => $value, ':record_id' => $row['record_id'])); - } catch (Exception $e) { - - } - } - $connbas->commit(); - - $sql = 'select record_id, coll_id, xml, BIN(status) as status - FROM record - WHERE migrated="0" AND record_id NOT IN (select distinct record_id from technical_datas) - LIMIT 0, 500'; - - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - if (count($rs) > 0) { - $this->running = true; - } - - $sql = 'REPLACE INTO technical_datas (id, record_id, name, value) - VALUES (null, :record_id, :name, :value)'; - $stmt = $connbas->prepare($sql); - $connbas->beginTransaction(); - - foreach ($rs as $row) { - try { - $record = new record_adapter($this->sbas_id, $row['record_id']); - $document = $record->get_subdef('document'); - - foreach ($document->readTechnicalDatas() as $name => $value) { - if (is_null($value)) { - continue; - } - - $stmt->execute(array( - ':record_id' => $record->get_record_id() - , ':name' => $name - , ':value' => $value - )); - } - } catch (Exception $e) { - - } - } - - $connbas->commit(); - $stmt->closeCursor(); - - $sql = 'select record_id, coll_id, xml, BIN(status) as status - FROM record - WHERE migrated=0 - LIMIT 0, 500'; - - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - if (count($rs) > 0) { - $this->running = true; - } - $connbas->beginTransaction(); - - $sql = 'UPDATE record SET migrated=1 WHERE record_id = :record_id'; - $stmt = $connbas->prepare($sql); - - foreach ($rs as $row) { - try { - $record = new record_adapter($this->sbas_id, $row['record_id']); - - $metas = $databox->get_meta_structure(); - - $metadatas = array(); - - if (($sxe = simplexml_load_string($row['xml'])) != FALSE) { - $z = $sxe->xpath('/record/description'); - if ($z && is_array($z)) { - foreach ($z[0] as $ki => $vi) { - $databox_field = $metas->get_element_by_name((string) $ki); - if ( ! $databox_field) { - continue; - } - - $value = (string) $vi; - - if (trim($value) === '') { - continue; - } - - if ($databox_field->is_multi()) { - $new_value = caption_field::get_multi_values($value, $databox_field->get_separator()); - if (isset($metadatas[$databox_field->get_id()])) { - $value = array_unique(array_merge($metadatas[$databox_field->get_id()]['value'], $new_value)); - } else { - $value = $new_value; - } - } else { - $new_value = array($value); - if (isset($metadatas[$databox_field->get_id()])) { - $value = array(array_shift($metadatas[$databox_field->get_id()]['value']) . ' ' . array_shift($new_value)); - } else { - $value = $new_value; - } - } - - $metadatas[$databox_field->get_id()] = array( - 'meta_struct_id' => $databox_field->get_id() - , 'meta_id' => null - , 'value' => $value - ); - } - } - } - $record->set_metadatas($metadatas, true); - unset($record); - } catch (Exception $e) { - - } - try { - $record = new record_adapter($this->sbas_id, $row['record_id']); - $record->set_binary_status($row['status']); - unset($record); - } catch (Exception $e) { - - } - $stmt->execute(array(':record_id' => $row['record_id'])); - } - - $stmt->closeCursor(); - unset($stmt); - $connbas->commit(); - - $n_done += 500; - - $memory = memory_get_usage() >> 20; - - if ($n_done >= 5000) { - $this->return_value = task_abstract::RETURNSTATUS_TORESTART; - - return; - } - if ($memory > 100) { - $this->return_value = task_abstract::RETURNSTATUS_TORESTART; - - return; - } - } catch (Exception $e) { - - } - usleep(500000); - } - - $sql = 'ALTER TABLE `record` DROP `migrated`'; - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $stmt->closeCursor(); - - $sql = "DELETE from technical_datas WHERE name='DONE'"; - $stmt = $connbas->prepare($sql); - $stmt->execute(); - $stmt->closeCursor(); - - $conn = connection::getPDOConnection(); - - printf("taskid %s ending." . PHP_EOL, $this->getID()); - sleep(1); - printf("good bye world I was task upgrade to version 3.2" . PHP_EOL); - - $sql = 'UPDATE task2 SET status="tostop" WHERE task_id = :task_id'; - - $stmt = $conn->prepare($sql); - $stmt->execute(array(':task_id' => $this->getID())); - $stmt->closeCursor(); - - $this->setProgress(0, 0); - - $this->return_value = self::RETURNSTATUS_TODELETE; - - flush(); - - return; - } -} - From 6355f5f7e252e8c7b3a66c83f7ae41425ccc58ba Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 20 Jun 2012 16:20:41 +0200 Subject: [PATCH 06/13] Add exception message --- lib/classes/databox.class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/classes/databox.class.php b/lib/classes/databox.class.php index ad06502213..2fce7fdb7a 100644 --- a/lib/classes/databox.class.php +++ b/lib/classes/databox.class.php @@ -114,8 +114,9 @@ class databox extends base $connection_params = phrasea::sbas_params(); - if ( ! isset($connection_params[$sbas_id])) - throw new Exception_DataboxNotFound (); + if ( ! isset($connection_params[$sbas_id])) { + throw new Exception_DataboxNotFound(sprintf('databox %d not found', $sbas_id)); + } $this->host = $connection_params[$sbas_id]['host']; $this->port = $connection_params[$sbas_id]['port']; From 05576b11c228820c523580fb4f7263e103a11ccb Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 20 Jun 2012 16:21:22 +0200 Subject: [PATCH 07/13] Add upgrade recommendations --- bin/console | 3 ++- lib/classes/Setup/Upgrade.class.php | 20 ++++++++++++++++ lib/classes/appbox.class.php | 13 +++++++++++ .../module/console/systemUpgrade.class.php | 23 +++++++++++++++---- 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/bin/console b/bin/console index a9f9268f0e..478f22d1ef 100755 --- a/bin/console +++ b/bin/console @@ -58,6 +58,7 @@ try { $app->add(new module_console_checkExtension('check:extension')); $app->add(new module_console_systemUpgrade('system:upgrade')); + $app->add(new \Alchemy\Phrasea\Command\UpgradeDBDatas('system:upgrade-datas')); $app->add(new module_console_sphinxGenerateSuggestion('sphinx:generate-suggestions')); @@ -85,7 +86,7 @@ try { $app->add(new Alchemy\Phrasea\Command\RescanTechnicalDatas('records:rescan-technical-datas')); $app->add(new Alchemy\Phrasea\Command\BuildMissingSubdefs('records:build-missing-subdefs')); - + $result_code = is_int($app->run()) ? : 1; } catch (Exception $e) { echo sprintf("an error occured : %s", $e->getMessage()); diff --git a/lib/classes/Setup/Upgrade.class.php b/lib/classes/Setup/Upgrade.class.php index 1c55031b45..23ed9220bf 100644 --- a/lib/classes/Setup/Upgrade.class.php +++ b/lib/classes/Setup/Upgrade.class.php @@ -31,6 +31,11 @@ class Setup_Upgrade * @var string */ protected $message; + /** + * + * @var array + */ + protected $recommendations = array(); /** * @@ -119,6 +124,21 @@ class Setup_Upgrade return $this; } + /** + * + * @param type $recommendation + * @param type $command + */ + public function addRecommendation($recommendation, $command = null) + { + $this->recommendations[] = array($recommendation, $command); + } + + public function getRecommendations() + { + return $this->recommendations; + } + /** * * @return float diff --git a/lib/classes/appbox.class.php b/lib/classes/appbox.class.php index 71957cbc9c..6f56448847 100644 --- a/lib/classes/appbox.class.php +++ b/lib/classes/appbox.class.php @@ -274,6 +274,8 @@ class appbox extends base public function forceUpgrade(Setup_Upgrade &$upgrader) { + $from_version = $this->get_version(); + $upgrader->add_steps(7 + count($this->get_databoxes())); $registry = $this->get_registry(); @@ -358,6 +360,17 @@ class appbox extends base $upgrader->add_steps_complete(1); + if(version_compare($from_version, '3.1') < 0) { + $upgrader->addRecommendation(_('Your install requires data migration, please execute the following command'), 'bin/upgrader --from=3.1'); + } elseif (version_compare($from_version, '3.5') < 0) { + $upgrader->addRecommendation(_('Your install requires data migration, please execute the following command'), 'bin/upgrader --from=3.5'); + } + + if (version_compare($from_version, '3.7') < 0) { + $upgrader->addRecommendation(_('Your install might need to re-read technical datas'), 'bin/console records:rescan-technical-datas'); + $upgrader->addRecommendation(_('Your install might need to re-read technical datas'), 'bin/console records:build-missing-subdefs'); + } + return $advices; } diff --git a/lib/classes/module/console/systemUpgrade.class.php b/lib/classes/module/console/systemUpgrade.class.php index 273f54c887..81ff69ee04 100644 --- a/lib/classes/module/console/systemUpgrade.class.php +++ b/lib/classes/module/console/systemUpgrade.class.php @@ -27,7 +27,7 @@ class module_console_systemUpgrade extends Command { parent::__construct($name); - $this->setDescription('Upgrade Phraseanet to the lastest version'); + $this->setDescription('Upgrade Phraseanet to the latest version'); return $this; } @@ -39,11 +39,12 @@ class module_console_systemUpgrade extends Command public function execute(InputInterface $input, OutputInterface $output) { - $this->checkSetup(); + $old_connexion_file = __DIR__ . '/../../../../config/connexion.inc'; + $old_config_file = __DIR__ . '/../../../../config/config.inc'; $Core = \bootstrap::getCore(); - if ( ! setup::is_installed()) { + if ( ! $Core->getConfiguration()->isInstalled() && file_exists($old_config_file) && file_exists($old_connexion_file)) { $output->writeln('This version of Phraseanet requires a config/config.yml, config/connexion.yml, config/service.yml'); $output->writeln('Would you like it to be created based on your settings ?'); @@ -55,8 +56,8 @@ class module_console_systemUpgrade extends Command if ($continue == 'y') { try { - $connexionInc = new \SplFileInfo(__DIR__ . '/../../../../config/connexion.inc', true); - $configInc = new \SplFileInfo(__DIR__ . '/../../../../config/config.inc', true); + $connexionInc = new \SplFileInfo($old_connexion_file, true); + $configInc = new \SplFileInfo($old_config_file, true); $Core->getConfiguration()->upgradeFromOldConf($configInc, $connexionInc); } catch (\Exception $e) { @@ -67,6 +68,8 @@ class module_console_systemUpgrade extends Command } } + $this->checkSetup(); + $output->write('Phraseanet is going to be upgraded', true); $dialog = $this->getHelperSet()->get('dialog'); @@ -86,6 +89,16 @@ class module_console_systemUpgrade extends Command $upgrader = new Setup_Upgrade($appbox); $appbox->forceUpgrade($upgrader); + + foreach ($upgrader->getRecommendations() as $recommendation) { + list($message, $command) = $recommendation; + + $output->writeln(sprintf('%s', $message)); + $output->writeln(""); + $output->writeln(sprintf("\t\t%s", $command)); + $output->writeln(""); + $output->writeln(""); + } } catch (\Exception $e) { $output->writeln(sprintf('An error occured while upgrading : %s ', $e->getMessage())); From d914d20b79fee8c225a58504bbf044018af2c8a3 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 20 Jun 2012 16:26:54 +0200 Subject: [PATCH 08/13] Add recommendation in admin view --- www/admin/databases.php | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/www/admin/databases.php b/www/admin/databases.php index 49a711dfe5..9c736b62c4 100644 --- a/www/admin/databases.php +++ b/www/admin/databases.php @@ -60,13 +60,30 @@ phrasea::headers(); $code .= $advice['sql'] . '
'; } - $code = _('Propositions de modifications des tables') - . '
' . $code . '
'; + $recommendations = $upgrader->getRecommendations(); + + if($code) { + $code = _('Propositions de modifications des tables') + . '
' . $code . '
'; ?>
                             
                         
- + +

+
+                                    
+
+
From c0174d44639bf646b83917f149aa9325d3764f9f Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 20 Jun 2012 16:30:25 +0200 Subject: [PATCH 09/13] Update documentation --- lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php b/lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php index ba395e64dc..1e9acf5955 100644 --- a/lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php +++ b/lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php @@ -33,7 +33,14 @@ class UpgradeDBDatas extends Command { parent::__construct($name); - $this->setDescription('Perform upgrade tasks on Phraseanet installs and older'); + $this + ->setDescription("Upgrade Phraseanet datas") + ->setHelp("Upgrade Phraseanet datas from older version + +Steps are + + - version 3.1 : records UUID + - version 3.5 : metadatas upgrade"); $this->addOption('from', 'f', null, 'The version where to start upgrade'); $this->addOption('at-version', null, null, 'The version step to upgrade'); From 7ad0a0cfccf7f542a0c52d6861ee7c2a0c17ad82 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 20 Jun 2012 17:10:20 +0200 Subject: [PATCH 10/13] Fix dropdown menu --- bin/console | 22 +++++++++++-------- .../Phrasea/Command/Upgrade/Step35.php | 2 +- .../Phrasea/Controller/Setup/Upgrader.php | 4 ++++ lib/classes/Setup/Upgrade.class.php | 5 +++++ templates/web/common/drop_down_options.html | 2 +- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/bin/console b/bin/console index 478f22d1ef..2ed97fac0c 100755 --- a/bin/console +++ b/bin/console @@ -9,13 +9,18 @@ * file that was distributed with this source code. */ +namespace KonsoleKommander; + /** * - * @package - * @package KonsoleKomander * @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @link www.phraseanet.com */ +use Alchemy\Phrasea\Core\Configuration; +use Alchemy\Phrasea\Core\Version; +use Alchemy\Phrasea\Command\UpgradeDBDatas; +use Alchemy\Phrasea\Command\RescanTechnicalDatas; +use Alchemy\Phrasea\Command\BuildMissingSubdefs; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -25,9 +30,9 @@ use Symfony\Component\Console\Application; require_once dirname(__FILE__) . '/../lib/classes/bootstrap.class.php'; -bootstrap::register_autoloads(); +\bootstrap::register_autoloads(); -$configuration = Alchemy\Phrasea\Core\Configuration::build(); +$configuration = Configuration::build(); if ($configuration->isInstalled()) { require_once dirname(__FILE__) . '/../lib/bootstrap.php'; } @@ -49,8 +54,7 @@ try { This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions; type `about:license' for details.\n\n" - . ' KONSOLE KOMMANDER', \Alchemy\Phrasea\Core\Version::getName() - . ' ' . \Alchemy\Phrasea\Core\Version::getNumber()); + . ' KONSOLE KOMMANDER', Version::getName() . ' ' . Version::getNumber()); $app->add(new module_console_aboutAuthors('about:authors')); $app->add(new module_console_aboutLicense('about:license')); @@ -58,7 +62,7 @@ try { $app->add(new module_console_checkExtension('check:extension')); $app->add(new module_console_systemUpgrade('system:upgrade')); - $app->add(new \Alchemy\Phrasea\Command\UpgradeDBDatas('system:upgrade-datas')); + $app->add(new UpgradeDBDatas('system:upgrade-datas')); $app->add(new module_console_sphinxGenerateSuggestion('sphinx:generate-suggestions')); @@ -84,8 +88,8 @@ try { $app->add(new module_console_fieldsRename('fields:rename')); $app->add(new module_console_fieldsMerge('fields:merge')); - $app->add(new Alchemy\Phrasea\Command\RescanTechnicalDatas('records:rescan-technical-datas')); - $app->add(new Alchemy\Phrasea\Command\BuildMissingSubdefs('records:build-missing-subdefs')); + $app->add(new RescanTechnicalDatas('records:rescan-technical-datas')); + $app->add(new BuildMissingSubdefs('records:build-missing-subdefs')); $result_code = is_int($app->run()) ? : 1; } catch (Exception $e) { diff --git a/lib/Alchemy/Phrasea/Command/Upgrade/Step35.php b/lib/Alchemy/Phrasea/Command/Upgrade/Step35.php index fe646cd9f0..92f4470465 100644 --- a/lib/Alchemy/Phrasea/Command/Upgrade/Step35.php +++ b/lib/Alchemy/Phrasea/Command/Upgrade/Step35.php @@ -303,4 +303,4 @@ class Step35 implements DatasUpgraderInterface } } -} \ No newline at end of file +} diff --git a/lib/Alchemy/Phrasea/Controller/Setup/Upgrader.php b/lib/Alchemy/Phrasea/Controller/Setup/Upgrader.php index acb064e0e6..831defe1f7 100644 --- a/lib/Alchemy/Phrasea/Controller/Setup/Upgrader.php +++ b/lib/Alchemy/Phrasea/Controller/Setup/Upgrader.php @@ -75,6 +75,10 @@ class Upgrader implements ControllerProviderInterface $upgrader = new \Setup_Upgrade($appbox); $appbox->forceUpgrade($upgrader); + /** + * @todo Show recomandation instead of redirect + */ + return new \Symfony\Component\HttpFoundation\RedirectResponse('/'); }); diff --git a/lib/classes/Setup/Upgrade.class.php b/lib/classes/Setup/Upgrade.class.php index 23ed9220bf..5bdd116fa2 100644 --- a/lib/classes/Setup/Upgrade.class.php +++ b/lib/classes/Setup/Upgrade.class.php @@ -134,6 +134,11 @@ class Setup_Upgrade $this->recommendations[] = array($recommendation, $command); } + /** + * Return an array of recommendations + * + * @return array + */ public function getRecommendations() { return $this->recommendations; diff --git a/templates/web/common/drop_down_options.html b/templates/web/common/drop_down_options.html index 54e1bd649a..9c3a48b1f1 100644 --- a/templates/web/common/drop_down_options.html +++ b/templates/web/common/drop_down_options.html @@ -1,5 +1,5 @@ {% macro prod(record, user, entry_id)%} - {% if entry_id is none %} + {% if not entry_id %} Date: Thu, 21 Jun 2012 09:30:02 +0200 Subject: [PATCH 11/13] Add license header --- .../Command/Upgrade/DatasUpgraderInterface.php | 12 ++++++++++++ lib/Alchemy/Phrasea/Command/Upgrade/Step31.php | 9 +++++++++ lib/Alchemy/Phrasea/Command/Upgrade/Step35.php | 9 +++++++++ 3 files changed, 30 insertions(+) diff --git a/lib/Alchemy/Phrasea/Command/Upgrade/DatasUpgraderInterface.php b/lib/Alchemy/Phrasea/Command/Upgrade/DatasUpgraderInterface.php index 38ca0fa96b..0f296d0193 100644 --- a/lib/Alchemy/Phrasea/Command/Upgrade/DatasUpgraderInterface.php +++ b/lib/Alchemy/Phrasea/Command/Upgrade/DatasUpgraderInterface.php @@ -1,10 +1,22 @@ Date: Thu, 21 Jun 2012 09:30:19 +0200 Subject: [PATCH 12/13] Update Help definition --- lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php b/lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php index 1e9acf5955..b34474efe6 100644 --- a/lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php +++ b/lib/Alchemy/Phrasea/Command/UpgradeDBDatas.php @@ -35,12 +35,15 @@ class UpgradeDBDatas extends Command $this ->setDescription("Upgrade Phraseanet datas") - ->setHelp("Upgrade Phraseanet datas from older version + ->setHelp(<<addOption('from', 'f', null, 'The version where to start upgrade'); $this->addOption('at-version', null, null, 'The version step to upgrade'); From 544a1997dfbb73d3fde85e497a14649e44045a06 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Thu, 21 Jun 2012 11:17:35 +0200 Subject: [PATCH 13/13] Fix CS --- lib/classes/task/abstract.class.php | 4 +- lib/classes/task/period/archive.class.php | 737 +++++++++++++--------- 2 files changed, 437 insertions(+), 304 deletions(-) diff --git a/lib/classes/task/abstract.class.php b/lib/classes/task/abstract.class.php index 3da7d3f961..be7d16beae 100755 --- a/lib/classes/task/abstract.class.php +++ b/lib/classes/task/abstract.class.php @@ -530,8 +530,10 @@ abstract class task_abstract protected function sleep($nsec) { $nsec = (integer) $nsec; - if ($nsec < 0) + if ($nsec < 0) { throw new \InvalidArgumentException(sprintf("(%s) is not > 0")); + } + while ($this->running && $nsec -- > 0) { sleep(1); } diff --git a/lib/classes/task/period/archive.class.php b/lib/classes/task/period/archive.class.php index 9fb8d7b851..81a537928c 100755 --- a/lib/classes/task/period/archive.class.php +++ b/lib/classes/task/period/archive.class.php @@ -13,6 +13,7 @@ use Alchemy\Phrasea\Border\Attribute as BorderAttribute; use MediaVorus\MediaVorus; use PHPExiftool\Driver\Metadata\Metadata; use PHPExiftool\Driver\Metadata\MetadataBag; +use Symfony\Component\Filesystem\Exception\IOException; /** * @@ -26,7 +27,7 @@ class task_period_archive extends task_abstract * * @var string */ - public $argt = array(); + protected $sbas_id; /** * @@ -58,13 +59,27 @@ class task_period_archive extends task_abstract */ protected $lazaretSession; + /** + * + * @var \Symfony\Component\Filesystem\Filesystem + */ + protected $filesystem; + + public function __construct($taskid, Monolog\Logger $logger) + { + parent::__construct($taskid, $logger); + + $core = \bootstrap::getCore(); + $this->filesystem = $core['file-system']; + } + /** * * @return string */ public function getName() { - return(_('task::archive:Archivage')); + return _('task::archive:Archivage'); } /** @@ -118,20 +133,20 @@ class task_period_archive extends task_abstract } } - return($dom->saveXML()); + return $dom->saveXML(); } /** - * xml2graphic : must fill the graphic form (using js) from xml + * fill the graphic form (using js) from xml * - * @param string $xml - * @param string $form - * @return Void + * @param string $xml + * @param string $form */ public function xml2graphic($xml, $form) { - if (($sxml = simplexml_load_string($xml)) != FALSE) { // in fact XML IS always valid here... - // ... but we could check for safe values (ex. 0 < period < 3600) + // XML should always be valid here... + if (($sxml = simplexml_load_string($xml)) != false) { + // sanitize values if ((int) ($sxml->period) < 10) { $sxml->period = 10; } elseif ((int) ($sxml->period) > 3600) { @@ -148,32 +163,28 @@ class task_period_archive extends task_abstract var opts = .base_id.options; var basefound = 0; for (i=1; basefound==0 && ibase_id, "form") ?>") + if(opts[i].value == "base_id, "form") ?>") basefound = i; } opts[basefound].selected = true; - .hotfolder.value = "hotfolder, "js", '"') ?>"; - .period.value = "period, "js", '"') ?>"; - .cold.value = "cold, "js", '"') ?>"; - .move_archived.checked = move_archived) ? "true" : "false" ?>; - .move_error.checked = move_error) ? "true" : "false" ?>; - .delfolder.checked = delfolder) ? "true" : "false" ?>; - .copy_spe.checked = copy_spe) ? "true" : "false" ?>; + .hotfolder.value = "hotfolder, "js", '"') ?>"; + .period.value = "period, "js", '"') ?>"; + .cold.value = "cold, "js", '"') ?>"; + .move_archived.checked = move_archived) ? "true" : "false" ?>; + .move_error.checked = move_error) ? "true" : "false" ?>; + .delfolder.checked = delfolder) ? "true" : "false" ?>; + .copy_spe.checked = copy_spe) ? "true" : "false" ?>; @@ -251,33 +260,30 @@ class task_period_archive extends task_abstract */ public function help() { - return(_("task::archive:Archiving files found into a 'hotfolder'")); + return _("task::archive:Archiving files found into a 'hotfolder'"); } - protected $sbas_id; /** - * - * @return void + * {@inheritdoc} */ protected function run2() { - $this->debug = FALSE; + $this->debug = false; - $core = \bootstrap::getCore(); - $conn = connection::getPDOConnection(); + $conn = \connection::getPDOConnection(); $this->sxTaskSettings = simplexml_load_string($this->settings); $base_id = (int) ($this->sxTaskSettings->base_id); - $this->sbas_id = phrasea::sbasFromBas($base_id); + $this->sbas_id = \phrasea::sbasFromBas($base_id); if ( ! $this->sbas_id) { $this->log('base_id unknown'); - return('tostop'); + return 'tostop'; } - $databox = databox::get_instance($this->sbas_id); + $databox = \databox::get_instance($this->sbas_id); $this->TColls = array(); $collection = null; @@ -289,12 +295,13 @@ class task_period_archive extends task_abstract } $server_coll_id = $collection->get_coll_id(); - $this->tmask = array(); // mask(s) of accepted files + // mask(s) of accepted files + $this->tmask = array(); $this->tmaskgrp = array(); $this->period = 60; $this->cold = 30; - if (($this->sxBasePrefs = simplexml_load_string($collection->get_prefs())) != FALSE) { + if (($this->sxBasePrefs = simplexml_load_string($collection->get_prefs())) != false) { $this->sxBasePrefs["id"] = $base_id; $this->period = (int) ($this->sxTaskSettings->period); @@ -311,11 +318,10 @@ class task_period_archive extends task_abstract $pathhd = (string) ($this->sxBasePrefs->path); if ($pathhd) { - - $core['file-system']->mkdir($pathhd, 0750); - - if ( ! is_dir($pathhd)) { - $this->log(sprintf(_('task::archive:Can\'t create or go to folder \'%s\''), $pathhd)); + try { + $this->filesystem->mkdir($pathhd, 0750); + } catch (IOException $e) { + $this->log($e->getMessage()); $this->running = false; return; @@ -358,18 +364,16 @@ class task_period_archive extends task_abstract if ($this->getRunner() == self::RUNNER_SCHEDULER) { $this->log(("Warning : abox connection lost, restarting in 10 min.")); - // DON'T do sleep(600) because it prevents ticks ! - for ($t = 60 * 10; $this->running && $t; $t -- ) { - sleep(1); - } - // because connection is lost we cannot change status to 'torestart' - // anyway the current status 'running' with no pid - // will enforce the scheduler to restart the task + $this->sleep(60 * 10); + /** + * because connection is lost we cannot change status to 'torestart' + * anyway the current status 'running' with no pid + * will enforce the scheduler to restart the task + */ } else { $this->log(("Error : abox connection lost, quitting.")); - // runner = manual : can't restart so simply quit } - $this->running = FALSE; + $this->running = false; return; } @@ -379,10 +383,8 @@ class task_period_archive extends task_abstract if ($this->getRunner() == self::RUNNER_SCHEDULER) { $this->log(sprintf(('Warning : missing hotfolder \'%s\', restarting in 10 min.'), $path_in)); - // DON'T do sleep(600) because it prevents ticks ! - for ($t = 60 * 10; $this->running && $t; $t -- ) { - sleep(1); - } + $this->sleep(60 * 10); + if ($this->getState() === self::STATE_STARTED) { $this->setState(self::STATE_TORESTART); } @@ -391,7 +393,7 @@ class task_period_archive extends task_abstract // runner = manual : can't restart so simply quit $this->setState(self::STATE_STOPPED); } - $this->running = FALSE; + $this->running = false; return; } @@ -429,7 +431,7 @@ class task_period_archive extends task_abstract // runner = manual : can't restart so simply quit $this->setState(self::STATE_STOPPED); } - $this->running = FALSE; + $this->running = false; return; } @@ -437,7 +439,7 @@ class task_period_archive extends task_abstract $status = $this->getState(); if ($status == self::STATE_TOSTOP) { - $this->running = FALSE; + $this->running = false; return; } @@ -452,15 +454,15 @@ class task_period_archive extends task_abstract switch ($r) { case 'TOSTOP': $this->setState(self::STATE_STOPPED); - $this->running = FALSE; + $this->running = false; break; case 'WAIT': $this->setState(self::STATE_STOPPED); - $this->running = FALSE; + $this->running = false; break; case 'BAD': $this->setState(self::STATE_STOPPED); - $this->running = FALSE; + $this->running = false; break; case 'NORECSTODO': $duration = time() - $duration; @@ -469,9 +471,9 @@ class task_period_archive extends task_abstract $s = $this->getState(); if ($s == self::STATE_TOSTOP) { $this->setState(self::STATE_STOPPED); - $this->running = FALSE; + $this->running = false; } else { - sleep(1); + $this->sleep(1); } } } @@ -481,13 +483,13 @@ class task_period_archive extends task_abstract case 'MAXLOOP': if ($status == self::STATE_STARTED && $this->getRunner() !== self::RUNNER_MANUAL) { $this->setState(self::STATE_TORESTART); - $this->running = FALSE; + $this->running = false; } break; default: if ($status == self::STATE_STARTED) { $this->setState(self::STATE_STOPPED); - $this->running = FALSE; + $this->running = false; } break; } @@ -498,7 +500,7 @@ class task_period_archive extends task_abstract /** * - * @param int $server_coll_id + * @param integer $server_coll_id * @return string */ protected function archiveHotFolder($server_coll_id) @@ -509,29 +511,33 @@ class task_period_archive extends task_abstract \databox::get_instance($this->sbas_id)->get_connection(); $path_in = p4string::delEndSlash(trim((string) ($this->sxTaskSettings->hotfolder))); - if ( ! @is_file($path_in . "/.phrasea.xml")) { + if (false === $this->filesystem->exists($path_in . "/.phrasea.xml")) { $this->log(sprintf(('NO .phrasea.xml AT ROOT v2 \'%s\' !'), $path_in)); - return('WAIT'); + return 'WAIT'; } $path_archived = $path_error = null; if ($this->move_archived) { $path_archived = $path_in . '_archived'; - @mkdir($path_archived, 0755, true); - if ( ! file_exists($path_archived)) { - $this->log(sprintf(('Can\'t create folder \'%s\' !'), $path_archived)); - return('BAD'); + try { + $this->filesystem->mkdir($path_archived, 0755); + } catch (IOException $e) { + $this->log($e->getMessage()); + + return 'BAD'; } } if ($this->move_error) { $path_error = $path_in . '_error'; - @mkdir($path_error, 0755, true); - if ( ! file_exists($path_error)) { - $this->log(sprintf(('archive:Can\'t create folder \'%s\' !'), $path_error)); - return('BAD'); + try { + $this->filesystem->mkdir($path_error, 0755); + } catch (IOException $e) { + $this->log($e->getMessage()); + + return 'BAD'; } } @@ -550,7 +556,7 @@ class task_period_archive extends task_abstract // special case : status has changed to TOSTOP while listing files if ($nnew === 'TOSTOP') { - return('TOSTOP'); + return 'TOSTOP'; } // wait for files to be cold @@ -562,9 +568,9 @@ class task_period_archive extends task_abstract while ($this->running && $cold > 0) { $s = $this->getState(); if ($s == self::STATE_TOSTOP) { - return('TOSTOP'); + return 'TOSTOP'; } - sleep(2); + $this->sleep(2); $cold -= 2; } @@ -575,7 +581,7 @@ class task_period_archive extends task_abstract // special case : status has changed to TOSTOP while listing files if ($nnew === 'TOSTOP') { - return('TOSTOP'); + return 'TOSTOP'; } $this->makePairs($dom, $root, $path_in, $path_archived, $path_error); @@ -606,36 +612,35 @@ class task_period_archive extends task_abstract if ($this->movedFiles) { // something happened : a least one file has moved - return('MAXRECSDONE'); + return self::STATE_MAXRECSDONE; } elseif (memory_get_usage() >> 20 > 25) { - return('MAXMEMORY'); + return self::STATE_MAXMEGSREACHED; } else { - return('NORECSTODO'); + return 'NORECSTODO'; } } /** * - * @param string $f + * @param string $f * @return boolean */ protected function isIgnoredFile($f) { $f = strtolower($f); - return(($f[0] == '.' && $f != '.phrasea.xml' && $f != '.grouping.xml') || $f == 'thumbs.db' || $f == 'par-system'); + return ($f[0] == '.' && $f != '.phrasea.xml' && $f != '.grouping.xml') || $f == 'thumbs.db' || $f == 'par-system'; } /** * check if the file matches any mask, and flag the 'caption' file if found * - * @param DOMDocument $dom - * @param DOMElement $node - * @return void + * @param \DOMDocument $dom + * @param \DOMElement $node */ - protected function checkMatch($dom, $node) + protected function checkMatch(\DOMDocument $dom, \DOMElement $node) { $file = $node->getAttribute('name'); @@ -673,13 +678,13 @@ class task_period_archive extends task_abstract * list every file, all 'hot' * read .phrasea.xml files * - * @param DOMDocument $dom - * @param DomElement $node - * @param string $path - * @param int $server_coll_id - * @return int|string the number on found files or "TOSTOP" if task is to stop + * @param \DOMDocument $dom + * @param \DomElement $node + * @param string $path + * @param integer $server_coll_id + * @return integer|string the number on found files or "TOSTOP" if task is to stop */ - private function listFilesPhase1($dom, $node, $path, $server_coll_id, $depth = 0) + private function listFilesPhase1(\DOMDocument $dom, \DomElement $node, $path, $server_coll_id, $depth = 0) { static $time0 = null; if ($depth == 0) { @@ -691,14 +696,14 @@ class task_period_archive extends task_abstract try { $listFolder = new CListFolder($path); - if (($sxDotPhrasea = @simplexml_load_file($path . '/.phrasea.xml')) != FALSE) { + if (($sxDotPhrasea = @simplexml_load_file($path . '/.phrasea.xml')) != false) { // test for magic file if (($magicfile = trim((string) ($sxDotPhrasea->magicfile))) != '') { $magicmethod = strtoupper($sxDotPhrasea->magicfile['method']); - if ($magicmethod == 'LOCK' && file_exists($path . '/' . $magicfile)) { + if ($magicmethod == 'LOCK' && true === $this->filesystem->exists($path . '/' . $magicfile)) { return; - } elseif ($magicmethod == 'UNLOCK' && ! file_exists($path . '/' . $magicfile)) { + } elseif ($magicmethod == 'UNLOCK' && false === $this->filesystem->exists($path . '/' . $magicfile)) { return; } } @@ -718,11 +723,13 @@ class task_period_archive extends task_abstract $iloop = 0; $time0 = time(); while (($file = $listFolder->read()) !== null) { - // each 2 secs, check the status of the task + // each 2 secs, check the status of the task if (time() - $time0 >= 2) { if ($this->getState() == self::STATE_TOSTOP) { - $nnew = 'TOSTOP'; // since we will return a string... - break; // ...we can check it against numerical result + // since we will return a string... + $nnew = 'TOSTOP'; + // ...we can check it against numerical result + break; } $time0 = time(); } @@ -742,10 +749,12 @@ class task_period_archive extends task_abstract $_nnew_ = $this->listFilesPhase1($dom, $n, $path . '/' . $file, $server_coll_id, $depth + 1); if ($_nnew_ === 'TOSTOP') { - $nnew = 'TOSTOP'; // special case to quit recursion + // special case to quit recursion + $nnew = 'TOSTOP'; break; } else { - $nnew += $_nnew_; // normal case, _nnew_ is a number + // normal case, _nnew_ is a number + $nnew += $_nnew_; } } else { $n = $node->appendChild($dom->createElement('file')); @@ -764,7 +773,7 @@ class task_period_archive extends task_abstract } - return($nnew); + return $nnew; } /** @@ -772,16 +781,16 @@ class task_period_archive extends task_abstract * list again and flag dead files as 'cold' * * @staticvar int $iloop - * @param DOMDocument $dom - * @param DOMElement $node - * @param string $path - * @param int $depth - * @return int|string the number of NEW files or "TOSTOP" if task is to stop + * @param \DOMDocument $dom + * @param \DOMElement $node + * @param string $path + * @param integer $depth + * @return integer|string the number of NEW files or "TOSTOP" if task is to stop */ - private function listFilesPhase2($dom, $node, $path, $depth = 0) + private function listFilesPhase2(\DOMDocument $dom, \DOMElement $node, $path, $depth = 0) { static $iloop = 0; - static $time0 = NULL; + static $time0 = null; if ($depth == 0) { $iloop = 0; $time0 = time(); @@ -794,25 +803,27 @@ class task_period_archive extends task_abstract $xp = new DOMXPath($dom); - if (($sxDotPhrasea = @simplexml_load_file($path . '/.phrasea.xml')) != FALSE) { + if (($sxDotPhrasea = @simplexml_load_file($path . '/.phrasea.xml')) != false) { // test magicfile if (($magicfile = trim((string) ($sxDotPhrasea->magicfile))) != '') { $magicmethod = strtoupper($sxDotPhrasea->magicfile['method']); - if ($magicmethod == 'LOCK' && file_exists($path . '/' . $magicfile)) { + if ($magicmethod == 'LOCK' && true === $this->filesystem->exists($path . '/' . $magicfile)) { return 0; - } elseif ($magicmethod == 'UNLOCK' && ! file_exists($path . '/' . $magicfile)) { + } elseif ($magicmethod == 'UNLOCK' && false === $this->filesystem->exists($path . '/' . $magicfile)) { return 0; } } } while (($file = $listFolder->read()) !== null) { - // each 2 secs, check the status of the task + // each 2 secs, check the status of the task if (time() - $time0 >= 2) { if ($this->getState() == self::STATE_TOSTOP) { - $nnew = 'TOSTOP'; // since we will return a string... - break; // ...we can check it against numerical result + // since we will return a string... + $nnew = 'TOSTOP'; + // ...we can check it against numerical result + break; } $time0 = time(); } @@ -834,10 +845,12 @@ class task_period_archive extends task_abstract $_nnew_ = $this->listFilesPhase2($dom, $n, $path . '/' . $file, $depth + 1); if ($_nnew_ === 'TOSTOP') { - $nnew = 'TOSTOP'; // special case to quit recursion + // special case to quit recursion + $nnew = 'TOSTOP'; break; } else { - $nnew += $_nnew_; // normal case, _nnew_ is a number + // normal case, _nnew_ is a number + $nnew += $_nnew_; } } else { $n = $node->appendChild($dom->createElement('file')); @@ -846,8 +859,9 @@ class task_period_archive extends task_abstract } $this->setBranchHot($dom, $n); } elseif ($dnl && $dnl->length == 1) { + $dnl->item(0)->setAttribute('temperature', 'cold'); - // $dnl->item(0)->removeAttribute('hot'); + if (is_dir($path . '/' . $file)) { $this->listFilesPhase2($dom, $dnl->item(0), $path . '/' . $file, $depth + 1); } else { @@ -875,16 +889,15 @@ class task_period_archive extends task_abstract * declare uncomplete grp as error * * @staticvar int $iloop - * @param DOMDocument $dom - * @param DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param boolean $inGrp - * @param int $depth - * @return void + * @param \DOMDocument $dom + * @param \DOMElement $node + * @param string $path + * @param string $path_archived + * @param string $path_error + * @param boolean $inGrp + * @param integer $depth */ - private function makePairs($dom, $node, $path, $path_archived, $path_error, $inGrp = false, $depth = 0) + private function makePairs(\DOMDocument $dom, \DOMElement $node, $path, $path_archived, $path_error, $inGrp = false, $depth = 0) { static $iloop = 0; if ($depth == 0) { @@ -895,7 +908,7 @@ class task_period_archive extends task_abstract return; } - $xpath = new DOMXPath($dom); // useful + $xpath = new DOMXPath($dom); for ($n = $node->firstChild; $n; $n = $n->nextSibling) { if (($iloop ++ % 100) == 0) { @@ -913,7 +926,8 @@ class task_period_archive extends task_abstract $name = $n->getAttribute('name'); if ($n->getAttribute('isdir') == '1') { - if (($grpSettings = $this->getGrpSettings($name)) !== FALSE) { // get 'caption', 'representation' + // get 'caption', 'representation' + if (($grpSettings = $this->getGrpSettings($name)) !== false) { // this is a grp folder, we check it $dnl = $xpath->query('./file[@name=".grouping.xml"]', $n); if ($dnl->length == 1) { @@ -935,10 +949,12 @@ class task_period_archive extends task_abstract $dnl = $xpath->query('./file[@name="' . $f . '"]', $node); if ($dnl->length == 1) { - $flink[$linkName] = $dnl->item(0); // it's here + // it's here + $flink[$linkName] = $dnl->item(0); } else { $this->log(sprintf(('missing linked file \'%1$s\' to group \'%2$s\''), $f, $name)); - $err = true; // missing -> error + // missing -> error + $err = true; } } } @@ -949,7 +965,8 @@ class task_period_archive extends task_abstract // ... as the existing linked file(s) ... foreach ($flink as $linkName => $v) { - if ($v) { // this linked file exists + // this linked file exists + if ($v) { $v->setAttribute('match', '*'); $n->setAttribute('grp_' . $linkName, $v->getAttribute('name')); } @@ -972,8 +989,10 @@ class task_period_archive extends task_abstract // ... as the existing linked file(s) ... foreach ($flink as $linkName => $v) { - if ($v) // this linked file exists, it goes error also + // this linked file exists, it goes error also + if ($v) { $v->setAttribute('error', '1'); + } } } } @@ -986,9 +1005,11 @@ class task_period_archive extends task_abstract } } else { // this is a file - if ( ! $n->getAttribute('match')) { // because match can be set before + if ( ! $n->getAttribute('match')) { + // because match can be set before if ($name == '.phrasea.xml') { - $n->setAttribute('match', '*'); // special file(s) always ok + // special file(s) always ok + $n->setAttribute('match', '*'); } else { $this->checkMatch($dom, $n); } @@ -1014,15 +1035,14 @@ class task_period_archive extends task_abstract * move files to archived or error dir * * @staticvar int $iloop - * @param DOMDocument $dom - * @param DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param int $depth - * @return void + * @param \DOMDocument $dom + * @param \DOMElement $node + * @param string $path + * @param string $path_archived + * @param string $path_error + * @param integer $depth */ - private function removeBadGroups($dom, $node, $path, $path_archived, $path_error, $depth = 0) + private function removeBadGroups(\DOMDocument $dom, \DOMElement $node, $path, $path_archived, $path_error, $depth = 0) { static $iloop = 0; if ($depth == 0) { @@ -1033,7 +1053,7 @@ class task_period_archive extends task_abstract // if root of hotfolder if hot, die... if ($depth == 0 && $node->getAttribute('temperature') == 'hot') { - return($ret); + return $ret; } $nodesToDel = array(); @@ -1043,35 +1063,53 @@ class task_period_archive extends task_abstract } if ($n->getAttribute('temperature') == 'hot') { - continue; // do not move hotfiles + // do not move hotfiles + continue; } $name = $n->getAttribute('name'); if ($n->getAttribute('isdir')) { - // a dir $ret |= $this->removeBadGroups($dom, $n, $path . '/' . $name , $path_archived . '/' . $name , $path_error . '/' . $name , $depth + 1); if ($n->getAttribute('grp') == 'todelete') { $nodesToDel[] = $n; - @unlink($path . '/' . $name); + + try { + $this->filesystem->remove($path . '/' . $name); + } catch (IOException $e) { + $this->log($e->getMessage()); + } } } else { - // a file if ($n->getAttribute('error')) { if ($this->move_error) { $rootpath = p4string::delEndSlash(trim((string) ($this->sxTaskSettings->hotfolder))); $subpath = substr($path, strlen($rootpath)); $this->log(sprintf(('copy \'%s\' to \'error\''), $subpath . '/' . $name)); - @mkdir($path_error, 0755, true); - @copy($path . '/' . $name, $path_error . '/' . $name); + try { + $this->filesystem->mkdir($path_error, 0755); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + + try { + $this->filesystem->copy($path . '/' . $name, $path_error . '/' . $name, true); + } catch (IOException $e) { + $this->log($e->getMessage()); + } } $nodesToDel[] = $n; - @unlink($path . '/' . $name); + + try { + $this->filesystem->remove($path . '/' . $name); + } catch (IOException $e) { + $this->log($e->getMessage()); + } $this->movedFiles ++; } @@ -1091,17 +1129,17 @@ class task_period_archive extends task_abstract * do special work on grp folders * * @staticvar int $iloop - * @param DOMDOcument $dom - * @param DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param int $depth - * @return void + * @param \DOMDOcument $dom + * @param \DOMElement $node + * @param string $path + * @param string $path_archived + * @param string $path_error + * @param integer $depth */ - private function archive($dom, $node, $path, $path_archived, $path_error, $depth = 0) + private function archive(\DOMDOcument $dom, \DOMElement $node, $path, $path_archived, $path_error, $depth = 0) { static $iloop = 0; + if ($depth == 0) { $iloop = 0; } @@ -1138,8 +1176,8 @@ class task_period_archive extends task_abstract , $depth + 1); } } else { - // a file - $this->archiveFile($dom, $n, $path, $path_archived, $path_error, $nodesToDel, 0); // 0 = no grp + // a file, 0 = no grp + $this->archiveFile($dom, $n, $path, $path_archived, $path_error, $nodesToDel, 0); } } foreach ($nodesToDel as $n) { @@ -1152,7 +1190,12 @@ class task_period_archive extends task_abstract if ($magicmethod == 'LOCK') { file_put_contents($path . '/' . $magicfile, ''); } elseif ($magicmethod == 'UNLOCK') { - unlink($path . '/' . $magicfile); + + try { + $this->filesystem->remove($path . '/' . $magicfile); + } catch (IOException $e) { + $this->log($e->getMessage()); + } } } @@ -1165,13 +1208,13 @@ class task_period_archive extends task_abstract * to help creation of result folders and cleaning of the hotfolder * * @staticvar int $iloop - * @param DOMDocument $dom - * @param DOMElement $node - * @param string $path - * @param int $depth - * @return int flags used only inside recursion + * @param \DOMDocument $dom + * @param \DOMElement $node + * @param string $path + * @param integer $depth + * @return integer flags used only inside recursion */ - private function bubbleResults($dom, $node, $path, $depth = 0) + private function bubbleResults(\DOMDocument $dom, \DOMElement $node, $path, $depth = 0) { static $iloop = 0; if ($depth == 0) { @@ -1218,23 +1261,22 @@ class task_period_archive extends task_abstract $node->setAttribute('error', '1'); } - return($ret); + return $ret; } /** - * Phase 5 : - * move files to archived or error dir + * Phase 5 : move files to archived or error dir * * @staticvar int $iloop - * @param DOMDocument $dom - * @param DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param int $depth - * @return boolean at least one file was moved + * @param \DOMDocument $dom + * @param \DOMElement $node + * @param string $path + * @param string $path_archived + * @param string $path_error + * @param integer $depth + * @return boolean at least one file was moved */ - private function moveFiles($dom, $node, $path, $path_archived, $path_error, $depth = 0) + private function moveFiles(\DOMDocument $dom, \DOMElement $node, $path, $path_archived, $path_error, $depth = 0) { static $iloop = 0; if ($depth == 0) { @@ -1245,7 +1287,7 @@ class task_period_archive extends task_abstract // if root of hotfolder if hot, die... if ($depth == 0 && $node->getAttribute('temperature') == 'hot') { - return($ret); + return $ret; } $nodesToDel = array(); @@ -1269,10 +1311,9 @@ class task_period_archive extends task_abstract if ( ! $n->firstChild) { $nodesToDel[] = $n; } -// ----- JY 20100318 : DO NOT DELETE EMPTY FOLDERS ANYMORE, AS THEY MAY DISAPEAR TOO SOON ----- -// if(!$n->getAttribute('keep')) -// @rmdir($path.'/'.$name); -// -------------------------------------------------------------------------------------------- + /** + * Do not remove empty folders yet + */ } else { $rootpath = p4string::delEndSlash(trim((string) ($this->sxTaskSettings->hotfolder))); $subpath = substr($path, strlen($rootpath)); @@ -1280,8 +1321,18 @@ class task_period_archive extends task_abstract if ($n->getAttribute('archived') && $this->move_archived) { $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $name)); - @mkdir($path_archived, 0755, true); - @copy($path . '/' . $name, $path_archived . '/' . $name); + try { + $this->filesystem->mkdir($path_archived); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + + try { + $this->filesystem->copy($path . '/' . $name, $path_archived . '/' . $name, true); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + if ( ! $n->getAttribute('keep')) { // do not count copy of special files as a real event $nodesToDel[] = $n; $ret = true; @@ -1291,8 +1342,18 @@ class task_period_archive extends task_abstract if ($n->getAttribute('error') && $this->move_error) { $this->log(sprintf(('copy \'%s\' to \'error\''), $subpath . '/' . $name)); - @mkdir($path_error, 0755, true); - @copy($path . '/' . $name, $path_error . '/' . $name); + try { + $this->filesystem->mkdir($path_error); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + + try { + $this->filesystem->copy($path . '/' . $name, $path_error . '/' . $name, true); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + if ( ! $n->getAttribute('keep')) { // do not count copy of special files as a real event $nodesToDel[] = $n; $ret = true; @@ -1301,10 +1362,12 @@ class task_period_archive extends task_abstract if ( ! $n->getAttribute('keep')) { $this->log(sprintf(('delete \'%s\''), $subpath . '/' . $name)); - if (@unlink($path . '/' . $name)) { + + try { + $this->filesystem->remove($path . '/' . $name); $this->movedFiles ++; - } else { - $this->log(sprintf(("Warning : can't delete '%s' from hotfolder, task is stopped"), $subpath . '/' . $name)); + } catch (IOException $e) { + $this->log($e->getMessage()); } } } @@ -1314,16 +1377,15 @@ class task_period_archive extends task_abstract $n->parentNode->removeChild($n); } - return($ret); + return $ret; } /** * - * @param DOMDocument $dom - * @param DOMElement $node - * @return void + * @param \DOMDocument $dom + * @param \DOMElement $node */ - private function setBranchHot($dom, $node) + private function setBranchHot(\DOMDocument $dom, \DOMElement $node) { for ($n = $node; $n; $n = $n->parentNode) { if ($n->nodeType == XML_ELEMENT_NODE) { @@ -1343,19 +1405,19 @@ class task_period_archive extends task_abstract * create the grp if needed * archive files * - * @param DOMDocument $dom - * @param DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param array $nodesToDel out, filled with deleted files - * @return void + * @param \DOMDocument $dom + * @param \DOMElement $node + * @param string $path + * @param string $path_archived + * @param string $path_error + * @param array $nodesToDel out, filled with deleted files */ - private function archiveGrp($dom, $node, $path, $path_archived, $path_error, &$nodesToDel) + private function archiveGrp(\DOMDocument $dom, \DOMElement $node, $path, $path_archived, $path_error, array &$nodesToDel) { - $xpath = new DOMXPath($dom); // useful + $xpath = new DOMXPath($dom); - $node->setAttribute('keep', '1'); // grp folders stay in place + // grp folders stay in place + $node->setAttribute('keep', '1'); $grpFolder = $node->getAttribute('name'); $groupingFile = $path . '/' . $grpFolder . '/.grouping.xml'; @@ -1377,7 +1439,13 @@ class task_period_archive extends task_abstract if ( ! ($rep = $node->getAttribute('grp_representation'))) { $registry = registry::get_instance(); - copy(p4string::addEndSlash($registry->get('GV_RootPath')) . 'www/skins/icons/substitution/regroup_doc.png', $genericdoc = ($path . '/group.jpg')); + + try { + $this->filesystem->copy(p4string::addEndSlash($registry->get('GV_RootPath')) . 'www/skins/icons/substitution/regroup_doc.png', $genericdoc = ($path . '/group.jpg'), true); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + $representationFileName = 'group.jpg'; $this->log((' (no representation file)')); } else { @@ -1412,7 +1480,12 @@ class task_period_archive extends task_abstract $this->archivedFiles ++; if ($genericdoc) { - unlink($genericdoc); + try { + $this->filesystem->remove($genericdoc); + $this->movedFiles ++; + } catch (IOException $e) { + $this->log($e->getMessage()); + } } file_put_contents($groupingFile, ''); @@ -1423,8 +1496,18 @@ class task_period_archive extends task_abstract $n->setAttribute('match', '*'); if ($this->move_archived) { $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $grpFolder . '/.grouping.xml')); - @mkdir($path_archived . '/' . $grpFolder, 0755, true); - @copy($path . '/' . $grpFolder . '/.grouping.xml', $path_archived . '/' . $grpFolder . '/.grouping.xml'); + + try { + $this->filesystem->mkdir($path_archived . '/' . $grpFolder, 0755); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + + try { + $this->filesystem->copy($path . '/' . $grpFolder . '/.grouping.xml', $path_archived . '/' . $grpFolder . '/.grouping.xml', true); + } catch (IOException $e) { + $this->log($e->getMessage()); + } } if ($captionFileNode) { @@ -1432,12 +1515,26 @@ class task_period_archive extends task_abstract if ($this->move_archived) { $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $captionFileName)); - if ( ! is_dir($path_archived)) { - @mkdir($path_archived, 0755, true); + try { + $this->filesystem->mkdir($path_archived, 0755); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + + try { + $this->filesystem->copy($path . '/' . $captionFileName, $path_archived . '/' . $captionFileName, true); + } catch (IOException $e) { + $this->log($e->getMessage()); } - @copy($path . '/' . $captionFileName, $path_archived . '/' . $captionFileName); } - @unlink($path . '/' . $captionFileName); + + try { + $this->filesystem->remove($path . '/' . $captionFileName); + $this->movedFiles ++; + } catch (IOException $e) { + $this->log($e->getMessage()); + } + $nodesToDel[] = $captionFileNode; $this->movedFiles ++; @@ -1447,17 +1544,29 @@ class task_period_archive extends task_abstract if ($this->move_archived) { $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $representationFileName)); - if ( ! is_dir($path_archived)) { - @mkdir($path_archived, 0755, true); + try { + $this->filesystem->mkdir($path_archived, 0755); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + + try { + $this->filesystem->copy($path . '/' . $representationFileName, $path_archived . '/' . $representationFileName, true); + } catch (IOException $e) { + $this->log($e->getMessage()); } - @copy($path . '/' . $representationFileName, $path_archived . '/' . $representationFileName); } - @unlink($path . '/' . $representationFileName); + + try { + $this->filesystem->remove($path . '/' . $representationFileName); + $this->movedFiles ++; + } catch (IOException $e) { + $this->log($e->getMessage()); + } $nodesToDel[] = $representationFileNode; $this->movedFiles ++; } - // $node->setAttribute('grp', 'tocomplete'); } catch (Exception $e) { $this->logger->addDebug($e->getMessage()); @@ -1465,13 +1574,9 @@ class task_period_archive extends task_abstract } // here the .grouping.xml should exists - if (file_exists($groupingFile)) { + if ($this->filesystem->exists($groupingFile)) { // a .grouping.xml must stay in place // -- don't do, done in phase4 - //$xpath = new DOMXPath($dom); - //$dnl = $xpath->query('./file[@name=".grouping.xml"]', $node); - //if($dnl->length == 1) - // $dnl->item(0)->setAttribute('keep', '1'); $sxGrouping = simplexml_load_file($groupingFile); $grp_rid = $sxGrouping['grouping']; @@ -1523,7 +1628,7 @@ class task_period_archive extends task_abstract $metadatas = $this->getIndexByFieldName($metadatasStructure, $media->getEntity()->getMetadatas()); - if ($captionFile !== null && file_exists($captionFile)) { + if ($captionFile !== null && true === $this->filesystem->exists($captionFile)) { $caption = $this->readXMLForDatabox($metadatasStructure, $captionFile); $captionStatus = $this->parseStatusBit(simplexml_load_file($captionFile)); @@ -1552,12 +1657,12 @@ class task_period_archive extends task_abstract /** * Creates a record * - * @param \collection $collection The destination collection - * @param string $pathfile The file to archive - * @param string|null $captionFile The Phrasea XML caption file or null if no caption file - * @param integer $grp_rid Add the record to a story - * @param integer $force Force lazaret or record ; use \Alchemy\Phrasea\Border\Manager::FORCE_* constants - * @return null + * @param \collection $collection The destination collection + * @param string $pathfile The file to archive + * @param string|null $captionFile The Phrasea XML caption file or null if no caption file + * @param integer $grp_rid Add the record to a story + * @param integer $force Force lazaret or record ; use \Alchemy\Phrasea\Border\Manager::FORCE_* constants + * @return \record_adapter */ public function createRecord(\collection $collection, $pathfile, $captionFile, $grp_rid, $force = null) { @@ -1589,7 +1694,7 @@ class task_period_archive extends task_abstract $metadatas = $this->getIndexByFieldName($metadatasStructure, $media->getEntity()->getMetadatas()); - if ($captionFile !== null && file_exists($captionFile)) { + if ($captionFile !== null && true === $this->filesystem->exists($captionFile)) { $caption = $this->readXMLForDatabox($metadatasStructure, $captionFile); $captionStatus = $this->parseStatusBit(simplexml_load_file($captionFile)); @@ -1631,15 +1736,14 @@ class task_period_archive extends task_abstract /** * - * @param DOMDocument $dom - * @param DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param int $grp_rid - * @return void + * @param \DOMDocument $dom + * @param \DOMElement $node + * @param string $path + * @param string $path_archived + * @param string $path_error + * @param integer $grp_rid */ - private function archiveFilesToGrp($dom, $node, $path, $path_archived, $path_error, $grp_rid) + private function archiveFilesToGrp(\DOMDocument $dom, \DOMElement $node, $path, $path_archived, $path_error, $grp_rid) { $nodesToDel = array(); for ($n = $node->firstChild; $n; $n = $n->nextSibling) { @@ -1665,16 +1769,15 @@ class task_period_archive extends task_abstract /** * Archive File * - * @param DOMDocument $dom - * @param DOMElement $node - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param array $nodesToDel out, filled with files to delete - * @param $grp_rid - * @return void + * @param \DOMDocument $dom + * @param \DOMDocument $node + * @param string $path + * @param string $path_archived + * @param string $path_error + * @param array $nodesToDel out, filled with files to delete + * @param integer $grp_rid */ - private function archiveFile($dom, $node, $path, $path_archived, $path_error, &$nodesToDel, $grp_rid = 0) + private function archiveFile(\DOMDocument $dom, \DOMDocument $node, $path, $path_archived, $path_error, array &$nodesToDel, $grp_rid = 0) { $match = $node->getAttribute('match'); @@ -1722,22 +1825,19 @@ class task_period_archive extends task_abstract /** * - * @param DOMDOcument $dom - * @param DOMElement $node - * @param DOMElement $captionFileNode - * @param string $path - * @param string $path_archived - * @param string $path_error - * @param int $grp_rid - * @param array $nodesToDel out, filled with files to delete - * @return void + * @param \DOMDOcument $dom + * @param \DOMElement $node + * @param \DOMElement $captionFileNode + * @param string $path + * @param string $path_archived + * @param string $path_error + * @param integer $grp_rid + * @param array $nodesToDel out, filled with files to delete */ - private function archiveFileAndCaption($dom, $node, $captionFileNode, $path, $path_archived, $path_error, $grp_rid, &$nodesToDel) + private function archiveFileAndCaption(\DOMDOcument$dom, \DOMElement$node, \DOMElement$captionFileNode, $path, $path_archived, $path_error, $grp_rid, array &$nodesToDel) { $ret = false; - $core = \bootstrap::getCore(); - $file = $node->getAttribute('name'); $cid = $node->getAttribute('cid'); $captionFileName = $captionFileNode ? $captionFileNode->getAttribute('name') : null; @@ -1798,11 +1898,26 @@ class task_period_archive extends task_abstract if ($node->getAttribute('archived') && $this->move_archived) { $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $file)); - @mkdir($path_archived, 0755, true); - @copy($path . '/' . $file, $path_archived . '/' . $file); + try { + $this->filesystem->mkdir($path_archived); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + + try { + $this->filesystem->copy($path . '/' . $file, $path_archived . '/' . $file, true); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + if ($captionFileName != $file) { $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $captionFileName)); - @copy($path . '/' . $captionFileName, $path_archived . '/' . $captionFileName); + + try { + $this->filesystem->copy($path . '/' . $captionFileName, $path_archived . '/' . $captionFileName, true); + } catch (IOException $e) { + $this->log($e->getMessage()); + } } if ( ! $node->getAttribute('keep')) // do not count copy of special files as a real event $ret = true; @@ -1811,11 +1926,26 @@ class task_period_archive extends task_abstract if ($node->getAttribute('error') && $this->move_error) { $this->log(sprintf(('copy \'%s\' to \'error\''), $subpath . '/' . $file)); - @mkdir($path_error, 0755, true); - @copy($path . '/' . $file, $path_error . '/' . $file); + try { + $this->filesystem->mkdir($path_error); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + + try { + $this->filesystem->copy($path . '/' . $file, $path_error . '/' . $file, true); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + if ($captionFileName != $file) { $this->log(sprintf(('copy \'%s\' to \'error\''), $subpath . '/' . $captionFileName)); - @copy($path . '/' . $captionFileName, $path_error . '/' . $captionFileName); + + try { + $this->filesystem->copy($path . '/' . $captionFileName, $path_error . '/' . $captionFileName, true); + } catch (IOException $e) { + $this->log($e->getMessage()); + } } // do not count copy of special files as a real event if ( ! $node->getAttribute('keep')) { @@ -1825,7 +1955,13 @@ class task_period_archive extends task_abstract if ( ! $node->getAttribute('keep')) { $file = $node->getAttribute('name'); - @unlink($path . '/' . $file); + + try { + $this->filesystem->remove($path . '/' . $file); + } catch (IOException $e) { + $this->log($e->getMessage()); + } + $nodesToDel[] = $node; $this->movedFiles ++; @@ -1833,7 +1969,14 @@ class task_period_archive extends task_abstract if ($captionFileNode && ! $captionFileNode->getAttribute('keep')) { $file = $captionFileNode->getAttribute('name'); - @unlink($path . '/' . $file); + + try { + $this->filesystem->remove($path . '/' . $file); + $this->movedFiles ++; + } catch (IOException $e) { + $this->log($e->getMessage()); + } + $nodesToDel[] = $captionFileNode; $this->movedFiles ++; @@ -1845,13 +1988,13 @@ class task_period_archive extends task_abstract /** * xml facility : set attributes to a node and all children * - * @staticvar int $iloop - * @param DOMDocument $dom - * @param DOMElement $node - * @param array $attributes associative name=>value - * @param int $depth + * @staticvar integer $iloop + * @param \DOMDocument $dom + * @param \DOMElement $node + * @param array $attributes An associative array of attributes + * @param integer $depth */ - private function setAllChildren($dom, $node, $attributes, $depth = 0) + private function setAllChildren(\DOMDocument $dom, \DOMElement $node, array $attributes, $depth = 0) { static $iloop = 0; if ($depth == 0) { @@ -1872,18 +2015,16 @@ class task_period_archive extends task_abstract } /** + * Return the story settings * * @param string $file * @return array */ private function getGrpSettings($file) { - $matched = FALSE; - foreach ($this->tmaskgrp as $maskgrp) { - //$attachments = null; - //$attachments["representation"] = null; - //$attachments["caption"] = null; + $matched = false; + foreach ($this->tmaskgrp as $maskgrp) { $preg_maskgrp = "/" . $maskgrp["mask"] . "/"; if (preg_match($preg_maskgrp, $file)) { $matched = $maskgrp; @@ -1893,7 +2034,7 @@ class task_period_archive extends task_abstract } } - return($matched); + return $matched; } /** @@ -1923,9 +2064,9 @@ class task_period_archive extends task_abstract * Map a Bag of metadatas indexed by **Tagnames** to a bag of metadatas * indexed by **FieldNames** * - * @param \databox_descriptionStructure $metadatasStructure The databox structure related - * @param MetadataBag $bag The metadata bag - * @return \PHPExiftool\Driver\Metadata\MetadataBag + * @param \databox_descriptionStructure $metadatasStructure The databox structure related + * @param MetadataBag $bag The metadata bag + * @return MetadataBag */ protected function getIndexByFieldName(\databox_descriptionStructure $metadatasStructure, MetadataBag $bag) { @@ -2002,7 +2143,7 @@ class task_period_archive extends task_abstract } } - $unicode = null; + unset($unicode); return $metas; } @@ -2055,19 +2196,9 @@ class task_period_archive extends task_abstract return $metadatasBag; } - /** - * Read a Phrasea XML file for Phrasea metadatas - * Returns a MetadataBag indexed by **FieldNames** - * - * @param \databox_descriptionStructure $metadatasStructure The databox structure related - * @param type $pathfile The path file to the XML - * @return \PHPExiftool\Driver\Metadata\MetadataBag - * - * @throws \InvalidArgumentException When the file is invalid or missing - */ protected function readXMLForDatabox(\databox_descriptionStructure $metadatasStructure, $pathfile) { - if ( ! file_exists($pathfile)) { + if (false === $this->filesystem->exists($pathfile)) { throw new \InvalidArgumentException(sprintf('file %s does not exists', $pathfile)); } @@ -2177,6 +2308,6 @@ class CListFolder */ public function read() { - return(array_shift($this->list)); + return array_shift($this->list); } }