1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-02-24 12:03:21 +01:00

[feature/system-cron] Refactored cron task naming, loading and running.

PHPBB3-9596
This commit is contained in:
Oleg Pudeyev 2010-04-17 03:13:30 -04:00
parent 61e0285da8
commit 0f9b3bcc27
17 changed files with 261 additions and 340 deletions

View File

@ -1,164 +0,0 @@
<?php
/**
*
* @package phpBB3
* @version $Id$
* @copyright (c) 2010 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Cron class
* @package phpBB3
*/
class cron
{
var $tasks = array();
function cron()
{
global $config, $phpbb_root_path, $phpEx;
$modules = $config['cron_modules'];
$modules = explode(',', $modules);
foreach ($modules as $module)
{
// explode will return array("") when exploding an empty string;
// users may also specify something like foo,,bar.
// Account for module being possibly empty
if (!empty($module))
{
// Misspelling or specifying nonexistent modules here may make the board
// unusable due to error messages screwing up header output
include_once($phpbb_root_path . "includes/cron/$module.$phpEx");
$cron_class = "cron_tasks_$module";
$object = new $cron_class;
foreach ($object->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 '<img src="' . append_sid($phpbb_root_path . 'cron.' . $phpEx, 'cron_type=' . $cron_type) . '" width="1" height="1" alt="cron" />';
}
function run_task($cron_type)
{
call_user_func(array($this->tasks[$cron_type]['object'], 'run_' . $cron_type));
}
}

View File

@ -0,0 +1,175 @@
<?php
/**
*
* @package phpBB3
* @version $Id$
* @copyright (c) 2010 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Cron manager class.
*
* Finds installed cron tasks, stores task objects, provides task selection.
*
* @package phpBB3
*/
class cron_manager
{
private $tasks = array();
public function __construct()
{
$task_files = $this->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 '<img src="' . $url . '" width="1" height="1" alt="cron" />';
}
}

View File

@ -0,0 +1,68 @@
<?php
/**
*
* @package phpBB3
* @version $Id$
* @copyright (c) 2010 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Cron task wrapper class.
* Enhances cron tasks with convenience methods that work identically for all tasks.
*
* @package phpBB3
*/
class cron_task_wrapper
{
public function __construct($task)
{
$this->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);
}
}

View File

@ -1,163 +0,0 @@
<?php
/**
*
* @package phpBB3
* @version $Id$
* @copyright (c) 2010 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Standard cron tasks
* @package phpBB3
*/
class cron_tasks_standard
{
var $tasks = array(
// key: cron type
// values: config name for enable/disable flag,
// whether to check condition function to determine if the task can/should be run,
// config name for interval,
// config name for last run time,
// whether task should be considered in phpbb cron mode,
// whether task should be considered in system cron mode,
// whether task requires special code generation
'prune_all_forums' => 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 '<img src="' . append_sid($phpbb_root_path . 'cron.' . $phpEx, 'cron_type=prune_forum&amp;f=' . $forum_id) . '" alt="cron" width="1" height="1" />';
}
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();
}
}

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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', '<img src="' . $url . '" width="1" height="1" alt="cron" />');
}
}

View File

@ -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', '<img src="' . $url . '" width="1" height="1" alt="cron" />');
}
}
// Forum rules and subscription info