diff --git a/phpBB/includes/cron.php b/phpBB/includes/cron.php
deleted file mode 100644
index b9a1bb778a..0000000000
--- a/phpBB/includes/cron.php
+++ /dev/null
@@ -1,164 +0,0 @@
-tasks as $cron_type => $params)
- {
- $params['object'] = $object;
- $this->tasks[$cron_type] = $params;
- }
- }
- }
- }
-
- function is_valid_task($cron_type)
- {
- return isset($this->tasks[$cron_type]);
- }
-
- function is_task_runnable($cron_type, $args=null)
- {
- global $config;
- $time_now = time();
- $cron_params = $this->tasks[$cron_type];
- if ($cron_params['enable_config'] && !$config[$cron_params['enable_config']])
- {
- return false;
- }
- if ($cron_param['custom_condition'])
- {
- $callable = array($cron_params['object'], $cron_type . '_condition');
- if ($args)
- {
- $answer = call_user_func_array($callable, $args);
- } else
- {
- $answer = call_user_func($callable);
- }
- if (!$answer)
- {
- return false;
- }
- }
- if ($time_now - $config[$cron_params['interval_config']] > $config[$cron_params['last_run_config']])
- {
- return true;
- }
- return false;
- }
-
- function is_task_shutdown_function_compatible($cron_type)
- {
- $cron_params = $this->tasks[$cron_type];
- if (isset($cron_params['shutdown_function_condition']))
- {
- return call_user_func(array($cron_params->object, $cron_type . '_shutdown_function_condition'));
- } else
- {
- return true;
- }
- }
-
- function determine_cron_mode_param()
- {
- global $config;
- if ($config['use_system_cron'])
- {
- $mode = 'run_from_system';
- } else
- {
- $mode_param = 'run_from_phpbb';
- }
- return $mode_param;
- }
-
- function find_one_runnable_task()
- {
- $mode_param = $this->determine_cron_mode_param();
- foreach ($this->tasks as $cron_type => $cron_params)
- {
- if ($cron_params[$mode_param] && $this->is_task_runnable($cron_type))
- {
- return $cron_type;
- }
- }
- return null;
- }
-
- function find_all_runnable_tasks()
- {
- $mode_param = $this->determine_cron_mode_param();
- $tasks = array();
- foreach ($this->tasks as $cron_type => $cron_params)
- {
- if ($cron_params[$mode_param] && $this->is_task_runnable($cron_type))
- {
- $tasks[] = $cron_type;
- }
- }
- return $tasks;
- }
-
- function generate_task_code($cron_type, $args=array())
- {
- $cron_params = $this->tasks[$cron_type];
- if ($cron_params['custom_code'])
- {
- $code = call_user_func_array(array($cron_params['object'], $cron_type . '_code'), $args);
- } else
- {
- $code = $this->generate_generic_task_code($cron_type);
- }
- return $code;
- }
-
- function generate_generic_task_code($cron_type)
- {
- global $phpbb_root_path, $phpEx;
- return '
';
- }
-
- function run_task($cron_type)
- {
- call_user_func(array($this->tasks[$cron_type]['object'], 'run_' . $cron_type));
- }
-}
diff --git a/phpBB/includes/cron_lock.php b/phpBB/includes/cron/cron_lock.php
similarity index 100%
rename from phpBB/includes/cron_lock.php
rename to phpBB/includes/cron/cron_lock.php
diff --git a/phpBB/includes/cron/cron_manager.php b/phpBB/includes/cron/cron_manager.php
new file mode 100644
index 0000000000..5ee06ac102
--- /dev/null
+++ b/phpBB/includes/cron/cron_manager.php
@@ -0,0 +1,175 @@
+find_cron_task_files();
+ $this->load_tasks($task_files);
+ }
+
+ /**
+ * Finds cron task files.
+ *
+ * A cron task file must follow the naming convention:
+ * includes/cron/tasks/$mod/$name.php.
+ * $mod is core for tasks that are part of phpbb.
+ * Modifications should use their name as $mod.
+ * $name is the name of the cron task.
+ * Cron task is expected to be a class named cron_task_${mod}_${name}.
+ *
+ * Todo: consider caching found task file list in global cache.
+ */
+ public function find_cron_task_files()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $tasks_root_path = $phpbb_root_path . 'includes/cron/tasks';
+ $dir = opendir($tasks_root_path);
+ $task_dirs = array();
+ while (($entry = readdir($dir)) !== false)
+ {
+ // ignore ., .. and dot directories
+ // todo: change is_dir to account for symlinks
+ if ($entry[0] == '.' || !is_dir($entry))
+ {
+ continue;
+ }
+ $task_dirs[] = $entry;
+ }
+ closedir($dir);
+
+ $ext = '.' . $phpEx;
+ $ext_length = strlen($ext);
+ $task_files = array();
+ foreach ($task_dirs as $task_dir)
+ {
+ $path = $phpbb_root_path . 'includes/cron/tasks/' . $task_dir;
+ $dir = opendir($path);
+ while (($entry = readdir($dir)) !== false && substr($entry, -$ext_length) == $ext)
+ {
+ $task_file = substr($entry, 0, -$ext_length);
+ $task_files[] = array($task_dir, $task_file);
+ }
+ closedir($dir);
+ }
+ return $task_files;
+ }
+
+ /**
+ * Checks whether $name is a valid identifier, and therefore part of valid cron task class name.
+ */
+ public function is_valid_name($name)
+ {
+ return preg_match('/^[a-zA-Z][a-zA-Z0-9_]*$/', $name);
+ }
+
+ public function load_tasks($task_files)
+ {
+ global $phpbb_root_path, $phpEx;
+
+ foreach ($task_files as $task_file)
+ {
+ list($mod, $filename) = $task_file;
+ if ($this->is_valid_name($mod) && $this->is_valid_name($filename))
+ {
+ include_once($phpbb_root_path . "includes/cron/$mod/$filename.$phpEx");
+ $class = "cron_task_${mod}_${filename}";
+ $object = new $class;
+ $this->tasks[] = $object;
+ }
+ }
+ }
+
+ /**
+ * Finds a task that is ready to run.
+ *
+ * If several tasks are ready, any one of them could be returned.
+ */
+ function find_one_ready_task()
+ {
+ foreach ($this->tasks as $task)
+ {
+ if ($task->is_ready())
+ {
+ return $task;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Finds all tasks that are ready to run.
+ */
+ function find_all_ready_tasks()
+ {
+ $tasks = array();
+ foreach ($this->tasks as $task)
+ {
+ if ($task->is_ready())
+ {
+ $tasks[] = $task;
+ }
+ }
+ return $tasks;
+ }
+
+ /**
+ * Finds a task by name.
+ *
+ * Web runner uses this method to resolve names to tasks.
+ */
+ function find_task($name)
+ {
+ foreach ($this->tasks as $task)
+ {
+ if ($task->get_name() == $name)
+ {
+ return $task;
+ }
+ }
+ return null;
+ }
+
+ function instantiate_task($name, $args)
+ {
+ $task = $this->find_task($name);
+ if ($task)
+ {
+ $class = get_class($task);
+ $task = new $class($args);
+ }
+ return $task;
+ }
+
+ function generate_generic_task_code($cron_type)
+ {
+ global $phpbb_root_path, $phpEx;
+ return '
';
+ }
+}
diff --git a/phpBB/includes/cron_task.php b/phpBB/includes/cron/cron_task.php
similarity index 100%
rename from phpBB/includes/cron_task.php
rename to phpBB/includes/cron/cron_task.php
diff --git a/phpBB/includes/cron_task_base.php b/phpBB/includes/cron/cron_task_base.php
similarity index 100%
rename from phpBB/includes/cron_task_base.php
rename to phpBB/includes/cron/cron_task_base.php
diff --git a/phpBB/includes/cron/cron_task_wrapper.php b/phpBB/includes/cron/cron_task_wrapper.php
new file mode 100644
index 0000000000..3919e4f049
--- /dev/null
+++ b/phpBB/includes/cron/cron_task_wrapper.php
@@ -0,0 +1,68 @@
+task = $task;
+ }
+
+ /**
+ * Returns whether the wrapped task is ready to run.
+ *
+ * A task is ready to run when it is runnable according to current configuration
+ * and enough time has passed since it was last run.
+ */
+ public function is_ready()
+ {
+ return $this->task->is_runnable() && $this->task->should_run();
+ }
+
+ /**
+ * Returns the name of wrapped task.
+ */
+ public function get_name()
+ {
+ $class = get_class($this->task);
+ return preg_replace('/^cron_task_/', '', $class);
+ }
+
+ public function get_url()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $name = $this->get_name();
+ $url = append_sid($phpbb_root_path . 'cron.' . $phpEx, 'cron_type=' . $name);
+ return $url;
+ }
+
+ /**
+ * Forwards all other method calls to the wrapped task implementation.
+ */
+ public function __call($name, $args)
+ {
+ return call_user_func_array(array($this->task, $name), $args);
+ }
+}
diff --git a/phpBB/includes/cron/standard.php b/phpBB/includes/cron/standard.php
deleted file mode 100644
index 1cb8738f17..0000000000
--- a/phpBB/includes/cron/standard.php
+++ /dev/null
@@ -1,163 +0,0 @@
- array(
- 'custom_condition' => true,
- 'run_from_system' => true,
- ),
- 'prune_forum' => array(
- 'custom_condition' => true,
- 'custom_code' => true,
- ),
- 'queue' => array(
- 'custom_condition' => true,
- 'interval_config' => 'queue_interval_config',
- 'last_run_config' => 'last_queue_run',
- 'run_from_phpbb' => true,
- 'run_from_system' => true,
- 'shutdown_function_condition' => true,
- ),
- 'tidy_cache' => array(
- 'custom_condition' => true,
- 'interval_config' => 'cache_gc',
- 'last_run_config' => 'cache_last_gc',
- 'run_from_phpbb' => true,
- 'run_from_system' => true,
- ),
- 'tidy_database' => array(
- 'interval_config' => 'database_gc',
- 'last_run_config' => 'database_last_gc',
- 'run_from_phpbb' => true,
- 'run_from_system' => true,
- ),
- 'tidy_search' => array(
- 'interval_config' => 'search_gc',
- 'last_run_config' => 'search_last_gc',
- 'run_from_phpbb' => true,
- 'run_from_system' => true,
- ),
- 'tidy_sessions' => array(
- 'interval_config' => 'session_gc',
- 'last_run_config' => 'session_last_gc',
- 'run_from_phpbb' => true,
- 'run_from_system' => true,
- ),
- 'tidy_warnings' => array(
- 'enable_config' => 'warnings_expire_days',
- 'interval_config' => 'warnings_gc',
- 'last_run_config' => 'warnings_last_gc',
- 'run_from_phpbb' => true,
- 'run_from_system' => true,
- ),
- );
-
- function prune_forum_condition($forum_data) {
- return $forum_data['enable_prune'] && $forum_data['prune_next'] < time();
- }
-
- function prune_forum_code($forum_id) {
- global $phpbb_root_path, $phpEx;
- return '
';
- }
-
- function run_prune_forum() {
- }
-
- function queue_condition() {
- global $phpbb_root_path, $phpEx;
- return file_exists($phpbb_root_path . 'cache/queue.' . $phpEx);
- }
-
- function queue_shutdown_function_condition() {
- global $config;
- return !$config['smtp_delivery'];
- }
-
- function run_queue() {
- global $phpbb_root_path, $phpEx;
- include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
- $queue = new queue();
- $queue->process();
- }
-
- function tidy_cache_condition() {
- global $cache;
- return method_exists($cache, 'tidy');
- }
-
- function run_tidy_cache() {
- global $cache;
- $cache->tidy();
- }
-
- function run_tidy_database() {
- include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
- tidy_database();
- }
-
- function tidy_search_condition() {
- global $phpbb_root_path, $phpEx, $config;
-
- // Select the search method
- $search_type = basename($config['search_type']);
-
- return file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx);
- }
-
- function run_tidy_search() {
- global $phpbb_root_path, $phpEx, $config, $error;
-
- // Select the search method
- $search_type = basename($config['search_type']);
-
- include_once("{$phpbb_root_path}includes/search/$search_type.$phpEx");
-
- // We do some additional checks in the module to ensure it can actually be utilised
- $error = false;
- $search = new $search_type($error);
-
- if (!$error) {
- $search->tidy();
- }
- }
-
- function run_tidy_sessions() {
- global $user;
- $user->session_gc();
- }
-
- function run_tidy_warnings() {
- include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
- tidy_warnings();
- }
-}
diff --git a/phpBB/includes/cron_tasks/standard/prune_all_forums.php b/phpBB/includes/cron/tasks/core/prune_all_forums.php
similarity index 95%
rename from phpBB/includes/cron_tasks/standard/prune_all_forums.php
rename to phpBB/includes/cron/tasks/core/prune_all_forums.php
index 569752dcb0..13286de2b0 100644
--- a/phpBB/includes/cron_tasks/standard/prune_all_forums.php
+++ b/phpBB/includes/cron/tasks/core/prune_all_forums.php
@@ -25,7 +25,7 @@ if (!defined('IN_PHPBB'))
*
* @package phpBB3
*/
-class prune_all_forums_cron_task extends cron_task_base
+class cron_task_core_prune_all_forums extends cron_task_base
{
/**
* Runs this cron task.
diff --git a/phpBB/includes/cron_tasks/standard/prune_forum.php b/phpBB/includes/cron/tasks/core/prune_forum.php
similarity index 96%
rename from phpBB/includes/cron_tasks/standard/prune_forum.php
rename to phpBB/includes/cron/tasks/core/prune_forum.php
index f4ef2ea6dd..4925447162 100644
--- a/phpBB/includes/cron_tasks/standard/prune_forum.php
+++ b/phpBB/includes/cron/tasks/core/prune_forum.php
@@ -25,7 +25,7 @@ if (!defined('IN_PHPBB'))
*
* @package phpBB3
*/
-class prune_forum_cron_task extends cron_task_base implements parametrized_cron_task
+class cron_task_core_prune_forum extends cron_task_base implements parametrized_cron_task
{
/**
* Constructor.
diff --git a/phpBB/includes/cron_tasks/standard/queue.php b/phpBB/includes/cron/tasks/core/queue.php
similarity index 96%
rename from phpBB/includes/cron_tasks/standard/queue.php
rename to phpBB/includes/cron/tasks/core/queue.php
index 6a69799ef4..d7dfeb9319 100644
--- a/phpBB/includes/cron_tasks/standard/queue.php
+++ b/phpBB/includes/cron/tasks/core/queue.php
@@ -21,7 +21,7 @@ if (!defined('IN_PHPBB'))
*
* @package phpBB3
*/
-class queue_cron_task extends cron_task_base
+class cron_task_core_queue extends cron_task_base
{
/**
* Runs this cron task.
diff --git a/phpBB/includes/cron_tasks/standard/tidy_cache.php b/phpBB/includes/cron/tasks/core/tidy_cache.php
similarity index 93%
rename from phpBB/includes/cron_tasks/standard/tidy_cache.php
rename to phpBB/includes/cron/tasks/core/tidy_cache.php
index 7c47be06c1..69038a8a5a 100644
--- a/phpBB/includes/cron_tasks/standard/tidy_cache.php
+++ b/phpBB/includes/cron/tasks/core/tidy_cache.php
@@ -21,7 +21,7 @@ if (!defined('IN_PHPBB'))
*
* @package phpBB3
*/
-class tidy_cache_cron_task extends cron_task_base
+class cron_task_core_tidy_cache extends cron_task_base
{
/**
* Runs this cron task.
diff --git a/phpBB/includes/cron_tasks/standard/tidy_database.php b/phpBB/includes/cron/tasks/core/tidy_database.php
similarity index 92%
rename from phpBB/includes/cron_tasks/standard/tidy_database.php
rename to phpBB/includes/cron/tasks/core/tidy_database.php
index 16a17b3538..c6c2a60445 100644
--- a/phpBB/includes/cron_tasks/standard/tidy_database.php
+++ b/phpBB/includes/cron/tasks/core/tidy_database.php
@@ -21,7 +21,7 @@ if (!defined('IN_PHPBB'))
*
* @package phpBB3
*/
-class tidy_database_cron_task extends cron_task_base
+class cron_task_core_tidy_database extends cron_task_base
{
/**
* Runs this cron task.
diff --git a/phpBB/includes/cron_tasks/standard/tidy_search.php b/phpBB/includes/cron/tasks/core/tidy_search.php
similarity index 96%
rename from phpBB/includes/cron_tasks/standard/tidy_search.php
rename to phpBB/includes/cron/tasks/core/tidy_search.php
index ac42c26689..0f409d114a 100644
--- a/phpBB/includes/cron_tasks/standard/tidy_search.php
+++ b/phpBB/includes/cron/tasks/core/tidy_search.php
@@ -23,7 +23,7 @@ if (!defined('IN_PHPBB'))
*
* @package phpBB3
*/
-class tidy_sessions_cron_task extends cron_task_base
+class cron_task_core_tidy_sessions extends cron_task_base
{
/**
* Runs this cron task.
diff --git a/phpBB/includes/cron_tasks/standard/tidy_sessions.php b/phpBB/includes/cron/tasks/core/tidy_sessions.php
similarity index 91%
rename from phpBB/includes/cron_tasks/standard/tidy_sessions.php
rename to phpBB/includes/cron/tasks/core/tidy_sessions.php
index 6ff2dee14b..ea6aa70699 100644
--- a/phpBB/includes/cron_tasks/standard/tidy_sessions.php
+++ b/phpBB/includes/cron/tasks/core/tidy_sessions.php
@@ -21,7 +21,7 @@ if (!defined('IN_PHPBB'))
*
* @package phpBB3
*/
-class tidy_sessions_cron_task extends cron_task_base
+class cron_task_core_tidy_sessions extends cron_task_base
{
/**
* Runs this cron task.
diff --git a/phpBB/includes/cron_tasks/standard/tidy_warnings.php b/phpBB/includes/cron/tasks/core/tidy_warnings.php
similarity index 94%
rename from phpBB/includes/cron_tasks/standard/tidy_warnings.php
rename to phpBB/includes/cron/tasks/core/tidy_warnings.php
index 059125b18d..c1ab14d788 100644
--- a/phpBB/includes/cron_tasks/standard/tidy_warnings.php
+++ b/phpBB/includes/cron/tasks/core/tidy_warnings.php
@@ -23,7 +23,7 @@ if (!defined('IN_PHPBB'))
*
* @package phpBB3
*/
-class tidy_warnings_cron_task extends cron_task_base
+class cron_task_core_tidy_warnings extends cron_task_base
{
/**
* Runs this cron task.
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index eb787bfc62..418e8dc51d 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -4617,11 +4617,12 @@ function page_footer($run_cron = true)
if ($call_cron)
{
global $cron;
- $cron_type = $cron->find_one_runnable_task();
+ $task = $cron->find_one_ready_task();
- if ($cron_type)
+ if ($task)
{
- $template->assign_var('RUN_CRON_TASK', $cron->generate_task_code($cron_type));
+ $url = $task->get_url();
+ $template->assign_var('RUN_CRON_TASK', '
');
}
}
diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php
index 8a06e28394..a3fd9fa6fb 100644
--- a/phpBB/viewforum.php
+++ b/phpBB/viewforum.php
@@ -193,9 +193,13 @@ if ($forum_data['forum_topics_per_page'])
}
// Do the forum Prune thang - cron type job ...
-if (!$config['use_system_cron'] && $cron->is_task_runnable('prune_forum', array($forum_data)))
+if (!$config['use_system_cron'])
{
- $template->assign_var('RUN_CRON_TASK', $cron->generate_task_code('prune_forum', array($forum_id)));
+ $task = $cron->instantiate_task('core_prune_forum', $forum_data);
+ if ($task && $task->is_ready()) {
+ $url = $task->get_url();
+ $template->assign_var('RUN_CRON_TASK', '
');
+ }
}
// Forum rules and subscription info