Customizing SMF > SMF Coding Discussion
How to create Scheduled Tasks in SMF 2.0
Arantor:
Judging by the number of mods that don't use scheduled tasks in 2.0, it seems to be that there is a little bit of confusion on how to create them. So, here goes - with thanks to JBlaze for getting me started on it in the first place.
Any scheduled task requires 3 basic things: code to run, a description in the language files, and an entry in the database.
For the purpose of this, I'm actually going to talk you through a simplified version of my Auto Lock Old Topics mod, where instead of locking threads configurably, we'll just say we lock every thread that hasn't been replied to in 30 days.
The very first thing we need to do is give our task an identifier. It doesn't have to be special but needs to be short and as unique as you can be. I used 'autoLock' for mine, so we'll continue to use that here to keep it straightforward.
Description
Let's start with the easiest thing: description. Each scheduled task has a name and a quick description, which you can see in the Scheduled Tasks part of the Admin area in 2.0. The name is also a link to configure when the script should run, and we don't want to get into modifying things we don't need to for it.
In fact, adding a description is nice and easy, you just have to add 2 lines to ManageScheduledTasks.english.php in the theme (for the budding mod authors out there, it's $languagedir/ManageScheduledTasks.english.php you want, plus any other language variations)
Here's where the identifier comes in. We create two language strings, scheduled_task_{identifier} and scheduled_task_desc_{identifier} and add them to $txt.
So to the bottom of ManageScheduledTasks.english.php, I would add:
--- Code: ---$txt['scheduled_task_autoLock'] = 'Auto Lock Old Topics';
$txt['scheduled_task_desc_autoLock'] = 'Locks topics that have not been replied to in 30 days.';
--- End code ---
And bippity-boppity-boop, that's that bit done.
Code to run
Having set up the description of the mod, we do actually need to write some code that would get run when our task is called for.
The key thing here is the name of the function, and location. It should live in Sources/ScheduledTasks.php (for you mod authors, $sourcedir/ScheduledTasks.php), and go by the name of scheduled_{identifier}. So with our autoLock identifier, we want something like:
--- Code: ---function scheduled_autoLock()
{
global $modSettings, $sourcedir, $mbname, $txt, $smcFunc, $scripturl;
$timestamp = time() - (30 * 86400);
$query = 'UPDATE {db_prefix}topics, {db_prefix}messages
SET {db_prefix}topics.locked = 1
WHERE {db_prefix}topics.id_last_msg = {db_prefix}messages.id_msg
AND {db_prefix}messages.poster_time <= {int:timestamp}';
$result = $smcFunc['db_query']('',
$query,
array(
'timestamp' => $timestamp,
)
);
return true;
}
--- End code ---
You only have to inherit what variables you actually need, though I tend to make sure all the variables I might need are handy, and the code simply needs to run, returning true if successful, and false if not. You can check out the fuller code in the mod I mentioned, which also does it on a per-board level.
So, with that we have the description for our task, and the code for it to run.
Database work
We do also have to do one last thing - tell SMF about the task that needs to be run. Code alone is not sufficient here for that. For the mod authors out there, this last bit would be managed via an install.php and uninstall.php script as part of your mod install. Again, the technique is shown in the master version of the Auto Lock Old Topics mod.
Adding it is a simple case of adding a new row to the scheduled_tasks table, perhaps smf_scheduled_tasks. The query you'll use with $smcFunc takes the form of:
--- Code: --- INSERT INTO {db_prefix}scheduled_tasks (id_task, next_time, time_offset, time_regularity, time_unit, disabled, task)
VALUES (NULL, 0, 0, 1, "d", 0, "autoLock")
--- End code ---
(Of course, if we're being proper, we should be using $smcFunc['db_insert'] instead of $smcFunc['db_query']. But this way you can see what the columns are and how they relate to each other.)
Just let's quickly step through the columns:
* id_task is a numeric identifier for the row. We don't know this yet, and it's going to be assigned by SMF anyway, so leave that as NULL.
* next_time is the next time SMF is due to run the task. We set this to 0 because the task hasn't been run before.
* time_offset is the offset to run the task against, which should be the same as the forum time.
* time_regularity is the number of times per unit that this runs. For example, if running once per day, this is 1 - related to the next topic.
* time_unit is the time period considered for running the task. Supports 'm', 'h', 'd', 'w', for per minute, per hour, per day, per week. If you want to run the task daily at a set time for example, you have time_regularity as 1, and time_unit as 'd'. Once every 2 days, regularity = 2, time_unit = 'd'.
* disabled reflects if the task is disabled or not, 0 for not disabled (enabled) and 1 for disabled.
* task is the task identifier, in our case here 'autoLock'.
Once all of this is done, your scheduled task should be available to set what time you want it to run (since it will likely be different for every user)
Hopefully that's helped - if you have any questions please do ask.
aED:
Hi Arantor,
Sorry to bump this but is there any way I can make a scheduled task to run every first day of the month?
Arantor:
No, you'd have to have it run every 4 weeks or every 30 days. Or when it runs, have it recalculate the next interval.
aED:
hehehe :P thanks I Just figured it out after posting my message:)
Arantor:
What did you do in the end?
Navigation
[0] Message Index
[#] Next page
Go to full version