diff --git a/lib/private/systemtag/managerfactory.php b/lib/private/systemtag/managerfactory.php index 2939caacde..7ad4f92260 100644 --- a/lib/private/systemtag/managerfactory.php +++ b/lib/private/systemtag/managerfactory.php @@ -57,7 +57,8 @@ class ManagerFactory implements ISystemTagManagerFactory { */ public function getManager() { return new SystemTagManager( - $this->serverContainer->getDatabaseConnection() + $this->serverContainer->getDatabaseConnection(), + $this->serverContainer->getEventDispatcher() ); } diff --git a/lib/private/systemtag/systemtagmanager.php b/lib/private/systemtag/systemtagmanager.php index af912a7493..76a60a9132 100644 --- a/lib/private/systemtag/systemtagmanager.php +++ b/lib/private/systemtag/systemtagmanager.php @@ -26,17 +26,20 @@ use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\ManagerEvent; use OCP\SystemTag\TagAlreadyExistsException; use OCP\SystemTag\TagNotFoundException; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; class SystemTagManager implements ISystemTagManager { const TAG_TABLE = 'systemtag'; - /** - * @var IDBConnection - */ - private $connection; + /** @var IDBConnection */ + protected $connection; + + /** @var EventDispatcherInterface */ + protected $dispatcher; /** * Prepared query for selecting tags directly @@ -46,12 +49,14 @@ class SystemTagManager implements ISystemTagManager { private $selectTagQuery; /** - * Constructor. - * - * @param IDBConnection $connection database connection - */ - public function __construct(IDBConnection $connection) { + * Constructor. + * + * @param IDBConnection $connection database connection + * @param EventDispatcherInterface $dispatcher + */ + public function __construct(IDBConnection $connection, EventDispatcherInterface $dispatcher) { $this->connection = $connection; + $this->dispatcher = $dispatcher; $query = $this->connection->getQueryBuilder(); $this->selectTagQuery = $query->select('*') @@ -190,14 +195,20 @@ class SystemTagManager implements ISystemTagManager { ); } - $tagId = $this->connection->lastInsertId('*PREFIX*' . self::TAG_TABLE); + $tagId = $query->getLastInsertId(); - return new SystemTag( + $tag = new SystemTag( (int)$tagId, $tagName, (bool)$userVisible, (bool)$userAssignable ); + + $this->dispatcher->dispatch(ManagerEvent::EVENT_CREATE, new ManagerEvent( + ManagerEvent::EVENT_CREATE, $tag + )); + + return $tag; } /** @@ -207,6 +218,22 @@ class SystemTagManager implements ISystemTagManager { $userVisible = (int)$userVisible; $userAssignable = (int)$userAssignable; + try { + $tags = $this->getTagsByIds($tagId); + } catch (TagNotFoundException $e) { + throw new TagNotFoundException( + 'Tag does not exist', 0, null, [$tagId] + ); + } + + $beforeUpdate = array_shift($tags); + $afterUpdate = new SystemTag( + (int) $tagId, + $tagName, + (bool) $userVisible, + (bool) $userAssignable + ); + $query = $this->connection->getQueryBuilder(); $query->update(self::TAG_TABLE) ->set('name', $query->createParameter('name')) @@ -231,6 +258,10 @@ class SystemTagManager implements ISystemTagManager { $e ); } + + $this->dispatcher->dispatch(ManagerEvent::EVENT_UPDATE, new ManagerEvent( + ManagerEvent::EVENT_UPDATE, $afterUpdate, $beforeUpdate + )); } /** @@ -242,10 +273,21 @@ class SystemTagManager implements ISystemTagManager { } $tagNotFoundException = null; + $tags = []; try { - $this->getTagsByIds($tagIds); + $tags = $this->getTagsByIds($tagIds); } catch (TagNotFoundException $e) { $tagNotFoundException = $e; + + // Get existing tag objects for the hooks later + $existingTags = array_diff($tagIds, $tagNotFoundException->getMissingTags()); + if (!empty($existingTags)) { + try { + $tags = $this->getTagsByIds($existingTags); + } catch (TagNotFoundException $e) { + // Ignore further errors... + } + } } // delete relationships first @@ -261,6 +303,12 @@ class SystemTagManager implements ISystemTagManager { ->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY) ->execute(); + foreach ($tags as $tag) { + $this->dispatcher->dispatch(ManagerEvent::EVENT_DELETE, new ManagerEvent( + ManagerEvent::EVENT_DELETE, $tag + )); + } + if ($tagNotFoundException !== null) { throw new TagNotFoundException( 'Tag id(s) not found', 0, $tagNotFoundException, $tagNotFoundException->getMissingTags() diff --git a/lib/public/systemtag/managerevent.php b/lib/public/systemtag/managerevent.php new file mode 100644 index 0000000000..a0429fc9f6 --- /dev/null +++ b/lib/public/systemtag/managerevent.php @@ -0,0 +1,85 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCP\SystemTag; + +use Symfony\Component\EventDispatcher\Event; + +/** + * Class ManagerEvent + * + * @package OCP\SystemTag + * @since 9.0.0 + */ +class ManagerEvent extends Event { + + const EVENT_CREATE = 'OCP\SystemTag\ISystemTagManager::createTag'; + const EVENT_UPDATE = 'OCP\SystemTag\ISystemTagManager::updateTag'; + const EVENT_DELETE = 'OCP\SystemTag\ISystemTagManager::deleteTag'; + + /** @var string */ + protected $event; + /** @var ISystemTag */ + protected $tag; + /** @var ISystemTag */ + protected $beforeTag; + + /** + * DispatcherEvent constructor. + * + * @param string $event + * @param ISystemTag $tag + * @param ISystemTag $beforeTag + * @since 9.0.0 + */ + public function __construct($event, ISystemTag $tag, ISystemTag $beforeTag = null) { + $this->event = $event; + $this->tag = $tag; + $this->beforeTag = $beforeTag; + } + + /** + * @return string + * @since 9.0.0 + */ + public function getEvent() { + return $this->event; + } + + /** + * @return ISystemTag + * @since 9.0.0 + */ + public function getTag() { + return $this->tag; + } + + /** + * @return ISystemTag + * @since 9.0.0 + */ + public function getTagBefore() { + if ($this->event !== self::EVENT_UPDATE) { + throw new \BadMethodCallException('getTagBefore is only available on the update Event'); + } + return $this->beforeTag; + } +} diff --git a/tests/lib/systemtag/systemtagmanagertest.php b/tests/lib/systemtag/systemtagmanagertest.php index f8d7117747..64220205ad 100644 --- a/tests/lib/systemtag/systemtagmanagertest.php +++ b/tests/lib/systemtag/systemtagmanagertest.php @@ -15,6 +15,7 @@ use OC\SystemTag\SystemTagObjectMapper; use OCP\IDBConnection; use OCP\SystemTag\ISystemTag; use OCP\SystemTag\ISystemTagManager; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Test\TestCase; /** @@ -35,11 +36,23 @@ class SystemTagManagerTest extends TestCase { */ private $connection; + /** + * @var EventDispatcherInterface + */ + private $dispatcher; + public function setUp() { parent::setUp(); $this->connection = \OC::$server->getDatabaseConnection(); - $this->tagManager = new SystemTagManager($this->connection); + + $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface') + ->getMock(); + + $this->tagManager = new SystemTagManager( + $this->connection, + $this->dispatcher + ); $this->pruneTagsTables(); }