Merge branch 'master' into PHRAS-2978_feedback_basket-change_date-format

This commit is contained in:
Nicolas Maillat
2020-03-20 19:07:51 +01:00
committed by GitHub
50 changed files with 701 additions and 154 deletions

View File

@@ -57,6 +57,7 @@ use Alchemy\Phrasea\Command\User\UserCreateCommand;
use Alchemy\Phrasea\Command\User\UserPasswordCommand; use Alchemy\Phrasea\Command\User\UserPasswordCommand;
use Alchemy\Phrasea\Command\User\UserListCommand; use Alchemy\Phrasea\Command\User\UserListCommand;
use Alchemy\Phrasea\Command\UpgradeDBDatas; use Alchemy\Phrasea\Command\UpgradeDBDatas;
use Alchemy\Phrasea\Command\ApplyRightsCommand;
require_once __DIR__ . '/../lib/autoload.php'; require_once __DIR__ . '/../lib/autoload.php';
@@ -93,6 +94,7 @@ $cli->command(new \module_console_aboutLicense('about:license'));
$cli->command(new CheckConfig('check:config')); $cli->command(new CheckConfig('check:config'));
$cli->command(new UpgradeDBDatas('system:upgrade-datas')); $cli->command(new UpgradeDBDatas('system:upgrade-datas'));
$cli->command(new ApplyRightsCommand('system:apply-rights'));
$cli->command(new \module_console_systemMailCheck('system:mail-check')); $cli->command(new \module_console_systemMailCheck('system:mail-check'));
$cli->command(new \module_console_systemBackupDB('system:backup-db')); $cli->command(new \module_console_systemBackupDB('system:backup-db'));
@@ -160,9 +162,9 @@ $cli->command(new QueryParseCommand());
$cli->command(new QuerySampleCommand()); $cli->command(new QuerySampleCommand());
$cli->command(new FindConceptsCommand()); $cli->command(new FindConceptsCommand());
$cli->command($cli['alchemy_worker.commands.run_dispatcher_command']); //$cli->command($cli['alchemy_worker.commands.run_dispatcher_command']);
$cli->command($cli['alchemy_worker.commands.run_worker_command']); //$cli->command($cli['alchemy_worker.commands.run_worker_command']);
$cli->command($cli['alchemy_worker.commands.show_configuration']); //$cli->command($cli['alchemy_worker.commands.show_configuration']);
$cli->loadPlugins(); $cli->loadPlugins();

View File

