Merge pull request #22049 from owncloud/issue-22041-activities-for-systemtags

Issue 22041 activities for systemtags
This commit is contained in:
Thomas Müller 2016-02-02 13:08:01 +01:00
commit 2d1d89ee29
13 changed files with 875 additions and 42 deletions

View File

@ -0,0 +1,300 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OCA\SystemTags\Activity;
use OCP\Activity\IExtension;
use OCP\Activity\IManager;
use OCP\IL10N;
use OCP\L10N\IFactory;
/**
* Class Extension
*
* @package OCA\SystemTags\Activity
*/
class Extension implements IExtension {
const APP_NAME = 'systemtags';
const CREATE_TAG = 'create_tag';
const UPDATE_TAG = 'update_tag';
const DELETE_TAG = 'delete_tag';
const ASSIGN_TAG = 'assign_tag';
const UNASSIGN_TAG = 'unassign_tag';
/** @var IFactory */
protected $languageFactory;
/** @var IManager */
protected $activityManager;
/**
* @param IFactory $languageFactory
* @param IManager $activityManager
*/
public function __construct(IFactory $languageFactory, IManager $activityManager) {
$this->languageFactory = $languageFactory;
$this->activityManager = $activityManager;
}
protected function getL10N($languageCode = null) {
return $this->languageFactory->get(self::APP_NAME, $languageCode);
}
/**
* The extension can return an array of additional notification types.
* If no additional types are to be added false is to be returned
*
* @param string $languageCode
* @return array|false
*/
public function getNotificationTypes($languageCode) {
$l = $this->getL10N($languageCode);
return array(
self::APP_NAME => (string) $l->t('<strong>System tags</strong> for a file have been modified'),
);
}
/**
* For a given method additional types to be displayed in the settings can be returned.
* In case no additional types are to be added false is to be returned.
*
* @param string $method
* @return array|false
*/
public function getDefaultTypes($method) {
return [self::APP_NAME];
}
/**
* A string naming the css class for the icon to be used can be returned.
* If no icon is known for the given type false is to be returned.
*
* @param string $type
* @return string|false
*/
public function getTypeIcon($type) {
switch ($type) {
case self::APP_NAME:
return false;
}
return false;
}
/**
* The extension can translate a given message to the requested languages.
* If no translation is available false is to be returned.
*
* @param string $app
* @param string $text
* @param array $params
* @param boolean $stripPath
* @param boolean $highlightParams
* @param string $languageCode
* @return string|false
*/
public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) {
if ($app !== self::APP_NAME) {
return false;
}
$l = $this->getL10N($languageCode);
if ($this->activityManager->isFormattingFilteredObject()) {
$translation = $this->translateShort($text, $l, $params);
if ($translation !== false) {
return $translation;
}
}
return $this->translateLong($text, $l, $params);
}
/**
* @param string $text
* @param IL10N $l
* @param array $params
* @return bool|string
*/
protected function translateShort($text, IL10N $l, array $params) {
switch ($text) {
case self::ASSIGN_TAG:
$params[2] = $this->convertParameterToTag($params[2], $l);
return (string) $l->t('%1$s assigned system tag %3$s', $params);
case self::UNASSIGN_TAG:
$params[2] = $this->convertParameterToTag($params[2], $l);
return (string) $l->t('%1$s unassigned system tag %3$s', $params);
}
return false;
}
/**
* @param string $text
* @param IL10N $l
* @param array $params
* @return bool|string
*/
protected function translateLong($text, IL10N $l, array $params) {
switch ($text) {
case self::CREATE_TAG:
$params[1] = $this->convertParameterToTag($params[1], $l);
return (string) $l->t('%1$s created system tag %2$s', $params);
case self::DELETE_TAG:
$params[1] = $this->convertParameterToTag($params[1], $l);
return (string) $l->t('%1$s deleted system tag %2$s', $params);
case self::UPDATE_TAG:
$params[1] = $this->convertParameterToTag($params[1], $l);
$params[2] = $this->convertParameterToTag($params[2], $l);
return (string) $l->t('%1$s updated system tag %3$s to %2$s', $params);
case self::ASSIGN_TAG:
$params[2] = $this->convertParameterToTag($params[2], $l);
return (string) $l->t('%1$s assigned system tag %3$s to %2$s', $params);
case self::UNASSIGN_TAG:
$params[2] = $this->convertParameterToTag($params[2], $l);
return (string) $l->t('%1$s unassigned system tag %3$s from %2$s', $params);
}
return false;
}
/**
* The extension can define the type of parameters for translation
*
* Currently known types are:
* * file => will strip away the path of the file and add a tooltip with it
* * username => will add the avatar of the user
*
* @param string $app
* @param string $text
* @return array|false
*/
public function getSpecialParameterList($app, $text) {
if ($app === self::APP_NAME) {
switch ($text) {
case self::CREATE_TAG:
case self::DELETE_TAG:
return array(
0 => 'username',
//1 => 'systemtag description',
);
case self::UPDATE_TAG:
return array(
0 => 'username',
//1 => 'systemtag description',
//2 => 'systemtag description',
);
case self::ASSIGN_TAG:
case self::UNASSIGN_TAG:
return array(
0 => 'username',
1 => 'file',
//2 => 'systemtag description',
);
}
}
return false;
}
/**
* The extension can define the parameter grouping by returning the index as integer.
* In case no grouping is required false is to be returned.
*
* @param array $activity
* @return integer|false
*/
public function getGroupParameter($activity) {
return false;
}
/**
* The extension can define additional navigation entries. The array returned has to contain two keys 'top'
* and 'apps' which hold arrays with the relevant entries.
* If no further entries are to be added false is no be returned.
*
* @return array|false
*/
public function getNavigation() {
return false;
}
/**
* The extension can check if a custom filter (given by a query string like filter=abc) is valid or not.
*
* @param string $filterValue
* @return boolean
*/
public function isFilterValid($filterValue) {
return false;
}
/**
* The extension can filter the types based on the filter if required.
* In case no filter is to be applied false is to be returned unchanged.
*
* @param array $types
* @param string $filter
* @return array|false
*/
public function filterNotificationTypes($types, $filter) {
return false;
}
/**
* For a given filter the extension can specify the sql query conditions including parameters for that query.
* In case the extension does not know the filter false is to be returned.
* The query condition and the parameters are to be returned as array with two elements.
* E.g. return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%'));
*
* @param string $filter
* @return array|false
*/
public function getQueryForFilter($filter) {
return false;
}
/**
* @param string $parameter
* @param IL10N $l
* @return string
*/
protected function convertParameterToTag($parameter, IL10N $l) {
if (preg_match('/^\<parameter\>\{\{\{(.*)\|\|\|(.*)\}\}\}\<\/parameter\>$/', $parameter, $matches)) {
switch ($matches[2]) {
case 'assignable':
return '<parameter>' . $matches[1] . '</parameter>';
case 'not-assignable':
return '<parameter>' . $l->t('%s (not-assignable)', $matches[1]) . '</parameter>';
case 'invisible':
return '<parameter>' . $l->t('%s (invisible)', $matches[1]) . '</parameter>';
}
}
return $parameter;
}
}

