diff --git a/phpBB/common.php b/phpBB/common.php
index 0ac7cbbd86..3586031c36 100644
--- a/phpBB/common.php
+++ b/phpBB/common.php
@@ -239,3 +239,9 @@ foreach ($cache->obtain_hooks() as $hook)
{
@include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx);
}
+
+if (!$config['use_system_cron'])
+{
+ require($phpbb_root_path . 'includes/cron.' . $phpEx);
+ $cron = new cron();
+}
diff --git a/phpBB/cron.php b/phpBB/cron.php
index 4462f52e93..1dbe1768c1 100644
--- a/phpBB/cron.php
+++ b/phpBB/cron.php
@@ -15,271 +15,58 @@ define('IN_CRON', true);
$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
+include($phpbb_root_path . 'includes/cron_lock.' . $phpEx);
// Do not update users last page entry
$user->session_begin(false);
$auth->acl($user->data);
-$cron_type = request_var('cron_type', '');
-$use_shutdown_function = (@function_exists('register_shutdown_function')) ? true : false;
+function output_image() {
+ // Output transparent gif
+ header('Cache-Control: no-cache');
+ header('Content-type: image/gif');
+ header('Content-length: 43');
-// Output transparent gif
-header('Cache-Control: no-cache');
-header('Content-type: image/gif');
-header('Content-length: 43');
+ echo base64_decode('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==');
-echo base64_decode('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==');
-
-// test without flush ;)
-// flush();
-
-//
-if (!isset($config['cron_lock']))
-{
- set_config('cron_lock', '0', true);
+ // test without flush ;)
+ // flush();
}
-// make sure cron doesn't run multiple times in parallel
-if ($config['cron_lock'])
-{
- // if the other process is running more than an hour already we have to assume it
- // aborted without cleaning the lock
- $time = explode(' ', $config['cron_lock']);
- $time = $time[0];
-
- if ($time + 3600 >= time())
- {
- exit;
+function do_cron($run_tasks) {
+ global $cron_lock;
+
+ foreach ($run_tasks as $cron_type) {
+ $cron->run_task($cron_type);
}
-}
-
-define('CRON_ID', time() . ' ' . unique_id());
-
-$sql = 'UPDATE ' . CONFIG_TABLE . "
- SET config_value = '" . $db->sql_escape(CRON_ID) . "'
- WHERE config_name = 'cron_lock' AND config_value = '" . $db->sql_escape($config['cron_lock']) . "'";
-$db->sql_query($sql);
-
-// another cron process altered the table between script start and UPDATE query so exit
-if ($db->sql_affectedrows() != 1)
-{
- exit;
-}
-
-/**
-* Run cron-like action
-* Real cron-based layer will be introduced in 3.2
-*/
-switch ($cron_type)
-{
- case 'queue':
-
- if (time() - $config['queue_interval'] <= $config['last_queue_run'] || !file_exists($phpbb_root_path . 'cache/queue.' . $phpEx))
- {
- break;
- }
-
- // A user reported using the mail() function while using shutdown does not work. We do not want to risk that.
- if ($use_shutdown_function && !$config['smtp_delivery'])
- {
- $use_shutdown_function = false;
- }
-
- include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
- $queue = new queue();
-
- if ($use_shutdown_function)
- {
- register_shutdown_function(array(&$queue, 'process'));
- }
- else
- {
- $queue->process();
- }
-
- break;
-
- case 'tidy_cache':
-
- if (time() - $config['cache_gc'] <= $config['cache_last_gc'] || !method_exists($cache, 'tidy'))
- {
- break;
- }
-
- if ($use_shutdown_function)
- {
- register_shutdown_function(array(&$cache, 'tidy'));
- }
- else
- {
- $cache->tidy();
- }
-
- break;
-
- case 'tidy_search':
-
- // Select the search method
- $search_type = basename($config['search_type']);
-
- if (time() - $config['search_gc'] <= $config['search_last_gc'] || !file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx))
- {
- break;
- }
-
- 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)
- {
- break;
- }
-
- if ($use_shutdown_function)
- {
- register_shutdown_function(array(&$search, 'tidy'));
- }
- else
- {
- $search->tidy();
- }
-
- break;
-
- case 'tidy_warnings':
-
- if (time() - $config['warnings_gc'] <= $config['warnings_last_gc'])
- {
- break;
- }
-
- include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
-
- if ($use_shutdown_function)
- {
- register_shutdown_function('tidy_warnings');
- }
- else
- {
- tidy_warnings();
- }
-
- break;
-
- case 'tidy_database':
-
- if (time() - $config['database_gc'] <= $config['database_last_gc'])
- {
- break;
- }
-
- include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
-
- if ($use_shutdown_function)
- {
- register_shutdown_function('tidy_database');
- }
- else
- {
- tidy_database();
- }
-
- break;
-
- case 'tidy_sessions':
-
- if (time() - $config['session_gc'] <= $config['session_last_gc'])
- {
- break;
- }
-
- if ($use_shutdown_function)
- {
- register_shutdown_function(array(&$user, 'session_gc'));
- }
- else
- {
- $user->session_gc();
- }
-
- break;
-
- case 'prune_forum':
-
- $forum_id = request_var('f', 0);
-
- $sql = 'SELECT forum_id, prune_next, enable_prune, prune_days, prune_viewed, forum_flags, prune_freq
- FROM ' . FORUMS_TABLE . "
- WHERE forum_id = $forum_id";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$row)
- {
- break;
- }
-
- // Do the forum Prune thang
- if ($row['prune_next'] < time() && $row['enable_prune'])
- {
- include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
-
- if ($row['prune_days'])
- {
- if ($use_shutdown_function)
- {
- register_shutdown_function('auto_prune', $row['forum_id'], 'posted', $row['forum_flags'], $row['prune_days'], $row['prune_freq']);
- }
- else
- {
- auto_prune($row['forum_id'], 'posted', $row['forum_flags'], $row['prune_days'], $row['prune_freq']);
- }
- }
-
- if ($row['prune_viewed'])
- {
- if ($use_shutdown_function)
- {
- register_shutdown_function('auto_prune', $row['forum_id'], 'viewed', $row['forum_flags'], $row['prune_viewed'], $row['prune_freq']);
- }
- else
- {
- auto_prune($row['forum_id'], 'viewed', $row['forum_flags'], $row['prune_viewed'], $row['prune_freq']);
- }
- }
- }
-
- break;
-}
-
-// Unloading cache and closing db after having done the dirty work.
-if ($use_shutdown_function)
-{
- register_shutdown_function('unlock_cron');
- register_shutdown_function('garbage_collection');
-}
-else
-{
- unlock_cron();
+
+ // Unloading cache and closing db after having done the dirty work.
+ $cron_lock->unlock();
garbage_collection();
}
-exit;
+if ($cron_lock->lock()) {
+ if ($config['use_system_cron']) {
+ $use_shutdown_function = false;
+
+ $run_tasks = $cron->find_all_runnable_tasks();
+ } else {
+ $cron_type = request_var('cron_type', '');
+ $use_shutdown_function = (@function_exists('register_shutdown_function')) ? true : false;
+
+ output_image();
-
-/**
-* Unlock cron script
-*/
-function unlock_cron()
-{
- global $db;
-
- $sql = 'UPDATE ' . CONFIG_TABLE . "
- SET config_value = '0'
- WHERE config_name = 'cron_lock' AND config_value = '" . $db->sql_escape(CRON_ID) . "'";
- $db->sql_query($sql);
+ if ($cron->is_valid_task($cron_type) && $cron->is_task_runnable($cron_type))
+ {
+ if ($use_shutdown_function && !$cron->is_task_shutdown_function_compatible($cron_type)) {
+ $use_shutdown_function = false;
+ }
+ $run_tasks = array($cron_type);
+ }
+ }
+ if ($use_shutdown_function) {
+ register_shutdown_function('do_cron', $run_tasks);
+ } else {
+ do_cron($run_tasks);
+ }
}
diff --git a/phpBB/includes/cron.php b/phpBB/includes/cron.php
new file mode 100644
index 0000000000..2aa22858b7
--- /dev/null
+++ b/phpBB/includes/cron.php
@@ -0,0 +1,135 @@
+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/standard.php b/phpBB/includes/cron/standard.php
new file mode 100644
index 0000000000..1cb8738f17
--- /dev/null
+++ b/phpBB/includes/cron/standard.php
@@ -0,0 +1,163 @@
+ 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_lock.php b/phpBB/includes/cron_lock.php
new file mode 100644
index 0000000000..2a09590772
--- /dev/null
+++ b/phpBB/includes/cron_lock.php
@@ -0,0 +1,71 @@
+= time())
+ {
+ return false;
+ }
+ }
+
+ define('CRON_ID', time() . ' ' . unique_id());
+
+ $sql = 'UPDATE ' . CONFIG_TABLE . "
+ SET config_value = '" . $db->sql_escape(CRON_ID) . "'
+ WHERE config_name = 'cron_lock' AND config_value = '" . $db->sql_escape($config['cron_lock']) . "'";
+ $db->sql_query($sql);
+
+ // another cron process altered the table between script start and UPDATE query so exit
+ if ($db->sql_affectedrows() != 1)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ function unlock() {
+ global $db;
+
+ $sql = 'UPDATE ' . CONFIG_TABLE . "
+ SET config_value = '0'
+ WHERE config_name = 'cron_lock' AND config_value = '" . $db->sql_escape(CRON_ID) . "'";
+ $db->sql_query($sql);
+ }
+}
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index 056d578e75..eb787bfc62 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -4595,7 +4595,7 @@ function page_footer($run_cron = true)
// Call cron-type script
$call_cron = false;
- if (!defined('IN_CRON') && $run_cron && !$config['board_disable'])
+ if (!defined('IN_CRON') && !$config['use_system_cron'] && $run_cron && !$config['board_disable'])
{
$call_cron = true;
$time_now = (!empty($user->time_now) && is_int($user->time_now)) ? $user->time_now : time();
@@ -4616,40 +4616,12 @@ function page_footer($run_cron = true)
// Call cron job?
if ($call_cron)
{
- $cron_type = '';
-
- if ($time_now - $config['queue_interval'] > $config['last_queue_run'] && !defined('IN_ADMIN') && file_exists($phpbb_root_path . 'cache/queue.' . $phpEx))
- {
- // Process email queue
- $cron_type = 'queue';
- }
- else if (method_exists($cache, 'tidy') && $time_now - $config['cache_gc'] > $config['cache_last_gc'])
- {
- // Tidy the cache
- $cron_type = 'tidy_cache';
- }
- else if ($config['warnings_expire_days'] && ($time_now - $config['warnings_gc'] > $config['warnings_last_gc']))
- {
- $cron_type = 'tidy_warnings';
- }
- else if ($time_now - $config['database_gc'] > $config['database_last_gc'])
- {
- // Tidy the database
- $cron_type = 'tidy_database';
- }
- else if ($time_now - $config['search_gc'] > $config['search_last_gc'])
- {
- // Tidy the search
- $cron_type = 'tidy_search';
- }
- else if ($time_now - $config['session_gc'] > $config['session_last_gc'])
- {
- $cron_type = 'tidy_sessions';
- }
+ global $cron;
+ $cron_type = $cron->find_one_runnable_task();
if ($cron_type)
{
- $template->assign_var('RUN_CRON_TASK', '
');
+ $template->assign_var('RUN_CRON_TASK', $cron->generate_task_code($cron_type));
}
}
diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php
index 47d71849cb..8a06e28394 100644
--- a/phpBB/viewforum.php
+++ b/phpBB/viewforum.php
@@ -193,9 +193,9 @@ if ($forum_data['forum_topics_per_page'])
}
// Do the forum Prune thang - cron type job ...
-if ($forum_data['prune_next'] < time() && $forum_data['enable_prune'])
+if (!$config['use_system_cron'] && $cron->is_task_runnable('prune_forum', array($forum_data)))
{
- $template->assign_var('RUN_CRON_TASK', '
');
+ $template->assign_var('RUN_CRON_TASK', $cron->generate_task_code('prune_forum', array($forum_id)));
}
// Forum rules and subscription info