This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace HM\BackUpWordPress; |
||
4 | |||
5 | /** |
||
6 | * The Backup Scheduler |
||
7 | * |
||
8 | * Handles everything related to managing and running a backup schedule |
||
9 | * |
||
10 | * @uses Backup |
||
11 | * @uses |
||
12 | */ |
||
13 | class Scheduled_Backup { |
||
14 | |||
15 | /** |
||
16 | * The unique schedule id |
||
17 | * |
||
18 | * @var string |
||
19 | * @access private |
||
20 | */ |
||
21 | private $id = ''; |
||
22 | |||
23 | /** |
||
24 | * The slugified version of the schedule name |
||
25 | * |
||
26 | * @var string |
||
27 | * @access private |
||
28 | */ |
||
29 | private $slug = ''; |
||
30 | |||
31 | /** |
||
32 | * The raw schedule options from the database |
||
33 | * |
||
34 | * @var array |
||
35 | * @access private |
||
36 | */ |
||
37 | private $options = array( |
||
38 | 'max_backups' => 3, |
||
39 | 'excludes' => array(), |
||
40 | 'type' => 'complete', |
||
41 | 'reoccurrence' => 'manually', |
||
42 | ); |
||
43 | |||
44 | /** |
||
45 | * Setup the schedule object |
||
46 | * Loads the options from the database and populates properties |
||
47 | * |
||
48 | * @param string $id |
||
49 | * |
||
50 | * @throws Exception |
||
51 | */ |
||
52 | |||
53 | public function __construct( $id ) { |
||
54 | |||
55 | // Verify the schedule id |
||
56 | if ( ! is_string( $id ) || ! trim( $id ) ) { |
||
57 | throw new \Exception( 'Argument 1 for ' . __METHOD__ . ' must be a non-empty string' ); |
||
58 | } |
||
59 | |||
60 | // Store id for later |
||
61 | $this->id = $id; |
||
62 | |||
63 | // Load the options |
||
64 | $this->options = array_merge( $this->options, array_filter( (array) get_option( 'hmbkp_schedule_' . $this->get_id() ) ) ); |
||
65 | |||
66 | if ( defined( 'HMBKP_SCHEDULE_START_TIME' ) && strtotime( 'HMBKP_SCHEDULE_START_TIME' ) ) { |
||
67 | $this->set_schedule_start_time( strtotime( 'HMBKP_SCHEDULE_START_TIME' ) ); |
||
68 | } |
||
69 | |||
70 | // Setup the schedule if it isn't set |
||
71 | if ( ( ! $this->is_cron_scheduled() && $this->get_reoccurrence() !== 'manually' ) ) { |
||
72 | $this->schedule(); |
||
73 | } |
||
74 | |||
75 | $this->backup_filename = implode( '-', array( |
||
0 ignored issues
–
show
|
|||
76 | sanitize_title( str_ireplace( array( |
||
77 | 'http://', |
||
78 | 'https://', |
||
79 | 'www', |
||
80 | ), '', home_url() ) ), |
||
81 | $this->get_id(), |
||
82 | $this->get_type(), |
||
83 | current_time( 'Y-m-d-H-i-s' ), |
||
84 | ) ) . '.zip'; |
||
85 | |||
86 | $this->database_dump_filename = implode( '-', array( |
||
0 ignored issues
–
show
The property
database_dump_filename does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
87 | 'database', |
||
88 | sanitize_title( str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ) ), |
||
89 | $this->get_id(), |
||
90 | ) ) . '.sql'; |
||
91 | |||
92 | $this->status = new Backup_Status( $this->get_id() ); |
||
0 ignored issues
–
show
The property
status does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
93 | |||
94 | } |
||
95 | |||
96 | /** |
||
97 | * Get the id for this schedule |
||
98 | */ |
||
99 | public function get_id() { |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
100 | return esc_attr( $this->id ); |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Get a slugified version of name |
||
105 | */ |
||
106 | public function get_slug() { |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
107 | |||
108 | // We cache slug in $this to save expensive calls to sanitize_title |
||
109 | if ( ! empty( $this->slug ) ) { |
||
110 | return $this->slug; |
||
111 | } |
||
112 | |||
113 | return $this->slug = sanitize_title( $this->get_name() ); |
||
114 | |||
115 | } |
||
116 | |||
117 | /** |
||
118 | * Returns the given option value |
||
119 | * |
||
120 | * @param $option_name |
||
121 | * @return mixed The option value |
||
122 | */ |
||
123 | public function get_schedule_option( $option_name ) { |
||
124 | if ( isset( $this->options[ $option_name ] ) ) { |
||
125 | return $this->options[ $option_name ]; |
||
126 | } |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * Get the name of this backup schedule |
||
131 | * |
||
132 | * @return string |
||
133 | */ |
||
134 | public function get_name() { |
||
135 | return ucwords( $this->get_type() ) . ' ' . $this->get_reoccurrence(); |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Get the type of backup |
||
140 | * |
||
141 | * @return string |
||
142 | */ |
||
143 | public function get_type() { |
||
144 | return $this->options['type']; |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * Set the type of backup |
||
149 | * |
||
150 | * @param string $type |
||
151 | */ |
||
152 | public function set_type( $type ) { |
||
153 | if ( ! isset( $this->options['type'] ) || $this->options['type'] !== $type ) { |
||
154 | $this->options['type'] = $type; |
||
155 | } |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * Get the exclude rules |
||
160 | * |
||
161 | * @return array |
||
0 ignored issues
–
show
|
|||
162 | */ |
||
163 | public function get_excludes() { |
||
164 | return new Excludes( $this->options['excludes'] ); |
||
165 | } |
||
166 | |||
167 | /** |
||
168 | * Set the exclude rules |
||
169 | * |
||
170 | * @param mixed $excludes A comma separated list or array of exclude rules |
||
0 ignored issues
–
show
There is no parameter named
$excludes . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
171 | * @param bool $append Whether to replace or append to existing rules |
||
172 | * |
||
173 | * @return string |
||
0 ignored issues
–
show
|
|||
174 | */ |
||
175 | public function set_excludes( $exclude_rules, $append = false ) { |
||
176 | |||
177 | // Normalize the exclude rules before we save them |
||
178 | $excludes = new Excludes; |
||
179 | $excludes = $excludes->normalize( (array) $exclude_rules ); |
||
180 | |||
181 | // If these are valid excludes and they are different save them |
||
182 | if ( empty( $this->options['excludes'] ) || $this->options['excludes'] !== $excludes ) { |
||
183 | $this->options['excludes'] = $append && ! empty( $this->options['excludes'] ) ? array_merge( (array) $this->options['excludes'], (array) $excludes ) : (array) $excludes; |
||
184 | } |
||
185 | |||
186 | } |
||
187 | |||
188 | /** |
||
189 | * Get the maximum number of backups to keep |
||
190 | * |
||
191 | * @return int |
||
192 | */ |
||
193 | public function get_max_backups() { |
||
194 | return (int) $this->options['max_backups']; |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * Set the maximum number of backups to keep |
||
199 | * |
||
200 | * @param int $max |
||
201 | * |
||
202 | * @return WP_Error|boolean |
||
0 ignored issues
–
show
|
|||
203 | */ |
||
204 | public function set_max_backups( $max ) { |
||
205 | $this->options['max_backups'] = $max; |
||
206 | } |
||
207 | |||
208 | public function get_status() { |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
209 | return $this->status; |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * Back compat with old set_status mathod |
||
214 | * |
||
215 | * @deprecated 3.4 Backup->status->set_status() |
||
216 | */ |
||
217 | public function set_status( $message ) { |
||
218 | _deprecated_function( __FUNCTION__, '3.4', 'Backup->status->set_status()' ); |
||
219 | $this->status->set_status( $message ); |
||
220 | } |
||
221 | |||
222 | /** |
||
223 | * Get the array of services options for this schedule |
||
224 | * |
||
225 | * @param $service |
||
226 | * @param null $option |
||
227 | * |
||
228 | * @return array |
||
229 | */ |
||
230 | public function get_service_options( $service, $option = null ) { |
||
231 | |||
232 | if ( ! is_null( $option ) ) { |
||
233 | |||
234 | if ( isset( $this->options[ $service ][ $option ] ) ) { |
||
235 | return $this->options[ $service ][ $option ]; |
||
236 | } |
||
237 | |||
238 | return array(); |
||
239 | |||
240 | } |
||
241 | |||
242 | if ( isset( $this->options[ $service ] ) ) { |
||
243 | return $this->options[ $service ]; |
||
244 | } |
||
245 | |||
246 | return array(); |
||
247 | |||
248 | } |
||
249 | |||
250 | /** |
||
251 | * Set the service options for this schedule |
||
252 | * |
||
253 | * @param $service |
||
254 | * @param array $options |
||
255 | */ |
||
256 | public function set_service_options( $service, array $options ) { |
||
257 | $this->options[ $service ] = $options; |
||
258 | } |
||
259 | |||
260 | /** |
||
261 | * Get the start time for the schedule |
||
262 | * |
||
263 | * @return int timestamp || 0 for manual only schedules |
||
0 ignored issues
–
show
|
|||
264 | */ |
||
265 | public function get_schedule_start_time( $gmt = true ) { |
||
266 | |||
267 | if ( 'manually' === $this->get_reoccurrence() ) { |
||
268 | return 0; |
||
269 | } |
||
270 | |||
271 | if ( ! $gmt ) { |
||
272 | $offset = get_option( 'gmt_offset' ) * 3600; |
||
273 | } else { |
||
274 | $offset = 0; |
||
275 | } |
||
276 | |||
277 | if ( ! empty( $this->options['schedule_start_time'] ) ) { |
||
278 | return $this->options['schedule_start_time'] + $offset; |
||
279 | } |
||
280 | |||
281 | $this->set_schedule_start_time( time() ); |
||
282 | |||
283 | return time() + $offset; |
||
284 | |||
285 | } |
||
286 | |||
287 | /** |
||
288 | * Set the schedule start time. |
||
289 | * |
||
290 | * @param Int $time A valid timestamp |
||
291 | */ |
||
292 | public function set_schedule_start_time( $time ) { |
||
293 | |||
294 | $this->options['schedule_start_time'] = $time; |
||
295 | |||
296 | $this->schedule(); |
||
297 | |||
298 | } |
||
299 | |||
300 | /** |
||
301 | * Get the schedule reoccurrence |
||
302 | * |
||
303 | */ |
||
304 | public function get_reoccurrence() { |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
305 | return $this->options['reoccurrence']; |
||
306 | } |
||
307 | |||
308 | /** |
||
309 | * Set the schedule reoccurrence |
||
310 | * |
||
311 | * @param string $reoccurrence |
||
312 | * |
||
313 | * @return \WP_Error|null|boolean |
||
314 | */ |
||
315 | public function set_reoccurrence( $reoccurrence ) { |
||
316 | |||
317 | $hmbkp_schedules = cron_schedules(); |
||
318 | |||
319 | // Check it's valid |
||
320 | if ( ! is_string( $reoccurrence ) || ! trim( $reoccurrence ) || ( ! in_array( $reoccurrence, array_keys( $hmbkp_schedules ) ) ) && 'manually' !== $reoccurrence ) { |
||
321 | return new \WP_Error( 'hmbkp_invalid_argument_error', sprintf( __( 'Argument 1 for %s must be a valid cron recurrence or "manually"', 'backupwordpress' ), __METHOD__ ) ); |
||
322 | } |
||
323 | |||
324 | // If the recurrence is already set to the same thing then there's no need to continue |
||
325 | if ( isset( $this->options['reoccurrence'] ) && $this->options['reoccurrence'] === $reoccurrence && $this->is_cron_scheduled() ) { |
||
326 | return; |
||
327 | } |
||
328 | |||
329 | $this->options['reoccurrence'] = $reoccurrence; |
||
330 | |||
331 | if ( 'manually' === $reoccurrence ) { |
||
332 | $this->unschedule(); |
||
333 | |||
334 | } else { |
||
335 | $this->schedule(); |
||
336 | } |
||
337 | |||
338 | return true; |
||
339 | |||
340 | } |
||
341 | |||
342 | /** |
||
343 | * Get the interval between backups |
||
344 | * |
||
345 | * @return int |
||
346 | */ |
||
347 | public function get_interval() { |
||
348 | |||
349 | $hmbkp_schedules = cron_schedules(); |
||
350 | |||
351 | if ( 'manually' === $this->get_reoccurrence() ) { |
||
352 | return 0; |
||
353 | } |
||
354 | |||
355 | return $hmbkp_schedules[ $this->get_reoccurrence() ]['interval']; |
||
356 | |||
357 | } |
||
358 | |||
359 | /** |
||
360 | * Get the next occurrence of this scheduled backup |
||
361 | * |
||
362 | */ |
||
363 | public function get_next_occurrence( $gmt = true ) { |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
364 | |||
365 | $time = wp_next_scheduled( 'hmbkp_schedule_hook', array( 'id' => $this->get_id() ) ); |
||
366 | |||
367 | if ( ! $time ) { |
||
368 | $time = 0; |
||
369 | } |
||
370 | |||
371 | if ( ! $gmt ) { |
||
372 | $time += get_option( 'gmt_offset' ) * 3600; |
||
373 | } |
||
374 | |||
375 | return $time; |
||
376 | |||
377 | } |
||
378 | |||
379 | public function is_cron_scheduled() { |
||
380 | return (bool) $this->get_next_occurrence(); |
||
381 | } |
||
382 | |||
383 | /** |
||
384 | * Schedule the backup cron |
||
385 | * |
||
386 | */ |
||
387 | public function schedule() { |
||
388 | |||
389 | // Clear any existing hooks |
||
390 | $this->unschedule(); |
||
391 | |||
392 | $schedule_timestamp = $this->get_schedule_start_time(); |
||
393 | |||
394 | wp_schedule_event( $schedule_timestamp, $this->get_reoccurrence(), 'hmbkp_schedule_hook', array( 'id' => $this->get_id() ) ); |
||
395 | |||
396 | } |
||
397 | |||
398 | |||
399 | /** |
||
400 | * Unschedule the backup cron. |
||
401 | * |
||
402 | * @return void |
||
403 | */ |
||
404 | public function unschedule() { |
||
405 | wp_clear_scheduled_hook( 'hmbkp_schedule_hook', array( 'id' => $this->get_id() ) ); |
||
406 | } |
||
407 | |||
408 | /** |
||
409 | * Run the backup |
||
410 | * |
||
411 | */ |
||
412 | public function run() { |
||
413 | |||
414 | // Don't run if this schedule is already running |
||
415 | if ( $this->status->is_started() ) { |
||
416 | return; |
||
417 | } |
||
418 | |||
419 | // Setup our Site Backup Object |
||
420 | $backup = new Backup( $this->get_backup_filename(), $this->get_database_dump_filename() ); |
||
421 | $backup->set_type( $this->get_type() ); |
||
422 | $backup->set_excludes( $this->get_excludes() ); |
||
423 | $backup->set_status( $this->status ); |
||
424 | |||
425 | $this->do_action( 'hmbkp_backup_started', $backup ); |
||
426 | |||
427 | $this->status->start( $this->get_backup_filename(), __( 'Starting backup...', 'backupwordpress' ) ); |
||
428 | |||
429 | $this->status->set_status( __( 'Deleting old backups...', 'backupwordpress' ) ); |
||
430 | |||
431 | // Delete old backups now in-case we fatal error during the backup process |
||
432 | $this->delete_old_backups(); |
||
433 | |||
434 | $backup->run(); |
||
435 | |||
436 | $errors = array_merge( $backup->errors, $backup->warnings ); |
||
437 | $notices = array(); |
||
438 | foreach ( $errors as $key => $error ) { |
||
439 | $key = str_replace( array( __NAMESPACE__ . '\\', '_File_Backup_Engine', '_Database_Backup_Engine' ), array( '', '', '' ), $key ); |
||
440 | $notices[] = $key . ': ' . implode( ', ', $error ); |
||
441 | } |
||
442 | Notices::get_instance()->set_notices( 'backup_errors', $notices ); |
||
443 | |||
444 | $this->status->set_status( __( 'Deleting old backups...', 'backupwordpress' ) ); |
||
445 | |||
446 | // Delete old backups again |
||
447 | $this->delete_old_backups(); |
||
448 | |||
449 | $this->do_action( 'hmbkp_backup_complete', $backup ); |
||
450 | |||
451 | $this->status->finish(); |
||
452 | $this->update_average_schedule_run_time( $this->status->get_start_time(), time() ); |
||
453 | |||
454 | } |
||
455 | |||
456 | public function get_backup_filename() { |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
457 | |||
458 | if ( $this->status->is_started() ) { |
||
459 | $this->backup_filename = $this->status->get_backup_filename(); |
||
460 | } |
||
461 | |||
462 | return $this->backup_filename; |
||
463 | } |
||
464 | |||
465 | public function get_database_dump_filename() { |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
466 | return $this->database_dump_filename; |
||
467 | } |
||
468 | |||
469 | /** |
||
470 | * Hook into the actions fired in the Backup class and set the status |
||
471 | * |
||
472 | * @param $action |
||
473 | */ |
||
474 | public function do_action( $action, Backup $backup ) { |
||
475 | |||
476 | // Pass the actions to all the services |
||
477 | // Todo should be decoupled into the service class |
||
478 | foreach ( Services::get_services( $this ) as $service ) { |
||
479 | if ( is_wp_error( $service ) ) { |
||
480 | return $service; |
||
481 | } |
||
482 | $service->action( $action, $backup ); |
||
483 | } |
||
484 | |||
485 | } |
||
486 | |||
487 | /** |
||
488 | * Calculate schedule run time. |
||
489 | * |
||
490 | * @param int Timestamp $end |
||
491 | */ |
||
492 | public function update_average_schedule_run_time( $start, $end ) { |
||
493 | |||
494 | if ( $end <= $start ) { |
||
495 | // Something went wrong, ignore. |
||
496 | return; |
||
497 | } |
||
498 | |||
499 | $diff = (int) abs( $end - $start ); |
||
500 | |||
501 | if ( isset( $this->options['duration_total'] ) && isset( $this->options['backup_run_count'] ) ) { |
||
502 | |||
503 | $this->options['duration_total'] += $diff; |
||
504 | $this->options['backup_run_count'] ++; |
||
505 | |||
506 | } else { |
||
507 | |||
508 | $this->options['duration_total'] = $diff; |
||
509 | $this->options['backup_run_count'] = 1; |
||
510 | |||
511 | } |
||
512 | |||
513 | $this->save(); |
||
514 | } |
||
515 | |||
516 | /** |
||
517 | * Calculates the average run time for this schedule. |
||
518 | * |
||
519 | * @return string |
||
520 | */ |
||
521 | public function get_schedule_average_duration() { |
||
522 | |||
523 | $duration = 'Unknown'; |
||
524 | |||
525 | if ( ! isset( $this->options['duration_total'] ) || ! isset( $this->options['backup_run_count'] ) ) { |
||
526 | return $duration; |
||
527 | } |
||
528 | |||
529 | if ( 0 === (int) $this->options['backup_run_count'] ) { |
||
530 | return $duration; |
||
531 | } |
||
532 | |||
533 | $average_run_time = (int) $this->options['duration_total'] / (int) $this->options['backup_run_count']; |
||
534 | |||
535 | if ( $average_run_time < HOUR_IN_SECONDS ) { |
||
536 | |||
537 | $mins = round( $average_run_time / MINUTE_IN_SECONDS ); |
||
538 | |||
539 | if ( $mins <= 1 ) { |
||
540 | $mins = 1; |
||
541 | } |
||
542 | |||
543 | /* translators: min=minute */ |
||
544 | $duration = sprintf( _n( '%s min', '%s mins', $mins, 'backupwordpress' ), $mins ); |
||
545 | |||
546 | } elseif ( $average_run_time < DAY_IN_SECONDS && $average_run_time >= HOUR_IN_SECONDS ) { |
||
547 | |||
548 | $hours = round( $average_run_time / HOUR_IN_SECONDS ); |
||
549 | |||
550 | if ( $hours <= 1 ) { |
||
551 | $hours = 1; |
||
552 | } |
||
553 | |||
554 | $duration = sprintf( _n( '%s hour', '%s hours', $hours, 'backupwordpress' ), $hours ); |
||
555 | } |
||
556 | |||
557 | return $duration; |
||
558 | } |
||
559 | |||
560 | /** |
||
561 | * Get the backups created by this schedule |
||
562 | * |
||
563 | * @todo look into using recursiveDirectoryIterator and recursiveRegexIterator |
||
564 | * @return string[] - file paths of the backups |
||
565 | */ |
||
566 | public function get_backups() { |
||
567 | |||
568 | $files = array(); |
||
569 | |||
570 | if ( $handle = @opendir( Path::get_path() ) ) { |
||
571 | |||
572 | while ( false !== ( $file = readdir( $handle ) ) ) { |
||
573 | |||
574 | if ( pathinfo( $file, PATHINFO_EXTENSION ) === 'zip' && strpos( $file, $this->get_id() ) !== false && ( isset( $this->status ) && $this->get_backup_filename() !== $file ) ) { |
||
575 | $files[ @filemtime( trailingslashit( Path::get_path() ) . $file ) ] = trailingslashit( Path::get_path() ) . $file; |
||
576 | } |
||
577 | } |
||
578 | |||
579 | closedir( $handle ); |
||
580 | |||
581 | } |
||
582 | |||
583 | krsort( $files ); |
||
584 | |||
585 | return $files; |
||
586 | |||
587 | } |
||
588 | |||
589 | /** |
||
590 | * Delete old backups |
||
591 | * |
||
592 | * @access private |
||
593 | */ |
||
594 | public function delete_old_backups() { |
||
595 | |||
596 | if ( count( $this->get_backups() ) <= $this->get_max_backups() ) { |
||
597 | return; |
||
598 | } |
||
599 | |||
600 | array_map( array( $this, 'delete_backup' ), array_slice( $this->get_backups(), $this->get_max_backups() ) ); |
||
601 | |||
602 | } |
||
603 | |||
604 | /** |
||
605 | * Delete a specific back up file created by this schedule |
||
606 | * |
||
607 | * @param string $filepath |
||
608 | * |
||
609 | * @return \WP_Error|boolean |
||
610 | */ |
||
611 | public function delete_backup( $filepath ) { |
||
612 | |||
613 | // Check that it's a valid filepath |
||
614 | if ( empty( $filepath ) || ! is_string( $filepath ) ) { |
||
615 | return new \WP_Error( 'hmbkp_empty_string_error', sprintf( __( 'Argument 1 for %s must be a non-empty string', 'backupwordpress' ), __METHOD__ ) ); |
||
616 | } |
||
617 | |||
618 | // Make sure it exists |
||
619 | if ( ! file_exists( $filepath ) ) { |
||
620 | return new \WP_Error( 'hmbkp_file_error', sprintf( __( '%s doesn\'t exist', 'backupwordpress' ), $filepath ) ); |
||
621 | } |
||
622 | |||
623 | // Make sure it was created by this schedule |
||
624 | if ( strpos( $filepath, $this->get_id() ) === false ) { |
||
625 | return new \WP_Error( 'hmbkp_backup_error', __( 'That backup wasn\'t created by this schedule', 'backupwordpress' ) ); |
||
626 | } |
||
627 | |||
628 | unlink( $filepath ); |
||
629 | |||
630 | return true; |
||
631 | |||
632 | } |
||
633 | |||
634 | /** |
||
635 | * Delete all back up files created by this schedule |
||
636 | * |
||
637 | */ |
||
638 | public function delete_backups() { |
||
639 | array_map( array( $this, 'delete_backup' ), $this->get_backups() ); |
||
640 | } |
||
641 | |||
642 | /** |
||
643 | * Save the schedules options. |
||
644 | * |
||
645 | */ |
||
646 | public function save() { |
||
647 | |||
648 | // Only save them if they have changed |
||
649 | if ( get_option( 'hmbkp_schedule_' . $this->get_id() ) !== $this->options ) { |
||
650 | update_option( 'hmbkp_schedule_' . $this->get_id(), $this->options ); |
||
651 | |||
652 | // Delete the schedule cache. |
||
653 | delete_transient( 'hmbkp_schedules' ); |
||
654 | } |
||
655 | |||
656 | } |
||
657 | |||
658 | /** |
||
659 | * Cancel this schedule |
||
660 | * |
||
661 | * Cancels the cron job, removes the schedules options |
||
662 | * and optionally deletes all backups created by |
||
663 | * this schedule. |
||
664 | * |
||
665 | */ |
||
666 | public function cancel( $delete_backups = false ) { |
||
667 | |||
668 | // Delete the schedule options |
||
669 | delete_option( 'hmbkp_schedule_' . $this->get_id() ); |
||
670 | |||
671 | // Delete the schedule cache. |
||
672 | delete_transient( 'hmbkp_schedules' ); |
||
673 | |||
674 | // Clear any existing schedules |
||
675 | $this->unschedule(); |
||
676 | |||
677 | // Delete it's backups |
||
678 | if ( $delete_backups ) { |
||
679 | $this->delete_backups(); |
||
680 | } |
||
681 | |||
682 | } |
||
683 | } |
||
684 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: