From 7541885637107aefd58f5cf4611ef6a40fc49adb Mon Sep 17 00:00:00 2001 From: aynsix Date: Fri, 20 Sep 2019 16:01:48 +0400 Subject: [PATCH 01/14] buildsubdef with worker --- bin/console | 6 ++-- lib/Alchemy/Phrasea/Border/Manager.php | 4 ++- .../Controller/Prod/StoryController.php | 6 +++- .../Controller/Prod/ToolsController.php | 3 +- .../Core/Event/Record/RecordEvents.php | 2 ++ .../Event/Record/SubdefinitionBuildEvent.php | 34 +++++++++++++++++++ .../Event/Subscriber/RecordEditSubscriber.php | 16 ++++++--- lib/Alchemy/Phrasea/Media/SubdefGenerator.php | 18 ++++++++++ .../Phrasea/Media/SubdefSubstituer.php | 3 +- .../Phrasea/TaskManager/Job/ArchiveJob.php | 7 ++-- lib/classes/record/adapter.php | 6 ++-- 11 files changed, 90 insertions(+), 15 deletions(-) create mode 100644 lib/Alchemy/Phrasea/Core/Event/Record/SubdefinitionBuildEvent.php diff --git a/bin/console b/bin/console index 552cb672d0..02f4ccee61 100755 --- a/bin/console +++ b/bin/console @@ -133,9 +133,9 @@ $cli->command(new QueryParseCommand()); $cli->command(new QuerySampleCommand()); $cli->command(new FindConceptsCommand()); -$cli->command($cli['alchemy_worker.commands.run_dispatcher_command']); -$cli->command($cli['alchemy_worker.commands.run_worker_command']); -$cli->command($cli['alchemy_worker.commands.show_configuration']); +//$cli->command($cli['alchemy_worker.commands.run_dispatcher_command']); +//$cli->command($cli['alchemy_worker.commands.run_worker_command']); +//$cli->command($cli['alchemy_worker.commands.show_configuration']); $cli->loadPlugins(); diff --git a/lib/Alchemy/Phrasea/Border/Manager.php b/lib/Alchemy/Phrasea/Border/Manager.php index d8abc9ac99..55c28d9cbf 100644 --- a/lib/Alchemy/Phrasea/Border/Manager.php +++ b/lib/Alchemy/Phrasea/Border/Manager.php @@ -14,6 +14,8 @@ namespace Alchemy\Phrasea\Border; use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Border\Checker\CheckerInterface; use Alchemy\Phrasea\Border\Attribute\AttributeInterface; +use Alchemy\Phrasea\Core\Event\Record\RecordEvents; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Metadata\Tag\TfArchivedate; use Alchemy\Phrasea\Metadata\Tag\TfQuarantine; @@ -333,7 +335,7 @@ class Manager $this->app['phraseanet.metadata-setter']->replaceMetadata($newMetadata, $element); if(!$nosubdef) { - $element->rebuild_subdefs(); + $this->app['dispatcher']->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($element, true)); } return $element; diff --git a/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php b/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php index 9a65ed61fa..19acc22a27 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php @@ -14,6 +14,8 @@ use Alchemy\Phrasea\Application\Helper\EntityManagerAware; use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Controller\RecordsRequest; use Alchemy\Phrasea\Controller\Exception as ControllerException; +use Alchemy\Phrasea\Core\Event\Record\RecordEvents; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; use Alchemy\Phrasea\Core\Event\RecordEdit; use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Model\Entities\StoryWZ; @@ -68,7 +70,9 @@ class StoryController extends Controller break; } - $story->set_metadatas($metadatas)->rebuild_subdefs(); + $recordAdapter = $story->set_metadatas($metadatas); + // tell phraseanet to rebuild subdef + $this->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($recordAdapter)); $storyWZ = new StoryWZ(); $storyWZ->setUser($this->getAuthenticatedUser()); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/ToolsController.php b/lib/Alchemy/Phrasea/Controller/Prod/ToolsController.php index 872f385455..2318cf0638 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/ToolsController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/ToolsController.php @@ -16,6 +16,7 @@ use Alchemy\Phrasea\Application\Helper\SubDefinitionSubstituerAware; use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Controller\RecordsRequest; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Metadata\PhraseanetMetadataReader; use Alchemy\Phrasea\Metadata\PhraseanetMetadataSetter; @@ -156,7 +157,7 @@ class ToolsController extends Controller } if (!$substituted || $force) { - $record->rebuild_subdefs(); + $this->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($record)); } } diff --git a/lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php b/lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php index c55245a7ff..ac725833ac 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php +++ b/lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php @@ -29,6 +29,8 @@ final class RecordEvents const SUB_DEFINITIONS_CREATED = 'record.sub_definitions_created'; const SUB_DEFINITION_CREATION_FAILED = 'record.sub_definition_creation_failed'; + const SUBDEFINITION_BUILD = 'record.subdefinition_build'; + const MEDIA_SUBSTITUTED = 'record.media_substituted'; const STORY_COVER_CHANGED = 'record.story_cover_changed'; diff --git a/lib/Alchemy/Phrasea/Core/Event/Record/SubdefinitionBuildEvent.php b/lib/Alchemy/Phrasea/Core/Event/Record/SubdefinitionBuildEvent.php new file mode 100644 index 0000000000..701e3a2028 --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Event/Record/SubdefinitionBuildEvent.php @@ -0,0 +1,34 @@ +isNewRecord = $isNewRecord; + } + + /** + * @return bool + */ + public function isNewRecord() + { + return $this->isNewRecord; + } +} diff --git a/lib/Alchemy/Phrasea/Core/Event/Subscriber/RecordEditSubscriber.php b/lib/Alchemy/Phrasea/Core/Event/Subscriber/RecordEditSubscriber.php index d5c0c69f54..e58e77cdf7 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Subscriber/RecordEditSubscriber.php +++ b/lib/Alchemy/Phrasea/Core/Event/Subscriber/RecordEditSubscriber.php @@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\Core\Event\Subscriber; use Alchemy\Phrasea\Core\Event\Record\CollectionChangedEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; use Alchemy\Phrasea\Core\Event\RecordEdit; use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Metadata\Tag\TfEditdate; @@ -26,10 +27,11 @@ class RecordEditSubscriber implements EventSubscriberInterface public static function getSubscribedEvents() { return array( - PhraseaEvents::RECORD_EDIT => 'onEdit', - PhraseaEvents::RECORD_UPLOAD => 'onEdit', - RecordEvents::ROTATE => 'onRecordChange', - RecordEvents::COLLECTION_CHANGED => 'onCollectionChanged', + PhraseaEvents::RECORD_EDIT => 'onEdit', + PhraseaEvents::RECORD_UPLOAD => 'onEdit', + RecordEvents::ROTATE => 'onRecordChange', + RecordEvents::COLLECTION_CHANGED => 'onCollectionChanged', + RecordEvents::SUBDEFINITION_BUILD => 'onBuildSubdefs', ); } @@ -49,6 +51,12 @@ class RecordEditSubscriber implements EventSubscriberInterface $recordAdapter->clearStampCache(); } + public function onBuildSubdefs(SubdefinitionBuildEvent $event) + { + $recordAdapter = $this->convertToRecordAdapter($event->getRecord()); + $recordAdapter->rebuild_subdefs(); + } + public function onEdit(RecordEdit $event) { static $into = false; diff --git a/lib/Alchemy/Phrasea/Media/SubdefGenerator.php b/lib/Alchemy/Phrasea/Media/SubdefGenerator.php index 2dede228c5..7710069948 100644 --- a/lib/Alchemy/Phrasea/Media/SubdefGenerator.php +++ b/lib/Alchemy/Phrasea/Media/SubdefGenerator.php @@ -167,6 +167,24 @@ class SubdefGenerator ); } + /** + * set a logger to use + * @param LoggerInterface $logger + */ + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + } + + /** + * to get the logger + * @return LoggerInterface + */ + public function getLogger() + { + return $this->logger; + } + private function generateSubdef(\record_adapter $record, \databox_subdef $subdef_class, $pathdest) { $start = microtime(true); diff --git a/lib/Alchemy/Phrasea/Media/SubdefSubstituer.php b/lib/Alchemy/Phrasea/Media/SubdefSubstituer.php index 2259fa572d..1d096cf785 100644 --- a/lib/Alchemy/Phrasea/Media/SubdefSubstituer.php +++ b/lib/Alchemy/Phrasea/Media/SubdefSubstituer.php @@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\Media; use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Core\Event\Record\MediaSubstitutedEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; use Alchemy\Phrasea\Filesystem\FilesystemService; use MediaAlchemyst\Alchemyst; use MediaAlchemyst\Exception\ExceptionInterface as MediaAlchemystException; @@ -79,7 +80,7 @@ class SubdefSubstituer $record->write_metas(); if ($shouldSubdefsBeRebuilt) { - $record->rebuild_subdefs(); + $this->dispatcher->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($record)); } $this->dispatcher->dispatch(RecordEvents::MEDIA_SUBSTITUTED, new MediaSubstitutedEvent($record)); diff --git a/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php b/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php index 532eb8bbb5..db1f6b083a 100644 --- a/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php +++ b/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php @@ -12,6 +12,8 @@ namespace Alchemy\Phrasea\TaskManager\Job; use Alchemy\Phrasea\Application; +use Alchemy\Phrasea\Core\Event\Record\RecordEvents; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Border\File; use Alchemy\Phrasea\Border\Manager as borderManager; @@ -1001,7 +1003,7 @@ class ArchiveJob extends AbstractJob { // quick fix to reconnect if mysql is lost $app->getApplicationBox()->get_connection(); - $databox->get_connection(); + $collection->get_connection(); $status = \databox_status::operation_or($stat0, $stat1); @@ -1032,7 +1034,8 @@ class ArchiveJob extends AbstractJob } $story->setStatus(\databox_status::operation_or($stat0, $stat1)); - $story->rebuild_subdefs(); + + $app['dispatcher']->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($story)); unset($media); diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index c4045d9fc5..9d7beb2c1a 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -19,6 +19,7 @@ use Alchemy\Phrasea\Core\Event\Record\OriginalNameChangedEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; use Alchemy\Phrasea\Core\Event\Record\StatusChangedEvent; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; use Alchemy\Phrasea\Core\PhraseaTokens; use Alchemy\Phrasea\Databox\Subdef\MediaSubdefRepository; use Alchemy\Phrasea\Filesystem\FilesystemService; @@ -284,7 +285,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface $this->getDataboxConnection()->executeUpdate($sql, ['type' => $type, 'record_id' => $this->getRecordId()]); if ($old_type !== $type) { - $this->rebuild_subdefs(); + $this->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($this)); } $this->type = $type; @@ -341,7 +342,8 @@ class record_adapter implements RecordInterface, cache_cacheableInterface array(':mime' => $mime, ':record_id' => $this->getRecordId()) )) { - $this->rebuild_subdefs(); + $this->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($this)); + $this->delete_data_from_cache(); } From c712cb7cc3bba2957a4398105576f95cb777b2fa Mon Sep 17 00:00:00 2001 From: aynsix Date: Fri, 20 Sep 2019 16:03:54 +0400 Subject: [PATCH 02/14] retrieve rabbitmq configuration from configuration.yml --- .../WorkerConfigurationServiceProvider.php | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/Alchemy/Phrasea/Core/Provider/WorkerConfigurationServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/WorkerConfigurationServiceProvider.php index 1b2e15d4f0..9931d4649f 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/WorkerConfigurationServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/WorkerConfigurationServiceProvider.php @@ -32,11 +32,12 @@ class WorkerConfigurationServiceProvider implements ServiceProviderInterface $app['alchemy_queues.queues'] = $app->share(function (Application $app) { $defaultConfiguration = [ 'worker-queue' => [ - 'registry' => 'alchemy_worker.queue_registry', - 'host' => 'localhost', - 'port' => 5672, - 'user' => 'guest', - 'vhost' => '/' + 'registry' => 'alchemy_worker.queue_registry', + 'host' => 'localhost', + 'port' => 5672, + 'user' => 'guest', + 'password' => 'guest', + 'vhost' => '/' ] ]; @@ -46,19 +47,22 @@ class WorkerConfigurationServiceProvider implements ServiceProviderInterface $queueConfigurations = $configuration->get(['workers', 'queue'], $defaultConfiguration); - $queueConfiguration = reset($queueConfigurations); - $queueKey = key($queueConfigurations); + $config = []; - if (! isset($queueConfiguration['name'])) { - if (! is_string($queueKey)) { - throw new \RuntimeException('Invalid queue configuration: configuration has no key or name.'); + foreach($queueConfigurations as $name => $queueConfiguration) { + $queueKey = $name; + + if (! isset($queueConfiguration['name'])) { + if (! is_string($queueKey)) { + throw new \RuntimeException('Invalid queue configuration: configuration has no key or name.'); + } + + $queueConfiguration['name'] = $queueKey; } - $queueConfiguration['name'] = $queueKey; + $config[$queueConfiguration['name']] = $queueConfiguration ; } - $config = [ $queueConfiguration['name'] => $queueConfiguration ]; - return $config; } catch (RuntimeException $exception) { From 65d7affcb53619e9ce406d8d2e75d0a4b7206e68 Mon Sep 17 00:00:00 2001 From: aynsix Date: Fri, 20 Sep 2019 16:15:49 +0400 Subject: [PATCH 03/14] export mail : make it event oriented to facilitate worker treatement --- .../Controller/Prod/ExportController.php | 47 +++++--------- .../Phrasea/Core/Event/ExportMailEvent.php | 53 +++++++++++++++ .../Event/Subscriber/ExportSubscriber.php | 65 ++++++++++++++++++- lib/Alchemy/Phrasea/Core/PhraseaEvents.php | 3 +- .../Phrasea/Controller/Prod/ExportTest.php | 3 +- 5 files changed, 137 insertions(+), 34 deletions(-) create mode 100644 lib/Alchemy/Phrasea/Core/Event/ExportMailEvent.php diff --git a/lib/Alchemy/Phrasea/Controller/Prod/ExportController.php b/lib/Alchemy/Phrasea/Controller/Prod/ExportController.php index df6f2a9f19..f4692c99ac 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/ExportController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/ExportController.php @@ -15,6 +15,7 @@ use Alchemy\Phrasea\Application\Helper\FilesystemAware; use Alchemy\Phrasea\Application\Helper\NotifierAware; use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Core\Event\ExportFailureEvent; +use Alchemy\Phrasea\Core\Event\ExportMailEvent; use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Exception\InvalidArgumentException; use Alchemy\Phrasea\Model\Manipulator\TokenManipulator; @@ -193,42 +194,26 @@ class ExportController extends Controller $token = $this->getTokenManipulator()->createEmailExportToken(serialize($list)); if (count($destMails) > 0) { - //zip documents - \set_export::build_zip( - $this->app, - $token, - $list, - $this->app['tmp.download.path'].'/'. $token->getValue() . '.zip' - ); + $emitterId = $this->getAuthenticatedUser()->getId(); - $remaingEmails = $destMails; + $tokenValue = $token->getValue(); $url = $this->app->url('prepare_download', ['token' => $token->getValue(), 'anonymous' => false, 'type' => \Session_Logger::EVENT_EXPORTMAIL]); - $user = $this->getAuthenticatedUser(); - $emitter = new Emitter($user->getDisplayName(), $user->getEmail()); + $params = [ + 'url' => $url, + 'textmail' => $request->request->get('textmail'), + 'reading_confirm' => !!$request->request->get('reading_confirm', false), + 'ssttid' => $ssttid = $request->request->get('ssttid', ''), + 'lst' => $lst = $request->request->get('lst', ''), + ]; - foreach ($destMails as $key => $mail) { - try { - $receiver = new Receiver(null, trim($mail)); - } catch (InvalidArgumentException $e) { - continue; - } - - $mail = MailRecordsExport::create($this->app, $receiver, $emitter, $request->request->get('textmail')); - $mail->setButtonUrl($url); - $mail->setExpiration($token->getExpiration()); - - $this->deliver($mail, !!$request->request->get('reading_confirm', false)); - unset($remaingEmails[$key]); - } - - //some mails failed - if (count($remaingEmails) > 0) { - foreach ($remaingEmails as $mail) { - $this->dispatch(PhraseaEvents::EXPORT_MAIL_FAILURE, new ExportFailureEvent($this->getAuthenticatedUser(), $ssttid, $lst, \eventsmanager_notify_downloadmailfail::MAIL_FAIL, $mail)); - } - } + $this->dispatch(PhraseaEvents::EXPORT_MAIL_CREATE, new ExportMailEvent( + $emitterId, + $tokenValue, + $destMails, + $params + )); } return $this->app->json([ diff --git a/lib/Alchemy/Phrasea/Core/Event/ExportMailEvent.php b/lib/Alchemy/Phrasea/Core/Event/ExportMailEvent.php new file mode 100644 index 0000000000..3acafb4c70 --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Event/ExportMailEvent.php @@ -0,0 +1,53 @@ +emitterUserId = $emitterUserId; + $this->tokenValue = $tokenValue; + $this->destinationMails = $destMails; + $this->params = $params; + } + + public function getTokenValue() + { + return $this->tokenValue; + } + + public function getDestinationMails() + { + return $this->destinationMails; + } + + public function getEmitterUserId() + { + return $this->emitterUserId; + } + + public function getParams() + { + return $this->params; + } +} diff --git a/lib/Alchemy/Phrasea/Core/Event/Subscriber/ExportSubscriber.php b/lib/Alchemy/Phrasea/Core/Event/Subscriber/ExportSubscriber.php index fca66dab4a..d3c05a64b6 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Subscriber/ExportSubscriber.php +++ b/lib/Alchemy/Phrasea/Core/Event/Subscriber/ExportSubscriber.php @@ -12,7 +12,15 @@ namespace Alchemy\Phrasea\Core\Event\Subscriber; use Alchemy\Phrasea\Core\Event\ExportFailureEvent; +use Alchemy\Phrasea\Core\Event\ExportMailEvent; use Alchemy\Phrasea\Core\PhraseaEvents; +use Alchemy\Phrasea\Exception\InvalidArgumentException; +use Alchemy\Phrasea\Model\Entities\Token; +use Alchemy\Phrasea\Model\Repositories\TokenRepository; +use Alchemy\Phrasea\Model\Repositories\UserRepository; +use Alchemy\Phrasea\Notification\Emitter; +use Alchemy\Phrasea\Notification\Mail\MailRecordsExport; +use Alchemy\Phrasea\Notification\Receiver; class ExportSubscriber extends AbstractNotificationSubscriber { @@ -39,10 +47,65 @@ class ExportSubscriber extends AbstractNotificationSubscriber $this->app['event-manager']->notify($params['usr_id'], 'eventsmanager_notify_downloadmailfail', $datas, $mailed); } + public function onCreateExportMail(ExportMailEvent $event) + { + $destMails = $event->getDestinationMails(); + + $params = $event->getParams(); + + /** @var UserRepository $userRepository */ + $userRepository = $this->app['repo.users']; + + $user = $userRepository->find($event->getEmitterUserId()); + + /** @var TokenRepository $tokenRepository */ + $tokenRepository = $this->app['repo.tokens']; + + /** @var Token $token */ + $token = $tokenRepository->findValidToken($event->getTokenValue()); + + $list = unserialize($token->getData()); + + //zip documents + \set_export::build_zip( + $this->app, + $token, + $list, + $this->app['tmp.download.path'].'/'. $token->getValue() . '.zip' + ); + + $remaingEmails = $destMails; + + $emitter = new Emitter($user->getDisplayName(), $user->getEmail()); + + foreach ($destMails as $key => $mail) { + try { + $receiver = new Receiver(null, trim($mail)); + } catch (InvalidArgumentException $e) { + continue; + } + + $mail = MailRecordsExport::create($this->app, $receiver, $emitter, $params['textmail']); + $mail->setButtonUrl($params['url']); + $mail->setExpiration($token->getExpiration()); + + $this->deliver($mail, $params['reading_confirm']); + unset($remaingEmails[$key]); + } + + //some mails failed + if (count($remaingEmails) > 0) { + foreach ($remaingEmails as $mail) { + $this->app['dispatcher']->dispatch(PhraseaEvents::EXPORT_MAIL_FAILURE, new ExportFailureEvent($user, $params['ssttid'], $params['lst'], \eventsmanager_notify_downloadmailfail::MAIL_FAIL, $mail)); + } + } + } + public static function getSubscribedEvents() { return [ - PhraseaEvents::EXPORT_MAIL_FAILURE => 'onMailExportFailure' + PhraseaEvents::EXPORT_MAIL_FAILURE => 'onMailExportFailure', + PhraseaEvents::EXPORT_MAIL_CREATE => 'onCreateExportMail', ]; } } diff --git a/lib/Alchemy/Phrasea/Core/PhraseaEvents.php b/lib/Alchemy/Phrasea/Core/PhraseaEvents.php index 97c9c10ba5..90adac69dd 100644 --- a/lib/Alchemy/Phrasea/Core/PhraseaEvents.php +++ b/lib/Alchemy/Phrasea/Core/PhraseaEvents.php @@ -48,7 +48,8 @@ final class PhraseaEvents const BRIDGE_UPLOAD_FAILURE = 'bridge.upload-failure'; const EXPORT_MAIL_FAILURE = 'export.mail-failure'; - const EXPORT_CREATE = 'export.create'; + const EXPORT_CREATE = 'export.create'; + const EXPORT_MAIL_CREATE = 'export.mail-create'; const RECORD_EDIT = 'record.edit'; const RECORD_UPLOAD = 'record.upload'; diff --git a/tests/Alchemy/Tests/Phrasea/Controller/Prod/ExportTest.php b/tests/Alchemy/Tests/Phrasea/Controller/Prod/ExportTest.php index da278639c2..925caa9945 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Prod/ExportTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Prod/ExportTest.php @@ -165,7 +165,8 @@ class ExportTest extends \PhraseanetAuthenticatedWebTestCase */ public function testExportMail() { - $this->mockNotificationDeliverer('Alchemy\Phrasea\Notification\Mail\MailRecordsExport'); + // deliver method removed in the listener +// $this->mockNotificationDeliverer('Alchemy\Phrasea\Notification\Mail\MailRecordsExport'); $this->getClient()->request('POST', '/prod/export/mail/', [ 'lst' => $this->getRecord1()->getId(), From 9aaf66dd7c0e14519e56d7991c36200b0f9322f0 Mon Sep 17 00:00:00 2001 From: aynsix Date: Fri, 20 Sep 2019 16:55:03 +0400 Subject: [PATCH 04/14] initialize webhook with worker --- .../Model/Manipulator/WebhookEventManipulator.php | 6 +++--- lib/Alchemy/Phrasea/Webhook/WebhookPublisher.php | 2 +- .../Phrasea/Webhook/WebhookPublisherInterface.php | 10 ++++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 lib/Alchemy/Phrasea/Webhook/WebhookPublisherInterface.php diff --git a/lib/Alchemy/Phrasea/Model/Manipulator/WebhookEventManipulator.php b/lib/Alchemy/Phrasea/Model/Manipulator/WebhookEventManipulator.php index 40e7f812a7..30d20d1045 100644 --- a/lib/Alchemy/Phrasea/Model/Manipulator/WebhookEventManipulator.php +++ b/lib/Alchemy/Phrasea/Model/Manipulator/WebhookEventManipulator.php @@ -12,7 +12,7 @@ namespace Alchemy\Phrasea\Model\Manipulator; use Alchemy\Phrasea\Model\Entities\WebhookEvent; -use Alchemy\Phrasea\Webhook\WebhookPublisher; +use Alchemy\Phrasea\Webhook\WebhookPublisherInterface; use Doctrine\Common\Persistence\ObjectManager; use Doctrine\ORM\EntityRepository; @@ -29,11 +29,11 @@ class WebhookEventManipulator implements ManipulatorInterface private $repository; /** - * @var WebhookPublisher + * @var WebhookPublisherInterface */ private $publisher; - public function __construct(ObjectManager $om, EntityRepository $repo, WebhookPublisher $publisher) + public function __construct(ObjectManager $om, EntityRepository $repo, WebhookPublisherInterface $publisher) { $this->om = $om; $this->repository = $repo; diff --git a/lib/Alchemy/Phrasea/Webhook/WebhookPublisher.php b/lib/Alchemy/Phrasea/Webhook/WebhookPublisher.php index 4304a5319f..2beaec292f 100644 --- a/lib/Alchemy/Phrasea/Webhook/WebhookPublisher.php +++ b/lib/Alchemy/Phrasea/Webhook/WebhookPublisher.php @@ -19,7 +19,7 @@ use Alchemy\Queue\MessageQueueRegistry; * Class WebhookPublisher publishes webhook event notifications in message queues * @package Alchemy\Phrasea\Webhook */ -class WebhookPublisher +class WebhookPublisher implements WebhookPublisherInterface { /** * @var MessageQueueRegistry diff --git a/lib/Alchemy/Phrasea/Webhook/WebhookPublisherInterface.php b/lib/Alchemy/Phrasea/Webhook/WebhookPublisherInterface.php new file mode 100644 index 0000000000..f8b4751ef0 --- /dev/null +++ b/lib/Alchemy/Phrasea/Webhook/WebhookPublisherInterface.php @@ -0,0 +1,10 @@ + Date: Tue, 24 Sep 2019 11:28:31 +0400 Subject: [PATCH 05/14] change event name --- lib/Alchemy/Phrasea/Border/Manager.php | 4 ++-- .../Phrasea/Controller/Prod/StoryController.php | 4 ++-- .../Phrasea/Controller/Prod/ToolsController.php | 4 ++-- .../Phrasea/Core/Event/Record/RecordEvents.php | 2 +- ...BuildEvent.php => SubdefinitionCreateEvent.php} | 2 +- .../Core/Event/Subscriber/RecordEditSubscriber.php | 14 +++++++------- lib/Alchemy/Phrasea/Media/SubdefSubstituer.php | 4 ++-- lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php | 4 ++-- lib/classes/record/adapter.php | 6 +++--- 9 files changed, 22 insertions(+), 22 deletions(-) rename lib/Alchemy/Phrasea/Core/Event/Record/{SubdefinitionBuildEvent.php => SubdefinitionCreateEvent.php} (92%) diff --git a/lib/Alchemy/Phrasea/Border/Manager.php b/lib/Alchemy/Phrasea/Border/Manager.php index 55c28d9cbf..d017d206e6 100644 --- a/lib/Alchemy/Phrasea/Border/Manager.php +++ b/lib/Alchemy/Phrasea/Border/Manager.php @@ -15,7 +15,7 @@ use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Border\Checker\CheckerInterface; use Alchemy\Phrasea\Border\Attribute\AttributeInterface; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; -use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Metadata\Tag\TfArchivedate; use Alchemy\Phrasea\Metadata\Tag\TfQuarantine; @@ -335,7 +335,7 @@ class Manager $this->app['phraseanet.metadata-setter']->replaceMetadata($newMetadata, $element); if(!$nosubdef) { - $this->app['dispatcher']->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($element, true)); + $this->app['dispatcher']->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($element, true)); } return $element; diff --git a/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php b/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php index 19acc22a27..a90f0a0ed1 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/StoryController.php @@ -15,7 +15,7 @@ use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Controller\RecordsRequest; use Alchemy\Phrasea\Controller\Exception as ControllerException; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; -use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; use Alchemy\Phrasea\Core\Event\RecordEdit; use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Model\Entities\StoryWZ; @@ -72,7 +72,7 @@ class StoryController extends Controller $recordAdapter = $story->set_metadatas($metadatas); // tell phraseanet to rebuild subdef - $this->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($recordAdapter)); + $this->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($recordAdapter)); $storyWZ = new StoryWZ(); $storyWZ->setUser($this->getAuthenticatedUser()); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/ToolsController.php b/lib/Alchemy/Phrasea/Controller/Prod/ToolsController.php index 2318cf0638..65f72a8a36 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/ToolsController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/ToolsController.php @@ -16,7 +16,7 @@ use Alchemy\Phrasea\Application\Helper\SubDefinitionSubstituerAware; use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Controller\RecordsRequest; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; -use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Metadata\PhraseanetMetadataReader; use Alchemy\Phrasea\Metadata\PhraseanetMetadataSetter; @@ -157,7 +157,7 @@ class ToolsController extends Controller } if (!$substituted || $force) { - $this->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($record)); + $this->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($record)); } } diff --git a/lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php b/lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php index ac725833ac..e68f4afa84 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php +++ b/lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php @@ -29,7 +29,7 @@ final class RecordEvents const SUB_DEFINITIONS_CREATED = 'record.sub_definitions_created'; const SUB_DEFINITION_CREATION_FAILED = 'record.sub_definition_creation_failed'; - const SUBDEFINITION_BUILD = 'record.subdefinition_build'; + const SUBDEFINITION_CREATE = 'record.subdefinition_create'; const MEDIA_SUBSTITUTED = 'record.media_substituted'; diff --git a/lib/Alchemy/Phrasea/Core/Event/Record/SubdefinitionBuildEvent.php b/lib/Alchemy/Phrasea/Core/Event/Record/SubdefinitionCreateEvent.php similarity index 92% rename from lib/Alchemy/Phrasea/Core/Event/Record/SubdefinitionBuildEvent.php rename to lib/Alchemy/Phrasea/Core/Event/Record/SubdefinitionCreateEvent.php index 701e3a2028..cbb36f4184 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Record/SubdefinitionBuildEvent.php +++ b/lib/Alchemy/Phrasea/Core/Event/Record/SubdefinitionCreateEvent.php @@ -13,7 +13,7 @@ namespace Alchemy\Phrasea\Core\Event\Record; use Alchemy\Phrasea\Model\RecordInterface; -class SubdefinitionBuildEvent extends RecordEvent +class SubdefinitionCreateEvent extends RecordEvent { private $isNewRecord; diff --git a/lib/Alchemy/Phrasea/Core/Event/Subscriber/RecordEditSubscriber.php b/lib/Alchemy/Phrasea/Core/Event/Subscriber/RecordEditSubscriber.php index e58e77cdf7..6c971002e5 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Subscriber/RecordEditSubscriber.php +++ b/lib/Alchemy/Phrasea/Core/Event/Subscriber/RecordEditSubscriber.php @@ -13,7 +13,7 @@ namespace Alchemy\Phrasea\Core\Event\Subscriber; use Alchemy\Phrasea\Core\Event\Record\CollectionChangedEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; -use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; use Alchemy\Phrasea\Core\Event\RecordEdit; use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Metadata\Tag\TfEditdate; @@ -27,11 +27,11 @@ class RecordEditSubscriber implements EventSubscriberInterface public static function getSubscribedEvents() { return array( - PhraseaEvents::RECORD_EDIT => 'onEdit', - PhraseaEvents::RECORD_UPLOAD => 'onEdit', - RecordEvents::ROTATE => 'onRecordChange', - RecordEvents::COLLECTION_CHANGED => 'onCollectionChanged', - RecordEvents::SUBDEFINITION_BUILD => 'onBuildSubdefs', + PhraseaEvents::RECORD_EDIT => 'onEdit', + PhraseaEvents::RECORD_UPLOAD => 'onEdit', + RecordEvents::ROTATE => 'onRecordChange', + RecordEvents::COLLECTION_CHANGED => 'onCollectionChanged', + RecordEvents::SUBDEFINITION_CREATE => 'onSubdefinitionCreate', ); } @@ -51,7 +51,7 @@ class RecordEditSubscriber implements EventSubscriberInterface $recordAdapter->clearStampCache(); } - public function onBuildSubdefs(SubdefinitionBuildEvent $event) + public function onSubdefinitionCreate(SubdefinitionCreateEvent $event) { $recordAdapter = $this->convertToRecordAdapter($event->getRecord()); $recordAdapter->rebuild_subdefs(); diff --git a/lib/Alchemy/Phrasea/Media/SubdefSubstituer.php b/lib/Alchemy/Phrasea/Media/SubdefSubstituer.php index 1d096cf785..8f7aa61e90 100644 --- a/lib/Alchemy/Phrasea/Media/SubdefSubstituer.php +++ b/lib/Alchemy/Phrasea/Media/SubdefSubstituer.php @@ -13,7 +13,7 @@ namespace Alchemy\Phrasea\Media; use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Core\Event\Record\MediaSubstitutedEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; -use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; use Alchemy\Phrasea\Filesystem\FilesystemService; use MediaAlchemyst\Alchemyst; use MediaAlchemyst\Exception\ExceptionInterface as MediaAlchemystException; @@ -80,7 +80,7 @@ class SubdefSubstituer $record->write_metas(); if ($shouldSubdefsBeRebuilt) { - $this->dispatcher->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($record)); + $this->dispatcher->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($record)); } $this->dispatcher->dispatch(RecordEvents::MEDIA_SUBSTITUTED, new MediaSubstitutedEvent($record)); diff --git a/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php b/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php index db1f6b083a..de418a4e71 100644 --- a/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php +++ b/lib/Alchemy/Phrasea/TaskManager/Job/ArchiveJob.php @@ -13,7 +13,7 @@ namespace Alchemy\Phrasea\TaskManager\Job; use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; -use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Border\File; use Alchemy\Phrasea\Border\Manager as borderManager; @@ -1035,7 +1035,7 @@ class ArchiveJob extends AbstractJob $story->setStatus(\databox_status::operation_or($stat0, $stat1)); - $app['dispatcher']->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($story)); + $app['dispatcher']->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($story)); unset($media); diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index 9d7beb2c1a..7c91e2e135 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -19,7 +19,7 @@ use Alchemy\Phrasea\Core\Event\Record\OriginalNameChangedEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; use Alchemy\Phrasea\Core\Event\Record\StatusChangedEvent; -use Alchemy\Phrasea\Core\Event\Record\SubdefinitionBuildEvent; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; use Alchemy\Phrasea\Core\PhraseaTokens; use Alchemy\Phrasea\Databox\Subdef\MediaSubdefRepository; use Alchemy\Phrasea\Filesystem\FilesystemService; @@ -285,7 +285,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface $this->getDataboxConnection()->executeUpdate($sql, ['type' => $type, 'record_id' => $this->getRecordId()]); if ($old_type !== $type) { - $this->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($this)); + $this->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($this)); } $this->type = $type; @@ -342,7 +342,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface array(':mime' => $mime, ':record_id' => $this->getRecordId()) )) { - $this->dispatch(RecordEvents::SUBDEFINITION_BUILD, new SubdefinitionBuildEvent($this)); + $this->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($this)); $this->delete_data_from_cache(); } From 4cac08c48fddd2251c915e3f76cd3aa38d18e324 Mon Sep 17 00:00:00 2001 From: aynsix Date: Wed, 25 Sep 2019 11:29:07 +0400 Subject: [PATCH 06/14] ask to write metadata only if record has subdefs --- lib/classes/record/adapter.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index 7c91e2e135..8475ff1d9c 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1107,8 +1107,11 @@ class record_adapter implements RecordInterface, cache_cacheableInterface $this->set_xml($xml); unset($xml); - $this->write_metas(); - $this->dispatch(RecordEvents::METADATA_CHANGED, new MetadataChangedEvent($this)); + // if there is yet subdefs, ask to write metadata + if (count($this->getMediaSubdefRepository()->findByRecordIdsAndNames([$this->getRecordId()])) > 1 ) { + $this->write_metas(); + $this->dispatch(RecordEvents::METADATA_CHANGED, new MetadataChangedEvent($this)); + } return $this; } From e50b60306c3cd5dec7feff20a9083d5778e7a7f4 Mon Sep 17 00:00:00 2001 From: aynsix Date: Wed, 25 Sep 2019 14:45:48 +0400 Subject: [PATCH 07/14] revert: 4cac08c48fddd2 do not use this approach --- lib/classes/record/adapter.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index 8475ff1d9c..7c91e2e135 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1107,11 +1107,8 @@ class record_adapter implements RecordInterface, cache_cacheableInterface $this->set_xml($xml); unset($xml); - // if there is yet subdefs, ask to write metadata - if (count($this->getMediaSubdefRepository()->findByRecordIdsAndNames([$this->getRecordId()])) > 1 ) { - $this->write_metas(); - $this->dispatch(RecordEvents::METADATA_CHANGED, new MetadataChangedEvent($this)); - } + $this->write_metas(); + $this->dispatch(RecordEvents::METADATA_CHANGED, new MetadataChangedEvent($this)); return $this; } From 2163f0452dc8a3c6ec0c7197769619ceb614ccdc Mon Sep 17 00:00:00 2001 From: aynsix Date: Wed, 30 Oct 2019 14:19:13 +0400 Subject: [PATCH 08/14] PHRAS-2797 retrieve available subdef in event record.sub_definitions_created --- lib/Alchemy/Phrasea/Media/SubdefGenerator.php | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/lib/Alchemy/Phrasea/Media/SubdefGenerator.php b/lib/Alchemy/Phrasea/Media/SubdefGenerator.php index 9ab4d7ebe0..9612e3bc19 100644 --- a/lib/Alchemy/Phrasea/Media/SubdefGenerator.php +++ b/lib/Alchemy/Phrasea/Media/SubdefGenerator.php @@ -18,6 +18,7 @@ use Alchemy\Phrasea\Core\Event\Record\SubDefinitionCreationEvent; use Alchemy\Phrasea\Core\Event\Record\SubDefinitionsCreationEvent; use Alchemy\Phrasea\Core\Event\Record\SubDefinitionCreationFailedEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; +use Alchemy\Phrasea\Databox\Subdef\MediaSubdefRepository; use Alchemy\Phrasea\Filesystem\FilesystemService; use Alchemy\Phrasea\Media\Subdef\Specification\PdfSpecification; use MediaAlchemyst\Alchemyst; @@ -170,13 +171,35 @@ class SubdefGenerator unset($this->tmpFilePath); } - $this->dispatch( - RecordEvents::SUB_DEFINITIONS_CREATED, - new SubDefinitionsCreatedEvent( - $record, - $mediaCreated - ) - ); + // if we created subdef one by one + if (count($wanted_subdefs) == 1) { + $mediaSubdefRepository = $this->getMediaSubdefRepository($record->getDataboxId()); + $mediaSubdefs = $mediaSubdefRepository->findByRecordIdsAndNames([$record->getRecordId()]); + $medias = []; + foreach ($mediaSubdefs as $subdef) { + try { + $medias[$subdef->get_name()] = $this->mediavorus->guess($subdef->getRealPath()); + } catch (MediaVorusFileNotFoundException $e) { + + } + } + + $this->dispatch( + RecordEvents::SUB_DEFINITIONS_CREATED, + new SubDefinitionsCreatedEvent( + $record, + $medias + ) + ); + } else { + $this->dispatch( + RecordEvents::SUB_DEFINITIONS_CREATED, + new SubDefinitionsCreatedEvent( + $record, + $mediaCreated + ) + ); + } } /** @@ -294,4 +317,14 @@ class SubdefGenerator $i = floor(log($bytes, 1024)); return round($bytes / pow(1024, $i), [0,0,2,2,3][$i]).['B','kB','MB','GB'][$i]; } + + /** + * @param $databoxId + * + * @return MediaSubdefRepository|Object + */ + private function getMediaSubdefRepository($databoxId) + { + return $this->app['provider.repo.media_subdef']->getRepositoryForDatabox($databoxId); + } } From 378f67c203d5930a91ee259fffc48cf4fd408d3f Mon Sep 17 00:00:00 2001 From: aynsix Date: Mon, 4 Nov 2019 17:19:18 +0400 Subject: [PATCH 09/14] PHRAS-2769 delete record --- lib/Alchemy/Phrasea/Controller/Prod/RecordController.php | 6 ++++-- lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php | 6 ++++-- .../Core/Event/Subscriber/RecordEditSubscriber.php | 8 ++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Prod/RecordController.php b/lib/Alchemy/Phrasea/Controller/Prod/RecordController.php index 0a948d6d1d..8e9a609811 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/RecordController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/RecordController.php @@ -14,6 +14,8 @@ use Alchemy\Phrasea\Application\Helper\EntityManagerAware; use Alchemy\Phrasea\Application\Helper\SearchEngineAware; use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Controller\RecordsRequest; +use Alchemy\Phrasea\Core\Event\Record\DeleteEvent; +use Alchemy\Phrasea\Core\Event\Record\RecordEvents; use Alchemy\Phrasea\Core\Event\RecordEdit; use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Model\Entities\BasketElement; @@ -234,7 +236,7 @@ class RecordController extends Controller if($trashCollectionsBySbasId[$sbasId] !== null) { if($record->getCollection()->get_coll_id() == $trashCollectionsBySbasId[$sbasId]->get_coll_id()) { // record is already in trash so delete it - $record->delete(); + $this->getEventDispatcher()->dispatch(RecordEvents::DELETE, new DeleteEvent($record)); } else { // move to trash collection $record->move_to_collection($trashCollectionsBySbasId[$sbasId], $this->getApplicationBox()); @@ -247,7 +249,7 @@ class RecordController extends Controller } } else { // no trash collection, delete - $record->delete(); + $this->getEventDispatcher()->dispatch(RecordEvents::DELETE, new DeleteEvent($record)); } } catch (\Exception $e) { } diff --git a/lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php b/lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php index e68f4afa84..1399b1c8f5 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php +++ b/lib/Alchemy/Phrasea/Core/Event/Record/RecordEvents.php @@ -13,8 +13,10 @@ namespace Alchemy\Phrasea\Core\Event\Record; final class RecordEvents { - const CREATED = 'record.created'; - const DELETED = 'record.deleted'; + const CREATED = 'record.created'; + const DELETED = 'record.deleted'; + const DELETE = 'record.delete'; + // Change const COLLECTION_CHANGED = 'record.collection_changed'; const METADATA_CHANGED = 'record.metadata_changed'; diff --git a/lib/Alchemy/Phrasea/Core/Event/Subscriber/RecordEditSubscriber.php b/lib/Alchemy/Phrasea/Core/Event/Subscriber/RecordEditSubscriber.php index 6c971002e5..8307749eb5 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Subscriber/RecordEditSubscriber.php +++ b/lib/Alchemy/Phrasea/Core/Event/Subscriber/RecordEditSubscriber.php @@ -11,6 +11,7 @@ namespace Alchemy\Phrasea\Core\Event\Subscriber; use Alchemy\Phrasea\Core\Event\Record\CollectionChangedEvent; +use Alchemy\Phrasea\Core\Event\Record\DeleteEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; @@ -32,6 +33,7 @@ class RecordEditSubscriber implements EventSubscriberInterface RecordEvents::ROTATE => 'onRecordChange', RecordEvents::COLLECTION_CHANGED => 'onCollectionChanged', RecordEvents::SUBDEFINITION_CREATE => 'onSubdefinitionCreate', + RecordEvents::DELETE => 'onDelete', ); } @@ -57,6 +59,12 @@ class RecordEditSubscriber implements EventSubscriberInterface $recordAdapter->rebuild_subdefs(); } + public function onDelete(DeleteEvent $event) + { + $recordAdapter = $this->convertToRecordAdapter($event->getRecord()); + $recordAdapter->delete(); + } + public function onEdit(RecordEdit $event) { static $into = false; From 97b579efc3ded6eb70f0d3c70f97a9fe8be5f15a Mon Sep 17 00:00:00 2001 From: aynsix Date: Mon, 4 Nov 2019 17:51:18 +0400 Subject: [PATCH 10/14] PHRAS-2769 add DeleteEvent file --- lib/Alchemy/Phrasea/Core/Event/Record/DeleteEvent.php | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 lib/Alchemy/Phrasea/Core/Event/Record/DeleteEvent.php diff --git a/lib/Alchemy/Phrasea/Core/Event/Record/DeleteEvent.php b/lib/Alchemy/Phrasea/Core/Event/Record/DeleteEvent.php new file mode 100644 index 0000000000..8d8bfdb379 --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Event/Record/DeleteEvent.php @@ -0,0 +1,7 @@ + Date: Thu, 19 Dec 2019 16:09:35 +0400 Subject: [PATCH 11/14] start subdef creation after first write meta --- lib/Alchemy/Phrasea/Border/Manager.php | 19 +++++++------- .../Event/Record/MetadataChangedEvent.php | 25 +++++++++++++++++++ .../Metadata/PhraseanetMetadataSetter.php | 4 +-- .../TaskManager/Job/WriteMetadataJob.php | 16 +++++++++++- lib/classes/record/adapter.php | 14 +++++++++-- 5 files changed, 64 insertions(+), 14 deletions(-) diff --git a/lib/Alchemy/Phrasea/Border/Manager.php b/lib/Alchemy/Phrasea/Border/Manager.php index d017d206e6..543f97ebd6 100644 --- a/lib/Alchemy/Phrasea/Border/Manager.php +++ b/lib/Alchemy/Phrasea/Border/Manager.php @@ -14,8 +14,6 @@ namespace Alchemy\Phrasea\Border; use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Border\Checker\CheckerInterface; use Alchemy\Phrasea\Border\Attribute\AttributeInterface; -use Alchemy\Phrasea\Core\Event\Record\RecordEvents; -use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Metadata\Tag\TfArchivedate; use Alchemy\Phrasea\Metadata\Tag\TfQuarantine; @@ -112,6 +110,9 @@ class Manager if (($visa->isValid() || $forceBehavior === self::FORCE_RECORD) && $forceBehavior !== self::FORCE_LAZARET) { + // Write UUID + $file->getUUID(false, true); + $this->addMediaAttributes($file); $element = $this->createRecord($file, $nosubdef); @@ -119,14 +120,14 @@ class Manager $code = self::RECORD_CREATED; } else { + // Write UUID + $file->getUUID(false, true); + $element = $this->createLazaret($file, $visa, $session, $forceBehavior === self::FORCE_LAZARET); $code = self::LAZARET_CREATED; } - // Write UUID - $file->getUUID(false, true); - if (is_callable($callable)) { $callable($element, $visa, $code); } @@ -332,12 +333,12 @@ class Manager } } - $this->app['phraseanet.metadata-setter']->replaceMetadata($newMetadata, $element); - - if(!$nosubdef) { - $this->app['dispatcher']->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($element, true)); + if ($nosubdef) { + $element->setNoSubdef(); } + $this->app['phraseanet.metadata-setter']->replaceMetadata($newMetadata, $element, true, $nosubdef);// true for $isNewRecord + return $element; } diff --git a/lib/Alchemy/Phrasea/Core/Event/Record/MetadataChangedEvent.php b/lib/Alchemy/Phrasea/Core/Event/Record/MetadataChangedEvent.php index 65326b894b..5a3ed5c2ef 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Record/MetadataChangedEvent.php +++ b/lib/Alchemy/Phrasea/Core/Event/Record/MetadataChangedEvent.php @@ -11,6 +11,31 @@ namespace Alchemy\Phrasea\Core\Event\Record; +use Alchemy\Phrasea\Model\RecordInterface; + class MetadataChangedEvent extends RecordEvent { + private $isNewRecord; + private $nosubdef; + + public function __construct(RecordInterface $record, $isNewRecord = false, $nosubdef = false) + { + parent::__construct($record); + + $this->isNewRecord = $isNewRecord; + $this->nosubdef = $nosubdef; + } + + /** + * @return bool + */ + public function isNewRecord() + { + return $this->isNewRecord; + } + + public function isNosubdef() + { + return $this->nosubdef; + } } diff --git a/lib/Alchemy/Phrasea/Metadata/PhraseanetMetadataSetter.php b/lib/Alchemy/Phrasea/Metadata/PhraseanetMetadataSetter.php index c72c884203..afa459f154 100644 --- a/lib/Alchemy/Phrasea/Metadata/PhraseanetMetadataSetter.php +++ b/lib/Alchemy/Phrasea/Metadata/PhraseanetMetadataSetter.php @@ -34,7 +34,7 @@ class PhraseanetMetadataSetter * @param \record_adapter $record * @throws \Exception_InvalidArgument */ - public function replaceMetadata($metadataCollection, \record_adapter $record) + public function replaceMetadata($metadataCollection, \record_adapter $record, $isNewRecord = false, $nosubdef = false) { $metaStructure = $this->repository->find($record->getDataboxId())->get_meta_structure()->get_elements(); @@ -82,7 +82,7 @@ class PhraseanetMetadataSetter } if (! empty($metadataInRecordFormat)) { - $record->set_metadatas($metadataInRecordFormat, true); + $record->set_metadatas($metadataInRecordFormat, true, $isNewRecord, $nosubdef); } } diff --git a/lib/Alchemy/Phrasea/TaskManager/Job/WriteMetadataJob.php b/lib/Alchemy/Phrasea/TaskManager/Job/WriteMetadataJob.php index 795b0b2a83..7631044cf2 100644 --- a/lib/Alchemy/Phrasea/TaskManager/Job/WriteMetadataJob.php +++ b/lib/Alchemy/Phrasea/TaskManager/Job/WriteMetadataJob.php @@ -12,6 +12,8 @@ namespace Alchemy\Phrasea\TaskManager\Job; use Alchemy\Phrasea\Application; +use Alchemy\Phrasea\Core\Event\Record\RecordEvents; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; use Alchemy\Phrasea\Core\PhraseaTokens; use Alchemy\Phrasea\Metadata\TagFactory; use Alchemy\Phrasea\TaskManager\Editor\WriteMetadataEditor; @@ -69,7 +71,7 @@ class WriteMetadataJob extends AbstractJob foreach ($jobData->getApplication()->getDataboxes() as $databox) { $connection = $databox->get_connection(); - $statement = $connection->prepare('SELECT record_id, coll_id, jeton FROM record WHERE (jeton & :token > 0)'); + $statement = $connection->prepare('SELECT record_id, coll_id, work, jeton FROM record WHERE (jeton & :token > 0)'); $statement->execute(['token' => PhraseaTokens::WRITE_META]); $rs = $statement->fetchAll(\PDO::FETCH_ASSOC); $statement->closeCursor(); @@ -203,6 +205,13 @@ class WriteMetadataJob extends AbstractJob 'record_id' => $record_id, 'token' => PhraseaTokens::WRITE_META, ]); + + // write meta for the document is finished + // if it's a new record, order to create subdef + if (count($record->get_subdefs()) == 3 && count($subdefs) == 1 && isset($subdefs['document']) && $row['work'] != 1) { + $this->getDispatcher($jobData->getApplication())->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($record, true)); + } + $statement->closeCursor(); } } @@ -217,6 +226,11 @@ class WriteMetadataJob extends AbstractJob return $app['exiftool.writer']; } + private function getDispatcher(Application $app) + { + return $app['dispatcher']; + } + /** * @param \databox $databox * @param string $subdefType diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index 7c91e2e135..ebf9c0d4e8 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1083,7 +1083,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface * * @return record_adapter */ - public function set_metadatas(array $metadatas, $force_readonly = false) + public function set_metadatas(array $metadatas, $force_readonly = false, $isNewRecord = false, $nosubdef = false) { $databox_descriptionStructure = $this->getDatabox()->get_meta_structure(); @@ -1108,7 +1108,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface unset($xml); $this->write_metas(); - $this->dispatch(RecordEvents::METADATA_CHANGED, new MetadataChangedEvent($this)); + $this->dispatch(RecordEvents::METADATA_CHANGED, new MetadataChangedEvent($this, $isNewRecord, $nosubdef)); return $this; } @@ -1175,6 +1175,16 @@ class record_adapter implements RecordInterface, cache_cacheableInterface return $this; } + public function setNoSubdef() + { + $this->getDataboxConnection()->executeUpdate( + 'UPDATE record SET work = 1 WHERE record_id= :record_id', + ['record_id' => $this->getRecordId()] + ); + + return $this; + } + private function dispatch($eventName, RecordEvent $event) { $this->app['dispatcher']->dispatch($eventName, $event); From db0489c05e271fff58cd648a09a839a95b4837e7 Mon Sep 17 00:00:00 2001 From: aynsix Date: Thu, 20 Feb 2020 11:11:18 +0300 Subject: [PATCH 12/14] Revert "start subdef creation after first write meta" This reverts commit cfa854f307edb356f8c79a67e84fa16f645a21da. --- lib/Alchemy/Phrasea/Border/Manager.php | 19 +++++++------- .../Event/Record/MetadataChangedEvent.php | 25 ------------------- .../Metadata/PhraseanetMetadataSetter.php | 4 +-- .../TaskManager/Job/WriteMetadataJob.php | 16 +----------- lib/classes/record/adapter.php | 14 ++--------- 5 files changed, 14 insertions(+), 64 deletions(-) diff --git a/lib/Alchemy/Phrasea/Border/Manager.php b/lib/Alchemy/Phrasea/Border/Manager.php index 543f97ebd6..d017d206e6 100644 --- a/lib/Alchemy/Phrasea/Border/Manager.php +++ b/lib/Alchemy/Phrasea/Border/Manager.php @@ -14,6 +14,8 @@ namespace Alchemy\Phrasea\Border; use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Border\Checker\CheckerInterface; use Alchemy\Phrasea\Border\Attribute\AttributeInterface; +use Alchemy\Phrasea\Core\Event\Record\RecordEvents; +use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Metadata\Tag\TfArchivedate; use Alchemy\Phrasea\Metadata\Tag\TfQuarantine; @@ -110,9 +112,6 @@ class Manager if (($visa->isValid() || $forceBehavior === self::FORCE_RECORD) && $forceBehavior !== self::FORCE_LAZARET) { - // Write UUID - $file->getUUID(false, true); - $this->addMediaAttributes($file); $element = $this->createRecord($file, $nosubdef); @@ -120,14 +119,14 @@ class Manager $code = self::RECORD_CREATED; } else { - // Write UUID - $file->getUUID(false, true); - $element = $this->createLazaret($file, $visa, $session, $forceBehavior === self::FORCE_LAZARET); $code = self::LAZARET_CREATED; } + // Write UUID + $file->getUUID(false, true); + if (is_callable($callable)) { $callable($element, $visa, $code); } @@ -333,11 +332,11 @@ class Manager } } - if ($nosubdef) { - $element->setNoSubdef(); - } + $this->app['phraseanet.metadata-setter']->replaceMetadata($newMetadata, $element); - $this->app['phraseanet.metadata-setter']->replaceMetadata($newMetadata, $element, true, $nosubdef);// true for $isNewRecord + if(!$nosubdef) { + $this->app['dispatcher']->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($element, true)); + } return $element; } diff --git a/lib/Alchemy/Phrasea/Core/Event/Record/MetadataChangedEvent.php b/lib/Alchemy/Phrasea/Core/Event/Record/MetadataChangedEvent.php index 5a3ed5c2ef..65326b894b 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Record/MetadataChangedEvent.php +++ b/lib/Alchemy/Phrasea/Core/Event/Record/MetadataChangedEvent.php @@ -11,31 +11,6 @@ namespace Alchemy\Phrasea\Core\Event\Record; -use Alchemy\Phrasea\Model\RecordInterface; - class MetadataChangedEvent extends RecordEvent { - private $isNewRecord; - private $nosubdef; - - public function __construct(RecordInterface $record, $isNewRecord = false, $nosubdef = false) - { - parent::__construct($record); - - $this->isNewRecord = $isNewRecord; - $this->nosubdef = $nosubdef; - } - - /** - * @return bool - */ - public function isNewRecord() - { - return $this->isNewRecord; - } - - public function isNosubdef() - { - return $this->nosubdef; - } } diff --git a/lib/Alchemy/Phrasea/Metadata/PhraseanetMetadataSetter.php b/lib/Alchemy/Phrasea/Metadata/PhraseanetMetadataSetter.php index afa459f154..c72c884203 100644 --- a/lib/Alchemy/Phrasea/Metadata/PhraseanetMetadataSetter.php +++ b/lib/Alchemy/Phrasea/Metadata/PhraseanetMetadataSetter.php @@ -34,7 +34,7 @@ class PhraseanetMetadataSetter * @param \record_adapter $record * @throws \Exception_InvalidArgument */ - public function replaceMetadata($metadataCollection, \record_adapter $record, $isNewRecord = false, $nosubdef = false) + public function replaceMetadata($metadataCollection, \record_adapter $record) { $metaStructure = $this->repository->find($record->getDataboxId())->get_meta_structure()->get_elements(); @@ -82,7 +82,7 @@ class PhraseanetMetadataSetter } if (! empty($metadataInRecordFormat)) { - $record->set_metadatas($metadataInRecordFormat, true, $isNewRecord, $nosubdef); + $record->set_metadatas($metadataInRecordFormat, true); } } diff --git a/lib/Alchemy/Phrasea/TaskManager/Job/WriteMetadataJob.php b/lib/Alchemy/Phrasea/TaskManager/Job/WriteMetadataJob.php index 7631044cf2..795b0b2a83 100644 --- a/lib/Alchemy/Phrasea/TaskManager/Job/WriteMetadataJob.php +++ b/lib/Alchemy/Phrasea/TaskManager/Job/WriteMetadataJob.php @@ -12,8 +12,6 @@ namespace Alchemy\Phrasea\TaskManager\Job; use Alchemy\Phrasea\Application; -use Alchemy\Phrasea\Core\Event\Record\RecordEvents; -use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; use Alchemy\Phrasea\Core\PhraseaTokens; use Alchemy\Phrasea\Metadata\TagFactory; use Alchemy\Phrasea\TaskManager\Editor\WriteMetadataEditor; @@ -71,7 +69,7 @@ class WriteMetadataJob extends AbstractJob foreach ($jobData->getApplication()->getDataboxes() as $databox) { $connection = $databox->get_connection(); - $statement = $connection->prepare('SELECT record_id, coll_id, work, jeton FROM record WHERE (jeton & :token > 0)'); + $statement = $connection->prepare('SELECT record_id, coll_id, jeton FROM record WHERE (jeton & :token > 0)'); $statement->execute(['token' => PhraseaTokens::WRITE_META]); $rs = $statement->fetchAll(\PDO::FETCH_ASSOC); $statement->closeCursor(); @@ -205,13 +203,6 @@ class WriteMetadataJob extends AbstractJob 'record_id' => $record_id, 'token' => PhraseaTokens::WRITE_META, ]); - - // write meta for the document is finished - // if it's a new record, order to create subdef - if (count($record->get_subdefs()) == 3 && count($subdefs) == 1 && isset($subdefs['document']) && $row['work'] != 1) { - $this->getDispatcher($jobData->getApplication())->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($record, true)); - } - $statement->closeCursor(); } } @@ -226,11 +217,6 @@ class WriteMetadataJob extends AbstractJob return $app['exiftool.writer']; } - private function getDispatcher(Application $app) - { - return $app['dispatcher']; - } - /** * @param \databox $databox * @param string $subdefType diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index e8dc587451..f58d54abea 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1083,7 +1083,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface * * @return record_adapter */ - public function set_metadatas(array $metadatas, $force_readonly = false, $isNewRecord = false, $nosubdef = false) + public function set_metadatas(array $metadatas, $force_readonly = false) { $databox_descriptionStructure = $this->getDatabox()->get_meta_structure(); @@ -1108,7 +1108,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface unset($xml); $this->write_metas(); - $this->dispatch(RecordEvents::METADATA_CHANGED, new MetadataChangedEvent($this, $isNewRecord, $nosubdef)); + $this->dispatch(RecordEvents::METADATA_CHANGED, new MetadataChangedEvent($this)); return $this; } @@ -1175,16 +1175,6 @@ class record_adapter implements RecordInterface, cache_cacheableInterface return $this; } - public function setNoSubdef() - { - $this->getDataboxConnection()->executeUpdate( - 'UPDATE record SET work = 1 WHERE record_id= :record_id', - ['record_id' => $this->getRecordId()] - ); - - return $this; - } - private function dispatch($eventName, RecordEvent $event) { $this->app['dispatcher']->dispatch($eventName, $event); From fba38da25cdeb70d06f66cc42c647b73d81496b5 Mon Sep 17 00:00:00 2001 From: Nicolas Maillat Date: Wed, 18 Mar 2020 01:33:39 +0000 Subject: [PATCH 13/14] Translated using Weblate (English) Currently translated at 98.9% (2451 of 2476 strings) --- resources/locales/messages.en.xlf | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/resources/locales/messages.en.xlf b/resources/locales/messages.en.xlf index 4c9560d4e9..4b5369e3e6 100644 --- a/resources/locales/messages.en.xlf +++ b/resources/locales/messages.en.xlf @@ -1,4 +1,4 @@ - +
@@ -7,8 +7,8 @@
- - + + Form/Login/PhraseaAuthenticationForm.php Form/Configuration/EmailFormType.php @@ -13432,14 +13432,14 @@ It is possible to place several search areas August prod/WorkZone/Basket.html.twig - + workzone:datepicker:closeText - workzone:datepicker:closeText + Close prod/WorkZone/Basket.html.twig - + workzone:datepicker:currentText - workzone:datepicker:currentText + Current prod/WorkZone/Basket.html.twig @@ -13543,9 +13543,9 @@ It is possible to place several search areas prod/WorkZone/Basket.html.twig prod/Tooltip/Basket.html.twig - + workzone:feedback:expiration-open - workzone:feedback:expiration-open + Feedback open until prod/WorkZone/Basket.html.twig prod/Tooltip/Basket.html.twig From 936c24329b4fc88950fdbee2b866897fe92d431a Mon Sep 17 00:00:00 2001 From: Nicolas Maillat Date: Wed, 18 Mar 2020 00:42:53 +0000 Subject: [PATCH 14/14] Translated using Weblate (French) Currently translated at 98.9% (2451 of 2476 strings) --- resources/locales/messages.fr.xlf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/resources/locales/messages.fr.xlf b/resources/locales/messages.fr.xlf index be1a6c9a97..d830633044 100644 --- a/resources/locales/messages.fr.xlf +++ b/resources/locales/messages.fr.xlf @@ -1,4 +1,4 @@ - +
@@ -7,8 +7,8 @@
- - + + Form/Login/PhraseaAuthenticationForm.php Form/Configuration/EmailFormType.php @@ -13540,15 +13540,15 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le Mercredi prod/WorkZone/Basket.html.twig
- + workzone:feedback:expiration-closed - workzone:feedback:expiration-closed + Validation close depuis prod/WorkZone/Basket.html.twig prod/Tooltip/Basket.html.twig - + workzone:feedback:expiration-open - workzone:feedback:expiration-open + validation ouverte jusqu'au prod/WorkZone/Basket.html.twig prod/Tooltip/Basket.html.twig