View File

@ -0,0 +1,223 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OCA\SystemTags\Activity;
use OCP\Activity\IManager;
use OCP\App\IAppManager;
use OCP\Files\Config\IMountProviderCollection;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Share;
use OCP\SystemTag\ISystemTag;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ManagerEvent;
use OCP\SystemTag\MapperEvent;
use OCP\SystemTag\TagNotFoundException;
class Listener {
/** @var IGroupManager */
protected $groupManager;
/** @var IManager */
protected $activityManager;
/** @var IUserSession */
protected $session;
/** @var \OCP\SystemTag\ISystemTagManager */
protected $tagManager;
/** @var \OCP\App\IAppManager */
protected $appManager;
/** @var \OCP\Files\Config\IMountProviderCollection */
protected $mountCollection;
/** @var \OCP\Files\IRootFolder */
protected $rootFolder;
/**
* Listener constructor.
*
* @param IGroupManager $groupManager
* @param IManager $activityManager
* @param IUserSession $session
* @param ISystemTagManager $tagManager
* @param IAppManager $appManager
* @param IMountProviderCollection $mountCollection
* @param IRootFolder $rootFolder
*/
public function __construct(IGroupManager $groupManager,
IManager $activityManager,
IUserSession $session,
ISystemTagManager $tagManager,
IAppManager $appManager,
IMountProviderCollection $mountCollection,
IRootFolder $rootFolder) {
$this->groupManager = $groupManager;
$this->activityManager = $activityManager;
$this->session = $session;
$this->tagManager = $tagManager;
$this->appManager = $appManager;
$this->mountCollection = $mountCollection;
$this->rootFolder = $rootFolder;
}
/**
* @param ManagerEvent $event
*/
public function event(ManagerEvent $event) {
$actor = $this->session->getUser();
if ($actor instanceof IUser) {
$actor = $actor->getUID();
} else {
$actor = '';
}
$activity = $this->activityManager->generateEvent();
$activity->setApp(Extension::APP_NAME)
->setType(Extension::APP_NAME)
->setAuthor($actor);
if ($event->getEvent() === ManagerEvent::EVENT_CREATE) {
$activity->setSubject(Extension::CREATE_TAG, [
$actor,
$this->prepareTagAsParameter($event->getTag()),
]);
} else if ($event->getEvent() === ManagerEvent::EVENT_UPDATE) {
$activity->setSubject(Extension::UPDATE_TAG, [
$actor,
$this->prepareTagAsParameter($event->getTag()),
$this->prepareTagAsParameter($event->getTagBefore()),
]);
} else if ($event->getEvent() === ManagerEvent::EVENT_DELETE) {
$activity->setSubject(Extension::DELETE_TAG, [
$actor,
$this->prepareTagAsParameter($event->getTag()),
]);
} else {
return;
}
$group = $this->groupManager->get('admin');
if ($group instanceof IGroup) {
foreach ($group->getUsers() as $user) {
$activity->setAffectedUser($user->getUID());
$this->activityManager->publish($activity);
}
}
}
/**
* @param MapperEvent $event
*/
public function mapperEvent(MapperEvent $event) {
$tagIds = $event->getTags();
if ($event->getObjectType() !== 'files' ||empty($tagIds)
|| !in_array($event->getEvent(), [MapperEvent::EVENT_ASSIGN, MapperEvent::EVENT_UNASSIGN])
|| !$this->appManager->isInstalled('activity')) {
// System tags not for files, no tags, not (un-)assigning or no activity-app enabled (save the energy)
return;
}
try {
$tags = $this->tagManager->getTagsByIds($tagIds);
} catch (TagNotFoundException $e) {
// User assigned/unassigned a non-existing tag, ignore...
return;
}
if (empty($tags)) {
return;
}
// Get all mount point owners
$cache = $this->mountCollection->getMountCache();
$mounts = $cache->getMountsForFileId($event->getObjectId());
if (empty($mounts)) {
return;
}
$users = [];
foreach ($mounts as $mount) {
$owner = $mount->getUser()->getUID();
$ownerFolder = $this->rootFolder->getUserFolder($owner);
$nodes = $ownerFolder->getById($event->getObjectId());
if (!empty($nodes)) {
/** @var Node $node */
$node = array_shift($nodes);
$path = $node->getPath();
if (strpos($path, '/' . $owner . '/files/') === 0) {
$path = substr($path, strlen('/' . $owner . '/files'));
}
// Get all users that have access to the mount point
$users = array_merge($users, Share::getUsersSharingFile($path, $owner, true, true));
}
}
$actor = $this->session->getUser();
if ($actor instanceof IUser) {
$actor = $actor->getUID();
} else {
$actor = '';
}
$activity = $this->activityManager->generateEvent();
$activity->setApp(Extension::APP_NAME)
->setType(Extension::APP_NAME)
->setAuthor($actor)
->setObject($event->getObjectType(), $event->getObjectId());
foreach ($users as $user => $path) {
$activity->setAffectedUser($user);
foreach ($tags as $tag) {
if ($event->getEvent() === MapperEvent::EVENT_ASSIGN) {
$activity->setSubject(Extension::ASSIGN_TAG, [
$actor,
$path,
$this->prepareTagAsParameter($tag),
]);
} else if ($event->getEvent() === MapperEvent::EVENT_UNASSIGN) {
$activity->setSubject(Extension::UNASSIGN_TAG, [
$actor,
$path,
$this->prepareTagAsParameter($tag),
]);
}
$this->activityManager->publish($activity);
}
}
}
/**
* @param ISystemTag $tag
* @return string
*/
protected function prepareTagAsParameter(ISystemTag $tag) {
if (!$tag->isUserVisible()) {
return '{{{' . $tag->getName() . '|||invisible}}}';
} else if (!$tag->isUserAssignable()) {
return '{{{' . $tag->getName() . '|||not-assignable}}}';
} else {
return '{{{' . $tag->getName() . '|||assignable}}}';
}
}
}

