/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $thirdPartyApplications = $app['repo.api-applications']->findWithDefinedWebhookCallback(); $that = $this; $this->httpClient->getEventDispatcher()->addListener('request.error', function (Event $event) { // override guzzle default behavior of throwing exceptions // when 4xx & 5xx responses are encountered $event->stopPropagation(); }, -254); $this->httpClient->addSubscriber(new BackoffPlugin(new TruncatedBackoffStrategy(WebhookEventDelivery::MAX_DELIVERY_TRIES, new CallbackBackoffStrategy(function ($retries, $request, $response, $e) use($app, $that) { $retry = true; if ($response && null !== ($deliverId = parse_url($request->getUrl(), PHP_URL_FRAGMENT))) { $delivery = $app['repo.webhook-delivery']->find($deliverId); if ($response->isSuccessful()) { $app['manipulator.webhook-delivery']->deliverySuccess($delivery); $that->log('info', sprintf('Deliver success event "%d:%s" for app "%s"', $delivery->getWebhookEvent()->getId(), $delivery->getWebhookEvent()->getName(), $delivery->getThirdPartyApplication()->getName())); $retry = false; } else { $app['manipulator.webhook-delivery']->deliveryFailure($delivery); $that->log('error', sprintf('Deliver failure event "%d:%s" for app "%s"', $delivery->getWebhookEvent()->getId(), $delivery->getWebhookEvent()->getName(), $delivery->getThirdPartyApplication()->getName())); } return $retry; } }, true, new CurlBackoffStrategy())))); $eventFactory = new EventProcessorFactory($app); foreach ($app['repo.webhook-event']->findUnprocessedEvents() as $event) { // set event as processed $app['manipulator.webhook-event']->processed($event); $this->log('info', sprintf('Processing event "%s" with id %d', $event->getName(), $event->getId())); // send requests $this->deliverEvent($eventFactory, $app, $thirdPartyApplications, $event); } }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $this->removeDeadExports($app); $exports = $this->retrieveExports($app); foreach ($exports as $export) { $this->doExport($app, $data->getTask(), $export); } }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $task = $data->getTask(); $settings = $task->getSettings(); $logsql = (bool) $settings->logsql; $tasks = (array) $settings->tasks; $data = $this->getData($app, $tasks, $logsql); foreach ($data as $record) { $this->processData($app, $record, $logsql); } }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $task = $data->getTask(); $settings = simplexml_load_string($task->getSettings()); $baseId = (string) $settings->base_id; $collection = \collection::get_from_base_id($app, $baseId); $collection->empty_collection(200); if (0 === $collection->get_record_amount()) { $this->stop(); $this->dispatcher->dispatch(JobEvents::FINISHED, new JobFinishedEvent($task)); } }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $settings = simplexml_load_string($data->getTask()->getSettings()); $logsql = (bool) $settings->logsql; $tasks = array(); foreach ($settings->tasks->task as $task) { $tasks[] = $task; } $data = $this->getData($app, $tasks, $logsql); foreach ($data as $record) { $this->processData($app, $record, $logsql); } }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $task = $data->getTask(); $settings = simplexml_load_string($task->getSettings()); $socketPort = (int) $settings->socket; $indexerPath = $this->getPhraseanetIndexerPath($app); $builder = new ProcessBuilder($this->getCommandline($indexerPath, $app, $task)); $builder->setWorkingDirectory(dirname($indexerPath))->setTimeout(0); $process = $builder->getProcess(); if (0 < $socketPort) { $this->addSubscriber(new PhraseanetIndexerStopperSubscriber($socketPort)); } $process->run(); }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $settings = simplexml_load_string($data->getTask()->getSettings()); $thumbnailExtraction = (bool) (string) $settings->embedded; Image2Image::$lookForEmbeddedPreview = $thumbnailExtraction; foreach ($app['phraseanet.appbox']->get_databoxes() as $databox) { if (!$this->isStarted()) { break; } $conn = $databox->get_connection(); $sql = 'SELECT coll_id, record_id FROM record WHERE jeton & ' . JETON_MAKE_SUBDEF . ' > 0 ORDER BY record_id DESC LIMIT 0, 30'; $stmt = $conn->prepare($sql); $stmt->execute(); $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); $stmt->closeCursor(); foreach ($rs as $row) { if (!$this->isStarted()) { break; } $this->log('info', sprintf("Generate subdefs for : sbasid=%s / databox=%s / recordid=%s ", $databox->get_sbas_id(), $databox->get_dbname(), $row['record_id'])); try { $record = $databox->get_record($row['record_id']); $app['subdef.generator']->generateSubdefs($record); } catch (\Exception $e) { $this->log('warning', sprintf("Generate subdefs failed for : sbasid=%s / databox=%s / recordid=%s : %s", $databox->get_sbas_id(), $databox->get_dbname(), $row['record_id'], $e->getMessage())); } $sql = 'UPDATE record SET jeton=(jeton & ~' . JETON_MAKE_SUBDEF . '), moddate=NOW() WHERE record_id=:record_id'; $stmt = $conn->prepare($sql); $stmt->execute([':record_id' => $row['record_id']]); $stmt->closeCursor(); // rewrite metadata $sql = 'UPDATE record SET status=(status & ~0x03), jeton=(jeton | ' . JETON_WRITE_META_SUBDEF . ') WHERE record_id=:record_id'; $stmt = $conn->prepare($sql); $stmt->execute([':record_id' => $row['record_id']]); $stmt->closeCursor(); unset($record); } } }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $status = [\Bridge_Element::STATUS_PENDING, \Bridge_Element::STATUS_PROCESSING, \Bridge_Element::STATUS_PROCESSING_SERVER]; $params = []; $n = 1; foreach ($status as $stat) { $params[':status' . $n] = $stat; $n++; } $sql = 'SELECT id, account_id FROM bridge_elements' . ' WHERE (status = ' . implode(' OR status = ', array_keys($params)) . ')'; $stmt = $app['phraseanet.appbox']->get_connection()->prepare($sql); $stmt->execute($params); $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); $stmt->closeCursor(); foreach ($rs as $row) { if (!$this->isStarted()) { break; } try { $account = \Bridge_Account::load_account($app, $row['account_id']); $element = new \Bridge_Element($app, $account, $row['id']); $this->log('debug', "process " . $element->get_id() . " with status " . $element->get_status()); if ($element->get_status() == \Bridge_Element::STATUS_PENDING) { $this->upload_element($element); } else { $this->update_element($app, $element); } } catch (\Exception $e) { $this->log('error', sprintf("An error occured : %s", $e->getMessage())); $sql = 'UPDATE bridge_elements SET status = :status WHERE id = :id'; $params = [':status' => \Bridge_Element::STATUS_ERROR, ':id' => $row['id']]; $stmt = $app['phraseanet.appbox']->get_connection()->prepare($sql); $stmt->execute($params); $stmt->closeCursor(); } } }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $settings = simplexml_load_string($data->getTask()->getSettings()); $clearDoc = (bool) (string) $settings->cleardoc; $MWG = (bool) (string) $settings->mwg; // move this in service provider configuration // $app['exiftool.writer']->setModule(Writer::MODULE_MWG, true); foreach ($app->getDataboxes() as $databox) { $conn = $databox->get_connection(); $metaSubdefs = []; foreach ($databox->get_subdef_structure() as $type => $definitions) { foreach ($definitions as $sub) { $name = $sub->get_name(); if ($sub->meta_writeable()) { $metaSubdefs[$name . '_' . $type] = true; } } } $sql = 'SELECT record_id, coll_id, jeton FROM record WHERE (jeton & ' . PhraseaTokens::WRITE_META . ' > 0)'; $stmt = $conn->prepare($sql); $stmt->execute(); $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); $stmt->closeCursor(); foreach ($rs as $row) { $record_id = $row['record_id']; $token = $row['jeton']; $record = $databox->get_record($record_id); $type = $record->get_type(); $subdefs = []; foreach ($record->get_subdefs() as $name => $subdef) { $write_document = $token & PhraseaTokens::WRITE_META_DOC && $name == 'document'; $write_subdef = $token & PhraseaTokens::WRITE_META_SUBDEF && isset($metaSubdefs[$name . '_' . $type]); if (($write_document || $write_subdef) && $subdef->is_physically_present()) { $subdefs[$name] = $subdef->get_pathfile(); } } $metadata = new Metadata\MetadataBag(); if ($record->getUuid()) { $metadata->add(new Metadata\Metadata(new Tag\XMPExif\ImageUniqueID(), new Value\Mono($record->getUuid()))); $metadata->add(new Metadata\Metadata(new Tag\ExifIFD\ImageUniqueID(), new Value\Mono($record->getUuid()))); $metadata->add(new Metadata\Metadata(new Tag\IPTC\UniqueDocumentID(), new Value\Mono($record->getUuid()))); } $caption = $record->get_caption(); foreach ($databox->get_meta_structure() as $fieldStructure) { $tagName = $fieldStructure->get_tag()->getTagname(); $fieldName = $fieldStructure->get_name(); // skip fields with no src if ($tagName == '') { continue; } // check exiftool known tags to skip Phraseanet:tf-* try { TagFactory::getFromRDFTagname($tagName); } catch (TagUnknown $e) { continue; } try { $field = $caption->get_field($fieldName); $data = $field->get_values(); if ($fieldStructure->is_multi()) { $values = array(); foreach ($data as $value) { $values[] = $value->getValue(); } $value = new Value\Multi($values); } else { $data = array_pop($data); $value = $data->getValue(); $value = new Value\Mono($value); } } catch (\Exception $e) { // the field is not set in the record, erase it if ($fieldStructure->is_multi()) { $value = new Value\Multi(array('')); } else { $value = new Value\Mono(''); } } $metadata->add(new Metadata\Metadata($fieldStructure->get_tag(), $value)); } $app['exiftool.writer']->reset(); if ($MWG) { $app['exiftool.writer']->setModule(ExifWriter::MODULE_MWG, true); } foreach ($subdefs as $name => $file) { $app['exiftool.writer']->erase($name != 'document' || $clearDoc, true); try { $app['exiftool.writer']->write($file, $metadata); $this->log('info', sprintf('meta written for sbasid=%1$d - recordid=%2$d (%3$s)', $databox->get_sbas_id(), $record_id, $name)); } catch (PHPExiftoolException $e) { $this->log('error', sprintf('meta NOT written for sbasid=%1$d - recordid=%2$d (%3$s) because "%s"', $databox->get_sbas_id(), $record_id, $name, $e->getMessage())); } } $sql = 'UPDATE record SET jeton=jeton & ~' . PhraseaTokens::WRITE_META . ' WHERE record_id = :record_id'; $stmt = $conn->prepare($sql); $stmt->execute([':record_id' => $record_id]); $stmt->closeCursor(); } } }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $task = $data->getTask(); $settings = simplexml_load_string($task->getSettings()); $baseId = (string) $settings->base_id; $sbasId = \phrasea::sbasFromBas($app, $baseId); if (!$sbasId) { throw new RuntimeException('Invalid collection base_id.'); } $databox = $app->findDataboxById($sbasId); $TColls = []; $collection = null; foreach ($databox->get_collections() as $coll) { $TColls['c' . $coll->get_coll_id()] = $coll->get_coll_id(); if ($baseId == $coll->get_base_id()) { $collection = $coll; } } $server_coll_id = $collection->get_coll_id(); // mask(s) of accepted files $tmask = []; $tmaskgrp = []; $cold = min(max((int) $settings->cold, self::MINCOLD), self::MAXCOLD); $stat0 = $stat1 = "0"; if (false !== ($sxBasePrefs = simplexml_load_string($collection->get_prefs()))) { if ($sxBasePrefs->status) { $stat0 = (string) $sxBasePrefs->status; } } if ($settings->status) { $stat1 = (string) $settings->status; } if (!$stat0) { $stat0 = '0'; } if (!$stat1) { $stat1 = '0'; } // check the data-repository exists $pathhd = (string) $settings->path; if ($pathhd) { $app['filesystem']->mkdir($pathhd, 0750); } // load masks if ($settings->files && $settings->files->file) { foreach ($settings->files->file as $ft) { $tmask[] = ["mask" => (string) $ft["mask"], "caption" => (string) $ft["caption"], "accept" => (string) $ft["accept"]]; } } if ($settings->files && $settings->files->grouping) { foreach ($settings->files->grouping as $ft) { $tmaskgrp[] = ["mask" => (string) $ft["mask"], "caption" => (string) $ft["caption"], "representation" => (string) $ft["representation"], "accept" => (string) $ft["accept"]]; } } if (count($tmask) == 0) { // no mask defined : accept all kind of files $tmask[] = ["mask" => ".*", "caption" => "", "accept" => ""]; } while ($this->isStarted()) { $path_in = (string) $settings->hotfolder; if (!@is_dir($path_in)) { throw new RuntimeException(sprintf('Error : missing hotfolder \'%s\', stopping.', $path_in)); } // copy settings to task, so it's easier to get later $moveArchived = \p4field::isyes($settings->move_archived); $moveError = \p4field::isyes($settings->move_error); clearstatcache(); if (false === $app['filesystem']->exists($path_in . "/.phrasea.xml")) { throw new RuntimeException(sprintf('NO .phrasea.xml AT ROOT \'%s\' !', $path_in)); } $path_archived = $path_error = null; if ($moveArchived) { $path_archived = $path_in . '_archived'; $app['filesystem']->mkdir($path_archived, 0755); } if ($moveError) { $path_error = $path_in . '_error'; $app['filesystem']->mkdir($path_error, 0755); } $dom = new \DOMDocument(); $dom->formatOutput = true; $root = $dom->appendChild($dom->createElement('root')); $nnew = $this->listFilesPhase1($app, $dom, $root, $path_in, $server_coll_id, 0, $TColls); if ($app['debug']) { $this->log('debug', "=========== listFilesPhase1 ========== (returned " . $nnew . ")\n" . $dom->saveXML()); } if (!$this->isStarted()) { return; } // wait for files to be cold $this->pause($cold); if (!$this->isStarted()) { return; } $this->listFilesPhase2($app, $dom, $root, $path_in, 0); if ($app['debug']) { $this->log('debug', "=========== listFilesPhase2 ========== : \n" . $dom->saveXML()); } if (!$this->isStarted()) { return; } $this->makePairs($dom, $root, $path_in, $path_archived, $path_error, false, 0, $tmask, $tmaskgrp); if ($app['debug']) { $this->log('debug', "=========== makePairs ========== : \n" . $dom->saveXML()); } $r = $this->removeBadGroups($app, $dom, $root, $path_in, $path_archived, $path_error, 0, $moveError); if ($app['debug']) { $this->log('debug', "=========== removeBadGroups ========== (returned " . ((bool) $r ? 'true' : 'false') . ") : \n" . $dom->saveXML()); } $this->archive($app, $databox, $dom, $root, $path_in, $path_archived, $path_error, 0, $moveError, $moveArchived, $stat0, $stat1); if ($app['debug']) { $this->log('debug', "=========== archive ========== : \n" . $dom->saveXML()); } if (!$this->isStarted()) { return; } $this->bubbleResults($dom, $root, $path_in, 0, \p4field::isyes($settings->copy_spe)); if ($app['debug']) { $this->log('debug', "=========== bubbleResults ========== : \n" . $dom->saveXML()); } $moved = $this->moveFiles($app, $dom, $root, $path_in, $path_archived, $path_error, 0, $moveArchived, $moveError); if ($app['debug']) { $this->log('debug', "=========== moveFiles ========== (returned " . ($moved ? 'true' : 'false') . ") : \n" . $dom->saveXML()); } } }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $app['elasticsearch.indexer']->indexScheduledRecords(); }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $settings = simplexml_load_string($data->getTask()->getSettings()); $thumbnailExtraction = (bool) (string) $settings->embedded; Image2Image::$lookForEmbeddedPreview = $thumbnailExtraction; $sqlqmark = array(); $sqlparms = array(); foreach (array('image', 'video', 'audio', 'document', 'flash', 'unknown') as $type) { if (!isset($settings->{"type_" . $type}) || !\p4field::isno($settings->{"type_" . $type})) { $sqlqmark[] = '?'; $sqlparms[] = $type; } } if (count($sqlqmark) == 0) { return; } foreach ($app->getDataboxes() as $databox) { if (!$this->isStarted()) { break; } if (count($settings->xpath("sbas[text()=" . $databox->get_sbas_id() . "]")) == 0) { continue; } $conn = $databox->get_connection(); $sql = 'SELECT coll_id, record_id FROM record' . ' WHERE jeton & ' . PhraseaTokens::MAKE_SUBDEF . ' > 0' . ' AND type IN(' . implode(',', $sqlqmark) . ')' . ' ORDER BY record_id DESC LIMIT 0, 30'; $stmt = $conn->prepare($sql); $stmt->execute($sqlparms); $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); $stmt->closeCursor(); $i = 0; foreach ($rs as $row) { if (!$this->isStarted()) { break; } $this->log('info', sprintf("Generate subdefs for : sbasid=%s / databox=%s / recordid=%s ", $databox->get_sbas_id(), $databox->get_dbname(), $row['record_id'])); try { $record = $databox->get_record($row['record_id']); /** @var SubdefGenerator $sg */ $sg = $app['subdef.generator']; $sg->generateSubdefs($record); } catch (\Exception $e) { $this->log('warning', sprintf("Generate subdefs failed for : sbasid=%s / databox=%s / recordid=%s : %s", $databox->get_sbas_id(), $databox->get_dbname(), $row['record_id'], $e->getMessage())); } $sql = 'UPDATE record' . ' SET jeton=(jeton & ~(:flag)), moddate=NOW()' . ' WHERE record_id=:record_id'; $stmt = $conn->prepare($sql); $stmt->execute([':record_id' => $row['record_id'], ':flag' => PhraseaTokens::MAKE_SUBDEF]); $stmt->closeCursor(); // rewrite metadata $sql = 'UPDATE record' . ' SET jeton=(jeton | :flag)' . ' WHERE record_id=:record_id'; $stmt = $conn->prepare($sql); $stmt->execute([':record_id' => $row['record_id'], ':flag' => PhraseaTokens::WRITE_META_SUBDEF | PhraseaTokens::TO_INDEX]); $stmt->closeCursor(); unset($record); $i++; if ($i % 5 === 0) { $app['elasticsearch.indexer']->flushQueue(); } } } $app['elasticsearch.indexer']->flushQueue(); }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $settings = simplexml_load_string($data->getTask()->getSettings()); $clearDoc = (bool) (string) $settings->cleardoc; // move this in service provider configuration $app['exiftool.writer']->setModule(Writer::MODULE_MWG, true); foreach ($app['phraseanet.appbox']->get_databoxes() as $databox) { $connbas = $databox->get_connection(); $subdefgroups = $databox->get_subdef_structure(); $metasubdefs = []; foreach ($subdefgroups as $type => $subdefs) { foreach ($subdefs as $sub) { $name = $sub->get_name(); if ($sub->meta_writeable()) { $metasubdefs[$name . '_' . $type] = true; } } } $sql = 'SELECT record_id, coll_id, jeton FROM record WHERE (jeton & ' . JETON_WRITE_META . ' > 0)'; $stmt = $connbas->prepare($sql); $stmt->execute(); $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); $stmt->closeCursor(); foreach ($rs as $row) { $record_id = $row['record_id']; $jeton = $row['jeton']; $record = $databox->get_record($record_id); $type = $record->get_type(); $subdefs = $record->get_subdefs(); $tsub = []; foreach ($subdefs as $name => $subdef) { $write_document = $jeton & JETON_WRITE_META_DOC && $name == 'document'; $write_subdef = $jeton & JETON_WRITE_META_SUBDEF && isset($metasubdefs[$name . '_' . $type]); if (($write_document || $write_subdef) && $subdef->is_physically_present()) { $tsub[$name] = $subdef->get_pathfile(); } } $metadatas = new Metadata\MetadataBag(); if ($record->get_uuid()) { $metadatas->add(new Metadata\Metadata(new Tag\XMPExif\ImageUniqueID(), new Value\Mono($record->get_uuid()))); $metadatas->add(new Metadata\Metadata(new Tag\ExifIFD\ImageUniqueID(), new Value\Mono($record->get_uuid()))); $metadatas->add(new Metadata\Metadata(new Tag\IPTC\UniqueDocumentID(), new Value\Mono($record->get_uuid()))); } foreach ($record->get_caption()->get_fields() as $field) { $meta = $field->get_databox_field(); /* @var $meta \databox_field */ $datas = $field->get_values(); if ($meta->is_multi()) { $values = []; foreach ($datas as $data) { $values[] = $data->getValue(); } $value = new Value\Multi($values); } else { $data = array_pop($datas); $value = new Value\Mono($data->getValue()); } $metadatas->add(new Metadata\Metadata($meta->get_tag(), $value)); } foreach ($tsub as $name => $file) { $app['exiftool.writer']->erase($name != 'document' || $clearDoc, true); try { $app['exiftool.writer']->write($file, $metadatas); $this->log('debug', sprintf('meta written for sbasid=%1$d - recordid=%2$d (%3$s)', $databox->get_sbas_id(), $record_id, $name)); } catch (PHPExiftoolException $e) { $this->log('error', sprintf('meta was not written for sbasid=%d - recordid=%d (%s) because "%s"', $databox->get_sbas_id(), $record_id, $name, $e->getMessage())); } } $sql = 'UPDATE record SET jeton=jeton & ~' . JETON_WRITE_META . ' WHERE record_id = :record_id'; $stmt = $connbas->prepare($sql); $stmt->execute([':record_id' => $row['record_id']]); $stmt->closeCursor(); } } }
/** * {@inheritdoc} */ protected function doJob(JobData $data) { $app = $data->getApplication(); $settings = simplexml_load_string($data->getTask()->getSettings()); $proxy = (string) $settings->proxy; $proxyport = (string) $settings->proxyport; $localPath = (string) $settings->localpath; $ftpPath = (string) $settings->ftppath; $host = (string) $settings->host; $port = (string) $settings->port; $user = (string) $settings->user; $password = (string) $settings->password; $ssl = (bool) (string) $settings->ssl; $passive = (bool) (string) $settings->passive; foreach (['localpath' => $localPath, 'host' => $host, 'port' => $host, 'user' => $user, 'password' => $password, 'ftppath' => $ftpPath] as $name => $value) { if (trim($value) === '') { // maybe throw an exception to consider the job as failing ? $this->log('error', sprintf('setting `%s` must be set', $name)); throw new RuntimeException(sprintf('`%s` setting is empty', $name)); } } $app['filesystem']->mkdir($localPath, 0750); if (!is_dir($localPath)) { $this->log('error', sprintf('`%s` does not exists', $localPath)); throw new RuntimeException(sprintf('`%s` does not exists', $localPath)); } if (!is_writeable($localPath)) { $this->log('error', sprintf('`%s` is not writeable', $localPath)); throw new RuntimeException(sprintf('`%s` is not writeable', $localPath)); } $ftp = $app['phraseanet.ftp.client']($host, $port, 90, $ssl, $proxy, $proxyport); $ftp->passive($passive); $ftp->login($user, $password); $ftp->chdir($ftpPath); $list_1 = $ftp->list_directory(true); $done = 0; $this->log('debug', "attente de 25sec pour avoir les fichiers froids..."); $this->pause(25); if (!$this->isStarted()) { $ftp->close(); $this->log('debug', "Stopping"); return; } $list_2 = $ftp->list_directory(true); foreach ($list_1 as $filepath => $timestamp) { $done++; if (!isset($list_2[$filepath])) { $this->log('debug', "le fichier {$filepath} a disparu...\n"); continue; } if ($list_2[$filepath] !== $timestamp) { $this->log('debug', "le fichier {$filepath} a ete modifie depuis le dernier passage..."); continue; } $finalpath = \p4string::addEndSlash($localPath) . ($filepath[0] == '/' ? mb_substr($filepath, 1) : $filepath); $this->log('debug', "Rappatriement de {$filepath} vers {$finalpath}\n"); if (file_exists($finalpath)) { $this->log('debug', "Un fichier du meme nom ({$finalpath}) existe deja, skipping"); continue; } $this->log('debug', "Create " . dirname($finalpath) . ""); $app['filesystem']->mkdir(dirname($finalpath), 0750); $this->log('debug', "Get {$filepath} to {$finalpath}"); $ftp->get($finalpath, $filepath); $this->log('debug', "Remove {$filepath}"); $ftp->delete($filepath); } $ftp->close(); }