@@ -167,11 +167,11 @@ class AccountService
* @param string $login * @param string $login
* @throws AccountException * @throws AccountException
*/ */
public function deleteAccount($login = null) public function deleteAccount($login = null, array $grantedBaseIdList = array())
{ {
$user = $this->getUserOrCurrentUser($login); $user = $this->getUserOrCurrentUser($login);
$this->userManipulator->delete($user); $this->userManipulator->delete($user, $grantedBaseIdList);
} }
/** /**

View File

@@ -328,11 +328,9 @@ class RegistrationService
$autoReg = $acl->get_granted_base(); $autoReg = $acl->get_granted_base();
$granted = [];
foreach ($autoReg as $baseId => $collection) { foreach ($autoReg as $baseId => $collection) {
$granted[$baseId] = $collection->get_label($this->app['locale']); $granted[$baseId] = $collection->get_label($this->app['locale']);
}
if(count($granted) > 0) {
$this->app['manipulator.webhook-event']->create( $this->app['manipulator.webhook-event']->create(
WebhookEvent::USER_REGISTRATION_GRANTED, WebhookEvent::USER_REGISTRATION_GRANTED,
WebhookEvent::USER_REGISTRATION_TYPE, WebhookEvent::USER_REGISTRATION_TYPE,
@@ -340,8 +338,11 @@ class RegistrationService
'user_id' => $user->getId(), 'user_id' => $user->getId(),
'granted' => $granted, 'granted' => $granted,
'rejected' => [] 'rejected' => []
] ],
[$baseId]
); );
unset($granted);
} }

View File

@@ -14,6 +14,8 @@ namespace Alchemy\Phrasea\Border;
use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Border\Checker\CheckerInterface; use Alchemy\Phrasea\Border\Checker\CheckerInterface;
use Alchemy\Phrasea\Border\Attribute\AttributeInterface; 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\Exception\RuntimeException;
use Alchemy\Phrasea\Metadata\Tag\TfArchivedate; use Alchemy\Phrasea\Metadata\Tag\TfArchivedate;
use Alchemy\Phrasea\Metadata\Tag\TfQuarantine; use Alchemy\Phrasea\Metadata\Tag\TfQuarantine;
@@ -333,7 +335,7 @@ class Manager
$this->app['phraseanet.metadata-setter']->replaceMetadata($newMetadata, $element); $this->app['phraseanet.metadata-setter']->replaceMetadata($newMetadata, $element);
if(!$nosubdef) { if(!$nosubdef) {
$element->rebuild_subdefs(); $this->app['dispatcher']->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($element, true));
} }
return $element; return $element;

View File

@@ -0,0 +1,89 @@
<?php
/**
* This file is part of Phraseanet
*
* (c) 2005-2020 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Alchemy\Phrasea\Model\Entities\User;
class ApplyRightsCommand extends Command
{
public function __construct($name = null)
{
parent::__construct($name);
$this->setDescription('Apply right on databox, inject appbox:basusr to dboxes:collusr')
->addOption('user_id', null, InputOption::VALUE_REQUIRED, 'the user ID to apply rights')
;
return $this;
}
protected function doExecute(InputInterface $input, OutputInterface $output)
{
$userId = $input->getOption('user_id');
$userRepository = $this->container['repo.users'];
if ($userId) {
if (($user = $userRepository->find($userId)) === null) {
$output->writeln('user not found!');
return 0;
}
$this->injectRightsSbas($user);
} else {
foreach ($userRepository->findAll() as $user) {
$this->injectRightsSbas($user);
}
}
$output->writeln('Apply right on databox finished!');
return 0;
}
private function injectRightsSbas(User $user)
{
$userAcl = $this->container->getAclForUser($user);
foreach ($userAcl->get_granted_sbas() as $databox) {
$userAcl->delete_injected_rights_sbas($databox);
$sql = "INSERT INTO collusr
(site, usr_id, coll_id, mask_and, mask_xor, ord)
VALUES (:site_id, :usr_id, :coll_id, :mask_and, :mask_xor, :ord)";
$stmt = $databox->get_connection()->prepare($sql);
$iord = 0;
// fix collusr if user has right on collection
foreach ($userAcl->get_granted_base([], [$databox->get_sbas_id()]) as $collection) {
try {
$stmt->execute([
':site_id' => $this->container['conf']->get(['main', 'key']),
':usr_id' => $user->getId(),
':coll_id' => $collection->get_coll_id(),
':mask_and' => $userAcl->get_mask_and($collection->get_base_id()),
':mask_xor' => $userAcl->get_mask_xor($collection->get_base_id()),
':ord' => $iord++
]);
} catch (DBALException $e) {
}
}
$stmt->closeCursor();
}
}
}

View File

@@ -515,9 +515,9 @@ class UserController extends Controller
$denyColl[] = $label; $denyColl[] = $label;
$hookData['rejected'][$bas] = $label; $hookData['rejected'][$bas] = $label;
} }
}
$this->app['manipulator.webhook-event']->create($hookName, $hookType, $hookData); $this->app['manipulator.webhook-event']->create($hookName, $hookType, $hookData, [$bas]);
}
if ($user->hasMailNotificationsActivated() && (0 !== count($acceptColl) || 0 !== count($denyColl))) { if ($user->hasMailNotificationsActivated() && (0 !== count($acceptColl) || 0 !== count($denyColl))) {
$message = ''; $message = '';

View File

@@ -15,6 +15,7 @@ use Alchemy\Phrasea\Application\Helper\FilesystemAware;
use Alchemy\Phrasea\Application\Helper\NotifierAware; use Alchemy\Phrasea\Application\Helper\NotifierAware;
use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Controller\Controller;
use Alchemy\Phrasea\Core\Event\ExportFailureEvent; use Alchemy\Phrasea\Core\Event\ExportFailureEvent;
use Alchemy\Phrasea\Core\Event\ExportMailEvent;
use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Core\PhraseaEvents;
use Alchemy\Phrasea\Exception\InvalidArgumentException; use Alchemy\Phrasea\Exception\InvalidArgumentException;
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator; use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
@@ -193,42 +194,26 @@ class ExportController extends Controller
$token = $this->getTokenManipulator()->createEmailExportToken(serialize($list)); $token = $this->getTokenManipulator()->createEmailExportToken(serialize($list));
if (count($destMails) > 0) { if (count($destMails) > 0) {
//zip documents $emitterId = $this->getAuthenticatedUser()->getId();
\set_export::build_zip(
$this->app,
$token,
$list,
$this->app['tmp.download.path'].'/'. $token->getValue() . '.zip'
);
$remaingEmails = $destMails; $tokenValue = $token->getValue();
$url = $this->app->url('prepare_download', ['token' => $token->getValue(), 'anonymous' => false, 'type' => \Session_Logger::EVENT_EXPORTMAIL]); $url = $this->app->url('prepare_download', ['token' => $token->getValue(), 'anonymous' => false, 'type' => \Session_Logger::EVENT_EXPORTMAIL]);
$user = $this->getAuthenticatedUser(); $params = [
$emitter = new Emitter($user->getDisplayName(), $user->getEmail()); '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) { $this->dispatch(PhraseaEvents::EXPORT_MAIL_CREATE, new ExportMailEvent(
try { $emitterId,
$receiver = new Receiver(null, trim($mail)); $tokenValue,
} catch (InvalidArgumentException $e) { $destMails,
continue; $params
} ));
$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));
}
}
} }
return $this->app->json([ return $this->app->json([

View File

@@ -14,6 +14,8 @@ use Alchemy\Phrasea\Application\Helper\EntityManagerAware;
use Alchemy\Phrasea\Application\Helper\SearchEngineAware; use Alchemy\Phrasea\Application\Helper\SearchEngineAware;
use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Controller\Controller;
use Alchemy\Phrasea\Controller\RecordsRequest; 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\Event\RecordEdit;
use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Core\PhraseaEvents;
use Alchemy\Phrasea\Model\Entities\BasketElement; use Alchemy\Phrasea\Model\Entities\BasketElement;
@@ -234,7 +236,7 @@ class RecordController extends Controller
if($trashCollectionsBySbasId[$sbasId] !== null) { if($trashCollectionsBySbasId[$sbasId] !== null) {
if($record->getCollection()->get_coll_id() == $trashCollectionsBySbasId[$sbasId]->get_coll_id()) { if($record->getCollection()->get_coll_id() == $trashCollectionsBySbasId[$sbasId]->get_coll_id()) {
// record is already in trash so delete it // record is already in trash so delete it
$record->delete(); $this->getEventDispatcher()->dispatch(RecordEvents::DELETE, new DeleteEvent($record));
} else { } else {
// move to trash collection // move to trash collection
$record->move_to_collection($trashCollectionsBySbasId[$sbasId], $this->getApplicationBox()); $record->move_to_collection($trashCollectionsBySbasId[$sbasId], $this->getApplicationBox());
@@ -247,7 +249,7 @@ class RecordController extends Controller
} }
} else { } else {
// no trash collection, delete // no trash collection, delete
$record->delete(); $this->getEventDispatcher()->dispatch(RecordEvents::DELETE, new DeleteEvent($record));
} }
} catch (\Exception $e) { } catch (\Exception $e) {
} }

View File

@@ -14,6 +14,8 @@ use Alchemy\Phrasea\Application\Helper\EntityManagerAware;
use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Controller\Controller;
use Alchemy\Phrasea\Controller\RecordsRequest; use Alchemy\Phrasea\Controller\RecordsRequest;
use Alchemy\Phrasea\Controller\Exception as ControllerException; use Alchemy\Phrasea\Controller\Exception as ControllerException;
use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent;
use Alchemy\Phrasea\Core\Event\RecordEdit; use Alchemy\Phrasea\Core\Event\RecordEdit;
use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Core\PhraseaEvents;
use Alchemy\Phrasea\Model\Entities\StoryWZ; use Alchemy\Phrasea\Model\Entities\StoryWZ;
@@ -68,7 +70,9 @@ class StoryController extends Controller
break; break;
} }
$story->set_metadatas($metadatas)->rebuild_subdefs(); $recordAdapter = $story->set_metadatas($metadatas);
// tell phraseanet to rebuild subdef
$this->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($recordAdapter));
$storyWZ = new StoryWZ(); $storyWZ = new StoryWZ();
$storyWZ->setUser($this->getAuthenticatedUser()); $storyWZ->setUser($this->getAuthenticatedUser());

View File

@@ -16,6 +16,7 @@ use Alchemy\Phrasea\Application\Helper\SubDefinitionSubstituerAware;
use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Controller\Controller;
use Alchemy\Phrasea\Controller\RecordsRequest; use Alchemy\Phrasea\Controller\RecordsRequest;
use Alchemy\Phrasea\Core\Event\Record\RecordEvents; use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent;
use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Exception\RuntimeException;
use Alchemy\Phrasea\Metadata\PhraseanetMetadataReader; use Alchemy\Phrasea\Metadata\PhraseanetMetadataReader;
use Alchemy\Phrasea\Metadata\PhraseanetMetadataSetter; use Alchemy\Phrasea\Metadata\PhraseanetMetadataSetter;
@@ -156,7 +157,7 @@ class ToolsController extends Controller
} }
if (!$substituted || $force) { if (!$substituted || $force) {
$record->rebuild_subdefs(); $this->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($record));
} }
} }

View File

@@ -518,7 +518,9 @@ class AccountController extends Controller
$this->getApiApplicationManipulator()->deleteApiApplications($applications); $this->getApiApplicationManipulator()->deleteApiApplications($applications);
// revoke access and delete phraseanet user account // get list of old granted base_id then revoke access and delete phraseanet user account
$oldGrantedBaseIds = array_keys($this->app->getAclForUser($user)->get_granted_base());
$list = array_keys($this->app['repo.collections-registry']->getBaseIdMap()); $list = array_keys($this->app['repo.collections-registry']->getBaseIdMap());
@@ -542,8 +544,9 @@ class AccountController extends Controller
$mail = null; $mail = null;
} }
$this->app['manipulator.user']->delete($user); $mail = MailSuccessAccountDelete::create($this->app, $receiver);
$this->app['manipulator.user']->delete($user, [$user->getId() => $oldGrantedBaseIds]);
if($mail) { if($mail) {
$this->deliver($mail); $this->deliver($mail);
} }

View File

@@ -0,0 +1,53 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2019 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Core\Event;
use Symfony\Component\EventDispatcher\Event as SfEvent;
class ExportMailEvent extends SfEvent
{
private $emitterUserId;
private $tokenValue;
/** @var array */
private $destinationMails;
/** @var array */
private $params;
public function __construct($emitterUserId, $tokenValue, array $destMails, array $params)
{
$this->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;
}
}

View File

@@ -0,0 +1,7 @@
<?php
namespace Alchemy\Phrasea\Core\Event\Record;
class DeleteEvent extends RecordEvent
{
}

View File

@@ -15,6 +15,8 @@ final class RecordEvents
{ {
const CREATED = 'record.created'; const CREATED = 'record.created';
const DELETED = 'record.deleted'; const DELETED = 'record.deleted';
const DELETE = 'record.delete';
// Change // Change
const COLLECTION_CHANGED = 'record.collection_changed'; const COLLECTION_CHANGED = 'record.collection_changed';
const METADATA_CHANGED = 'record.metadata_changed'; const METADATA_CHANGED = 'record.metadata_changed';
@@ -29,6 +31,8 @@ final class RecordEvents
const SUB_DEFINITIONS_CREATED = 'record.sub_definitions_created'; const SUB_DEFINITIONS_CREATED = 'record.sub_definitions_created';
const SUB_DEFINITION_CREATION_FAILED = 'record.sub_definition_creation_failed'; const SUB_DEFINITION_CREATION_FAILED = 'record.sub_definition_creation_failed';
const SUBDEFINITION_CREATE = 'record.subdefinition_create';
const MEDIA_SUBSTITUTED = 'record.media_substituted'; const MEDIA_SUBSTITUTED = 'record.media_substituted';
const STORY_COVER_CHANGED = 'record.story_cover_changed'; const STORY_COVER_CHANGED = 'record.story_cover_changed';

View File

@@ -0,0 +1,34 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2014 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Core\Event\Record;
use Alchemy\Phrasea\Model\RecordInterface;
class SubdefinitionCreateEvent extends RecordEvent
{
private $isNewRecord;
public function __construct(RecordInterface $record, $isNewRecord = false)
{
parent::__construct($record);
$this->isNewRecord = $isNewRecord;
}
/**
* @return bool
*/
public function isNewRecord()
{
return $this->isNewRecord;
}
}

View File

@@ -12,7 +12,15 @@
namespace Alchemy\Phrasea\Core\Event\Subscriber; namespace Alchemy\Phrasea\Core\Event\Subscriber;
use Alchemy\Phrasea\Core\Event\ExportFailureEvent; use Alchemy\Phrasea\Core\Event\ExportFailureEvent;
use Alchemy\Phrasea\Core\Event\ExportMailEvent;
use Alchemy\Phrasea\Core\PhraseaEvents; 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 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); $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() public static function getSubscribedEvents()
{ {
return [ return [
PhraseaEvents::EXPORT_MAIL_FAILURE => 'onMailExportFailure' PhraseaEvents::EXPORT_MAIL_FAILURE => 'onMailExportFailure',
PhraseaEvents::EXPORT_MAIL_CREATE => 'onCreateExportMail',
]; ];
} }
} }

View File

@@ -33,7 +33,8 @@ class FeedEntrySubscriber extends AbstractNotificationSubscriber
$this->app['manipulator.webhook-event']->create( $this->app['manipulator.webhook-event']->create(
WebhookEvent::NEW_FEED_ENTRY, WebhookEvent::NEW_FEED_ENTRY,
WebhookEvent::FEED_ENTRY_TYPE, WebhookEvent::FEED_ENTRY_TYPE,
array_merge(array('feed_id' => $entry->getFeed()->getId()), $params) array_merge(array('feed_id' => $entry->getFeed()->getId()), $params),
$entry->getFeed()->getBaseId() ? [$entry->getFeed()->getBaseId()] : []
); );
$datas = json_encode($params); $datas = json_encode($params);

View File

@@ -41,13 +41,13 @@ class OrderSubscriber extends AbstractNotificationSubscriber
public function onCreate(OrderEvent $event) public function onCreate(OrderEvent $event)
{ {
$base_ids = array_unique(array_map(function (OrderElement $element) { $baseIds = array_unique(array_map(function (OrderElement $element) {
return $element->getBaseId(); return $element->getBaseId();
}, iterator_to_array($event->getOrder()->getElements()))); }, iterator_to_array($event->getOrder()->getElements())));
$query = $this->app['phraseanet.user-query']; $query = $this->app['phraseanet.user-query'];
/** @var User[] $users */ /** @var User[] $users */
$users = $query->on_base_ids($base_ids) $users = $query->on_base_ids($baseIds)
->who_have_right([\ACL::ORDER_MASTER]) ->who_have_right([\ACL::ORDER_MASTER])
->execute()->get_results(); ->execute()->get_results();
@@ -60,10 +60,12 @@ class OrderSubscriber extends AbstractNotificationSubscriber
'order_id' => $event->getOrder()->getId(), 'order_id' => $event->getOrder()->getId(),
]); ]);
$notifier = $this->notifierRegistry->getNotifier($event->getOrder()->getNotificationMethod()); // notify by webhook
$notifier = $this->notifierRegistry->getNotifier(Order::NOTIFY_WEBHOOK);
$notifier->notifyCreation($event->getOrder(), $event->getOrder()->getUser()); $notifier->notifyCreation($event->getOrder(), $event->getOrder()->getUser(), $baseIds);
// notify by mail
$notifier = $this->notifierRegistry->getNotifier(Order::NOTIFY_MAIL); $notifier = $this->notifierRegistry->getNotifier(Order::NOTIFY_MAIL);
foreach ($users as $user) { foreach ($users as $user) {
@@ -85,7 +87,13 @@ class OrderSubscriber extends AbstractNotificationSubscriber
public function onDeliver(OrderDeliveryEvent $event) public function onDeliver(OrderDeliveryEvent $event)
{ {
// notify by webhook
$notifier = $this->notifierRegistry->getNotifier(Order::NOTIFY_WEBHOOK);
$notifier->notifyDelivery($event->getDelivery(), $event->getDelivery()->getPartialOrder()->getBaseIds());
$notified = false; $notified = false;
// actually NotificationMethod is always by mail
$notifier = $this->notifierRegistry->getNotifier($event->getOrder()->getNotificationMethod()); $notifier = $this->notifierRegistry->getNotifier($event->getOrder()->getNotificationMethod());
$notificationData = json_encode([ $notificationData = json_encode([
'from' => $event->getDelivery()->getAdmin()->getId(), 'from' => $event->getDelivery()->getAdmin()->getId(),
@@ -109,7 +117,13 @@ class OrderSubscriber extends AbstractNotificationSubscriber
public function onDeny(OrderDeliveryEvent $event) public function onDeny(OrderDeliveryEvent $event)
{ {
// notify by webhook
$notifier = $this->notifierRegistry->getNotifier(Order::NOTIFY_WEBHOOK);
$notifier->notifyDenial($event->getDelivery(), $event->getDelivery()->getPartialOrder()->getBaseIds());
$notified = false; $notified = false;
// actually NotificationMethod is always by mail
$notifier = $this->notifierRegistry->getNotifier($event->getOrder()->getNotificationMethod()); $notifier = $this->notifierRegistry->getNotifier($event->getOrder()->getNotificationMethod());
$notificationData = json_encode([ $notificationData = json_encode([
'from' => $event->getDelivery()->getAdmin()->getId(), 'from' => $event->getDelivery()->getAdmin()->getId(),

View File

@@ -11,8 +11,10 @@
namespace Alchemy\Phrasea\Core\Event\Subscriber; namespace Alchemy\Phrasea\Core\Event\Subscriber;
use Alchemy\Phrasea\Core\Event\Record\CollectionChangedEvent; 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\RecordEvent;
use Alchemy\Phrasea\Core\Event\Record\RecordEvents; use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent;
use Alchemy\Phrasea\Core\Event\RecordEdit; use Alchemy\Phrasea\Core\Event\RecordEdit;
use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Core\PhraseaEvents;
use Alchemy\Phrasea\Metadata\Tag\TfEditdate; use Alchemy\Phrasea\Metadata\Tag\TfEditdate;
@@ -30,6 +32,8 @@ class RecordEditSubscriber implements EventSubscriberInterface
PhraseaEvents::RECORD_UPLOAD => 'onEdit', PhraseaEvents::RECORD_UPLOAD => 'onEdit',
RecordEvents::ROTATE => 'onRecordChange', RecordEvents::ROTATE => 'onRecordChange',
RecordEvents::COLLECTION_CHANGED => 'onCollectionChanged', RecordEvents::COLLECTION_CHANGED => 'onCollectionChanged',
RecordEvents::SUBDEFINITION_CREATE => 'onSubdefinitionCreate',
RecordEvents::DELETE => 'onDelete',
); );
} }
@@ -49,6 +53,18 @@ class RecordEditSubscriber implements EventSubscriberInterface
$recordAdapter->clearStampCache(); $recordAdapter->clearStampCache();
} }
public function onSubdefinitionCreate(SubdefinitionCreateEvent $event)
{
$recordAdapter = $this->convertToRecordAdapter($event->getRecord());
$recordAdapter->rebuild_subdefs();
}
public function onDelete(DeleteEvent $event)
{
$recordAdapter = $this->convertToRecordAdapter($event->getRecord());
$recordAdapter->delete();
}
public function onEdit(RecordEdit $event) public function onEdit(RecordEdit $event)
{ {
static $into = false; static $into = false;

View File

@@ -0,0 +1,75 @@
<?php
namespace Alchemy\Phrasea\Core\Event\Subscriber;
use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
use Alchemy\Phrasea\Core\Event\Record\SubDefinitionCreatedEvent;
use Alchemy\Phrasea\Core\Event\Record\SubDefinitionCreationFailedEvent;
use Alchemy\Phrasea\Core\Event\Record\SubDefinitionsCreatedEvent;
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
use Silex\Application;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class WebhookSubdefEventSubscriber implements EventSubscriberInterface
{
private $app;
public function __construct(Application $app)
{
$this->app = $app;
}
public function onSubdefCreated(SubDefinitionCreatedEvent $event)
{
$eventData = [
'databox_id' => $event->getRecord()->getDataboxId(),
'record_id' => $event->getRecord()->getRecordId(),
'subdef' => $event->getSubDefinitionName()
];
$this->app['manipulator.webhook-event']->create(
WebhookEvent::RECORD_SUBDEF_CREATED,
WebhookEvent::RECORD_SUBDEF_TYPE,
$eventData
);
}
public function onSubdefCreationFailed(SubDefinitionCreationFailedEvent $event)
{
$eventData = [
'databox_id' => $event->getRecord()->getDataboxId(),
'record_id' => $event->getRecord()->getRecordId(),
'subdef' => $event->getSubDefinitionName()
];
$this->app['manipulator.webhook-event']->create(
WebhookEvent::RECORD_SUBDEF_FAILED,
WebhookEvent::RECORD_SUBDEF_TYPE,
$eventData
);
}
public function onSubdefsCreated(SubDefinitionsCreatedEvent $event)
{
$eventData = [
'databox_id' => $event->getRecord()->getDataboxId(),
'record_id' => $event->getRecord()->getRecordId(),
'subdef_count' => count($event->getMedia())
];
$this->app['manipulator.webhook-event']->create(
WebhookEvent::RECORD_SUBDEFS_CREATED,
WebhookEvent::RECORD_SUBDEF_TYPE,
$eventData
);
}
public static function getSubscribedEvents()
{
return [
RecordEvents::SUB_DEFINITION_CREATED => 'onSubdefCreated',
RecordEvents::SUB_DEFINITIONS_CREATED => 'onSubdefsCreated',
RecordEvents::SUB_DEFINITION_CREATION_FAILED => 'onSubdefCreationFailed'
];
}
}

View File

@@ -45,7 +45,7 @@ class WebhookUserEventSubscriber implements EventSubscriberInterface
'user_id' => $event->getUserId(), 'user_id' => $event->getUserId(),
'email' => $event->getEmailAddress(), 'email' => $event->getEmailAddress(),
'login' => $event->getLogin() 'login' => $event->getLogin()
]); ], $event->getGrantedBaseIds());
} }
public static function getSubscribedEvents() public static function getSubscribedEvents()

View File

@@ -36,4 +36,12 @@ class DeletedEvent extends UserEvent
{ {
return $this->args['email']; return $this->args['email'];
} }
/**
* @return array
*/
public function getGrantedBaseIds()
{
return $this->args['grantedBaseIds'];
}
} }

View File

@@ -49,6 +49,7 @@ final class PhraseaEvents
const EXPORT_MAIL_FAILURE = 'export.mail-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_EDIT = 'record.edit';
const RECORD_UPLOAD = 'record.upload'; const RECORD_UPLOAD = 'record.upload';

View File

@@ -2,6 +2,7 @@
namespace Alchemy\Phrasea\Core\Provider; namespace Alchemy\Phrasea\Core\Provider;
use Alchemy\Phrasea\Core\Event\Subscriber\WebhookSubdefEventSubscriber;
use Alchemy\Phrasea\Webhook\EventProcessorFactory; use Alchemy\Phrasea\Webhook\EventProcessorFactory;
use Alchemy\Phrasea\Webhook\EventProcessorWorker; use Alchemy\Phrasea\Webhook\EventProcessorWorker;
use Alchemy\Phrasea\Webhook\WebhookInvoker; use Alchemy\Phrasea\Webhook\WebhookInvoker;
@@ -10,6 +11,7 @@ use Alchemy\Worker\CallableWorkerFactory;
use Alchemy\Worker\TypeBasedWorkerResolver; use Alchemy\Worker\TypeBasedWorkerResolver;
use Silex\Application; use Silex\Application;
use Silex\ServiceProviderInterface; use Silex\ServiceProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
class WebhookServiceProvider implements ServiceProviderInterface class WebhookServiceProvider implements ServiceProviderInterface
{ {
@@ -58,6 +60,14 @@ class WebhookServiceProvider implements ServiceProviderInterface
return $resolver; return $resolver;
} }
); );
$app['dispatcher'] = $app->share(
$app->extend('dispatcher', function (EventDispatcher $dispatcher, Application $app) {
$dispatcher->addSubscriber(new WebhookSubdefEventSubscriber($app));
return $dispatcher;
})
);
} }
private function createAlias(Application $app, $alias, $targetServiceKey) private function createAlias(Application $app, $alias, $targetServiceKey)
@@ -69,6 +79,6 @@ class WebhookServiceProvider implements ServiceProviderInterface
public function boot(Application $app) public function boot(Application $app)
{ {
// no-op
} }
} }