View File

@ -19,6 +19,11 @@
*
*/
use OCA\SystemTags\Activity\Extension;
use OCA\SystemTags\Activity\Listener;
use OCP\SystemTag\ManagerEvent;
use OCP\SystemTag\MapperEvent;
$eventDispatcher = \OC::$server->getEventDispatcher();
$eventDispatcher->addListener(
'OCA\Files::loadAdditionalScripts',
@ -39,3 +44,32 @@ $eventDispatcher->addListener(
\OCP\Util::addStyle('systemtags');
}
);
$activityManager = \OC::$server->getActivityManager();
$activityManager->registerExtension(function() {
$application = new \OCP\AppFramework\App('systemtags');
/** @var \OCA\SystemTags\Activity\Extension $extension */
$extension = $application->getContainer()->query('OCA\SystemTags\Activity\Extension');
return $extension;
});
$managerListener = function(ManagerEvent $event) use ($activityManager) {
$application = new \OCP\AppFramework\App('systemtags');
/** @var \OCA\SystemTags\Activity\Listener $listener */
$listener = $application->getContainer()->query('OCA\SystemTags\Activity\Listener');
$listener->event($event);
};
$eventDispatcher->addListener(ManagerEvent::EVENT_CREATE, $managerListener);
$eventDispatcher->addListener(ManagerEvent::EVENT_DELETE, $managerListener);
$eventDispatcher->addListener(ManagerEvent::EVENT_UPDATE, $managerListener);
$mapperListener = function(MapperEvent $event) use ($activityManager) {
$application = new \OCP\AppFramework\App('systemtags');
/** @var \OCA\SystemTags\Activity\Listener $listener */
$listener = $application->getContainer()->query('OCA\SystemTags\Activity\Listener');
$listener->mapperEvent($event);
};
$eventDispatcher->addListener(MapperEvent::EVENT_ASSIGN, $mapperListener);
$eventDispatcher->addListener(MapperEvent::EVENT_UNASSIGN, $mapperListener);

