diff options
author | Thomas Steur <thomas.steur@googlemail.com> | 2014-06-05 08:44:37 +0400 |
---|---|---|
committer | Thomas Steur <thomas.steur@googlemail.com> | 2014-06-05 08:44:37 +0400 |
commit | 3e03b0a7ca4055b4f05be7d4ec7bcfaacf364eff (patch) | |
tree | 47afa18c0b671f38e17405078bdee156ad020058 /core | |
parent | 0ed11b178860844b97b967f6cfa1ffd12ab2eaab (diff) |
refs #5301 started to simplify scheduled tasks API while staying backwards compatible
Diffstat (limited to 'core')
-rw-r--r-- | core/Menu/MenuAbstract.php | 33 | ||||
-rw-r--r-- | core/Plugin.php | 38 | ||||
-rw-r--r-- | core/Plugin/Manager.php | 33 | ||||
-rw-r--r-- | core/Plugin/Tasks.php | 133 | ||||
-rw-r--r-- | core/TaskScheduler.php | 55 |
5 files changed, 237 insertions, 55 deletions
diff --git a/core/Menu/MenuAbstract.php b/core/Menu/MenuAbstract.php index 4ffbe8f532..06d972f064 100644 --- a/core/Menu/MenuAbstract.php +++ b/core/Menu/MenuAbstract.php @@ -61,42 +61,11 @@ abstract class MenuAbstract extends Singleton return self::$menus; } - $pluginNames = PluginManager::getInstance()->getLoadedPluginsName(); - - self::$menus = array(); - foreach ($pluginNames as $pluginName) { - $menu = $this->findMenuInPlugin($pluginName); - - if (!empty($menu)) { - self::$menus[] = $menu; - } - } + self::$menus = PluginManager::getInstance()->findComponents('Menu', 'Piwik\\Plugin\\Menu'); return self::$menus; } - private function findMenuInPlugin($pluginName) - { - $menuFile = PIWIK_INCLUDE_PATH . '/plugins/' . $pluginName . '/Menu.php'; - - if (!file_exists($menuFile)) { - return; - } - - $klassName = sprintf('Piwik\\Plugins\\%s\\Menu', $pluginName); - - if (!class_exists($klassName)) { - return; - } - - if (!is_subclass_of($klassName, 'Piwik\\Plugin\\Menu')) { - Log::warning(sprintf('Cannot use menu for plugin %s, class %s does not extend Piwik\Plugin\Menu', $pluginName, $klassName)); - return; - } - - return new $klassName; - } - /** * Adds a new entry to the menu. * diff --git a/core/Plugin.php b/core/Plugin.php index 1392fc3bc0..0c2c8e8d8b 100644 --- a/core/Plugin.php +++ b/core/Plugin.php @@ -277,6 +277,44 @@ class Plugin } /** + * Tries to find a component such as a Menu or Tasks within this plugin. + * + * @param string $componentName The name of the component you want to look for. In case you request a + * component named 'Menu' it'll look for a file named 'Menu.php' within the + * root of the plugin folder that implements a class named + * Piwik\Plugin\$PluginName\Menu . If such a file exists but does not implement + * this class it'll silently ignored. + * @param string $expectedSubclass If not empty, a check will be performed whether a found file extends the + * given subclass. If the requested file exists but does not extend this class + * a warning will be shown to advice a developer to extend this certain class. + * + * @return \stdClass|null Null if the requested component does not exist or an instance of the found + * component. + */ + public function findComponent($componentName, $expectedSubclass) + { + $componentFile = sprintf('%s/plugins/%s/%s.php', PIWIK_INCLUDE_PATH, $this->pluginName, $componentName); + + if (!file_exists($componentFile)) { + return; + } + + $klassName = sprintf('Piwik\\Plugins\\%s\\%s', $this->pluginName, $componentName); + + if (!class_exists($klassName)) { + return; + } + + if (!empty($expectedSubclass) && !is_subclass_of($klassName, $expectedSubclass)) { + Log::warning(sprintf('Cannot use component %s for plugin %s, class %s does not extend %s', + $componentName, $this->pluginName, $klassName, $expectedSubclass)); + return; + } + + return new $klassName; + } + + /** * Detect whether there are any missing dependencies. * * @param null $piwikVersion Defaults to the current Piwik version diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php index 9c481bb03b..5a31e484e4 100644 --- a/core/Plugin/Manager.php +++ b/core/Plugin/Manager.php @@ -34,6 +34,7 @@ class Manager extends Singleton protected $pluginsToLoad = array(); protected $doLoadPlugins = true; + /** * @var Plugin[] */ @@ -325,6 +326,38 @@ class Manager extends Singleton } /** + * Tries to find the given components such as a Menu or Tasks implemented by plugins. + * This method won't cache the found components. If you need to find the same component multiple times you might + * want to cache the result to save a tiny bit of time. + * + * @param string $componentName The name of the component you want to look for. In case you request a + * component named 'Menu' it'll look for a file named 'Menu.php' within the + * root of all plugin folders that implement a class named + * Piwik\Plugin\$PluginName\Menu. + * @param string $expectedSubclass If not empty, a check will be performed whether a found file extends the + * given subclass. If the requested file exists but does not extend this class + * a warning will be shown to advice a developer to extend this certain class. + * + * @return \stdClass[] + */ + public function findComponents($componentName, $expectedSubclass) + { + $pluginNames = $this->getLoadedPlugins(); + + $components = array(); + + foreach ($pluginNames as $plugin) { + $component = $plugin->findComponent($componentName, $expectedSubclass); + + if (!empty($component)) { + $components[] = $component; + } + } + + return $components; + } + + /** * Uninstalls a Plugin (deletes plugin files from the disk) * Only deactivated plugins can be uninstalled * diff --git a/core/Plugin/Tasks.php b/core/Plugin/Tasks.php new file mode 100644 index 0000000000..2b22c90825 --- /dev/null +++ b/core/Plugin/Tasks.php @@ -0,0 +1,133 @@ +<?php +/** + * Piwik - Open source web analytics + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugin; + +use Piwik\ScheduledTask; +use Piwik\ScheduledTime; + +class Tasks +{ + /** + * @var ScheduledTask[] + */ + private $tasks = array(); + + const LOWEST_PRIORITY = ScheduledTask::LOWEST_PRIORITY; + const LOW_PRIORITY = ScheduledTask::LOW_PRIORITY; + const NORMAL_PRIORITY = ScheduledTask::NORMAL_PRIORITY; + const HIGH_PRIORITY = ScheduledTask::HIGH_PRIORITY; + const HIGHEST_PRIORITY = ScheduledTask::HIGHEST_PRIORITY; + + public function schedule() + { + } + + /** + * @return ScheduledTask[] $tasks + */ + public function getScheduledTasks() + { + return $this->tasks; + } + + /** + * Schedule the given tasks/method to run once every hour. + * + * @param string $methodName The name of the method that will be called when the task is being + * exectuted. To make it work you need to create a public method having the + * given method name in your Tasks class. + * @param null|string $methodParameter Can be null if the task does not need any parameter or a string. It is not + * possible to specify multiple parameters as an array etc. If you need to + * pass multiple parameters separate them via any characters such as '###'. + * For instance '$param1###$param2###$param3' + * @param int $priority Can be any constant such as self::LOW_PRIORITY + * + * @return ScheduledTime + * @api + */ + protected function hourly($methodName, $methodParameter = null, $priority = self::NORMAL_PRIORITY) + { + return $this->custom($this, $methodName, $methodParameter, 'hourly', $priority); + } + + /** + * Schedule the given tasks/method to run once every day. + * + * See {@link hourly()} + * @api + */ + protected function daily($methodName, $methodParameter = null, $priority = self::NORMAL_PRIORITY) + { + return $this->custom($this, $methodName, $methodParameter, 'daily', $priority); + } + + /** + * Schedule the given tasks/method to run once every week. + * + * See {@link hourly()} + * @api + */ + protected function weekly($methodName, $methodParameter = null, $priority = self::NORMAL_PRIORITY) + { + return $this->custom($this, $methodName, $methodParameter, 'weekly', $priority); + } + + /** + * Schedule the given tasks/method to run once every month. + * + * See {@link hourly()} + * @api + */ + protected function monthly($methodName, $methodParameter = null, $priority = self::NORMAL_PRIORITY) + { + return $this->custom($this, $methodName, $methodParameter, 'monthly', $priority); + } + + /** + * Schedules the given tasks/method to run depending at the given scheduled time. Unlike the convenient methods + * such as {@link hourly()} you need to specify the object on which the given method should be called. This can be + * either an instance of a class or a class name. For more information about these parameters see {@link hourly()} + * + * @param string|object $objectOrClassName + * @param string $methodName + * @param null|string $methodParameter + * @param string|ScheduledTime $time + * @param int $priority + * + * @return ScheduledTime + * + * @throws \Exception If a wrong time format is given. Needs to be either a string such as 'daily', 'weekly', ... + * or an instance of {@link Piwik\ScheduledTime} + * + * @api + */ + protected function custom($objectOrClassName, $methodName, $methodParameter, $time, $priority = self::NORMAL_PRIORITY) + { + if (is_string($time)) { + $time = ScheduledTime::factory($time); + } + + if (!($time instanceof ScheduledTime)) { + throw new \Exception('$time should be an instance of ScheduledTime'); + } + + if (!is_string($objectOrClassName)) { + $objectOrClassName = get_class($objectOrClassName); + } + + $this->addScheduledTask(new ScheduledTask($objectOrClassName, $methodName, $methodParameter, $time, $priority)); + + return $time; + } + + protected function addScheduledTask(ScheduledTask $task) + { + $this->tasks[] = $task; + } +}
\ No newline at end of file diff --git a/core/TaskScheduler.php b/core/TaskScheduler.php index a3eab34c24..85c71c9ef8 100644 --- a/core/TaskScheduler.php +++ b/core/TaskScheduler.php @@ -10,6 +10,7 @@ namespace Piwik; use Exception; +use Piwik\Plugin\Manager as PluginManager; // When set to true, all scheduled tasks will be triggered in all requests (careful!) define('DEBUG_FORCE_SCHEDULED_TASKS', false); @@ -52,7 +53,7 @@ define('DEBUG_FORCE_SCHEDULED_TASKS', false); */ class TaskScheduler extends Singleton { - const GET_TASKS_EVENT = "TaskScheduler.getScheduledTasks"; + const GET_TASKS_EVENT = 'TaskScheduler.getScheduledTasks'; private $isRunning = false; @@ -81,34 +82,42 @@ class TaskScheduler extends Singleton return self::getInstance()->doRunTasks(); } - private function doRunTasks() + + // for backwards compatibility + private function collectTasksRegisteredViaEvent() { - // collect tasks $tasks = array(); /** - * Triggered during scheduled task execution. Collects all the tasks to run. - * - * Subscribe to this event to schedule code execution on an hourly, daily, weekly or monthly - * basis. - * - * **Example** - * - * public function getScheduledTasks(&$tasks) - * { - * $tasks[] = new ScheduledTask( - * 'Piwik\Plugins\CorePluginsAdmin\MarketplaceApiClient', - * 'clearAllCacheEntries', - * null, - * ScheduledTime::factory('daily'), - * ScheduledTask::LOWEST_PRIORITY - * ); - * } - * - * @param ScheduledTask[] &$tasks List of tasks to run periodically. + * @ignore */ Piwik::postEvent(self::GET_TASKS_EVENT, array(&$tasks)); - /** @var ScheduledTask[] $tasks */ + + return $tasks; + } + + private function getScheduledTasks() + { + /** @var \Piwik\ScheduledTask[] $tasks */ + $tasks = $this->collectTasksRegisteredViaEvent(); + + /** @var \Piwik\Plugin\Tasks[] $pluginTasks */ + $pluginTasks = PluginManager::getInstance()->findComponents('Tasks', 'Piwik\\Plugin\\Tasks'); + foreach ($pluginTasks as $pluginTask) { + + $pluginTask->schedule(); + + foreach ($pluginTask->getScheduledTasks() as $task) { + $tasks[] = $task; + } + } + + return $tasks; + } + + private function doRunTasks() + { + $tasks = $this->getScheduledTasks(); // remove from timetable tasks that are not active anymore $this->timetable->removeInactiveTasks($tasks); |