Total Upkeep – WordPress Backup Plugin plus Restore & Migrate by BoldGrid - Version 1.15.4

Version Description

Release date: November 2nd, 2022

  • Update: Fixing tdcron dependency.
Download this release

Release Info

Developer boldgrid
Plugin Icon 128x128 Total Upkeep – WordPress Backup Plugin plus Restore & Migrate by BoldGrid
Version 1.15.4
Comparing to
See all releases

Code changes from version 1.15.3 to 1.15.4

admin/cron/entry/class-crontab.php CHANGED
@@ -101,8 +101,8 @@ class Crontab extends Base implements Entry {
101
  public function get_next_runtime() {
102
  $core = apply_filters( 'boldgrid_backup_get_core', null );
103
 
104
- require_once BOLDGRID_BACKUP_PATH . '/vendor/chland/tdcron/class.tdcron.php';
105
- require_once BOLDGRID_BACKUP_PATH . '/vendor/chland/tdcron/class.tdcron.entry.php';
106
 
107
  /*
108
  * Get our next runtime.
101
  public function get_next_runtime() {
102
  $core = apply_filters( 'boldgrid_backup_get_core', null );
103
 
104
+ require_once BOLDGRID_BACKUP_PATH . '/vendor/boldgrid/tdcron/class.tdcron.php';
105
+ require_once BOLDGRID_BACKUP_PATH . '/vendor/boldgrid/tdcron/class.tdcron.entry.php';
106
 
107
  /*
108
  * Get our next runtime.
boldgrid-backup.php CHANGED
@@ -16,7 +16,7 @@
16
  * Plugin Name: Total Upkeep
17
  * Plugin URI: https://www.boldgrid.com/boldgrid-backup/
18
  * Description: Automated backups, remote backup to Amazon S3 and Google Drive, stop website crashes before they happen and more. Total Upkeep is the backup solution you need.
19
- * Version: 1.15.3
20
  * Author: BoldGrid
21
  * Author URI: https://www.boldgrid.com/
22
  * License: GPL-2.0+
16
  * Plugin Name: Total Upkeep
17
  * Plugin URI: https://www.boldgrid.com/boldgrid-backup/
18
  * Description: Automated backups, remote backup to Amazon S3 and Google Drive, stop website crashes before they happen and more. Total Upkeep is the backup solution you need.
19
+ * Version: 1.15.4
20
  * Author: BoldGrid
21
  * Author URI: https://www.boldgrid.com/
22
  * License: GPL-2.0+
cli/{verify-ef3bf6331c85b535eed0cffc76d35d3a.php → verify-539173f42c5a408cc287e505a961335f.php} RENAMED
File without changes
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: backup, cloud backup, database backup, restore, wordpress backup
4
  Requires at least: 4.4
5
  Tested up to: 6.1
6
  Requires PHP: 5.4
7
- Stable tag: 1.15.3
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -132,6 +132,12 @@ Have a problem? First, take a look at our [Getting Started](https://www.boldgrid
132
 
133
  == Changelog ==
134
 
 
 
 
 
 
 
135
  = 1.15.3 =
136
 
137
  Release date: November 1st, 2022
4
  Requires at least: 4.4
5
  Tested up to: 6.1
6
  Requires PHP: 5.4
7
+ Stable tag: 1.15.4
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
132
 
133
  == Changelog ==
134
 
135
+ = 1.15.4 =
136
+
137
+ Release date: November 2nd, 2022
138
+
139
+ * Update: Fixing tdcron dependency.
140
+
141
  = 1.15.3 =
142
 
143
  Release date: November 1st, 2022
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInitd3475abad362b46ca6ec161094303b5a::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit8907797e5ce4c58cc1367210818a76bc::getLoader();
vendor/boldgrid/tdcron/LICENSE.md ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Christian Land
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.
vendor/boldgrid/tdcron/README.md ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ > **WARNING**: This class was written back in 2010 ! Its pretty much untested with all PHP versions > 5.6.0 and might act funny. I mostly pushed it to GitHub for easier access and in case if somebody is looking for a simple cron-parser.
3
+
4
+ # tdCron
5
+
6
+ tdCron is a ***very*** simple class to parse cron-expressions and calculate schedules.
7
+
8
+ For something more sophisticated (and WAY more modern) you can take a look at the [cron-expression](https://github.com/dragonmantank/cron-expression) package by Michael Dowling and Chris Tankersley.
9
+
10
+ ## Getting Started
11
+
12
+ ### Installation
13
+
14
+ Just include `class.tdcron.php` and `class.tdcron.entry.php` in your project and you're done.
15
+
16
+ ## Documentation
17
+
18
+ As i mentioned before - this class is really, really simple :-)
19
+
20
+ Please just look at the code in `test.php` and `class.tdcron.php` - its reasonably well documented and should be pretty easy to understand.
21
+
22
+ It basically comes down to calling `tdCron::getNextOccurrence()` or `tdCron::getLastOccurrence()` with your cron-expression as the first parameter and an optional reference-time as the second parameter.
23
+
24
+ Lets say you've got a cron-expression like `5 0 * 8 2` (so something at 00:05 on every tuesday in august). You could use something like
25
+
26
+ echo 'next: '.date('d.m.Y, H:i:s', tdCron::getNextOccurrence('5 0 * 8 2');
27
+
28
+ to see when it should run the next time.
29
+
30
+ ## Running the tests
31
+
32
+ There aren't any "real" tests included with the class (so you won't find any PHPUnit-stuff here). You can find a bunch of edge-cases in the test.php / test.data.php files that were used to test the class during development.
33
+
34
+ ## License
35
+
36
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE.md) file for details
37
+
vendor/boldgrid/tdcron/class.tdcron.entry.php ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * tinyCronEntry is part of tdCron. Its a class to parse Cron-Expressions like "1-45 1,2,3 1-30/5 January,February Mon,Tue"
5
+ * and convert it to an easily useable format.
6
+ *
7
+ * The parser is quite powerful and understands pretty much everything you will ever find in a Cron-Expression.
8
+ *
9
+ * A Cron-Expression consists of 5 segments:
10
+ *
11
+ * <pre>
12
+ * .---------------- minute (0 - 59)
13
+ * | .------------- hour (0 - 23)
14
+ * | | .---------- day of month (1 - 31)
15
+ * | | | .------- month (1 - 12)
16
+ * | | | | .----- day of week (0 - 6)
17
+ * | | | | |
18
+ * * * * * *
19
+ * </pre>
20
+ *
21
+ * Each segment can contain values, ranges and intervals. A range is always written as "value1-value2" and
22
+ * intervals as "value1/value2".
23
+ *
24
+ * Of course each segment can contain multiple values seperated by commas.
25
+ *
26
+ * Some valid examples:
27
+ *
28
+ * <pre>
29
+ * 1,2,3,4,5
30
+ * 1-5
31
+ * 10-20/*
32
+ * Jan,Feb,Oct
33
+ * Monday-Friday
34
+ * 1-10,15,20,40-50/2
35
+ * </pre>
36
+ *
37
+ * The current version of the parser understands all weekdays and month names in german and english!
38
+ *
39
+ * Usually you won't need to call this class directly.
40
+ *
41
+ * @author Christian Land <devel@tagdocs.de>
42
+ * @package tdCron
43
+ * @copyright Copyright (c) 2010-2018, Christian Land / tagdocs.de
44
+ * @license http://opensource.org/licenses/MIT MIT License
45
+ * @version 1.0.0
46
+ */
47
+
48
+ class tdCronEntry {
49
+
50
+ /**
51
+ * The parsed cron-expression.
52
+ * @var mixed
53
+ */
54
+ static private $cron = array();
55
+
56
+ /**
57
+ * Ranges.
58
+ * @var mixed
59
+ */
60
+ static private $ranges = array(IDX_MINUTE => array( 'min' => 0,
61
+ 'max' => 59 ), // Minutes
62
+ IDX_HOUR => array( 'min' => 0,
63
+ 'max' => 23 ), // Hours
64
+ IDX_DAY => array( 'min' => 1,
65
+ 'max' => 31 ), // Days
66
+ IDX_MONTH => array( 'min' => 1,
67
+ 'max' => 12 ), // Months
68
+ IDX_WEEKDAY => array( 'min' => 0,
69
+ 'max' => 7 ) ); // Weekdays
70
+
71
+ /**
72
+ * Named intervals.
73
+ * @var mixed
74
+ */
75
+ static private $intervals = array('@yearly' => '0 0 1 1 *',
76
+ '@annualy' => '0 0 1 1 *',
77
+ '@monthly' => '0 0 1 * *',
78
+ '@weekly' => '0 0 * * 0',
79
+ '@midnight' => '0 0 * * *',
80
+ '@daily' => '0 0 * * *',
81
+ '@hourly' => '0 * * * *' );
82
+
83
+
84
+ /**
85
+ * Possible keywords for months/weekdays.
86
+ * @var mixed
87
+ */
88
+ static private $keywords = array(IDX_MONTH => array('/(january|januar|jan)/i' => 1,
89
+ '/(february|februar|feb)/i' => 2,
90
+ '/(march|maerz|m�rz|mar|mae|m�r)/i' => 3,
91
+ '/(april|apr)/i' => 4,
92
+ '/(may|mai)/i' => 5,
93
+ '/(june|juni|jun)/i' => 6,
94
+ '/(july|juli|jul)/i' => 7,
95
+ '/(august|aug)/i' => 8,
96
+ '/(september|sep)/i' => 9,
97
+ '/(october|oktober|okt|oct)/i' => 10,
98
+ '/(november|nov)/i' => 11,
99
+ '/(december|dezember|dec|dez)/i' => 12 ),
100
+ IDX_WEEKDAY => array('/(sunday|sonntag|sun|son|su|so)/i' => 0,
101
+ '/(monday|montag|mon|mo)/i' => 1,
102
+ '/(tuesday|dienstag|die|tue|tu|di)/i' => 2,
103
+ '/(wednesdays|mittwoch|mit|wed|we|mi)/i' => 3,
104
+ '/(thursday|donnerstag|don|thu|th|do)/i' => 4,
105
+ '/(friday|freitag|fre|fri|fr)/i' => 5,
106
+ '/(saturday|samstag|sam|sat|sa)/i' => 6 ) );
107
+
108
+ /**
109
+ * parseExpression() analyses crontab-expressions like "* * 1,2,3 * mon,tue" and returns an array
110
+ * containing all values. If it can't be parsed, an exception is thrown.
111
+ *
112
+ * @access public
113
+ * @param string $expression The cron-expression to parse.
114
+ * @return mixed
115
+ */
116
+
117
+ static public function parse($expression) {
118
+
119
+ // Convert named expressions if neccessary
120
+
121
+ if (substr($expression,0,1) == '@') {
122
+
123
+ $expression = strtr($expression, self::$intervals);
124
+
125
+ if (substr($expression,0,1) == '@') {
126
+
127
+ // Oops... unknown named interval!?!!
128
+ throw new Exception('Unknown named interval ['.$expression.']', 10000);
129
+
130
+ }
131
+
132
+ }
133
+
134
+ // Next basic check... do we have 5 segments?
135
+
136
+ $cron = explode(' ',$expression);
137
+
138
+ if (count($cron) <> 5) {
139
+
140
+ // No... we haven't...
141
+ throw new Exception('Wrong number of segments in expression. Expected: 5, Found: '.count($cron), 10001);
142
+
143
+ } else {
144
+
145
+ // Yup, 5 segments... lets see if we can work with them
146
+
147
+ foreach ($cron as $idx=>$segment) {
148
+
149
+ try {
150
+
151
+ $dummy[$idx] = self::expandSegment($idx, $segment);
152
+
153
+ } catch (Exception $e) {
154
+
155
+ throw $e;
156
+
157
+ }
158
+
159
+ }
160
+
161
+ }
162
+
163
+ return $dummy;
164
+
165
+ }
166
+
167
+ /**
168
+ * expandSegment() analyses a single segment
169
+ *
170
+ * @access public
171
+ * @param void
172
+ * @return void
173
+ */
174
+
175
+ static private function expandSegment($idx, $segment) {
176
+
177
+ // Store original segment for later use
178
+
179
+ $osegment = $segment;
180
+
181
+ // Replace months/weekdays like "January", "February", etc. with numbers
182
+
183
+ if (isset(self::$keywords[$idx])) {
184
+
185
+ $segment = preg_replace( array_keys(self::$keywords[$idx]),
186
+ array_values(self::$keywords[$idx]),
187
+ $segment );
188
+
189
+ }
190
+
191
+ // Replace wildcards
192
+
193
+ if (substr($segment,0,1) == '*') {
194
+
195
+ $segment = preg_replace('/^\*(\/\d+)?$/i',
196
+ self::$ranges[$idx]['min'].'-'.self::$ranges[$idx]['max'].'$1',
197
+ $segment);
198
+
199
+ }
200
+
201
+ // Make sure that nothing unparsed is left :)
202
+
203
+ $dummy = preg_replace('/[0-9\-\/\,]/','',$segment);
204
+
205
+ if (!empty($dummy)) {
206
+
207
+ // Ohoh.... thats not good :-)
208
+ throw new Exception('Failed to parse segment: '.$osegment, 10002);
209
+
210
+ }
211
+
212
+ // At this point our string should be OK - lets convert it to an array
213
+
214
+ $result = array();
215
+ $atoms = explode(',',$segment);
216
+
217
+ foreach ($atoms as $curatom) {
218
+
219
+ $result = array_merge($result, self::parseAtom($curatom));
220
+
221
+ }
222
+
223
+ // Get rid of duplicates and sort the array
224
+
225
+ $result = array_unique($result);
226
+ sort($result);
227
+
228
+ // Check for invalid values
229
+
230
+ if ($idx == IDX_WEEKDAY) {
231
+
232
+ if (end($result) == 7) {
233
+
234
+ if (reset($result) <> 0) {
235
+ array_unshift($result, 0);
236
+ }
237
+
238
+ array_pop($result);
239
+
240
+ }
241
+
242
+ }
243
+
244
+ foreach ($result as $key=>$value) {
245
+
246
+ if (($value < self::$ranges[$idx]['min']) || ($value > self::$ranges[$idx]['max'])) {
247
+ throw new Exception('Failed to parse segment, invalid value ['.$value.']: '.$osegment, 10003);
248
+ }
249
+
250
+ }
251
+
252
+ return $result;
253
+
254
+ }
255
+
256
+ /**
257
+ * parseAtom() analyses a single segment
258
+ *
259
+ * @access public
260
+ * @param string $atom The segment to parse
261
+ * @return array
262
+ */
263
+
264
+ static private function parseAtom($atom) {
265
+
266
+ $expanded = array();
267
+
268
+ if (preg_match('/^(\d+)-(\d+)(\/(\d+))?/i', $atom, $matches)) {
269
+
270
+ $low = $matches[1];
271
+ $high = $matches[2];
272
+
273
+ if ($low > $high) {
274
+ list($low,$high) = array($high,$low);
275
+ }
276
+
277
+ $step = isset($matches[4]) ? $matches[4] : 1;
278
+
279
+ for($i = $low; $i <= $high; $i += $step) {
280
+ $expanded[] = (int)$i;
281
+ }
282
+
283
+ } else {
284
+
285
+ $expanded[] = (int)$atom;
286
+
287
+ }
288
+
289
+ $expanded2 = array_unique($expanded);
290
+
291
+ return $expanded;
292
+
293
+ }
294
+
295
+ }
vendor/boldgrid/tdcron/class.tdcron.php ADDED
@@ -0,0 +1,438 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ define('IDX_MINUTE', 0);
4
+ define('IDX_HOUR', 1);
5
+ define('IDX_DAY', 2);
6
+ define('IDX_MONTH', 3);
7
+ define('IDX_WEEKDAY', 4);
8
+ define('IDX_YEAR', 5);
9
+
10
+ /*
11
+ * @author Christian Land <devel@tagdocs.de>
12
+ * @package tdCron
13
+ * @copyright Copyright (c) 2010-2018, Christian Land / tagdocs.de
14
+ * @license http://opensource.org/licenses/MIT MIT License
15
+ * @version 1.0.0
16
+ */
17
+
18
+ class tdCron {
19
+
20
+ /**
21
+ * Parsed cron-expressions cache.
22
+ * @var mixed
23
+ */
24
+ static private $pcron = array();
25
+
26
+ /**
27
+ * getNextOccurrence() uses a cron-expression to calculate the time and date at which a cronjob
28
+ * should be executed the next time. If a reference-time is passed, the next time and date
29
+ * after that time is calculated.
30
+ *
31
+ * @access public
32
+ * @param string $expression cron-expression to use
33
+ * @param int $timestamp optional reference-time
34
+ * @return int
35
+ * @since 0.0.1 Initial Release
36
+ * @author Christian Land
37
+ */
38
+ static public function getNextOccurrence($expression, $timestamp = null) {
39
+
40
+ try {
41
+
42
+ // Convert timestamp to array
43
+
44
+ $next = self::getTimestamp($timestamp);
45
+
46
+ // Calculate date/time
47
+
48
+ $next_time = self::calculateDateTime($expression, $next);
49
+
50
+ } catch (Exception $e) {
51
+
52
+ throw $e;
53
+
54
+ }
55
+
56
+ // return calculated time
57
+
58
+ return $next_time;
59
+
60
+ }
61
+
62
+ /**
63
+ * getLastOccurrence() does pretty much the same as getNextOccurrence(). The only difference
64
+ * is, that it doesn't calculate the next but the last time a cronjob should have been executed.
65
+ *
66
+ * @access public
67
+ * @param string $expression cron-expression to use
68
+ * @param int $timestamp optional reference-time
69
+ * @return int
70
+ * @since 0.0.1 Initial Release
71
+ * @author Christian Land
72
+ */
73
+
74
+ static public function getLastOccurrence($expression, $timestamp = null) {
75
+
76
+ try {
77
+
78
+ // Convert timestamp to array
79
+
80
+ $last = self::getTimestamp($timestamp);
81
+
82
+ // Calculate date/time
83
+
84
+ $last_time = self::calculateDateTime($expression, $last, false);
85
+
86
+ } catch (Exception $e) {
87
+
88
+ throw $e;
89
+
90
+ }
91
+
92
+ // return calculated time
93
+
94
+ return $last_time;
95
+
96
+ }
97
+
98
+ /**
99
+ * calculateDateTime() is the function where all the magic happens :-)
100
+ *
101
+ * It calculates the time and date at which the next/last call of a cronjob is/was due.
102
+ *
103
+ * @access private
104
+ * @param mixed $value cron-expression
105
+ * @param mixed $rtime reference-time
106
+ * @param bool $next true = nextOccurence, false = lastOccurence
107
+ * @return int
108
+ * @since 0.0.1 Initial Release
109
+ * @author Christian Land
110
+ */
111
+
112
+ static private function calculateDateTime($expression, $rtime, $next = true) {
113
+
114
+ // Initialize vars
115
+
116
+ $calc_date = true;
117
+
118
+ // Parse cron-expression (if neccessary)
119
+
120
+ $cron = self::getExpression($expression, !$next);
121
+
122
+ // OK, lets see if the day/month/weekday of the reference-date exist in our
123
+ // $cron-array.
124
+
125
+ if (!in_array($rtime[IDX_DAY], $cron[IDX_DAY]) ||
126
+ !in_array($rtime[IDX_MONTH], $cron[IDX_MONTH]) ||
127
+ !in_array($rtime[IDX_WEEKDAY], $cron[IDX_WEEKDAY])) {
128
+
129
+ // OK, things are easy. The day/month/weekday of the reference time
130
+ // can't be found in the $cron-array. This means that no matter what
131
+ // happens, we WILL end up at at a different date than that of our
132
+ // reference-time. And in this case, the lastOccurrence will ALWAYS
133
+ // happen at the latest possible time of the day and the nextOccurrence
134
+ // at the earliest possible time.
135
+ //
136
+ // In both cases, the time can be found in the first elements of the
137
+ // hour/minute cron-arrays.
138
+
139
+ $rtime[IDX_HOUR] = reset($cron[IDX_HOUR]);
140
+ $rtime[IDX_MINUTE] = reset($cron[IDX_MINUTE]);
141
+
142
+ } else {
143
+
144
+ // OK, things are getting a little bit more complicated...
145
+
146
+ $nhour = self::findValue($rtime[IDX_HOUR], $cron[IDX_HOUR], $next);
147
+
148
+ // Meh. Such a cruel world. Something has gone awry. Lets see HOW awry it went.
149
+
150
+ if ($nhour === false) {
151
+
152
+ // Ah, the hour-part went wrong. Thats easy. Wrong hour means that no
153
+ // matter what we do we'll end up at a different date. Thus we can use
154
+ // some simple operations to make things look pretty ;-)
155
+ //
156
+ // As alreasy mentioned before -> different date means earliest/latest
157
+ // time:
158
+
159
+ $rtime[IDX_HOUR] = reset($cron[IDX_HOUR]);
160
+ $rtime[IDX_MINUTE] = reset($cron[IDX_MINUTE]);
161
+
162
+ // Now all we have to do is add/subtract a day to get a new reference time
163
+ // to use later to find the right date. The following line probably looks
164
+ // a little odd but thats the easiest way of adding/substracting a day without
165
+ // screwing up the date. Just trust me on that one ;-)
166
+
167
+ $rtime = explode(',', strftime('%M,%H,%d,%m,%w,%Y', mktime($rtime[IDX_HOUR], $rtime[IDX_MINUTE], 0, $rtime[IDX_MONTH], $rtime[IDX_DAY], $rtime[IDX_YEAR]) + ((($next) ? 1 : -1) * 86400)));
168
+
169
+ } else {
170
+
171
+ // OK, there is a higher/lower hour available. Check the minutes-part.
172
+
173
+ $nminute = self::findValue($rtime[IDX_MINUTE], $cron[IDX_MINUTE], $next);
174
+
175
+ if ($nminute === false) {
176
+
177
+ // No matching minute-value found... lets see what happens if we substract/add an hour
178
+
179
+ $nhour = self::findValue($rtime[IDX_HOUR] + (($next) ? 1 : -1), $cron[IDX_HOUR], $next);
180
+
181
+ if ($nhour === false) {
182
+
183
+ // No more hours available... add/substract a day... you know what happens ;-)
184
+
185
+ $nminute = reset($cron[IDX_MINUTE]);
186
+ $nhour = reset($cron[IDX_HOUR]);
187
+
188
+ $rtime = explode(',', strftime('%M,%H,%d,%m,%w,%Y', mktime($nhour, $nminute, 0, $rtime[IDX_MONTH], $rtime[IDX_DAY], $rtime[IDX_YEAR]) + ((($next) ? 1 : -1) * 86400)));
189
+
190
+ } else {
191
+
192
+ // OK, there was another hour. Set the right minutes-value
193
+
194
+ $rtime[IDX_HOUR] = $nhour;
195
+ $rtime[IDX_MINUTE] = (($next) ? reset($cron[IDX_MINUTE]) : end($cron[IDX_MINUTE]));
196
+
197
+ $calc_date = false;
198
+
199
+ }
200
+
201
+ } else {
202
+
203
+ // OK, there is a matching minute... reset minutes if hour has changed
204
+
205
+ if ($nhour <> $rtime[IDX_HOUR]) {
206
+ $nminute = reset($cron[IDX_MINUTE]);
207
+ }
208
+
209
+ // Set time
210
+
211
+ $rtime[IDX_HOUR] = $nhour;
212
+ $rtime[IDX_MINUTE] = $nminute;
213
+
214
+ $calc_date = false;
215
+
216
+ }
217
+
218
+ }
219
+
220
+ }
221
+
222
+ // If we have to calculate the date... we'll do so
223
+
224
+ if ($calc_date === true) {
225
+
226
+ if (in_array($rtime[IDX_DAY], $cron[IDX_DAY]) &&
227
+ in_array($rtime[IDX_MONTH], $cron[IDX_MONTH]) &&
228
+ in_array($rtime[IDX_WEEKDAY], $cron[IDX_WEEKDAY])) {
229
+
230
+ return mktime($rtime[1], $rtime[0], 0, $rtime[3], $rtime[2], $rtime[5]);
231
+
232
+ } else {
233
+
234
+ // OK, some searching necessary...
235
+
236
+ $cdate = mktime(0, 0, 0, $rtime[IDX_MONTH], $rtime[IDX_DAY], $rtime[IDX_YEAR]);
237
+
238
+ // OK, these three nested loops are responsible for finding the date...
239
+ //
240
+ // The class has 2 limitations/bugs right now:
241
+ //
242
+ // -> it doesn't work for dates in 2036 or later!
243
+ // -> it will most likely fail if you search for a February, 29th with a given weekday
244
+ // (this does happen because the class only searches in the next/last 10 years! And
245
+ // while it usually takes less than 10 years for a "normal" date to iterate through
246
+ // all weekdays, it can take 20+ years for Feb, 29th to iterate through all weekdays!
247
+
248
+ for ($nyear = $rtime[IDX_YEAR];(($next) ? ($nyear <= $rtime[IDX_YEAR] + 10) : ($nyear >= $rtime[IDX_YEAR] -10));$nyear = $nyear + (($next) ? 1 : -1)) {
249
+
250
+ foreach ($cron[IDX_MONTH] as $nmonth) {
251
+
252
+ foreach ($cron[IDX_DAY] as $nday) {
253
+
254
+ if (checkdate($nmonth,$nday,$nyear)) {
255
+
256
+ $ndate = mktime(0,0,1,$nmonth,$nday,$nyear);
257
+
258
+ if (($next) ? ($ndate >= $cdate) : ($ndate <= $cdate)) {
259
+
260
+ $dow = date('w',$ndate);
261
+
262
+ // The date is "OK" - lets see if the weekday matches, too...
263
+
264
+ if (in_array($dow,$cron[IDX_WEEKDAY])) {
265
+
266
+ // WIN! :-) We found a valid date...
267
+
268
+ $rtime = explode(',', strftime('%M,%H,%d,%m,%w,%Y', mktime($rtime[IDX_HOUR], $rtime[IDX_MINUTE], 0, $nmonth, $nday, $nyear)));
269
+
270
+ return mktime($rtime[1], $rtime[0], 0, $rtime[3], $rtime[2], $rtime[5]);
271
+
272
+ }
273
+
274
+ }
275
+
276
+ }
277
+
278
+ }
279
+
280
+ }
281
+
282
+ }
283
+
284
+ }
285
+
286
+ throw new Exception('Failed to find date, No matching date found in a 10 years range!', 10004);
287
+
288
+ }
289
+
290
+ return mktime($rtime[1], $rtime[0], 0, $rtime[3], $rtime[2], $rtime[5]);
291
+
292
+ }
293
+
294
+ /**
295
+ * getTimestamp() converts an unix-timestamp to an array. The returned array contains the following values:
296
+ *
297
+ * [0] -> minute
298
+ * [1] -> hour
299
+ * [2] -> day
300
+ * [3] -> month
301
+ * [4] -> weekday
302
+ * [5] -> year
303
+ *
304
+ * The array is used by various functions.
305
+ *
306
+ * @access private
307
+ * @param int $timestamp If none is given, the current time is used
308
+ * @return mixed
309
+ * @since 0.0.1 Initial Release
310
+ * @author Christian Land
311
+ */
312
+
313
+ static private function getTimestamp($timestamp = null) {
314
+
315
+ if (is_null($timestamp)) {
316
+ $arr = explode(',', strftime('%M,%H,%d,%m,%w,%Y', time()));
317
+ } else {
318
+ $arr = explode(',', strftime('%M,%H,%d,%m,%w,%Y', $timestamp));
319
+ }
320
+
321
+ // Remove leading zeros (or we'll get in trouble ;-)
322
+
323
+ foreach ($arr as $key=>$value) {
324
+ $arr[$key] = (int)ltrim($value,'0');
325
+ }
326
+
327
+ return $arr;
328
+
329
+ }
330
+
331
+ /**
332
+ * findValue() checks if the given value exists in an array. If it does not exist, the next
333
+ * higher/lower value is returned (depending on $next). If no higher/lower value exists,
334
+ * false is returned.
335
+ *
336
+ * @access public
337
+ * @param int $value
338
+ * @param mixed $data
339
+ * @param bool $next
340
+ * @return mixed
341
+ * @since 0.0.1 Initial Release
342
+ * @author Christian Land
343
+ */
344
+
345
+ static private function findValue($value, $data, $next = true) {
346
+
347
+ if (in_array($value, $data)) {
348
+
349
+ return (int)$value;
350
+
351
+ } else {
352
+
353
+ if (($next) ? ($value <= end($data)) : ($value >= end($data))) {
354
+
355
+ foreach ($data as $curval) {
356
+
357
+ if (($next) ? ($value <= (int)$curval) : ($curval <= $value)) {
358
+
359
+ return (int)$curval;
360
+
361
+ }
362
+
363
+ }
364
+
365
+ }
366
+
367
+ }
368
+
369
+ return false;
370
+
371
+ }
372
+
373
+ /**
374
+ * getExpression() returns a parsed cron-expression. Parsed cron-expressions are cached to reduce
375
+ * unneccessary calls of the parser.
376
+ *
377
+ * @access public
378
+ * @param string $value
379
+ * @param bool $reverse
380
+ * @return mixed
381
+ * @since 0.0.1 Initial Release
382
+ * @author Christian Land
383
+ */
384
+
385
+ static private function getExpression($expression, $reverse=false) {
386
+
387
+ // First of all we cleanup the expression and remove all duplicate tabs/spaces/etc.
388
+ // For example "* * * * *" would be converted to "* * * * *", etc.
389
+
390
+ $expression = preg_replace('/(\s+)/', ' ', strtolower(trim($expression)));
391
+
392
+ // Lets see if we've already parsed that expression
393
+
394
+ if (!isset(self::$pcron[$expression])) {
395
+
396
+ // Nope - parse it!
397
+
398
+ try {
399
+
400
+ self::$pcron[$expression] = tdCronEntry::parse($expression);
401
+ self::$pcron['reverse'][$expression] = self::arrayReverse(self::$pcron[$expression]);
402
+
403
+ } catch (Exception $e) {
404
+
405
+ throw $e;
406
+
407
+ }
408
+
409
+ }
410
+
411
+ return ($reverse ? self::$pcron['reverse'][$expression] : self::$pcron[$expression]);
412
+
413
+ }
414
+
415
+ /**
416
+ * arrayReverse() reverses all sub-arrays of our cron array. The reversed values are used for calculations
417
+ * that are run when getLastOccurence() is called.
418
+ *
419
+ * @access public
420
+ * @param mixed $cron
421
+ * @return mixed
422
+ * @since 0.0.1 Initial Release
423
+ * @author Christian Land
424
+ */
425
+
426
+ static private function arrayReverse($cron) {
427
+
428
+ foreach ($cron as $key=>$value) {
429
+
430
+ $cron[$key] = array_reverse($value);
431
+
432
+ }
433
+
434
+ return $cron;
435
+
436
+ }
437
+
438
+ }
vendor/boldgrid/tdcron/composer.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "boldgrid/tdcron",
3
+ "description": "A simple utility to manipulate cron jobs.",
4
+ "type": "library",
5
+ "license": "GPL-2.0-or-later",
6
+ "authors": [
7
+ {
8
+ "name": "Joe Cartonia",
9
+ "email": "joec@boldgrid.com",
10
+ "homepage": "https://twitter.com/joemotocss",
11
+ "role": "Developer"
12
+ },
13
+ {
14
+ "name": "bwmarkle",
15
+ "role": "Developer"
16
+ }
17
+ ]
18
+ }
vendor/boldgrid/tdcron/test.data.php ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Define some tests :-)
4
+
5
+ $tests = array();
6
+
7
+ $tests[] = array(
8
+ 'expression' => '10,20,45 9,10,11,12 * * *',
9
+ 'reftime' => mktime(9,9,0,8,2,2010),
10
+ 'expected_n' => '02.08.2010, 09:10:00',
11
+ 'expected_l' => '01.08.2010, 12:45:00'
12
+ );
13
+
14
+ $tests[] = array(
15
+ 'expression' => '10,20,45 9,10,11,12 * * *',
16
+ 'reftime' => mktime(9,46,0,8,2,2010),
17
+ 'expected_n' => '02.08.2010, 10:10:00',
18
+ 'expected_l' => '02.08.2010, 09:45:00'
19
+ );
20
+
21
+ $tests[] = array(
22
+ 'expression' => '10,20,45 9,10,11,12 * * *',
23
+ 'reftime' => mktime(12,46,0,8,2,2010),
24
+ 'expected_n' => '03.08.2010, 09:10:00',
25
+ 'expected_l' => '02.08.2010, 12:45:00'
26
+ );
27
+
28
+ $tests[] = array(
29
+ 'expression' => '10,20,45 9,10,11,12 * * *',
30
+ 'reftime' => mktime(10,36,0,8,2,2010),
31
+ 'expected_n' => '02.08.2010, 10:45:00',
32
+ 'expected_l' => '02.08.2010, 10:20:00'
33
+ );
34
+
35
+ $tests[] = array(
36
+ 'expression' => '10,20,45 9,10,11,12 * * *',
37
+ 'reftime' => mktime(12,46,0,8,2,2010),
38
+ 'expected_n' => '03.08.2010, 09:10:00',
39
+ 'expected_l' => '02.08.2010, 12:45:00'
40
+ );
41
+
42
+ $tests[] = array(
43
+ 'expression' => '25 9,10,12 * * *',
44
+ 'reftime' => mktime(10,20,0,8,2,2010),
45
+ 'expected_n' => '02.08.2010, 10:25:00',
46
+ 'expected_l' => '02.08.2010, 09:25:00'
47
+ );
48
+
49
+ $tests[] = array(
50
+ 'expression' => '1,2,10-20,40-50/5 10,11,12 * * *',
51
+ 'reftime' => mktime(9,45,0,8,2,2010),
52
+ 'expected_n' => '02.08.2010, 10:01:00',
53
+ 'expected_l' => '01.08.2010, 12:50:00'
54
+ );
55
+
56
+ $tests[] = array(
57
+ 'expression' => '10,30,50 10,11,12 * * *',
58
+ 'reftime' => mktime(11,45,0,8,2,2010),
59
+ 'expected_n' => '02.08.2010, 11:50:00',
60
+ 'expected_l' => '02.08.2010, 11:30:00'
61
+ );
62
+
63
+ $tests[] = array(
64
+ 'expression' => '* * 29 2 *',
65
+ 'reftime' => mktime(11,45,0,8,2,2010),
66
+ 'expected_n' => '29.02.2012, 00:00:00',
67
+ 'expected_l' => '29.02.2008, 23:59:00'
68
+ );
69
+
70
+ $tests[] = array(
71
+ 'expression' => '* * * * *',
72
+ 'reftime' => mktime(11,45,0,8,2,2010),
73
+ 'expected_n' => '02.08.2010, 11:45:00',
74
+ 'expected_l' => '02.08.2010, 11:45:00'
75
+ );
76
+
77
+ $tests[] = array(
78
+ 'expression' => '* * 3 6 3',
79
+ 'reftime' => mktime(11,45,0,8,2,2010),
80
+ 'expected_n' => '03.06.2015, 00:00:00',
81
+ 'expected_l' => '03.06.2009, 23:59:00'
82
+ );
83
+
84
+ $tests[] = array(
85
+ 'expression' => '* * 3 Feb Sat',
86
+ 'reftime' => mktime(11,45,0,8,2,2010),
87
+ 'expected_n' => '03.02.2018, 00:00:00',
88
+ 'expected_l' => '03.02.2007, 23:59:00'
89
+ );
90
+
91
+ $tests[] = array(
92
+ 'expression' => '*/15 * * * *',
93
+ 'reftime' => mktime(11,40,0,8,2,2010),
94
+ 'expected_n' => '02.08.2010, 11:45:00',
95
+ 'expected_l' => '02.08.2010, 11:30:00'
96
+ );
97
+
98
+ $tests[] = array(
99
+ 'expression' => '*/15 * * * Fri,Tue',
100
+ 'reftime' => mktime(11,40,0,8,2,2010),
101
+ 'expected_n' => '03.08.2010, 00:00:00',
102
+ 'expected_l' => '30.07.2010, 23:45:00'
103
+ );
104
+
105
+ $tests[] = array(
106
+ 'expression' => '*/15 * 1 4 Fri,Tue',
107
+ 'reftime' => mktime(11,40,0,8,2,2010),
108
+ 'expected_n' => '01.04.2011, 00:00:00',
109
+ 'expected_l' => '01.04.2008, 23:45:00'
110
+ );
111
+
112
+ $tests[] = array(
113
+ 'desc' => 'Hours match, no more minutes -> next day',
114
+ 'expression' => '10,20,45 9,10,11 * * *',
115
+ 'reftime' => mktime(11,50,0,2,1,2010),
116
+ 'expected_n' => '02.02.2010, 09:10:00'
117
+ );
118
+
119
+ $tests[] = array(
120
+ 'desc' => 'Hours match, no more minutes -> last day',
121
+ 'expression' => '10,20,45 9,10,11 * * *',
122
+ 'reftime' => mktime(9,5,0,2,1,2010),
123
+ 'expected_l' => '31.01.2010, 11:45:00'
124
+ );
125
+
126
+ $tests[] = array(
127
+ 'desc' => 'Hours match, no more minutes -> next day -> LEAP YEAR',
128
+ 'expression' => '10,20,45 9,10,11 * * *',
129
+ 'reftime' => mktime(11,50,0,2,28,2008),
130
+ 'expected_n' => '29.02.2008, 09:10:00'
131
+ );
132
+
133
+ $tests[] = array(
134
+ 'desc' => 'Hours match, no more minutes -> last day -> LEAP YEAR',
135
+ 'expression' => '10,20,45 9,10,11 * * *',
136
+ 'reftime' => mktime(9,5,0,3,1,2008),
137
+ 'expected_l' => '29.02.2008, 11:45:00'
138
+ );
139
+
140
+ $tests[] = array(
141
+ 'desc' => 'Thursday before/after Feb. 1st 2010',
142
+ 'expression' => '* * * * 4',
143
+ 'reftime' => mktime(11,50,0,2,1,2010),
144
+ 'expected_n' => '04.02.2010, 00:00:00',
145
+ 'expected_l' => '28.01.2010, 23:59:00'
146
+ );
147
+
148
+ $tests[] = array(
149
+ 'desc' => 'Tuesday before/after Jan. 1st 2010',
150
+ 'expression' => '* * * * 2',
151
+ 'reftime' => mktime(11,50,0,1,1,2010),
152
+ 'expected_n' => '05.01.2010, 00:00:00',
153
+ 'expected_l' => '29.12.2009, 23:59:00'
154
+ );
155
+
156
+ $tests[] = array(
157
+ 'desc' => 'Hours match, no more minutes -> next day -> August',
158
+ 'expression' => '10,20,45 9,10,11 * 8,9 *',
159
+ 'reftime' => mktime(11,50,0,2,1,2010),
160
+ 'expected_n' => '01.08.2010, 09:10:00'
161
+ );
162
+
163
+ $tests[] = array(
164
+ 'desc' => 'Hours match, no more minutes -> last day -> September',
165
+ 'expression' => '10,20,45 9,10,11 * 8,9 *',
166
+ 'reftime' => mktime(11,50,0,2,1,2010),
167
+ 'expected_l' => '30.09.2009, 11:45:00'
168
+ );
169
+
170
+ $tests[] = array(
171
+ 'desc' => 'Last February, 29th - 11:45',
172
+ 'expression' => '10,20,45 9,10,11 29 2 5',
173
+ 'reftime' => mktime(11,50,0,2,1,2010),
174
+ 'expected_l' => '29.02.2008, 11:45:00'
175
+ );
176
+
177
+ $tests[] = array(
178
+ 'desc' => 'Lets get wild with the cron-expression...',
179
+ 'expression' => '7-20,3,1 5-8,12-20/3 1-10,13,15,20-30/2 March-Sep Wed-Friday',
180
+ 'reftime' => mktime(11,50,0,2,1,2010),
181
+ 'expected_l' => '30.09.2009, 18:20:00',
182
+ 'expected_n' => '03.03.2010, 05:01:00'
183
+ );
184
+
185
+ $tests[] = array(
186
+ 'desc' => 'Just a simple -> * * * * *',
187
+ 'expression' => '* * * * *',
188
+ 'reftime' => mktime(11,50,0,2,1,2010),
189
+ 'expected_l' => '01.02.2010, 11:50:00',
190
+ 'expected_n' => '01.02.2010, 11:50:00'
191
+ );
192
+
193
+ /*
194
+ // This WILL FAIL!
195
+
196
+ $tests[] = array(
197
+ 'expression' => '99 * * * *',
198
+ 'reftime' => mktime(11,40,0,8,2,2010),
199
+ 'expected_n' => 'Error',
200
+ 'expected_l' => 'Error'
201
+ );
202
+ */
vendor/boldgrid/tdcron/test.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Load classes
4
+
5
+ require_once('class.tdcron.php');
6
+ require_once('class.tdcron.entry.php');
7
+
8
+ // Load tests
9
+
10
+ require_once('test.data.php');
11
+
12
+ // Rock it....
13
+
14
+ $ok = 0;
15
+ $fail = 0;
16
+
17
+ echo "\n".str_repeat('-',80)."\n";
18
+
19
+ echo 'Testing '.count($tests).' expressions...';
20
+
21
+ echo "\n\n".str_repeat('-',80)."\n";
22
+
23
+ foreach ($tests as $curtest) {
24
+
25
+ try {
26
+
27
+ if (!empty($curtest['desc'])) {
28
+ echo 'Description: ['.$curtest['desc'].']'."\n";
29
+ }
30
+ echo 'Expression: ['.$curtest['expression'].']'."\n";
31
+
32
+ echo 'Ref-Time: ['.date('d.m.Y, H:i:s', $curtest['reftime'])."]\n\n";
33
+
34
+ if (isset($curtest['expected_n'])) {
35
+
36
+ echo 'nextRun(): ['.date('d.m.Y, H:i:s', tdCron::getNextOccurrence($curtest['expression'],$curtest['reftime']))."]\n";
37
+ echo 'Expected: ['.$curtest['expected_n']."] - ";
38
+
39
+ if (date('d.m.Y, H:i:s', tdCron::getNextOccurrence($curtest['expression'],$curtest['reftime'])) == $curtest['expected_n']) {
40
+ echo 'passed!';
41
+ $ok++;
42
+ } else {
43
+ echo 'FAILED!';
44
+ $fail++;
45
+ }
46
+
47
+ echo "\n\n";
48
+
49
+ }
50
+
51
+ if (isset($curtest['expected_l'])) {
52
+
53
+ echo 'lastRun(): ['.date('d.m.Y, H:i:s', tdCron::getLastOccurrence($curtest['expression'],$curtest['reftime']))."]\n";
54
+ echo 'Expected: ['.$curtest['expected_l']."] - ";
55
+
56
+ if (date('d.m.Y, H:i:s', tdCron::getLastOccurrence($curtest['expression'],$curtest['reftime'])) == $curtest['expected_l']) {
57
+ echo 'passed!';
58
+ $ok++;
59
+ } else {
60
+ echo 'FAILED!';
61
+ $fail++;
62
+ }
63
+
64
+ echo "\n\n";
65
+
66
+ }
67
+
68
+ } catch (Exception $e) {
69
+
70
+ echo 'ERROR!'."\n\n";
71
+ print_r($e);
72
+
73
+ }
74
+
75
+ echo str_repeat('-',80)."\n";
76
+
77
+ }
78
+
79
+ echo 'OK: '.$ok."\n";
80
+ echo 'FAIL: '.$fail."\n";
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInitd3475abad362b46ca6ec161094303b5a
6
  {
7
  private static $loader;
8
 
@@ -22,15 +22,15 @@ class ComposerAutoloaderInitd3475abad362b46ca6ec161094303b5a
22
  return self::$loader;
23
  }