View File

@ -6,11 +6,14 @@
<licence>AGPL</licence>
<author>Vincent Petry</author>
<default_enable/>
<version>0.1</version>
<version>0.2</version>
<dependencies>
<owncloud min-version="9.0" max-version="9.0" />
</dependencies>
<documentation>
<user>user-systemtags</user>
</documentation>
<types>
<logging/>
</types>
</info>

View File

@ -310,20 +310,19 @@ class ActivityManager implements IManager {
/**
* @param string $type
* @param int $id
* @param string $id
*/
public function setFormattingObject($type, $id) {
$this->formattingObjectType = $type;
$this->formattingObjectId = $id;
$this->formattingObjectId = (string) $id;
}
/**
* @return bool
*/
public function isFormattingFilteredObject() {
return 'filter' === $this->request->getParam('filter')
&& $this->formattingObjectType === $this->request->getParam('objecttype')
&& $this->formattingObjectId === $this->request->getParam('objectid');
return $this->formattingObjectType === $this->request->getParam('object_type')
&& $this->formattingObjectId === $this->request->getParam('object_id');
}
/**

View File

@ -152,6 +152,10 @@ class DIContainer extends SimpleContainer implements IAppContainer {
return $this->getServer()->getL10N($c->query('AppName'));
});
$this->registerService('OCP\\L10N\\IFactory', function($c) {
return $this->getServer()->getL10NFactory();
});
$this->registerService('OCP\\ILogger', function($c) {
return $this->getServer()->getLogger();
});

View File

@ -20,11 +20,10 @@
*/
namespace OC\SystemTag;
use OCP\SystemTag\ISystemTagManagerFactory;
use OCP\SystemTag\ISystemTagManager;
use OC\SystemTag\SystemTagManager;
use OC\SystemTag\SystemTagObjectMapper;
use OCP\IServerContainer;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagManagerFactory;
use OCP\SystemTag\ISystemTagObjectMapper;
/**
* Default factory class for system tag managers
@ -58,7 +57,8 @@ class ManagerFactory implements ISystemTagManagerFactory {
*/
public function getManager() {
return new SystemTagManager(
$this->serverContainer->getDatabaseConnection()
$this->serverContainer->getDatabaseConnection(),
$this->serverContainer->getEventDispatcher()
);
}
@ -72,7 +72,8 @@ class ManagerFactory implements ISystemTagManagerFactory {
public function getObjectMapper() {
return new SystemTagObjectMapper(
$this->serverContainer->getDatabaseConnection(),
$this->getManager()
$this->getManager(),
$this->serverContainer->getEventDispatcher()
);
}
}

View File

@ -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()

View File

@ -28,31 +28,34 @@ use OCP\IDBConnection;
use OCP\SystemTag\ISystemTag;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\MapperEvent;
use OCP\SystemTag\TagNotFoundException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class SystemTagObjectMapper implements ISystemTagObjectMapper {
const RELATION_TABLE = 'systemtag_object_mapping';
/**
* @var ISystemTagManager
*/
private $tagManager;
/** @var ISystemTagManager */
protected $tagManager;
/**
* @var IDBConnection
*/
private $connection;
/** @var IDBConnection */
protected $connection;
/** @var EventDispatcherInterface */
protected $dispatcher;
/**
* Constructor.
*
* @param IDBConnection $connection database connection
* @param ISystemTagManager $tagManager system tag manager
* @param EventDispatcherInterface $dispatcher
*/
public function __construct(IDBConnection $connection, ISystemTagManager $tagManager) {
public function __construct(IDBConnection $connection, ISystemTagManager $tagManager, EventDispatcherInterface $dispatcher) {
$this->connection = $connection;
$this->tagManager = $tagManager;
$this->dispatcher = $dispatcher;
}
/**
@ -143,6 +146,13 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
// ignore existing relations
}
}
$this->dispatcher->dispatch(MapperEvent::EVENT_ASSIGN, new MapperEvent(
MapperEvent::EVENT_ASSIGN,
$objectType,
$objId,
$tagIds
));
}
/**
@ -164,6 +174,13 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
->setParameter('objecttype', $objectType)
->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY)
->execute();
$this->dispatcher->dispatch(MapperEvent::EVENT_UNASSIGN, new MapperEvent(
MapperEvent::EVENT_UNASSIGN,
$objectType,
$objId,
$tagIds
));
}
/**

View File

@ -0,0 +1,85 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @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 <http://www.gnu.org/licenses/>
*
*/
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;
}
}

View File

@ -0,0 +1,93 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OCP\SystemTag;
use Symfony\Component\EventDispatcher\Event;
/**
* Class MapperEvent
*
* @package OCP\SystemTag
* @since 9.0.0
*/
class MapperEvent extends Event {
const EVENT_ASSIGN = 'OCP\SystemTag\ISystemTagObjectMapper::assignTags';
const EVENT_UNASSIGN = 'OCP\SystemTag\ISystemTagObjectMapper::unassignTags';
/** @var string */
protected $event;
/** @var string */
protected $objectType;
/** @var string */
protected $objectId;
/** @var int[] */
protected $tags;
/**
* DispatcherEvent constructor.
*
* @param string $event
* @param string $objectType
* @param string $objectId
* @param int[] $tags
* @since 9.0.0
*/
public function __construct($event, $objectType, $objectId, array $tags) {
$this->event = $event;
$this->objectType = $objectType;
$this->objectId = $objectId;
$this->tags = $tags;
}
/**
* @return string
* @since 9.0.0
*/
public function getEvent() {
return $this->event;
}
/**
* @return string
* @since 9.0.0
*/
public function getObjectType() {
return $this->objectType;
}
/**
* @return string
* @since 9.0.0
*/
public function getObjectId() {
return $this->objectId;
}
/**
* @return int[]
* @since 9.0.0
*/
public function getTags() {
return $this->tags;
}
}

View File

@ -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();
}
@ -378,7 +391,7 @@ class SystemTagManagerTest extends TestCase {
$tag1 = $this->tagManager->createTag('one', true, false);
$tag2 = $this->tagManager->createTag('two', true, true);
$tagMapper = new SystemTagObjectMapper($this->connection, $this->tagManager);
$tagMapper = new SystemTagObjectMapper($this->connection, $this->tagManager, $this->dispatcher);
$tagMapper->assignTags(1, 'testtype', $tag1->getId());
$tagMapper->assignTags(1, 'testtype', $tag2->getId());

View File

@ -10,14 +10,15 @@
namespace Test\SystemTag;
use OC\SystemTag\SystemTag;
use OC\SystemTag\SystemTagManager;
use OC\SystemTag\SystemTagObjectMapper;
use \OCP\SystemTag\ISystemTag;
use \OCP\SystemTag\ISystemTagManager;
use \OCP\SystemTag\ISystemTagObjectMapper;
use \OCP\SystemTag\TagNotFoundException;
use \OCP\IDBConnection;
use \OC\SystemTag\SystemTag;
use OCP\IDBConnection;
use OCP\SystemTag\ISystemTag;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagNotFoundException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Test\TestCase;
/**
@ -43,6 +44,11 @@ class SystemTagObjectMapperTest extends TestCase {
*/
private $connection;
/**
* @var EventDispatcherInterface
*/
private $dispatcher;
/**
* @var ISystemTag
*/
@ -67,7 +73,14 @@ class SystemTagObjectMapperTest extends TestCase {
$this->tagManager = $this->getMockBuilder('OCP\SystemTag\ISystemTagManager')
->getMock();
$this->tagMapper = new SystemTagObjectMapper($this->connection, $this->tagManager);
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')
->getMock();
$this->tagMapper = new SystemTagObjectMapper(
$this->connection,
$this->tagManager,
$this->dispatcher
);
$this->tag1 = new SystemTag(1, 'testtag1', false, false);
$this->tag2 = new SystemTag(2, 'testtag2', true, false);