View File

@@ -36,6 +36,7 @@ class WorkerConfigurationServiceProvider implements ServiceProviderInterface
'host' => 'localhost', 'host' => 'localhost',
'port' => 5672, 'port' => 5672,
'user' => 'guest', 'user' => 'guest',
'password' => 'guest',
'vhost' => '/' 'vhost' => '/'
] ]
]; ];
@@ -46,8 +47,10 @@ class WorkerConfigurationServiceProvider implements ServiceProviderInterface
$queueConfigurations = $configuration->get(['workers', 'queue'], $defaultConfiguration); $queueConfigurations = $configuration->get(['workers', 'queue'], $defaultConfiguration);
$queueConfiguration = reset($queueConfigurations); $config = [];
$queueKey = key($queueConfigurations);
foreach($queueConfigurations as $name => $queueConfiguration) {
$queueKey = $name;
if (! isset($queueConfiguration['name'])) { if (! isset($queueConfiguration['name'])) {
if (! is_string($queueKey)) { if (! is_string($queueKey)) {
@@ -57,7 +60,8 @@ class WorkerConfigurationServiceProvider implements ServiceProviderInterface
$queueConfiguration['name'] = $queueKey; $queueConfiguration['name'] = $queueKey;
} }
$config = [ $queueConfiguration['name'] => $queueConfiguration ]; $config[$queueConfiguration['name']] = $queueConfiguration ;
}
return $config; return $config;
} }

View File

