From 280d5325c7ea9cca872b907ffec0eacf35e42f2f Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 20 Oct 2016 17:57:44 +0200 Subject: [PATCH] Allow to register activity filters via info.xml Signed-off-by: Joas Schilling --- lib/private/Activity/LegacyFilter.php | 108 +++++++++++++++ lib/private/Activity/Manager.php | 185 ++++++++++++++++++-------- lib/private/App/InfoParser.php | 9 ++ lib/private/legacy/app.php | 7 + lib/public/Activity/IExtension.php | 4 + lib/public/Activity/IFilter.php | 74 +++++++++++ lib/public/Activity/IManager.php | 67 +++++++--- 7 files changed, 378 insertions(+), 76 deletions(-) create mode 100644 lib/private/Activity/LegacyFilter.php create mode 100644 lib/public/Activity/IFilter.php diff --git a/lib/private/Activity/LegacyFilter.php b/lib/private/Activity/LegacyFilter.php new file mode 100644 index 00000000000..4641151245b --- /dev/null +++ b/lib/private/Activity/LegacyFilter.php @@ -0,0 +1,108 @@ + + * + * @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 . + * + */ + +namespace OC\Activity; + +use OCP\Activity\IFilter; +use OCP\Activity\IManager; + +class LegacyFilter implements IFilter { + + /** @var IManager */ + protected $manager; + /** @var string */ + protected $identifier; + /** @var string */ + protected $name; + /** @var bool */ + protected $isTopFilter; + + /** + * LegacySetting constructor. + * + * @param IManager $manager + * @param string $identifier + * @param string $name + * @param bool $isTopFilter + */ + public function __construct(IManager $manager, + $identifier, + $name, + $isTopFilter) { + $this->manager = $manager; + $this->identifier = $identifier; + $this->name = $name; + $this->isTopFilter = $isTopFilter; + } + + /** + * @return string Lowercase a-z and underscore only identifier + * @since 9.2.0 + */ + public function getIdentifier() { + return $this->identifier; + } + + /** + * @return string A translated string + * @since 9.2.0 + */ + public function getName() { + return $this->name; + } + + /** + * @return int whether the filter should be rather on the top or bottom of + * the admin section. The filters are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. + * @since 9.2.0 + */ + public function getPriority() { + return $this->isTopFilter ? 40 : 50; + } + + /** + * @return string Full URL to an icon, empty string when none is given + * @since 9.2.0 + */ + public function getIcon() { + // Old API was CSS class, so we can not use this... + return ''; + } + + /** + * @param string[] $types + * @return string[] An array of allowed apps from which activities should be displayed + * @since 9.2.0 + */ + public function filterTypes(array $types) { + return $this->manager->filterNotificationTypes($types, $this->getIdentifier()); + } + + /** + * @return string[] An array of allowed apps from which activities should be displayed + * @since 9.2.0 + */ + public function allowedApps() { + return []; + } +} + diff --git a/lib/private/Activity/Manager.php b/lib/private/Activity/Manager.php index 455bb3b8ee8..a18dace88ee 100644 --- a/lib/private/Activity/Manager.php +++ b/lib/private/Activity/Manager.php @@ -27,6 +27,7 @@ namespace OC\Activity; use OCP\Activity\IConsumer; use OCP\Activity\IEvent; use OCP\Activity\IExtension; +use OCP\Activity\IFilter; use OCP\Activity\IManager; use OCP\IConfig; use OCP\IRequest; @@ -235,7 +236,7 @@ class Manager implements IManager { * In order to improve lazy loading a closure can be registered which will be called in case * activity consumers are actually requested * - * $callable has to return an instance of OCA\Activity\IConsumer + * $callable has to return an instance of OCA\Activity\IExtension * * @param \Closure $callable * @return void @@ -245,6 +246,76 @@ class Manager implements IManager { $this->extensions = []; } + /** @var IFilter[] */ + protected $filterClasses; + + /** @var IFilter[] */ + protected $filters; + + /** @var bool */ + protected $loadedLegacyFilters = false; + + /** + * @param string $filter Class must implement OCA\Activity\IFilter + * @return void + */ + public function registerFilter($filter) { + $this->filterClasses[$filter] = false; + } + + /** + * @return IFilter[] + * @throws \InvalidArgumentException + */ + public function getFilters() { + if (!$this->loadedLegacyFilters) { + $legacyFilters = $this->getNavigation(); + + foreach ($legacyFilters['top'] as $filter => $data) { + $this->filters[$filter] = new LegacyFilter( + $this, $filter, $data['name'], true + ); + } + + foreach ($legacyFilters['apps'] as $filter => $data) { + $this->filters[$filter] = new LegacyFilter( + $this, $filter, $data['name'], false + ); + } + $this->loadedLegacyFilters = true; + } + + foreach ($this->filterClasses as $class => $false) { + /** @var IFilter $filter */ + $filter = \OC::$server->query($class); + + if (!$filter instanceof IFilter) { + throw new \InvalidArgumentException('Invalid activity filter registered'); + } + + $this->filters[$filter->getIdentifier()] = $filter; + + unset($this->filterClasses[$class]); + } + return $this->filters; + } + + /** + * @param string $id + * @return IFilter + * @throws \InvalidArgumentException when the filter was not found + * @since 9.2.0 + */ + public function getFilterById($id) { + $filters = $this->getFilters(); + + if (isset($filters[$id])) { + return $filters[$id]; + } + + throw new \InvalidArgumentException('Requested filter does not exist'); + } + /** * Will return additional notification types as specified by other apps * @@ -390,8 +461,63 @@ class Manager implements IManager { return false; } + /** + * Set the user we need to use + * + * @param string|null $currentUserId + * @throws \UnexpectedValueException If the user is invalid + */ + public function setCurrentUserId($currentUserId) { + if (!is_string($currentUserId) && $currentUserId !== null) { + throw new \UnexpectedValueException('The given current user is invalid'); + } + $this->currentUserId = $currentUserId; + } + + /** + * Get the user we need to use + * + * Either the user is logged in, or we try to get it from the token + * + * @return string + * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique + */ + public function getCurrentUserId() { + if ($this->currentUserId !== null) { + return $this->currentUserId; + } else if (!$this->session->isLoggedIn()) { + return $this->getUserFromToken(); + } else { + return $this->session->getUser()->getUID(); + } + } + + /** + * Get the user for the token + * + * @return string + * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique + */ + protected function getUserFromToken() { + $token = (string) $this->request->getParam('token', ''); + if (strlen($token) !== 30) { + throw new \UnexpectedValueException('The token is invalid'); + } + + $users = $this->config->getUsersForUserValue('activity', 'rsstoken', $token); + + if (sizeof($users) !== 1) { + // No unique user found + throw new \UnexpectedValueException('The token is invalid'); + } + + // Token found login as that user + return array_shift($users); + } + /** * @return array + * @deprecated 9.2.0 - Use getFilters() instead */ public function getNavigation() { $entries = array( @@ -412,6 +538,7 @@ class Manager implements IManager { /** * @param string $filterValue * @return boolean + * @deprecated 9.2.0 - Use getFilterById() instead */ public function isFilterValid($filterValue) { if (isset($this->validFilters[$filterValue])) { @@ -433,6 +560,7 @@ class Manager implements IManager { * @param array $types * @param string $filter * @return array + * @deprecated 9.2.0 - Use getFilterById()->filterTypes() instead */ public function filterNotificationTypes($types, $filter) { if (!$this->isFilterValid($filter)) { @@ -451,6 +579,7 @@ class Manager implements IManager { /** * @param string $filter * @return array + * @deprecated 9.2.0 - Use getFilterById() instead */ public function getQueryForFilter($filter) { if (!$this->isFilterValid($filter)) { @@ -477,58 +606,4 @@ class Manager implements IManager { return array(' and ((' . implode(') or (', $conditions) . '))', $parameters); } - - /** - * Set the user we need to use - * - * @param string|null $currentUserId - * @throws \UnexpectedValueException If the user is invalid - */ - public function setCurrentUserId($currentUserId) { - if (!is_string($currentUserId) && $currentUserId !== null) { - throw new \UnexpectedValueException('The given current user is invalid'); - } - $this->currentUserId = $currentUserId; - } - - /** - * Get the user we need to use - * - * Either the user is logged in, or we try to get it from the token - * - * @return string - * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique - */ - public function getCurrentUserId() { - if ($this->currentUserId !== null) { - return $this->currentUserId; - } else if (!$this->session->isLoggedIn()) { - return $this->getUserFromToken(); - } else { - return $this->session->getUser()->getUID(); - } - } - - /** - * Get the user for the token - * - * @return string - * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique - */ - protected function getUserFromToken() { - $token = (string) $this->request->getParam('token', ''); - if (strlen($token) !== 30) { - throw new \UnexpectedValueException('The token is invalid'); - } - - $users = $this->config->getUsersForUserValue('activity', 'rsstoken', $token); - - if (sizeof($users) !== 1) { - // No unique user found - throw new \UnexpectedValueException('The token is invalid'); - } - - // Token found login as that user - return array_shift($users); - } } diff --git a/lib/private/App/InfoParser.php b/lib/private/App/InfoParser.php index 44f495534c9..2a6909c484c 100644 --- a/lib/private/App/InfoParser.php +++ b/lib/private/App/InfoParser.php @@ -110,6 +110,12 @@ class InfoParser { if (!array_key_exists('commands', $array)) { $array['commands'] = []; } + if (!array_key_exists('activity', $array)) { + $array['activity'] = []; + } + if (!array_key_exists('filters', $array['activity'])) { + $array['activity']['filters'] = []; + } if (array_key_exists('types', $array)) { if (is_array($array['types'])) { @@ -144,6 +150,9 @@ class InfoParser { if (isset($array['commands']['command']) && is_array($array['commands']['command'])) { $array['commands'] = $array['commands']['command']; } + if (isset($array['activity']['filters']['filter']) && is_array($array['activity']['filters']['filter'])) { + $array['activity']['filters'] = $array['activity']['filters']['filter']; + } if(!is_null($this->cache)) { $this->cache->set($fileCacheKey, json_encode($array)); diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php index a89a4650c5d..746dcd4f7cc 100644 --- a/lib/private/legacy/app.php +++ b/lib/private/legacy/app.php @@ -162,6 +162,13 @@ class OC_App { } \OC::$server->getEventLogger()->end('load_app_' . $app); } + + $info = self::getAppInfo($app); + if (!empty($info['activity']['filters'])) { + foreach ($info['activity']['filters'] as $filter) { + \OC::$server->getActivityManager()->registerFilter($filter); + } + } } /** diff --git a/lib/public/Activity/IExtension.php b/lib/public/Activity/IExtension.php index aaa4c869561..21d1bd150ac 100644 --- a/lib/public/Activity/IExtension.php +++ b/lib/public/Activity/IExtension.php @@ -129,6 +129,7 @@ interface IExtension { * * @return array|false * @since 8.0.0 + * @deprecated 9.2.0 - Register an IFilter instead */ public function getNavigation(); @@ -138,6 +139,7 @@ interface IExtension { * @param string $filterValue * @return boolean * @since 8.0.0 + * @deprecated 9.2.0 - Register an IFilter instead */ public function isFilterValid($filterValue); @@ -149,6 +151,7 @@ interface IExtension { * @param string $filter * @return array|false * @since 8.0.0 + * @deprecated 9.2.0 - Register an IFilter instead */ public function filterNotificationTypes($types, $filter); @@ -161,6 +164,7 @@ interface IExtension { * @param string $filter * @return array|false * @since 8.0.0 + * @deprecated 9.2.0 - Register an IFilter instead */ public function getQueryForFilter($filter); } diff --git a/lib/public/Activity/IFilter.php b/lib/public/Activity/IFilter.php new file mode 100644 index 00000000000..f3c57c14e97 --- /dev/null +++ b/lib/public/Activity/IFilter.php @@ -0,0 +1,74 @@ + + * @author Morris Jobke + * @author Thomas Müller + * + * @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\Activity; + +/** + * Interface IFilter + * + * @package OCP\Activity + * @since 9.2.0 + */ +interface IFilter { + + /** + * @return string Lowercase a-z and underscore only identifier + * @since 9.2.0 + */ + public function getIdentifier(); + + /** + * @return string A translated string + * @since 9.2.0 + */ + public function getName(); + + /** + * @return int whether the filter should be rather on the top or bottom of + * the admin section. The filters are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. + * @since 9.2.0 + */ + public function getPriority(); + + /** + * @return string Full URL to an icon, empty string when none is given + * @since 9.2.0 + */ + public function getIcon(); + + /** + * @param string[] $types + * @return string[] An array of allowed apps from which activities should be displayed + * @since 9.2.0 + */ + public function filterTypes(array $types); + + /** + * @return string[] An array of allowed apps from which activities should be displayed + * @since 9.2.0 + */ + public function allowedApps(); +} + diff --git a/lib/public/Activity/IManager.php b/lib/public/Activity/IManager.php index c1476e1a2ae..387a1d85144 100644 --- a/lib/public/Activity/IManager.php +++ b/lib/public/Activity/IManager.php @@ -110,6 +110,27 @@ interface IManager { */ public function registerExtension(\Closure $callable); + /** + * @param string $filter Class must implement OCA\Activity\IFilter + * @return void + * @since 9.2.0 + */ + public function registerFilter($filter); + + /** + * @return IFilter[] + * @since 9.2.0 + */ + public function getFilters(); + + /** + * @param string $id + * @return IFilter + * @throws \InvalidArgumentException when the filter was not found + * @since 9.2.0 + */ + public function getFilterById($id); + /** * Will return additional notification types as specified by other apps * @@ -177,9 +198,31 @@ interface IManager { */ public function getGroupParameter($activity); + + /** + * Set the user we need to use + * + * @param string|null $currentUserId + * @throws \UnexpectedValueException If the user is invalid + * @since 9.0.1 + */ + public function setCurrentUserId($currentUserId); + + /** + * Get the user we need to use + * + * Either the user is logged in, or we try to get it from the token + * + * @return string + * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique + * @since 8.1.0 + */ + public function getCurrentUserId(); + /** * @return array * @since 8.0.0 + * @deprecated 9.2.0 - Use getFilters() instead */ public function getNavigation(); @@ -187,6 +230,7 @@ interface IManager { * @param string $filterValue * @return boolean * @since 8.0.0 + * @deprecated 9.2.0 - Use getFilterById() instead */ public function isFilterValid($filterValue); @@ -195,6 +239,7 @@ interface IManager { * @param string $filter * @return array * @since 8.0.0 + * @deprecated 9.2.0 - Use getFilterById()->filterTypes() instead */ public function filterNotificationTypes($types, $filter); @@ -202,27 +247,7 @@ interface IManager { * @param string $filter * @return array * @since 8.0.0 + * @deprecated 9.2.0 - Use getFilterById() instead */ public function getQueryForFilter($filter); - - - /** - * Set the user we need to use - * - * @param string|null $currentUserId - * @throws \UnexpectedValueException If the user is invalid - * @since 9.0.1 - */ - public function setCurrentUserId($currentUserId); - - /** - * Get the user we need to use - * - * Either the user is logged in, or we try to get it from the token - * - * @return string - * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique - * @since 8.1.0 - */ - public function getCurrentUserId(); } -- 2.39.5