diff options
| author | Andreas Fischer <bantu@phpbb.com> | 2014-05-30 20:12:15 +0200 | 
|---|---|---|
| committer | Andreas Fischer <bantu@phpbb.com> | 2014-05-30 20:12:15 +0200 | 
| commit | bbb83c09c0f53fda26ff0d06083bf900f4babdae (patch) | |
| tree | 2b67788b30422a33675e43cc5e23f397508ae948 | |
| parent | 807e000b912a30f3c8010dd7c2acdfa04f6c5392 (diff) | |
| parent | fa3a634ae11af0a89000d5770b1c3fae10486195 (diff) | |
| download | forums-bbb83c09c0f53fda26ff0d06083bf900f4babdae.tar forums-bbb83c09c0f53fda26ff0d06083bf900f4babdae.tar.gz forums-bbb83c09c0f53fda26ff0d06083bf900f4babdae.tar.bz2 forums-bbb83c09c0f53fda26ff0d06083bf900f4babdae.tar.xz forums-bbb83c09c0f53fda26ff0d06083bf900f4babdae.zip  | |
Merge pull request #2508 from ptitlazy/ticket/12597
[ticket/12597] Command for executing all available cron tasks
* ptitlazy/ticket/12597: (27 commits)
  [ticket/12597] Reformating an acp message
  [ticket/12597] Modifiying acp message
  [ticket/12597] Fix wrong global variable name
  [ticket/12597] Typo correction
  [ticket/12597] Typo corrections
  [ticket/12597] Changing place of lock release in execute() method
  [ticket/12597] Fix test file
  [ticket/12597] Typing corrections and improvement of code consistency
  [ticket/12597] Fix various mistakes
  [ticket/12597] Fix various mistakes
  [ticket/12597] Fix visibilty of two functions in run.php
  [ticket/12597] Refactoring and test improving
  [ticket/12597] Fix language key name
  [ticket/12597] Fix coding style and typing mistakes
  [ticket/12597] Changes name of command  cron:run-all to cron:run.
  [ticket/12597] Fix various problems
  [ticket/12597] Fix constructor bug and servral doc blocs
  [ticket/12597] Modification of return statuses and of test files
  [ticket/12597] Fix misplaced release of db lock
  [ticket/12597] Change EXECUTE to RUN in language
  ...
