The first step
If you already have a file for your Cron Job, you can skip this step.
At first you need to create your Cron Job file. Let's give it the name
cron_task.php
.For example you are developing the extension
vendor/ext
.The extension's folder is located in
ext/vendor/ext
path from the board root.Let's put our Cron Job file in
ext/vendor/ext/cron/task/cron_task.php
.How can we tell the board that our
cron_task.php
file contains a Cron Job?We need to create a service in the
config
folder of our extension.You can use an existing configuration file with the extension
.yml
or you can create a new one, e.g. cron.yml
.The following code should exist in your configuration file (note that the line
services:
is needed to be present in the file only once):Code: Select all
services:
vendor.ext.cron.task.cron_task:
class: vendor\ext\cron\task\cron_task
arguments:
- @config
calls:
- [set_name, [cron.task.cron_task]]
tags:
- { name: cron.task }
OK. Then you need to edit your
cron_task.php
to create the code of your Cron Job.You can study some examples of Cron Job files:
autogroups_check, rxu_tidy_warnings.
Core Cron Jobs are also the examples that you can study (e.g. tidy_sessions)
In the case of our example you need to add the following header to the file:
Code: Select all
<?php
namespace vendor\ext\cron\task;
class cron_task extends \phpbb\cron\task\base
Then you need to define the constructor and the necessary methods of your
cron_task
class.The methods are described here.
Now you've completed the preparations and you can choose the names of configuration variables.
Simple solution:
_gc
endingsThe
_gc
ending is used as the default ending for all Cron events (we suppose that config variables with _gc
endings are Cron Tasks, other variables are not searched for (with some exceptions)).The configuration variable with the
_gc
ending in its name is the interval between two Cron Jobs of the same Cron Job class. This is the time in seconds that means the delay before the next Cron Job can run.The configuration variable with the
_last_gc
ending in its name is the last time when the Cron Job ran. The format of this time is the format that is used in the time()
function of PHP.Let's look at an example from the core (tidy_sessions):
Code: Select all
/**
* Returns whether this cron task should run now, because enough time
* has passed since it was last run.
*
* The interval between session tidying is specified in board
* configuration.
*
* @return bool
*/
public function should_run()
{
return $this->config['session_last_gc'] < time() - $this->config['session_gc'];
}
Note: the core Cron Jobs are handled differently than the Cron Jobs from extensions.
The core Cron Jobs are detected almost individually.
You need to specify the names of configuration variables like
class_name_last_gc
and class_name_gc
where class_name
is the name of the Cron Task's class.In our example the names of configuration variables should be
cron_task_last_gc
and cron_task_gc
.Don't forget to add those variables to the database in one of your migration files.
Example:
Code: Select all
public function update_data()
{
return array(
array('config.add', array('cron_task_last_gc', 0)), // last run
array('config.add', array('cron_task_gc', (60 * 60 * 24))), // seconds between run; 1 day
);
}
Combining the notes above together we can create a simple example
cron_task.php
file:Code: Select all
<?php
/* Put your header comments here. */
namespace vendor\ext\cron\task;
class cron_task extends \phpbb\cron\task\base
{
protected $config;
/**
* Constructor.
*
* @param \phpbb\config\config $config The config
*/
public function __construct(\phpbb\config\config $config)
{
$this->config = $config;
}
/**
* Runs this cron task.
*
* @return null
*/
public function run()
{
// Your code goes here.
// Do the actions that are the purpose for the Cron Job that we have created.
// Do not forget to update the configuration variable for last run time.
$this->config->set('cron_task_last_gc', time());
}
/**
* Returns whether this cron task should run now, because enough time
* has passed since it was last run.
*
* @return bool
*/
public function should_run()
{
return $this->config['cron_task_last_gc'] < time() - $this->config['cron_task_gc'];
}
}
You can also add other arguments after
@config
specified in this example in the same way as they are set for listeners.Simple solution example
This is the full example of implementation of a Cron Job to your extension. The example contains the most preferred way to specify configuration variables for your Cron Task.
Please change
vendor
, ext
and cron_task
names in this example to your own names according to your extension.Note: The names of your Cron Task's configuration variables should be unique.
The best way to specify them is to add the full name of your extension as a prefix:
vendor_ext_my_cron_task_last_gc
and vendor_ext_my_cron_task_gc
.In this case change the class name and the file name of your Cron Job to
vendor_ext_my_cron_task
.Example migration file (
migrations/my_migration.php
).Code: Select all
<?php
/* Put your header comments here. */
namespace vendor\ext\migrations;
class my_migration extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return isset($this->config['cron_task_gc']);
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v310\dev');
}
public function update_data()
{
return array(
array('config.add', array('cron_task_last_gc', 0)), // last run
array('config.add', array('cron_task_gc', (60 * 60 * 24))), // seconds between run; 1 day
);
}
}
Example configuration file (
config/services.yml
).Code: Select all
services:
vendor.ext.cron.task.cron_task:
class: vendor\ext\cron\task\cron_task
arguments:
- @config
calls:
- [set_name, [cron.task.cron_task]]
tags:
- { name: cron.task }
Example cron task file (
cron/task/cron_task.php
).Code: Select all
<?php
/* Put your header comments here. */
namespace vendor\ext\cron\task;
class cron_task extends \phpbb\cron\task\base
{
protected $config;
/**
* Constructor.
*
* @param \phpbb\config\config $config The config
*/
public function __construct(\phpbb\config\config $config)
{
$this->config = $config;
}
/**
* Runs this cron task.
*
* @return null
*/
public function run()
{
// Your code goes here.
// Do the actions that are the purpose for the Cron Job that we have created.
// Do not forget to update the configuration variable for last run time.
$this->config->set('cron_task_last_gc', time());
}
/**
* Returns whether this cron task should run now, because enough time
* has passed since it was last run.
*
* @return bool
*/
public function should_run()
{
return $this->config['cron_task_last_gc'] < time() - $this->config['cron_task_gc'];
}
}
Professional solution: your own endings
If you want your own Cron Jobs with no
_gc
endings to work with Cron Status, you can use the event "boardtools.cronstatus.modify_cron_config" to add any of your Cron Jobs to the rows
array.If you don't want to use
_last_gc
suffix for your new task dates, you will also need to use the event "boardtools.cronstatus.modify_cron_task" to manually handle your task.All times should be in the
time()
function format. (The same as for other dates in phpBB.)Simply work with the
$event['rows']
in your listener.php
file in the same way as with $lang
in your language files.Professional solution example
Please use this solution only when it's absolutely needed.
It's much easier to specify proper
_gc
endings to use automatic detection.Example migration file (
migrations/my_migration.php
).Code: Select all
<?php
/* Put your header comments here. */
namespace vendor\ext\migrations;
class my_migration extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return isset($this->config['cron_task_custom_gc']);
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v310\dev');
}
public function update_data()
{
return array(
array('config.add', array('cron_task_custom_last_gc', 0)), // last run
array('config.add', array('cron_task_custom_gc', (60 * 60 * 24))), // seconds between run; 1 day
);
}
}
Example configuration file (
config/services.yml
).Code: Select all
services:
vendor.ext.cron.task.cron_task:
class: vendor\ext\cron\task\cron_task
arguments:
- @config
calls:
- [set_name, [cron.task.cron_task]]
tags:
- { name: cron.task }
vendor.ext.listener:
class: vendor\ext\event\listener
arguments:
- @config
- @service_container
tags:
- { name: event.listener }
Example cron task file (
cron/task/cron_task.php
).Code: Select all
<?php
/* Put your header comments here. */
namespace vendor\ext\cron\task;
class cron_task extends \phpbb\cron\task\base
{
protected $config;
/**
* Constructor.
*
* @param \phpbb\config\config $config The config
*/
public function __construct(\phpbb\config\config $config)
{
$this->config = $config;
}
/**
* Runs this cron task.
*
* @return null
*/
public function run()
{
// Your code goes here.
// Do the actions that are the purpose for the Cron Job that we have created.
// Do not forget to update the configuration variable for last run time.
$this->config->set('cron_task_custom_last_gc', time());
}
/**
* Returns whether this cron task should run now, because enough time
* has passed since it was last run.
*
* @return bool
*/
public function should_run()
{
return $this->config['cron_task_custom_last_gc'] < time() - $this->config['cron_task_custom_gc'];
}
}
Example event listener file (
event/listener.php
).Code: Select all
<?php
/* Put your header comments here. */
namespace vendor\ext\event;
/**
* @ignore
*/
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Event listener
*/
class listener implements EventSubscriberInterface
{
protected $config;
protected $phpbb_container;
/**
* Constructor
*
* @param \phpbb\config\config $config Config object
* @param object $phpbb_container Container object
*/
public function __construct(\phpbb\config\config $config, $phpbb_container)
{
$this->config = $config;
$this->phpbb_container = $phpbb_container;
}
static public function getSubscribedEvents()
{
return array(
'boardtools.cronstatus.modify_cron_task' => 'add_my_cron_task',
'boardtools.cronstatus.modify_cron_config' => 'modify_cronlock',
);
}
public function add_my_cron_task($event)
{
// Detect our task (defined by its name).
if ($event['task_name'] === 'cron.task.cron_task_test')
{
// Get configuration variables.
$last_task_date = $this->config['cron_task_custom_last_gc'];
$task_interval = $this->config['cron_task_custom_gc'];
// Set last task date.
$event['task_date'] = $last_task_date;
// Set next task date.
$event['new_task_date'] = $last_task_date + $task_interval;
}
}
public function modify_cronlock($event)
{
// Get configuration variable.
$last_task_date = $this->config['cron_task_custom_last_gc'];
// 'last_task_date' variable is only specified in Cron Status 3.1.2 and higher.
if (isset($event['last_task_date']))
{
if ($last_task_date >= $event['last_task_date'])
{
$event['cronlock'] = 'cron_task'; // The name of our Cron Job.
$event['last_task_date'] = $last_task_date; // Update the time.
}
}
// Workaround for Cron Status 3.1.1.
// The maximum value for the date of the cronlock is not passed to the event object.
// We need to find it again.
else if ($last_task_date >= $this->phpbb_container->get('boardtools.cronstatus.listener')->maxValueInArray($event['rows'], 'config_value'))
{
$event['cronlock'] = 'cron_task'; // The name of our Cron Job.
// Update the time.
$rows = $event['rows'];
$rows[] = array(
"config_name" => "cron_task_last_gc", // Any name ending with '_last_gc'.
"config_value" => $last_task_date
);
$event['rows'] = $rows;
}
}
}
Have a nice extension!