@@ -73,10 +73,12 @@ class Edit extends \Alchemy\Phrasea\Helper\Helper
{ {
$list = array_keys($this->app->getAclForUser($this->app->getAuthenticatedUser())->get_granted_base([\ACL::CANADMIN])); $list = array_keys($this->app->getAclForUser($this->app->getAuthenticatedUser())->get_granted_base([\ACL::CANADMIN]));
$oldGrantedBaseIds = array_keys($this->app->getAclForUser($user)->get_granted_base());
$this->app->getAclForUser($user)->revoke_access_from_bases($list); $this->app->getAclForUser($user)->revoke_access_from_bases($list);
if ($this->app->getAclForUser($user)->is_phantom()) { if ($this->app->getAclForUser($user)->is_phantom()) {
$this->app['manipulator.user']->delete($user); $this->app['manipulator.user']->delete($user, [$user->getId() => $oldGrantedBaseIds]);
} }
return $this; return $this;
@@ -583,8 +585,8 @@ class Edit extends \Alchemy\Phrasea\Helper\Helper
$user = $this->app['repo.users']->find($usr_id); $user = $this->app['repo.users']->find($usr_id);
$this->app->getAclForUser($user)->revoke_access_from_bases($delete) $this->app->getAclForUser($user)->revoke_access_from_bases($delete)
->give_access_to_base($create) ->give_access_to_sbas($create_sbas) // give access to sbas before bas
->give_access_to_sbas($create_sbas); ->give_access_to_base($create);
foreach ($update as $base_id => $rights) { foreach ($update as $base_id => $rights) {
$this->app->getAclForUser($user) $this->app->getAclForUser($user)

View File

@@ -18,6 +18,7 @@ use Alchemy\Phrasea\Core\Event\Record\SubDefinitionCreationEvent;
use Alchemy\Phrasea\Core\Event\Record\SubDefinitionsCreationEvent; use Alchemy\Phrasea\Core\Event\Record\SubDefinitionsCreationEvent;
use Alchemy\Phrasea\Core\Event\Record\SubDefinitionCreationFailedEvent; use Alchemy\Phrasea\Core\Event\Record\SubDefinitionCreationFailedEvent;
use Alchemy\Phrasea\Core\Event\Record\RecordEvents; use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
use Alchemy\Phrasea\Databox\Subdef\MediaSubdefRepository;
use Alchemy\Phrasea\Filesystem\FilesystemService; use Alchemy\Phrasea\Filesystem\FilesystemService;
use Alchemy\Phrasea\Media\Subdef\Specification\PdfSpecification; use Alchemy\Phrasea\Media\Subdef\Specification\PdfSpecification;
use MediaAlchemyst\Alchemyst; use MediaAlchemyst\Alchemyst;
@@ -170,6 +171,27 @@ class SubdefGenerator
unset($this->tmpFilePath); unset($this->tmpFilePath);
} }
// 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( $this->dispatch(
RecordEvents::SUB_DEFINITIONS_CREATED, RecordEvents::SUB_DEFINITIONS_CREATED,
new SubDefinitionsCreatedEvent( new SubDefinitionsCreatedEvent(
@@ -178,6 +200,25 @@ 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) private function generateSubdef(\record_adapter $record, \databox_subdef $subdef_class, $pathdest)
{ {
@@ -276,4 +317,14 @@ class SubdefGenerator
$i = floor(log($bytes, 1024)); $i = floor(log($bytes, 1024));
return round($bytes / pow(1024, $i), [0,0,2,2,3][$i]).['B','kB','MB','GB'][$i]; 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);
}
} }

View File

@@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\Media;
use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Core\Event\Record\MediaSubstitutedEvent; use Alchemy\Phrasea\Core\Event\Record\MediaSubstitutedEvent;
use Alchemy\Phrasea\Core\Event\Record\RecordEvents; use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent;
use Alchemy\Phrasea\Filesystem\FilesystemService; use Alchemy\Phrasea\Filesystem\FilesystemService;
use MediaAlchemyst\Alchemyst; use MediaAlchemyst\Alchemyst;
use MediaAlchemyst\Exception\ExceptionInterface as MediaAlchemystException; use MediaAlchemyst\Exception\ExceptionInterface as MediaAlchemystException;
@@ -79,7 +80,7 @@ class SubdefSubstituer
$record->write_metas(); $record->write_metas();
if ($shouldSubdefsBeRebuilt) { if ($shouldSubdefsBeRebuilt) {
$record->rebuild_subdefs(); $this->dispatcher->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($record));
} }
$this->dispatcher->dispatch(RecordEvents::MEDIA_SUBSTITUTED, new MediaSubstitutedEvent($record)); $this->dispatcher->dispatch(RecordEvents::MEDIA_SUBSTITUTED, new MediaSubstitutedEvent($record));

View File

@@ -68,6 +68,14 @@ class WebhookEvent
*/ */
private $created; private $created;
/**
* List of collection base_id concerned
* @var array
*
* @ORM\Column(name="collection_base_ids", type="json_array", nullable=true)
*/
private $collectionBaseIds;
/** /**
* @param \DateTime $created * @param \DateTime $created
* *
@@ -175,4 +183,24 @@ class WebhookEvent
return $this; return $this;
} }
/**
* @param array $collectionBaseIds
*
* @return $this
*/
public function setCollectionBaseIds(array $collectionBaseIds)
{
$this->collectionBaseIds = $collectionBaseIds;
return $this;
}
/**
* @return array
*/
public function getCollectionBaseIds()
{
return $this->collectionBaseIds;
}
} }

View File

@@ -126,8 +126,9 @@ class UserManipulator implements ManipulatorInterface
* Deletes a user. * Deletes a user.
* *
* @param User|User[] $users * @param User|User[] $users
* @param array $grantedBaseIdList List of the old granted base_id per userId [user_id => [base_id, ...] ]
*/ */
public function delete($users) public function delete($users, array $grantedBaseIdList = array())
{ {
/** @var User $user */ /** @var User $user */
foreach ($this->makeTraversable($users) as $user) { foreach ($this->makeTraversable($users) as $user) {
@@ -148,7 +149,8 @@ class UserManipulator implements ManipulatorInterface
array( array(
'user_id' => $old_id, 'user_id' => $old_id,
'login' => $old_login, 'login' => $old_login,
'email'=>$old_email 'email' => $old_email,
'grantedBaseIds' => isset($grantedBaseIdList[$old_id]) ? $grantedBaseIdList[$old_id] : []
) )
) )
); );

View File

@@ -12,7 +12,7 @@
namespace Alchemy\Phrasea\Model\Manipulator; namespace Alchemy\Phrasea\Model\Manipulator;
use Alchemy\Phrasea\Model\Entities\WebhookEvent; use Alchemy\Phrasea\Model\Entities\WebhookEvent;
use Alchemy\Phrasea\Webhook\WebhookPublisher; use Alchemy\Phrasea\Webhook\WebhookPublisherInterface;
use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityRepository;
@@ -29,18 +29,18 @@ class WebhookEventManipulator implements ManipulatorInterface
private $repository; private $repository;
/** /**
* @var WebhookPublisher * @var WebhookPublisherInterface
*/ */
private $publisher; private $publisher;
public function __construct(ObjectManager $om, EntityRepository $repo, WebhookPublisher $publisher) public function __construct(ObjectManager $om, EntityRepository $repo, WebhookPublisherInterface $publisher)
{ {
$this->om = $om; $this->om = $om;
$this->repository = $repo; $this->repository = $repo;
$this->publisher = $publisher; $this->publisher = $publisher;
} }
public function create($eventName, $type, array $data) public function create($eventName, $type, array $data, array $collectionBaseIds = array())
{ {
$event = new WebhookEvent(); $event = new WebhookEvent();
@@ -48,6 +48,10 @@ class WebhookEventManipulator implements ManipulatorInterface
$event->setType($type); $event->setType($type);
$event->setData($data); $event->setData($data);
if (count($collectionBaseIds) > 0) {
$event->setCollectionBaseIds($collectionBaseIds);
}
$this->update($event); $this->update($event);
$this->publisher->publishWebhookEvent($event); $this->publisher->publishWebhookEvent($event);

View File

@@ -172,7 +172,7 @@ class BaseOrderController extends Controller
$manager->persist($element); $manager->persist($element);
} }
$delivery = new OrderDelivery($order, $acceptor, count($basketElements)); $delivery = new OrderDelivery($order, $acceptor, count($basketElements), $partialOrder);
$this->dispatch(PhraseaEvents::ORDER_DELIVER, new OrderDeliveryEvent($delivery)); $this->dispatch(PhraseaEvents::ORDER_DELIVER, new OrderDeliveryEvent($delivery));
} }
@@ -198,11 +198,13 @@ class BaseOrderController extends Controller
$elements = $this->findRequestedElements($order_id, $elementIds, $acceptor); $elements = $this->findRequestedElements($order_id, $elementIds, $acceptor);
$order = $this->findOr404($order_id); $order = $this->findOr404($order_id);
$partialOrder = new PartialOrder($order, $elements);
$this->getOrderValidator()->deny($acceptor, new PartialOrder($order, $elements)); $this->getOrderValidator()->deny($acceptor, new PartialOrder($order, $elements));
try { try {
if (!empty($elements)) { if (!empty($elements)) {
$delivery = new OrderDelivery($order, $acceptor, count($elements)); $delivery = new OrderDelivery($order, $acceptor, count($elements), $partialOrder);
$this->dispatch(PhraseaEvents::ORDER_DENY, new OrderDeliveryEvent($delivery)); $this->dispatch(PhraseaEvents::ORDER_DENY, new OrderDeliveryEvent($delivery));
} }

View File

@@ -31,16 +31,23 @@ class OrderDelivery
*/ */
private $quantity; private $quantity;
/**
* @var PartialOrder
*/
private $partialOrder;
/** /**
* @param Order $deliveredOrder * @param Order $deliveredOrder
* @param User $manager * @param User $manager
* @param int $quantity * @param int $quantity
* @param PartialOrder $partialOrder
*/ */
public function __construct(Order $deliveredOrder, User $manager, $quantity) public function __construct(Order $deliveredOrder, User $manager, $quantity, PartialOrder $partialOrder)
{ {
$this->order = $deliveredOrder; $this->order = $deliveredOrder;
$this->admin = $manager; $this->admin = $manager;
$this->quantity = $quantity; $this->quantity = $quantity;
$this->partialOrder = $partialOrder;
} }
/** /**
@@ -66,4 +73,12 @@ class OrderDelivery
{ {
return $this->quantity; return $this->quantity;
} }
/**
* @return PartialOrder
*/
public function getPartialOrder()
{
return $this->partialOrder;
}
} }

