Skip to content

Commit a568b8d

Browse files
committed
Initial release
0 parents  commit a568b8d

File tree

3 files changed

+234
-0
lines changed

3 files changed

+234
-0
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Shuaib Yusuf Shuaib
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# CRON
2+
Web-based Task Scheduler
3+
4+
## Install
5+
- Download the zip file of the plugin from this repo.
6+
- Extract the contents of the zip file.
7+
- Create a folder `cron` in the `plugins/` directory on your server.
8+
- Copy the `plugin.php` file to the `cron` folder.
9+
- Follow the [steps to activate and configure](https://boidcms.github.io/#/plugins/configure) the plugin.
10+
11+
## Compatibility
12+
This plugin works on any version of BoidCMS.

plugin.php

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
<?php defined( 'App' ) or die( 'BoidCMS' );
2+
/**
3+
*
4+
* CRON – Web-Based Task Scheduler
5+
*
6+
* @package Plugin_Cron
7+
* @author Shuaib Yusuf Shuaib
8+
* @version 0.1.0
9+
*/
10+
11+
if ( 'cron' !== basename( __DIR__ ) ) return;
12+
13+
global $App;
14+
$App->set_action( 'install', 'cron_install' );
15+
$App->set_action( 'uninstall', 'cron_uninstall' );
16+
$App->set_action( 'rendered', 'cron_exec', 20 );
17+
$App->set_action( 'admin', 'cron_admin' );
18+
19+
/**
20+
* Initialize CRON, first time install
21+
* @param string $plugin
22+
* @return void
23+
*/
24+
function cron_install( string $plugin ): void {
25+
global $App;
26+
if ( 'cron' === $plugin ) {
27+
$file = $App->root( 'data/cron.json' );
28+
file_put_contents( $file, '{}', LOCK_EX );
29+
}
30+
}
31+
32+
/**
33+
* Free hosting space, while uninstalled
34+
* @param string $plugin
35+
* @return void
36+
*/
37+
function cron_uninstall( string $plugin ): void {
38+
global $App;
39+
if ( 'cron' === $plugin ) {
40+
$file = $App->root( 'data/cron.json' );
41+
if ( is_file( $file ) ) unlink( $file );
42+
}
43+
}
44+
45+
/**
46+
* Runs due cron tasks if inactive
47+
* @return void
48+
*/
49+
function cron_exec(): void {
50+
if ( ! is_cron_running() ) {
51+
touch( cron_file() );
52+
run_cron_tasks();
53+
}
54+
}
55+
56+
/**
57+
* Admin settings
58+
* @return void
59+
*/
60+
function cron_admin(): void {
61+
global $App, $layout, $page;
62+
switch ( $page ) {
63+
case 'cron':
64+
$layout[ 'title' ] = 'CRON';
65+
$layout[ 'content' ] = '
66+
<ul class="ss-list ss-fieldset ss-mobile ss-w-6 ss-mx-auto">
67+
<li class="ss-bd-none">
68+
<h3 class="ss-monospace">Scheduled Tasks</h3>
69+
<hr class="ss-hr">
70+
</li>';
71+
$cron_tasks = get_cron_tasks();
72+
foreach ( $cron_tasks as $id => $cron ) {
73+
$layout[ 'content' ] .= '
74+
<li class="ss-responsive">
75+
<h4 class="ss-monospace">' . $App->esc( $id ) . '</h4>
76+
<hr class="ss-hr ss-w-3 ss-mx-auto">
77+
<p><b>One-time Only</b>: ' . ( ! $cron[ 'interval' ] ? 'Yes' : 'No' ) . '</p>
78+
<p><b>Interval</b>: Every ' . $cron[ 'interval' ] . ' second(s) / ' . floor( $cron[ 'interval' ] / 60 ) . ' minute(s) / ' . floor( ( $cron[ 'interval' ] / 60 ) / 60 ) . ' hour(s)</p>
79+
<p><b>Dues</b>: ' . $cron[ 'dues' ] . '</p>
80+
</li>';
81+
}
82+
$layout[ 'content' ] .= '</ul>';
83+
require_once $App->root( 'app/layout.php' );
84+
break;
85+
}
86+
}
87+
88+
/**
89+
* Schedule a cron task
90+
* @param string $id
91+
* @param string $callback
92+
* @param int $interval
93+
* @param array $args
94+
* @return bool
95+
*/
96+
function schedule_task( string $id, string $callback, int $interval = 86400, array $args = array() ): bool {
97+
$cron_tasks = get_cron_tasks();
98+
if ( isset( $cron_tasks[ $id ] ) ) {
99+
return false;
100+
}
101+
102+
$cron_tasks[ $id ] = array();
103+
$cron_tasks[ $id ][ 'dues' ] = 0;
104+
$cron_tasks[ $id ][ 'args' ] = $args;
105+
$cron_tasks[ $id ][ 'interval' ] = $interval;
106+
$cron_tasks[ $id ][ 'callback' ] = $callback;
107+
return save_cron_tasks( $cron_tasks );
108+
}
109+
110+
/**
111+
* Remove a scheduled task
112+
* @param string $id
113+
* @return bool
114+
*/
115+
function unschedule_task( string $id ): bool {
116+
$cron_tasks = get_cron_tasks();
117+
if ( ! isset( $cron_tasks[ $id ] ) ) {
118+
return false;
119+
}
120+
121+
unset( $cron_tasks[ $id ] );
122+
return save_cron_tasks( $cron_tasks );
123+
}
124+
125+
/**
126+
* Check if task is scheduled
127+
* @param string $id
128+
* @return bool
129+
*/
130+
function is_task_scheduled( string $id ): bool {
131+
return isset( get_cron_tasks()[ $id ] );
132+
}
133+
134+
/**
135+
* Checks if the cron task was executed within the last 5 minutes
136+
* @return bool
137+
*/
138+
function is_cron_running(): bool {
139+
$mtime = filemtime( cron_file() );
140+
return ( ( time() - $mtime ) <= 300 );
141+
}
142+
143+
/**
144+
* Storage file
145+
* @return string
146+
*/
147+
function cron_file(): string {
148+
global $App;
149+
return $App->root( 'data/cron.json' );
150+
}
151+
152+
/**
153+
* Load the cron data
154+
* @return array
155+
*/
156+
function get_cron_tasks(): array {
157+
$cron_tasks = file_get_contents( cron_file() );
158+
return json_decode( $cron_tasks, true );
159+
}
160+
161+
/**
162+
* Save the cron data
163+
* @param array $cron_tasks
164+
* @return bool
165+
*/
166+
function save_cron_tasks( array $cron_tasks ): bool {
167+
$cron_tasks = json_encode( $cron_tasks, JSON_FORCE_OBJECT );
168+
return ( bool ) file_put_contents( cron_file(), $cron_tasks, LOCK_EX );
169+
}
170+
171+
/**
172+
* Run due cron tasks
173+
* @return bool
174+
*/
175+
function run_cron_tasks(): bool {
176+
$now = time();
177+
$cron_tasks = get_cron_tasks();
178+
foreach ( $cron_tasks as $id => $cron ) {
179+
$interval = $cron[ 'interval' ];
180+
$last_run = ( $cron[ 'last_run' ] ?? 0 );
181+
if ( $now >= ( $last_run + $interval ) ) {
182+
$args = $cron[ 'args' ];
183+
$callback = $cron[ 'callback' ];
184+
if ( is_callable( $callback ) ) {
185+
try {
186+
call_user_func_array( $callback, $args );
187+
} catch ( Throwable $e ) {}
188+
}
189+
190+
$cron_tasks[ $id ][ 'last_run' ] = $now;
191+
$cron_tasks[ $id ][ 'dues' ]++;
192+
193+
if ( ! $cron[ 'interval' ] ) {
194+
unset( $cron_tasks[ $id ] );
195+
}
196+
}
197+
}
198+
199+
return save_cron_tasks( $cron_tasks );
200+
}
201+
?>

0 commit comments

Comments
 (0)