Merge pull request #17832 from nextcloud/fix/noid/wfe-event-proxying

relax dependency on GenericEvent, instead stay compatible with old events
This commit is contained in:
blizzz 2019-11-13 16:42:05 +01:00 committed by GitHub
commit 51d3f98bfb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 159 additions and 25 deletions

View File

@ -23,12 +23,14 @@ namespace OCA\WorkflowEngine\AppInfo;
use OCA\WorkflowEngine\Manager;
use OCP\AppFramework\QueryException;
use OCP\EventDispatcher\Event;
use OCP\Template;
use OCA\WorkflowEngine\Controller\RequestTime;
use OCP\WorkflowEngine\IEntity;
use OCP\WorkflowEngine\IEntityCompat;
use OCP\WorkflowEngine\IOperation;
use OCP\WorkflowEngine\IOperationCompat;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
class Application extends \OCP\AppFramework\App {
@ -54,7 +56,7 @@ class Application extends \OCP\AppFramework\App {
public function registerHooksAndListeners() {
$this->dispatcher->addListener(
'OCP\WorkflowEngine::loadAdditionalSettingScripts',
function() {
function () {
if (!function_exists('style')) {
// This is hacky, but we need to load the template class
class_exists(Template::class, true);
@ -88,15 +90,35 @@ class Application extends \OCP\AppFramework\App {
array_map(function (string $eventName) use ($operationClass, $entityClass) {
$this->dispatcher->addListener(
$eventName,
function (GenericEvent $event) use ($eventName, $operationClass, $entityClass) {
function ($event) use ($eventName, $operationClass, $entityClass) {
$ruleMatcher = $this->manager->getRuleMatcher();
try {
/** @var IEntity $entity */
$entity = $this->getContainer()->query($entityClass);
$entity->prepareRuleMatcher($ruleMatcher, $eventName, $event);
/** @var IOperation $operation */
$operation = $this->getContainer()->query($operationClass);
$operation->onEvent($eventName, $event, $ruleMatcher);
if ($event instanceof Event) {
$entity->prepareRuleMatcher($ruleMatcher, $eventName, $event);
$operation->onEvent($eventName, $event, $ruleMatcher);
} else if ($entity instanceof IEntityCompat && $operation instanceof IOperationCompat) {
// TODO: Remove this block (and the compat classes) in the first major release in 2023
$entity->prepareRuleMatcherCompat($ruleMatcher, $eventName, $event);
$operation->onEventCompat($eventName, $event, $ruleMatcher);
} else {
$logger = $this->getContainer()->getServer()->getLogger();
$logger->warning(
'Cannot handle event {name} of {event} against entity {entity} and operation {operation}',
[
'app' => self::APP_ID,
'name' => $eventName,
'event' => get_class($event),
'entity' => $entityClass,
'operation' => $operationClass,
]
);
}
} catch (QueryException $e) {
// Ignore query exceptions since they might occur when an entity/operation were setup before by an app that is disabled now
}

View File

@ -24,8 +24,11 @@ declare(strict_types=1);
namespace OCA\WorkflowEngine\Entity;
use OCA\WorkflowEngine\AppInfo\Application;
use OCP\EventDispatcher\Event;
use OCP\Files\IRootFolder;
use OCP\IL10N;
use OCP\ILogger;
use OCP\IURLGenerator;
use OCP\SystemTag\MapperEvent;
use OCP\WorkflowEngine\GenericEntityEvent;
@ -40,12 +43,15 @@ class File implements IEntity {
/** @var IURLGenerator */
protected $urlGenerator;
/** @var IRootFolder */
private $root;
protected $root;
/** @var ILogger */
protected $logger;
public function __construct(IL10N $l10n, IURLGenerator $urlGenerator, IRootFolder $root) {
public function __construct(IL10N $l10n, IURLGenerator $urlGenerator, IRootFolder $root, ILogger $logger) {
$this->l10n = $l10n;
$this->urlGenerator = $urlGenerator;
$this->root = $root;
$this->logger = $logger;
}
public function getName(): string {
@ -59,20 +65,20 @@ class File implements IEntity {
public function getEvents(): array {
$namespace = '\OCP\Files::';
return [
new GenericEntityEvent($this->l10n->t('File created'), $namespace . 'postCreate' ),
new GenericEntityEvent($this->l10n->t('File updated'), $namespace . 'postWrite' ),
new GenericEntityEvent($this->l10n->t('File renamed'), $namespace . 'postRename' ),
new GenericEntityEvent($this->l10n->t('File deleted'), $namespace . 'postDelete' ),
new GenericEntityEvent($this->l10n->t('File accessed'), $namespace . 'postTouch' ),
new GenericEntityEvent($this->l10n->t('File copied'), $namespace . 'postCopy' ),
new GenericEntityEvent($this->l10n->t('Tag assigned'), MapperEvent::EVENT_ASSIGN ),
new GenericEntityEvent($this->l10n->t('File created'), $namespace . 'postCreate'),
new GenericEntityEvent($this->l10n->t('File updated'), $namespace . 'postWrite'),
new GenericEntityEvent($this->l10n->t('File renamed'), $namespace . 'postRename'),
new GenericEntityEvent($this->l10n->t('File deleted'), $namespace . 'postDelete'),
new GenericEntityEvent($this->l10n->t('File accessed'), $namespace . 'postTouch'),
new GenericEntityEvent($this->l10n->t('File copied'), $namespace . 'postCopy'),
new GenericEntityEvent($this->l10n->t('Tag assigned'), MapperEvent::EVENT_ASSIGN),
];
}
/**
* @since 18.0.0
*/
public function prepareRuleMatcher(IRuleMatcher $ruleMatcher, string $eventName, GenericEvent $event): void {
public function prepareRuleMatcher(IRuleMatcher $ruleMatcher, string $eventName, Event $event): void {
if (!$event instanceof GenericEvent && !$event instanceof MapperEvent) {
return;
}
switch ($eventName) {
case 'postCreate':
case 'postWrite':
@ -85,11 +91,11 @@ class File implements IEntity {
$ruleMatcher->setEntitySubject($this, $event->getSubject()[1]);
break;
case MapperEvent::EVENT_ASSIGN:
if(!$event instanceof MapperEvent || $event->getObjectType() !== 'files') {
if (!$event instanceof MapperEvent || $event->getObjectType() !== 'files') {
break;
}
$nodes = $this->root->getById((int)$event->getObjectId());
if(is_array($nodes) && !empty($nodes)) {
if (is_array($nodes) && !empty($nodes)) {
$node = array_shift($nodes);
$ruleMatcher->setEntitySubject($this, $node);
}

View File

@ -279,7 +279,12 @@ class ManagerTest extends TestCase {
return $this->createMock(IOperation::class);
} else if($class === File::class) {
return $this->getMockBuilder(File::class)
->setConstructorArgs([$this->l, $this->createMock(IURLGenerator::class), $this->createMock(IRootFolder::class)])
->setConstructorArgs([
$this->l,
$this->createMock(IURLGenerator::class),
$this->createMock(IRootFolder::class),
$this->createMock(ILogger::class)
])
->setMethodsExcept(['getEvents'])
->getMock();
}

View File

@ -446,10 +446,12 @@ return array(
'OCP\\WorkflowEngine\\IComplexOperation' => $baseDir . '/lib/public/WorkflowEngine/IComplexOperation.php',
'OCP\\WorkflowEngine\\IEntity' => $baseDir . '/lib/public/WorkflowEngine/IEntity.php',
'OCP\\WorkflowEngine\\IEntityCheck' => $baseDir . '/lib/public/WorkflowEngine/IEntityCheck.php',
'OCP\\WorkflowEngine\\IEntityCompat' => $baseDir . '/lib/public/WorkflowEngine/IEntityCompat.php',
'OCP\\WorkflowEngine\\IEntityEvent' => $baseDir . '/lib/public/WorkflowEngine/IEntityEvent.php',
'OCP\\WorkflowEngine\\IFileCheck' => $baseDir . '/lib/public/WorkflowEngine/IFileCheck.php',
'OCP\\WorkflowEngine\\IManager' => $baseDir . '/lib/public/WorkflowEngine/IManager.php',
'OCP\\WorkflowEngine\\IOperation' => $baseDir . '/lib/public/WorkflowEngine/IOperation.php',
'OCP\\WorkflowEngine\\IOperationCompat' => $baseDir . '/lib/public/WorkflowEngine/IOperationCompat.php',
'OCP\\WorkflowEngine\\IRuleMatcher' => $baseDir . '/lib/public/WorkflowEngine/IRuleMatcher.php',
'OCP\\WorkflowEngine\\ISpecificOperation' => $baseDir . '/lib/public/WorkflowEngine/ISpecificOperation.php',
'OC\\Accounts\\Account' => $baseDir . '/lib/private/Accounts/Account.php',

View File

@ -475,10 +475,12 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\WorkflowEngine\\IComplexOperation' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/IComplexOperation.php',
'OCP\\WorkflowEngine\\IEntity' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/IEntity.php',
'OCP\\WorkflowEngine\\IEntityCheck' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/IEntityCheck.php',
'OCP\\WorkflowEngine\\IEntityCompat' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/IEntityCompat.php',
'OCP\\WorkflowEngine\\IEntityEvent' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/IEntityEvent.php',
'OCP\\WorkflowEngine\\IFileCheck' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/IFileCheck.php',
'OCP\\WorkflowEngine\\IManager' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/IManager.php',
'OCP\\WorkflowEngine\\IOperation' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/IOperation.php',
'OCP\\WorkflowEngine\\IOperationCompat' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/IOperationCompat.php',
'OCP\\WorkflowEngine\\IRuleMatcher' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/IRuleMatcher.php',
'OCP\\WorkflowEngine\\ISpecificOperation' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/ISpecificOperation.php',
'OC\\Accounts\\Account' => __DIR__ . '/../../..' . '/lib/private/Accounts/Account.php',

View File

@ -24,7 +24,7 @@ declare(strict_types=1);
namespace OCP\WorkflowEngine;
use Symfony\Component\EventDispatcher\GenericEvent;
use OCP\EventDispatcher\Event;
/**
* Interface IEntity
@ -72,6 +72,6 @@ interface IEntity {
/**
* @since 18.0.0
*/
public function prepareRuleMatcher(IRuleMatcher $ruleMatcher, string $eventName, GenericEvent $event): void;
public function prepareRuleMatcher(IRuleMatcher $ruleMatcher, string $eventName, Event $event): void;
}

View File

@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2019 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCP\WorkflowEngine;
/**
* Interface IEntityCompat
*
* This interface extends IEntity to provide compatibility with old style
* Event classes. It is only present for a transition period and will be
* removed in 2023 again.
*
* @package OCP\WorkflowEngine
* @since 18.0.0
* @deprecated
*/
interface IEntityCompat extends IEntity {
/**
* Like prepareRuleMatcherCompat, but works with events that are not based
* on \OCP\EventDispatcher\Event.
*
* @since 18.0.0
* @deprecated
*/
public function prepareRuleMatcherCompat(IRuleMatcher $ruleMatcher, string $eventName, $event): void;
}

View File

@ -23,7 +23,7 @@
namespace OCP\WorkflowEngine;
use Symfony\Component\EventDispatcher\GenericEvent;
use OCP\EventDispatcher\Event;
/**
* Interface IOperation
@ -99,5 +99,5 @@ interface IOperation {
*
* @since 18.0.0
*/
public function onEvent(string $eventName, GenericEvent $event, IRuleMatcher $ruleMatcher): void;
public function onEvent(string $eventName, Event $event, IRuleMatcher $ruleMatcher): void;
}

View File

@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2019 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCP\WorkflowEngine;
/**
* Interface IOperationCompat
*
* This interface extends IOperation to provide compatibility with old style
* Event classes. It is only present for a transition period and will be
* removed in 2023 again.
*
* @package OCP\WorkflowEngine
* @since 18.0.0
* @deprecated
*/
interface IOperationCompat {
/**
* Like onEvent, but used with events that are not based on
* \OCP\EventDispatcher\Event.
*
* This method is introduced for compatibility reasons and will be removed
* in 2023 again.
*
* @since 18.0.0
* @deprecated
*/
public function onEventCompat(string $eventName, $event, IRuleMatcher $ruleMatcher): void;
}