View File

@@ -19,20 +19,23 @@ interface ValidationNotifier
/** /**
* @param Order $order * @param Order $order
* @param User $recipient * @param User $recipient
* @param array $baseIds
* @return void * @return void
*/ */
public function notifyCreation(Order $order, User $recipient); public function notifyCreation(Order $order, User $recipient, array $baseIds = array());
/** /**
* @param OrderDelivery $delivery * @param OrderDelivery $delivery
* @param array $baseIds
* @return void * @return void
*/ */
public function notifyDelivery(OrderDelivery $delivery); public function notifyDelivery(OrderDelivery $delivery, array $baseIds = array());
/** /**
* @param OrderDelivery $delivery * @param OrderDelivery $delivery
* @param array $baseIds
* @return void * @return void
*/ */
public function notifyDenial(OrderDelivery $delivery); public function notifyDenial(OrderDelivery $delivery, array $baseIds = array());
} }

View File

@@ -26,8 +26,9 @@ class CompositeNotifier implements ValidationNotifier
/** /**
* @param Order $order * @param Order $order
* @param User $recipient * @param User $recipient
* @param array $baseIds
*/ */
public function notifyCreation(Order $order, User $recipient) public function notifyCreation(Order $order, User $recipient, array $baseIds = array())
{ {
foreach ($this->notifiers as $notifier) { foreach ($this->notifiers as $notifier) {
$notifier->notifyCreation($order, $recipient); $notifier->notifyCreation($order, $recipient);
@@ -36,21 +37,23 @@ class CompositeNotifier implements ValidationNotifier
/** /**
* @param OrderDelivery $delivery * @param OrderDelivery $delivery
* @param array $baseIds
*/ */
public function notifyDelivery(OrderDelivery $delivery) public function notifyDelivery(OrderDelivery $delivery, array $baseIds = array())
{ {
foreach ($this->notifiers as $notifier) { foreach ($this->notifiers as $notifier) {
$notifier->notifyDelivery($delivery); $notifier->notifyDelivery($delivery, $baseIds);
} }
} }
/** /**
* @param OrderDelivery $delivery * @param OrderDelivery $delivery
* @param array $baseIds
*/ */
public function notifyDenial(OrderDelivery $delivery) public function notifyDenial(OrderDelivery $delivery, array $baseIds = array())
{ {
foreach ($this->notifiers as $notifier) { foreach ($this->notifiers as $notifier) {
$notifier->notifyDenial($delivery); $notifier->notifyDenial($delivery, $baseIds);
} }
} }
} }

View File

@@ -46,8 +46,9 @@ class MailNotifier implements ValidationNotifier
/** /**
* @param Order $order * @param Order $order
* @param User $recipient * @param User $recipient
* @param array $baseIds
*/ */
public function notifyCreation(Order $order, User $recipient) public function notifyCreation(Order $order, User $recipient, array $baseIds = array())
{ {
$mail = MailInfoNewOrder::create($this->application, Receiver::fromUser($recipient)); $mail = MailInfoNewOrder::create($this->application, Receiver::fromUser($recipient));
@@ -58,8 +59,9 @@ class MailNotifier implements ValidationNotifier
/** /**
* @param OrderDelivery $delivery * @param OrderDelivery $delivery
* @param array $baseIds
*/ */
public function notifyDelivery(OrderDelivery $delivery) public function notifyDelivery(OrderDelivery $delivery, array $baseIds = array())
{ {
$order = $delivery->getOrder(); $order = $delivery->getOrder();
@@ -85,8 +87,9 @@ class MailNotifier implements ValidationNotifier
/** /**
* @param OrderDelivery $delivery * @param OrderDelivery $delivery
* @param array $baseIds
*/ */
public function notifyDenial(OrderDelivery $delivery) public function notifyDenial(OrderDelivery $delivery, array $baseIds = array())
{ {
$sender = Emitter::fromUser($delivery->getAdmin()); $sender = Emitter::fromUser($delivery->getAdmin());
$recipient = Receiver::fromUser($delivery->getOrder()->getUser()); $recipient = Receiver::fromUser($delivery->getOrder()->getUser());

View File

@@ -47,21 +47,23 @@ class WebhookNotifier implements ValidationNotifier
/** /**
* @param Order $order * @param Order $order
* @param User $recipient * @param User $recipient
* @param array $baseIds
*/ */
public function notifyCreation(Order $order, User $recipient) public function notifyCreation(Order $order, User $recipient, array $baseIds = array())
{ {
$eventData = [ $eventData = [
'order_id' => $order->getId(), 'order_id' => $order->getId(),
'user_id' => $recipient->getId(), 'user_id' => $recipient->getId(),
]; ];
$this->getManipulator()->create(WebhookEvent::ORDER_CREATED, WebhookEvent::ORDER_TYPE, $eventData); $this->getManipulator()->create(WebhookEvent::ORDER_CREATED, WebhookEvent::ORDER_TYPE, $eventData, $baseIds);
} }
/** /**
* @param OrderDelivery $delivery * @param OrderDelivery $delivery
* @param array $baseIds
*/ */
public function notifyDelivery(OrderDelivery $delivery) public function notifyDelivery(OrderDelivery $delivery, array $baseIds = array())
{ {
$eventData = [ $eventData = [
'order_id' => $delivery->getOrder()->getId(), 'order_id' => $delivery->getOrder()->getId(),
@@ -69,13 +71,14 @@ class WebhookNotifier implements ValidationNotifier
'quantity' => $delivery->getQuantity() 'quantity' => $delivery->getQuantity()
]; ];
$this->getManipulator()->create(WebhookEvent::ORDER_DELIVERED, WebhookEvent::ORDER_TYPE, $eventData); $this->getManipulator()->create(WebhookEvent::ORDER_DELIVERED, WebhookEvent::ORDER_TYPE, $eventData, $baseIds);
} }
/** /**
* @param OrderDelivery $delivery * @param OrderDelivery $delivery
* @param array $baseIds
*/ */
public function notifyDenial(OrderDelivery $delivery) public function notifyDenial(OrderDelivery $delivery, array $baseIds = array())
{ {
$eventData = [ $eventData = [
'order_id' => $delivery->getOrder()->getId(), 'order_id' => $delivery->getOrder()->getId(),
@@ -83,6 +86,6 @@ class WebhookNotifier implements ValidationNotifier
'quantity' => $delivery->getQuantity() 'quantity' => $delivery->getQuantity()
]; ];
$this->getManipulator()->create(WebhookEvent::ORDER_DENIED, WebhookEvent::ORDER_TYPE, $eventData); $this->getManipulator()->create(WebhookEvent::ORDER_DENIED, WebhookEvent::ORDER_TYPE, $eventData, $baseIds);
} }
} }

View File

@@ -12,6 +12,8 @@
namespace Alchemy\Phrasea\TaskManager\Job; namespace Alchemy\Phrasea\TaskManager\Job;
use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent;
use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Exception\RuntimeException;
use Alchemy\Phrasea\Border\File; use Alchemy\Phrasea\Border\File;
use Alchemy\Phrasea\Border\Manager as borderManager; use Alchemy\Phrasea\Border\Manager as borderManager;
@@ -1001,7 +1003,7 @@ class ArchiveJob extends AbstractJob
{ {
// quick fix to reconnect if mysql is lost // quick fix to reconnect if mysql is lost
$app->getApplicationBox()->get_connection(); $app->getApplicationBox()->get_connection();
$databox->get_connection(); $collection->get_connection();
$status = \databox_status::operation_or($stat0, $stat1); $status = \databox_status::operation_or($stat0, $stat1);
@@ -1032,7 +1034,8 @@ class ArchiveJob extends AbstractJob
} }
$story->setStatus(\databox_status::operation_or($stat0, $stat1)); $story->setStatus(\databox_status::operation_or($stat0, $stat1));
$story->rebuild_subdefs();
$app['dispatcher']->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($story));
unset($media); unset($media);

View File

@@ -12,6 +12,7 @@ use Alchemy\Phrasea\Webhook\Processor\ProcessorFactory;
use Alchemy\Phrasea\Webhook\Processor\ProcessorInterface; use Alchemy\Phrasea\Webhook\Processor\ProcessorInterface;
use Alchemy\Phrasea\Webhook\Processor\UserDeletedProcessorFactory; use Alchemy\Phrasea\Webhook\Processor\UserDeletedProcessorFactory;
use Alchemy\Phrasea\Webhook\Processor\UserRegistrationProcessorFactory; use Alchemy\Phrasea\Webhook\Processor\UserRegistrationProcessorFactory;
use Alchemy\Phrasea\Webhook\Processor\SubdefEventProcessor;
class EventProcessorFactory class EventProcessorFactory
{ {
@@ -29,7 +30,10 @@ class EventProcessorFactory
$this->registerFactory(WebhookEvent::FEED_ENTRY_TYPE, new FeedEntryProcessorFactory($app)); $this->registerFactory(WebhookEvent::FEED_ENTRY_TYPE, new FeedEntryProcessorFactory($app));
$this->registerFactory(WebhookEvent::USER_REGISTRATION_TYPE, new UserRegistrationProcessorFactory($app)); $this->registerFactory(WebhookEvent::USER_REGISTRATION_TYPE, new UserRegistrationProcessorFactory($app));
$this->registerFactory(WebhookEvent::ORDER_TYPE, new OrderNotificationProcessorFactory($app)); $this->registerFactory(WebhookEvent::ORDER_TYPE, new OrderNotificationProcessorFactory($app));
$this->registerFactory(WebhookEvent::USER_DELETED_TYPE, new UserDeletedProcessorFactory($app)); $this->registerFactory(WebhookEvent::USER_DELETED_TYPE, new UserDeletedProcessorFactory());
$this->registerCallableFactory(WebhookEvent::RECORD_SUBDEF_TYPE, function () {
return new SubdefEventProcessor();
});
} }
/** /**
@@ -43,7 +47,7 @@ class EventProcessorFactory
/** /**
* @param string $eventType * @param string $eventType
* @param callback|callable $callable * @param callback|callable|\Closure $callable
*/ */
public function registerCallableFactory($eventType, $callable) public function registerCallableFactory($eventType, $callable)
{ {

View File

@@ -34,17 +34,16 @@ class FeedEntryProcessor implements ProcessorInterface
{ {
$data = $event->getData(); $data = $event->getData();
if (!isset($data->entry_id)) { if (!isset($data['entry_id'])) {
return null; return null;
} }
$entry = $this->entryRepository->find($data->entry_id); $entry = $this->entryRepository->find($data['entry_id']);
if (null === $entry) { if (null === $entry) {
return null; return null;
} }
$data = $event->getData();
$feed = $entry->getFeed(); $feed = $entry->getFeed();
$query = $this->userQuery; $query = $this->userQuery;
@@ -54,8 +53,8 @@ class FeedEntryProcessor implements ProcessorInterface
->include_templates(false) ->include_templates(false)
->email_not_null(true); ->email_not_null(true);
if ($feed->getCollection($this->app)) { if ($feed->getCollection($this->application)) {
$query->on_base_ids([$feed->getCollection($this->app)->get_base_id()]); $query->on_base_ids([$feed->getCollection($this->application)->get_base_id()]);
} }
$start = 0; $start = 0;
@@ -76,7 +75,7 @@ class FeedEntryProcessor implements ProcessorInterface
return [ return [
'event' => $event->getName(), 'event' => $event->getName(),
'users_were_notified' => isset($data->notify_email) ?: (bool) $data->notify_email, 'users_were_notified' => isset($data['notify_email']) ? (bool) $data['notify_email'] : false,
'feed' => [ 'feed' => [
'id' => $feed->getId(), 'id' => $feed->getId(),
'title' => $feed->getTitle(), 'title' => $feed->getTitle(),

View File

@@ -0,0 +1,17 @@
<?php
namespace Alchemy\Phrasea\Webhook\Processor;
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
class SubdefEventProcessor implements ProcessorInterface
{
public function process(WebhookEvent $event)
{
return [
'event' => $event->getName(),
'data' => $event->getData()
];
}
}

View File

@@ -19,7 +19,7 @@ use Alchemy\Queue\MessageQueueRegistry;
* Class WebhookPublisher publishes webhook event notifications in message queues * Class WebhookPublisher publishes webhook event notifications in message queues
* @package Alchemy\Phrasea\Webhook * @package Alchemy\Phrasea\Webhook
*/ */
class WebhookPublisher class WebhookPublisher implements WebhookPublisherInterface
{ {
/** /**
* @var MessageQueueRegistry * @var MessageQueueRegistry

View File

@@ -0,0 +1,10 @@
<?php
namespace Alchemy\Phrasea\Webhook;
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
interface WebhookPublisherInterface
{
public function publishWebhookEvent(WebhookEvent $event);
}

View File

@@ -19,6 +19,7 @@ use Alchemy\Phrasea\Core\Event\Record\OriginalNameChangedEvent;
use Alchemy\Phrasea\Core\Event\Record\RecordEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvent;
use Alchemy\Phrasea\Core\Event\Record\RecordEvents; use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
use Alchemy\Phrasea\Core\Event\Record\StatusChangedEvent; use Alchemy\Phrasea\Core\Event\Record\StatusChangedEvent;
use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent;
use Alchemy\Phrasea\Core\PhraseaTokens; use Alchemy\Phrasea\Core\PhraseaTokens;
use Alchemy\Phrasea\Databox\Subdef\MediaSubdefRepository; use Alchemy\Phrasea\Databox\Subdef\MediaSubdefRepository;
use Alchemy\Phrasea\Filesystem\FilesystemService; 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()]); $this->getDataboxConnection()->executeUpdate($sql, ['type' => $type, 'record_id' => $this->getRecordId()]);
if ($old_type !== $type) { if ($old_type !== $type) {
$this->rebuild_subdefs(); $this->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($this));
} }
$this->type = $type; $this->type = $type;
@@ -341,7 +342,8 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
array(':mime' => $mime, ':record_id' => $this->getRecordId()) array(':mime' => $mime, ':record_id' => $this->getRecordId())
)) { )) {
$this->rebuild_subdefs(); $this->dispatch(RecordEvents::SUBDEFINITION_CREATE, new SubdefinitionCreateEvent($this));
$this->delete_data_from_cache(); $this->delete_data_from_cache();
} }
@@ -1735,7 +1737,9 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
throw new Exception('This record is not a grouping'); throw new Exception('This record is not a grouping');
} }
$selections = $this->getDatabox()->getRecordRepository()->findChildren([$this->getRecordId()], null, $offset, $max_items); $user = $this->getAuthenticatedUser();
$selections = $this->getDatabox()->getRecordRepository()->findChildren([$this->getRecordId()], $user, $offset, $max_items);
return reset($selections); return reset($selections);
} }
@@ -1745,7 +1749,9 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
*/ */
public function get_grouping_parents() public function get_grouping_parents()
{ {
$selections = $this->getDatabox()->getRecordRepository()->findParents([$this->getRecordId()]); $user = $this->getAuthenticatedUser();
$selections = $this->getDatabox()->getRecordRepository()->findParents([$this->getRecordId()], $user);
return reset($selections); return reset($selections);
} }
@@ -1948,4 +1954,15 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
{ {
return $this->app['provider.repo.media_subdef']->getRepositoryForDatabox($this->getDataboxId()); return $this->app['provider.repo.media_subdef']->getRepositoryForDatabox($this->getDataboxId());
} }
/**
* @return User|null
*/
protected function getAuthenticatedUser()
{
/** @var \Alchemy\Phrasea\Authentication\Authenticator $authenticator */
$authenticator = $this->app['authentication'];
return $authenticator->getUser();
}
} }

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version='1.0' encoding='utf-8'?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2"> <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2020-03-17T12:44:55Z" source-language="en" target-language="en" datatype="plaintext" original="not.available"> <file date="2020-03-17T12:44:55Z" source-language="en" target-language="en" datatype="plaintext" original="not.available">
<header> <header>
@@ -7,8 +7,8 @@
</header> </header>
<body> <body>
<trans-unit id="da39a3ee5e6b4b0d3255bfef95601890afd80709" resname=""> <trans-unit id="da39a3ee5e6b4b0d3255bfef95601890afd80709" resname="">
<source></source> <source/>
<target state="new"></target> <target state="new"/>
<jms:reference-file line="60">Form/Login/PhraseaAuthenticationForm.php</jms:reference-file> <jms:reference-file line="60">Form/Login/PhraseaAuthenticationForm.php</jms:reference-file>
<jms:reference-file line="47">Form/Configuration/EmailFormType.php</jms:reference-file> <jms:reference-file line="47">Form/Configuration/EmailFormType.php</jms:reference-file>
</trans-unit> </trans-unit>
@@ -13432,14 +13432,14 @@ It is possible to place several search areas</target>
<target state="translated">August</target> <target state="translated">August</target>
<jms:reference-file line="170">prod/WorkZone/Basket.html.twig</jms:reference-file> <jms:reference-file line="170">prod/WorkZone/Basket.html.twig</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="63c83f397c51202a27320349456ec75b844a75e6" resname="workzone:datepicker:closeText"> <trans-unit id="63c83f397c51202a27320349456ec75b844a75e6" resname="workzone:datepicker:closeText" approved="no">
<source>workzone:datepicker:closeText</source> <source>workzone:datepicker:closeText</source>
<target state="new">workzone:datepicker:closeText</target> <target state="needs-translation">Close</target>
<jms:reference-file line="165">prod/WorkZone/Basket.html.twig</jms:reference-file> <jms:reference-file line="165">prod/WorkZone/Basket.html.twig</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="32037015798672f75f469624c847da64e5953a27" resname="workzone:datepicker:currentText"> <trans-unit id="32037015798672f75f469624c847da64e5953a27" resname="workzone:datepicker:currentText" approved="no">
<source>workzone:datepicker:currentText</source> <source>workzone:datepicker:currentText</source>
<target state="new">workzone:datepicker:currentText</target> <target state="needs-translation">Current</target>
<jms:reference-file line="168">prod/WorkZone/Basket.html.twig</jms:reference-file> <jms:reference-file line="168">prod/WorkZone/Basket.html.twig</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="7e55bc758f272d38198385584d6f50c2dd0eae13" resname="workzone:datepicker:december" approved="yes"> <trans-unit id="7e55bc758f272d38198385584d6f50c2dd0eae13" resname="workzone:datepicker:december" approved="yes">
@@ -13543,9 +13543,9 @@ It is possible to place several search areas</target>
<jms:reference-file line="105">prod/WorkZone/Basket.html.twig</jms:reference-file> <jms:reference-file line="105">prod/WorkZone/Basket.html.twig</jms:reference-file>
<jms:reference-file line="15">prod/Tooltip/Basket.html.twig</jms:reference-file> <jms:reference-file line="15">prod/Tooltip/Basket.html.twig</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="32285b1e113decb0a3fdf090b0698c5508a2bd09" resname="workzone:feedback:expiration-open"> <trans-unit id="32285b1e113decb0a3fdf090b0698c5508a2bd09" resname="workzone:feedback:expiration-open" approved="no">
<source>workzone:feedback:expiration-open</source> <source>workzone:feedback:expiration-open</source>
<target state="new">workzone:feedback:expiration-open</target> <target state="needs-translation">Feedback open until</target>
<jms:reference-file line="107">prod/WorkZone/Basket.html.twig</jms:reference-file> <jms:reference-file line="107">prod/WorkZone/Basket.html.twig</jms:reference-file>
<jms:reference-file line="17">prod/Tooltip/Basket.html.twig</jms:reference-file> <jms:reference-file line="17">prod/Tooltip/Basket.html.twig</jms:reference-file>
</trans-unit> </trans-unit>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version='1.0' encoding='utf-8'?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2"> <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2020-03-17T12:45:08Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available"> <file date="2020-03-17T12:45:08Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available">
<header> <header>
@@ -7,8 +7,8 @@
</header> </header>
<body> <body>
<trans-unit id="da39a3ee5e6b4b0d3255bfef95601890afd80709" resname=""> <trans-unit id="da39a3ee5e6b4b0d3255bfef95601890afd80709" resname="">
<source></source> <source/>
<target state="new"></target> <target state="new"/>
<jms:reference-file line="60">Form/Login/PhraseaAuthenticationForm.php</jms:reference-file> <jms:reference-file line="60">Form/Login/PhraseaAuthenticationForm.php</jms:reference-file>
<jms:reference-file line="47">Form/Configuration/EmailFormType.php</jms:reference-file> <jms:reference-file line="47">Form/Configuration/EmailFormType.php</jms:reference-file>
</trans-unit> </trans-unit>
@@ -13540,15 +13540,15 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le
<target state="translated">Mercredi</target> <target state="translated">Mercredi</target>
<jms:reference-file line="171">prod/WorkZone/Basket.html.twig</jms:reference-file> <jms:reference-file line="171">prod/WorkZone/Basket.html.twig</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="cbfb58c29147c5881e828d18a477f922211873a0" resname="workzone:feedback:expiration-closed"> <trans-unit id="cbfb58c29147c5881e828d18a477f922211873a0" resname="workzone:feedback:expiration-closed" approved="no">
<source>workzone:feedback:expiration-closed</source> <source>workzone:feedback:expiration-closed</source>
<target state="new">workzone:feedback:expiration-closed</target> <target state="needs-translation">Validation close depuis</target>
<jms:reference-file line="105">prod/WorkZone/Basket.html.twig</jms:reference-file> <jms:reference-file line="105">prod/WorkZone/Basket.html.twig</jms:reference-file>
<jms:reference-file line="15">prod/Tooltip/Basket.html.twig</jms:reference-file> <jms:reference-file line="15">prod/Tooltip/Basket.html.twig</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="32285b1e113decb0a3fdf090b0698c5508a2bd09" resname="workzone:feedback:expiration-open"> <trans-unit id="32285b1e113decb0a3fdf090b0698c5508a2bd09" resname="workzone:feedback:expiration-open" approved="no">
<source>workzone:feedback:expiration-open</source> <source>workzone:feedback:expiration-open</source>
<target state="new">workzone:feedback:expiration-open</target> <target state="needs-translation">validation ouverte jusqu'au</target>
<jms:reference-file line="107">prod/WorkZone/Basket.html.twig</jms:reference-file> <jms:reference-file line="107">prod/WorkZone/Basket.html.twig</jms:reference-file>
<jms:reference-file line="17">prod/Tooltip/Basket.html.twig</jms:reference-file> <jms:reference-file line="17">prod/Tooltip/Basket.html.twig</jms:reference-file>
</trans-unit> </trans-unit>

View File

@@ -169,7 +169,8 @@ class ExportTest extends \PhraseanetAuthenticatedWebTestCase
*/ */
public function testExportMail() 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/', [ $this->getClient()->request('POST', '/prod/export/mail/', [
'lst' => $this->getRecord1()->getId(), 'lst' => $this->getRecord1()->getId(),

View File

@@ -79,7 +79,7 @@ class UserDeletionTest extends \PhraseanetAuthenticatedWebTestCase
$apiLog = $apiLogManipulator->create($account, new Request(), new Response()); $apiLog = $apiLogManipulator->create($account, new Request(), new Response());
$apiLogId = $apiLog->getId(); $apiLogId = $apiLog->getId();
$this->userManipulator->delete($this->user, true); $this->userManipulator->delete($this->user);
$this->assertTrue($this->user->isDeleted(), 'User was not properly deleted'); $this->assertTrue($this->user->isDeleted(), 'User was not properly deleted');
$apiLogRepository->clear(); $apiLogRepository->clear();

View File

@@ -12,6 +12,6 @@ class WebhookEventRepositoryTest extends \PhraseanetTestCase
{ {
$events = self::$DI['app']['orm.em']->getRepository('Phraseanet:WebhookEvent')->findUnprocessedEvents(); $events = self::$DI['app']['orm.em']->getRepository('Phraseanet:WebhookEvent')->findUnprocessedEvents();
// I have no clue as to why this magic number is here, probably best to discard test // I have no clue as to why this magic number is here, probably best to discard test
$this->assertCount(6, $events); $this->assertCount(41, $events);
} }
} }

View File

@@ -59,6 +59,6 @@ class FeedEntryProcessorTest extends \PhraseanetTestCase
self::$DI['app']['repo.feed-entries'], self::$DI['app']['repo.feed-entries'],
self::$DI['app']['phraseanet.user-query'] self::$DI['app']['phraseanet.user-query']
); );
$this->assertEquals($processor->process($event), null); $this->assertInternalType(\PHPUnit_Framework_Constraint_IsType::TYPE_ARRAY, $processor->process($event));
} }
} }