| -rw-r--r-- | phpBB/config/console.yml | 9 | ||||
| -rw-r--r-- | phpBB/cron.php | 58 | ||||
| -rw-r--r-- | phpBB/language/en/acp/board.php | 2 | ||||
| -rw-r--r-- | phpBB/language/en/acp/common.php | 7 | ||||
| -rw-r--r-- | phpBB/phpbb/console/command/cron/run.php | 176 | ||||
| -rw-r--r-- | tests/console/cron/fixtures/config.xml | 8 | ||||
| -rw-r--r-- | tests/console/cron/run_test.php | 157 | ||||
| -rw-r--r-- | tests/console/cron/tasks/simple.php | 27 | 
8 files changed, 399 insertions, 45 deletions
diff --git a/phpBB/config/console.yml b/phpBB/config/console.yml index 56bf99390a..a102a8c609 100644 --- a/phpBB/config/console.yml +++ b/phpBB/config/console.yml @@ -46,6 +46,15 @@ services:          tags:              - { name: console.command } +    console.command.cron.run: +        class: phpbb\console\command\cron\run +        arguments: +            - @cron.manager +            - @cron.lock_db +            - @user +        tags: +            - { name: console.command } +      console.command.db.migrate:          class: phpbb\console\command\db\migrate          arguments: diff --git a/phpBB/cron.php b/phpBB/cron.php index e070c8f5fb..611d5d4aaf 100644 --- a/phpBB/cron.php +++ b/phpBB/cron.php @@ -37,25 +37,6 @@ function output_image()  	flush();  } -function do_cron($cron_lock, $run_tasks) -{ -	global $config; - -	foreach ($run_tasks as $task) -	{ -		if (defined('DEBUG') && $config['use_system_cron']) -		{ -			echo "[phpBB cron] Running task '{$task->get_name()}'\n"; -		} - -		$task->run(); -	} - -	// Unloading cache and closing db after having done the dirty work. -	$cron_lock->release(); -	garbage_collection(); -} -  // Thanks to various fatal errors and lack of try/finally, it is quite easy to leave  // the cron lock locked, especially when working on cron-related code.  // @@ -63,47 +44,36 @@ function do_cron($cron_lock, $run_tasks)  //  // If DEBUG is defined and cron lock cannot be obtained, a message will be printed. -if (!$config['use_system_cron']) -{ -	$cron_type = request_var('cron_type', ''); +$cron_type = request_var('cron_type', ''); -	// Comment this line out for debugging so the page does not return an image. -	output_image(); -} +// Comment this line out for debugging so the page does not return an image. +output_image();  $cron_lock = $phpbb_container->get('cron.lock_db');  if ($cron_lock->acquire())  {  	$cron = $phpbb_container->get('cron.manager'); -	if ($config['use_system_cron']) +	$task = $cron->find_task($cron_type); +	if ($task)  	{ -		$run_tasks = $cron->find_all_ready_tasks(); -	} -	else -	{ -		// If invalid task is specified, empty $run_tasks is passed to do_cron which then does nothing -		$run_tasks = array(); -		$task = $cron->find_task($cron_type); -		if ($task) +		if ($task->is_parametrized()) +		{ +			$task->parse_parameters($request); +		} +		if ($task->is_ready())  		{ -			if ($task->is_parametrized()) -			{ -				$task->parse_parameters($request); -			} -			if ($task->is_ready()) -			{ -				$run_tasks = array($task); -			} +			$task->run(); +			garbage_collection();  		}  	} +	$cron_lock->release(); -	do_cron($cron_lock, $run_tasks);  }  else  {  	if (defined('DEBUG'))  	{ -		echo "Could not obtain cron lock.\n"; +		echo $user->lang('CRON_LOCK_ERROR') . "\n";  	}  } diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index e2f89839c5..3702662253 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -461,7 +461,7 @@ $lang = array_merge($lang, array(  	'UPLOAD_ICONS_PATH'			=> 'Extension group icons storage path',  	'UPLOAD_ICONS_PATH_EXPLAIN'	=> 'Path under your phpBB root directory, e.g. <samp>images/upload_icons</samp>.',  	'USE_SYSTEM_CRON'		=> 'Run periodic tasks from system cron', -	'USE_SYSTEM_CRON_EXPLAIN'		=> 'When off, phpBB will arrange for periodic tasks to be run automatically. When on, phpBB will not schedule any periodic tasks by itself; a system administrator must arrange for <code>cron.php</code> to be invoked by the system cron facility at regular intervals (e.g. every 5 minutes).', +	'USE_SYSTEM_CRON_EXPLAIN'		=> 'When off, phpBB will arrange for periodic tasks to be run automatically. When on, phpBB will not schedule any periodic tasks by itself; a system administrator must arrange for <code>cron:run</code> command to be run by the system cron facility at regular intervals (e.g. every 5 minutes).',  ));  // Security Settings diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index d340e467be..a9c5eaf184 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -223,8 +223,14 @@ $lang = array_merge($lang, array(  	'BACK'					=> 'Back', +	'CLI_DESCRIPTION_CRON_RUN'		=> 'Runs all available cron tasks.', +	'CLI_DESCRIPTION_CRON_RUN_ARGUMENT_1'	=> 'Name of the task to be run', +  	'COLOUR_SWATCH'			=> 'Web-safe colour swatch',  	'CONFIG_UPDATED'		=> 'Configuration updated successfully.', +	'CRON_LOCK_ERROR'		=> 'Could not obtain cron lock.', +	'CRON_NO_SUCH_TASK'		=> 'No such cron task', +	'CRON_NO_TASK'			=> 'No task to be run',  	'DEACTIVATE'				=> 'Deactivate',  	'DIRECTORY_DOES_NOT_EXIST'	=> 'The entered path ā%sā does not exist.', @@ -285,6 +291,7 @@ $lang = array_merge($lang, array(  	'REMIND'							=> 'Remind',  	'RESYNC'							=> 'Resynchronise', +	'RUNNING_TASK'			=> 'Running task: %s.',  	'SELECT_ANONYMOUS'		=> 'Select anonymous user',  	'SELECT_OPTION'			=> 'Select option', diff --git a/phpBB/phpbb/console/command/cron/run.php b/phpBB/phpbb/console/command/cron/run.php new file mode 100644 index 0000000000..f76fb30e3b --- /dev/null +++ b/phpBB/phpbb/console/command/cron/run.php @@ -0,0 +1,176 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited  +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\console\command\cron; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class run extends \phpbb\console\command\command +{ +	/** @var \phpbb\cron\manager */ +	protected $cron_manager; + +	/** @var \phpbb\lock\db */ +	protected $lock_db; + +	/** @var \phpbb\user */ +	protected $user; + +	/** +	* Construct method +	* +	* @param \phpbb\cron\manager $cron_manager The cron manager containing +	*		the cron tasks to be executed. +	* @param \phpbb\lock\db $lock_db The lock for accessing database. +	* @param \phobb\user $user The user object (used to get language information) +	*/ +	public function __construct(\phpbb\cron\manager $cron_manager, \phpbb\lock\db $lock_db, \phpbb\user $user) +	{ +		$this->cron_manager = $cron_manager; +		$this->lock_db = $lock_db; +		$this->user = $user; +		parent::__construct(); +	} + +	/** +	* Sets the command name and description +	* +	* @return null +	*/ +	protected function configure() +	{ +		$this +			->setName('cron:run') +			->setDescription($this->user->lang('CLI_DESCRIPTION_CRON_RUN')) +			->addArgument('name', InputArgument::OPTIONAL, $this->user->lang('CLI_DESCRIPTION_CRON_RUN_ARGUMENT_1')) +		; +	} + +	/** +	* Executes the command cron:run. +	* +	* Tries to acquire the cron lock, then if no argument has been given runs all ready cron tasks. +	* If the cron lock can not be obtained, an error message is printed +	*		and the exit status is set to 1. +	* If the verbose option is specified, each start of a task is printed. +	*		Otherwise there is no output. +	* If an argument is given to the command, only the task whose name matches the  +	*		argument will be started. If verbose option is specified, +	*		an info message containing the name of the task is printed. +	* If no task matches the argument given, an error message is printed +	*		and the exit status is set to 2. +	* +	* @param InputInterface $input The input stream used to get the argument and verboe option. +	* @param OutputInterface $output The output stream, used for printing verbose-mode and error information. +	* +	* @return int 0 if all is ok, 1 if a lock error occured and 2 if no task matching the argument was found. +	*/ +	protected function execute(InputInterface $input, OutputInterface $output) +	{ +		if ($this->lock_db->acquire()) +		{ +			$task_name = $input->getArgument('name'); +			if ($task_name) +			{ +				$exit_status = $this->run_one($input, $output, $task_name); +			} +			else +			{ +				$exit_status = $this->run_all($input, $output); +			} + +			$this->lock_db->release(); +			return $exit_status; +		} +		else +		{ +			$output->writeln('<error>' . $this->user->lang('CRON_LOCK_ERROR') . '</error>'); +			return 1; +		} +	} + +	/* +	* Executes all ready cron tasks. +	* +	* If verbose mode is set, an info message will be printed if there is no task to +	*		be run, or else for each starting task. +	* +	* @see execute +	* @param InputInterface $input The input stream used to get the argument and verbose option. +	* @param OutputInterface $output The output stream, used for printing verbose-mode and error information. +	* @return int 0 +	*/ +	protected function run_all(InputInterface $input, OutputInterface $output) +	{ +		$run_tasks = $this->cron_manager->find_all_ready_tasks(); + +		if ($run_tasks) +		{ +			foreach ($run_tasks as $task) +			{ +				if ($input->getOption('verbose')) +				{ +					$output->writeln('<info>' . $this->user->lang('RUNNING_TASK', $task->get_name()) . '</info>'); +				} + +				$task->run(); +			} +		} +		else +		{ +			if ($input->getOption('verbose')) +			{ +				$output->writeln('<info>' . $this->user->lang('CRON_NO_TASK') . '</info>'); +			} +		} + +		return 0; +	} + +	/* +	* Executes a given cron task, if it is ready. +	* +	* If there is a task whose name matches $task_name, it is run and 0 is returned. +	*		and if verbose mode is set, print an info message with the name of the task. +	* If there is no task matching $task_name, the function prints an error message +	*		and returns with status 2. +	* +	* @see execute +	* @param string $task_name The name of the task that should be run. +	* @param InputInterface $input The input stream used to get the argument and verbose option. +	* @param OutputInterface $output The output stream, used for printing verbose-mode and error information. +	* @return int 0 if all is well, 2 if no task matches $task_name. +	*/ +	protected function run_one(InputInterface $input, OutputInterface $output, $task_name) +	{ +		$task = $this->cron_manager->find_task($task_name); +		if ($task) +		{ +			if ($input->getOption('verbose')) +			{ +				$output->writeln('<info>' . $this->user->lang('RUNNING_TASK', $task_name) . '</info>'); +			} + +			$task->run(); +			return 0; +		} +		else +		{ +			$output->writeln('<error>' . $this->user->lang('CRON_NO_SUCH_TASK') . '</error>'); +			return 2; +		} +	} +} diff --git a/tests/console/cron/fixtures/config.xml b/tests/console/cron/fixtures/config.xml new file mode 100644 index 0000000000..2cb683d409 --- /dev/null +++ b/tests/console/cron/fixtures/config.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_config"> +		<column>config_name</column> +		<column>config_value</column> +		<column>is_dynamic</column> +	</table> +</dataset> diff --git a/tests/console/cron/run_test.php b/tests/console/cron/run_test.php new file mode 100644 index 0000000000..8908c536c0 --- /dev/null +++ b/tests/console/cron/run_test.php @@ -0,0 +1,157 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited  +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use phpbb\console\command\cron\run; + +require_once dirname(__FILE__) . '/tasks/simple.php'; + +class phpbb_console_command_cron_run_test extends phpbb_database_test_case +{ +	protected $db; +	protected $config; +	protected $lock; +	protected $user; +	protected $cron_manager; +	protected $command_name; +	protected $task; + +	public function getDataSet() +	{ +		return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/config.xml'); +	} + +	public function setUp() +	{ +		global $db, $config, $phpbb_root_path, $phpEx; + +		$db = $this->db = $this->new_dbal(); +		$config = $this->config = new \phpbb\config\config(array('cron_lock' => '0')); +		set_config(null, null, null, $this->config); +		$this->lock = new \phpbb\lock\db('cron_lock', $this->config, $this->db); + +		$this->user = $this->getMock('\phpbb\user'); +		$this->user->method('lang')->will($this->returnArgument(0)); + +		$this->task = new phpbb_cron_task_simple(); +		$tasks = array( +			$this->task, +		); +		$this->cron_manager = new \phpbb\cron\manager($tasks, $phpbb_root_path, $phbEx); + +		$this->assertSame('0', $config['cron_lock']); +	} + +	public function test_normal_use() +	{ +		$command_tester = $this->get_command_tester(); +		$exit_status = $command_tester->execute(array('command' => $this->command_name)); + +		$this->assertSame('', $command_tester->getDisplay()); +		$this->assertSame(true, $this->task->executed); +		$this->assertSame(0, $exit_status); +		$this->assertSame(false, $this->lock->owns_lock()); +	} + +	public function test_verbose_mode() +	{ +		$command_tester = $this->get_command_tester(); +		$exit_status = $command_tester->execute(array('command' => $this->command_name, '--verbose' => true)); + +		$this->assertContains('RUNNING_TASK', $command_tester->getDisplay()); +		$this->assertSame(true, $this->task->executed); +		$this->assertSame(0, $exit_status); +		$this->assertSame(false, $this->lock->owns_lock()); +	} + +	public function test_error_lock() +	{ +		$this->lock->acquire(); +		$command_tester = $this->get_command_tester(); +		$exit_status = $command_tester->execute(array('command' => $this->command_name)); + +		$this->assertContains('CRON_LOCK_ERROR', $command_tester->getDisplay()); +		$this->assertSame(false, $this->task->executed); +		$this->assertSame(1, $exit_status); +	} + +	public function test_no_task() +	{ +		$tasks = array( +		); +		$this->cron_manager = new \phpbb\cron\manager($tasks, $phpbb_root_path, $phpEx); +		$command_tester = $this->get_command_tester(); +		$exit_status = $command_tester->execute(array('command' => $this->command_name)); + +		$this->assertSame('', $command_tester->getDisplay()); +		$this->assertSame(0, $exit_status); +		$this->assertSame(false, $this->lock->owns_lock()); +	} + +	public function test_no_task_verbose() +	{ +		$tasks = array( +		); +		$this->cron_manager = new \phpbb\cron\manager($tasks, $phpbb_root_path, $phpEx); +		$command_tester = $this->get_command_tester(); +		$exit_status = $command_tester->execute(array('command' => $this->command_name, '--verbose' => true)); + +		$this->assertContains('CRON_NO_TASK', $command_tester->getDisplay()); +		$this->assertSame(0, $exit_status); +		$this->assertSame(false, $this->lock->owns_lock()); +	} + +	public function test_arg_valid() +	{ +		$command_tester = $this->get_command_tester(); +		$exit_status = $command_tester->execute(array('command' => $this->command_name, 'name' => 'phpbb_cron_task_simple')); + +		$this->assertSame('', $command_tester->getDisplay()); +		$this->assertSame(true, $this->task->executed); +		$this->assertSame(0, $exit_status); +		$this->assertSame(false, $this->lock->owns_lock()); +	} + +	public function test_arg_invalid() +	{ +		$command_tester = $this->get_command_tester(); +		$exit_status = $command_tester->execute(array('command' => $this->command_name, 'name' => 'foo')); + +		$this->assertContains('CRON_NO_SUCH_TASK', $command_tester->getDisplay()); +		$this->assertSame(false, $this->task->executed); +		$this->assertSame(2, $exit_status); +		$this->assertSame(false, $this->lock->owns_lock()); +	} + +	public function test_arg_valid_verbose() +	{ +		$command_tester = $this->get_command_tester(); +		$exit_status = $command_tester->execute(array('command' => $this->command_name, 'name' => 'phpbb_cron_task_simple', '--verbose' => true)); + +		$this->assertContains('RUNNING_TASK', $command_tester->getDisplay()); +		$this->assertSame(true, $this->task->executed); +		$this->assertSame(0, $exit_status); +		$this->assertSame(false, $this->lock->owns_lock()); +	} + +	public function get_command_tester() +	{ +		$application = new Application(); +		$application->add(new run($this->cron_manager, $this->lock, $this->user)); + +		$command = $application->find('cron:run'); +		$this->command_name = $command->getName(); +		return new CommandTester($command); +	} +} diff --git a/tests/console/cron/tasks/simple.php b/tests/console/cron/tasks/simple.php new file mode 100644 index 0000000000..c814c29bde --- /dev/null +++ b/tests/console/cron/tasks/simple.php @@ -0,0 +1,27 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited  +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_cron_task_simple extends \phpbb\cron\task\base +{ +	public $executed = false; + +	public function get_name() +	{ +		return get_class($this); +	} + +	public function run() +	{ +		$this->executed = true; +	} +}  | 