24
 
25
- spl_autoload_register(array('ComposerAutoloaderInitd3475abad362b46ca6ec161094303b5a', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
- spl_autoload_unregister(array('ComposerAutoloaderInitd3475abad362b46ca6ec161094303b5a', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
  require_once __DIR__ . '/autoload_static.php';
32
 
33
- call_user_func(\Composer\Autoload\ComposerStaticInitd3475abad362b46ca6ec161094303b5a::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
@@ -51,19 +51,19 @@ class ComposerAutoloaderInitd3475abad362b46ca6ec161094303b5a
51
  $loader->register(true);
52
 
53
  if ($useStaticLoader) {
54
- $includeFiles = Composer\Autoload\ComposerStaticInitd3475abad362b46ca6ec161094303b5a::$files;
55
  } else {
56
  $includeFiles = require __DIR__ . '/autoload_files.php';
57
  }
58
  foreach ($includeFiles as $fileIdentifier => $file) {
59
- composerRequired3475abad362b46ca6ec161094303b5a($fileIdentifier, $file);
60
  }
61
 
62
  return $loader;
63
  }
64
  }
65
 
66
- function composerRequired3475abad362b46ca6ec161094303b5a($fileIdentifier, $file)
67
  {
68
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
69
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit8907797e5ce4c58cc1367210818a76bc
6
  {
7
  private static $loader;
8
 
22
  return self::$loader;
23
  }
24
 
25
+ spl_autoload_register(array('ComposerAutoloaderInit8907797e5ce4c58cc1367210818a76bc', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
+ spl_autoload_unregister(array('ComposerAutoloaderInit8907797e5ce4c58cc1367210818a76bc', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
  require_once __DIR__ . '/autoload_static.php';
32
 
33
+ call_user_func(\Composer\Autoload\ComposerStaticInit8907797e5ce4c58cc1367210818a76bc::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
51
  $loader->register(true);
52
 
53
  if ($useStaticLoader) {
54
+ $includeFiles = Composer\Autoload\ComposerStaticInit8907797e5ce4c58cc1367210818a76bc::$files;
55
  } else {
56
  $includeFiles = require __DIR__ . '/autoload_files.php';
57
  }
58
  foreach ($includeFiles as $fileIdentifier => $file) {
59
+ composerRequire8907797e5ce4c58cc1367210818a76bc($fileIdentifier, $file);
60
  }
61
 
62
  return $loader;
63
  }
64
  }
65
 
66
+ function composerRequire8907797e5ce4c58cc1367210818a76bc($fileIdentifier, $file)
67
  {
68
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
69
  require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInitd3475abad362b46ca6ec161094303b5a
8
  {
9
  public static $files = array (
10
  'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
@@ -91,9 +91,9 @@ class ComposerStaticInitd3475abad362b46ca6ec161094303b5a
91
  public static function getInitializer(ClassLoader $loader)
92
  {
93
  return \Closure::bind(function () use ($loader) {
94
- $loader->prefixLengthsPsr4 = ComposerStaticInitd3475abad362b46ca6ec161094303b5a::$prefixLengthsPsr4;
95
- $loader->prefixDirsPsr4 = ComposerStaticInitd3475abad362b46ca6ec161094303b5a::$prefixDirsPsr4;
96
- $loader->classMap = ComposerStaticInitd3475abad362b46ca6ec161094303b5a::$classMap;
97
 
98
  }, null, ClassLoader::class);
99
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit8907797e5ce4c58cc1367210818a76bc
8
  {
9
  public static $files = array (
10
  'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
91
  public static function getInitializer(ClassLoader $loader)
92
  {
93
  return \Closure::bind(function () use ($loader) {
94
+ $loader->prefixLengthsPsr4 = ComposerStaticInit8907797e5ce4c58cc1367210818a76bc::$prefixLengthsPsr4;
95
+ $loader->prefixDirsPsr4 = ComposerStaticInit8907797e5ce4c58cc1367210818a76bc::$prefixDirsPsr4;
96
+ $loader->classMap = ComposerStaticInit8907797e5ce4c58cc1367210818a76bc::$classMap;
97
 
98
  }, null, ClassLoader::class);
99
  }
vendor/composer/installed.json CHANGED
@@ -54,6 +54,18 @@
54
  ],
55
  "description": "The BoldGrid Library for shared code used in official BoldGrid plugins and themes."
56
  },
 
 
 
 
 
 
 
 
 
 
 
 
57
  {
58
  "name": "ifsnop/mysqldump-php",
59
  "version": "v2.9",
54
  ],
55
  "description": "The BoldGrid Library for shared code used in official BoldGrid plugins and themes."
56
  },
57
+ {
58
+ "name": "boldgrid/tdcron",
59
+ "version": "dev-master",
60
+ "version_normalized": "9999999-dev",
61
+ "source": {
62
+ "type": "git",
63
+ "url": "https://github.com/boldgrid/tdcron",
64
+ "reference": "origin/master"
65
+ },
66
+ "type": "library",
67
+ "installation-source": "source"
68
+ },
69
  {
70
  "name": "ifsnop/mysqldump-php",
71
  "version": "v2.9",