Completed
Pull Request — master (#1907)
by
unknown
19:56
created

Give_Updates::get_instance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 9 and the first side effect is on line 501.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
/**
4
 * Created by PhpStorm.
5
 * User: ravinderkumar
6
 * Date: 14/07/17
7
 * Time: 3:27 PM
8
 */
9
class Give_Updates {
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
10
	/**
11
	 * Instance.
12
	 *
13
	 * @since
14
	 * @access static
15
	 * @var
16
	 */
17
	static private $instance;
18
19
	/**
20
	 * Updates
21
	 *
22
	 * @since  1.8.12
23
	 * @access private
24
	 * @var array
25
	 */
26
	static private $updates = array();
27
28
29
	/**
30
	 * Current update percentage number
31
	 *
32
	 * @since  1.8.12
33
	 * @access private
34
	 * @var array
35
	 */
36
	static public $percentage = 0;
37
38
	/**
39
	 * Current update step number
40
	 *
41
	 * @since  1.8.12
42
	 * @access private
43
	 * @var array
44
	 */
45
	static public $step = 1;
46
47
	/**
48
	 * Current update number
49
	 *
50
	 * @since  1.8.12
51
	 * @access private
52
	 * @var array
53
	 */
54
	static public $update = 1;
55
56
	/**
57
	 * Singleton pattern.
58
	 *
59
	 * @since  1.8.12
60
	 * @access private
61
	 *
62
	 * @param Give_Updates .
63
	 */
64
	private function __construct() {
65
	}
66
67
	/**
68
	 * Register updates
69
	 *
70
	 * @since  1.8.12
71
	 * @access public
72
	 *
73
	 * @param array $args
74
	 */
75
	public function register( $args ) {
76
		$args_default = array(
77
			'id'       => '',
78
			'version'  => '',
79
			'callback' => '',
80
		);
81
82
		$args = wp_parse_args( $args, $args_default );
83
84
		// You can only register database upgrade.
85
		$args['type'] = 'database';
86
87
		// Bailout.
88
		if ( empty( $args['id'] ) || empty( $args['version'] ) || empty( $args['callback'] ) || ! is_callable( $args['callback'] ) ) {
89
			return;
90
		}
91
92
		self::$updates[ $args['type'] ][] = $args;
93
	}
94
95
96
	/**
97
	 * Get updates.
98
	 *
99
	 * @since  1.8.12
100
	 * @access public
101
	 *
102
	 * @param string $update_type Tye of update.
103
	 * @param string $status      Tye of update.
104
	 *
105
	 * @return array
106
	 */
107
	public function get_updates( $update_type = '', $status = 'all' ) {
108
		// return all updates.
109
		if ( empty( $update_type ) ) {
110
			return self::$updates;
111
		}
112
113
		// Get specific update.
114
		$updates = ! empty( self::$updates[ $update_type ] ) ? self::$updates[ $update_type ] : array();
115
116
		// Bailout.
117
		if ( empty( $updates ) ) {
118
			return $updates;
119
		}
120
121
		switch ( $status ) {
122
			case 'new':
123
				// Remove already completed updates.
124
125
				$completed_updates = give_get_completed_upgrades();
126
127
				if ( ! empty( $completed_updates ) ) {
128
					foreach ( $updates as $index => $update ) {
129
						if ( in_array( $update['id'], $completed_updates ) ) {
130
							unset( $updates[ $index ] );
131
						}
132
					}
133
					$updates = array_values( $updates );
134
				}
135
136
				break;
137
		}
138
139
		return $updates;
140
	}
141
142
143
	/**
144
	 * Get instance.
145
	 *
146
	 * @since
147
	 * @access static
148
	 * @return static
149
	 */
150
	static function get_instance() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
151
		if ( null === static::$instance ) {
0 ignored issues
show
Bug introduced by
Since $instance is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $instance to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
152
			self::$instance = new static();
153
		}
154
155
		return self::$instance;
156
	}
157
158
	/**
159
	 *
160
	 * Setup hook
161
	 *
162
	 * @since  1.8.12
163
	 * @access public
164
	 *
165
	 */
166
	public function setup() {
167
		/**
168
		 * Setup hooks.
169
		 */
170
		add_action( 'init', array( $this, '__register_upgrade' ), 9999 );
171
		add_action( 'admin_init', array( $this, '__change_donations_label' ), 9999 );
172
		add_action( 'admin_menu', array( $this, '__register_menu' ), 9999 );
173
		add_action( 'give_set_upgrade_completed', array( $this, '__flush_resume_updates' ), 9999 );
174
		add_action( 'wp_ajax_give_do_ajax_updates', array( $this, '__give_ajax_updates' ) );
175
176
		/**
177
		 * Load file
178
		 */
179
		require_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/upgrade-functions.php';
180
	}
181
182
	/**
183
	 * Register plugin addon updates
184
	 *
185
	 * @since  1.8.12
186
	 * @access public
187
	 */
188
	public function __register_plugin_addon_updates() {
189
		$addons         = give_get_plugins();
190
		$plugin_updates = get_plugin_updates();
191
192
		foreach ( $addons as $key => $info ) {
193
			if ( 'active' != $info['Status'] || 'add-on' != $info['Type'] || empty( $plugin_updates[ $key ] ) ) {
194
				continue;
195
			}
196
197
			self::$updates['plugin'][] = array_merge( $info, (array) $plugin_updates[ $key ] );
198
		}
199
	}
200
201
202
	/**
203
	 * Fire custom aciton hook to register updates
204
	 *
205
	 * @since  1.8.12
206
	 * @access public
207
	 */
208
	public function __register_upgrade() {
209
		if ( ! is_admin() ) {
210
			return;
211
		}
212
213
		/**
214
		 * Fire the hook
215
		 *
216
		 * @since 1.8.12
217
		 */
218
		do_action( 'give_register_updates', $this );
219
	}
220
221
	/**
222
	 * Rename `Donations` menu title if updates exists
223
	 *
224
	 * @since  1.8.12
225
	 * @access public
226
	 */
227
	function __change_donations_label() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
228
		global $menu;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
229
		global $submenu;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
230
231
		// Bailout.
232
		if ( empty( $menu ) || ! $this->get_update_count() ) {
233
			return;
234
		}
235
236
		foreach ( $menu as $index => $menu_item ) {
237
			if ( 'edit.php?post_type=give_forms' !== $menu_item[2] ) {
238
				continue;
239
			}
240
241
			$menu[ $index ][0] = sprintf(
242
				__( 'Donations <span class="update-plugins count-%1$d"><span class="plugin-count">%1$d</span></span>', 'give' ),
243
				$this->get_update_count()
244
			);
245
246
			break;
247
		}
248
	}
249
250
	/**
251
	 * Register updates menu
252
	 *
253
	 * @since  1.8.12
254
	 * @access public
255
	 */
256
	public function __register_menu() {
257
		// Load plugin updates.
258
		$this->__register_plugin_addon_updates();
259
260
		// Bailout.
261
		if ( ! $this->get_update_count() ) {
262
			return;
263
		}
264
265
		//Upgrades
266
		add_submenu_page(
267
			'edit.php?post_type=give_forms',
268
			esc_html__( 'Give Updates', 'give' ),
269
			sprintf(
270
				'%1$s <span class="update-plugins count-%2$d"><span class="plugin-count">%2$d</span></span>',
271
				__( 'Updates', 'give' ),
272
				$this->get_update_count()
273
			),
274
			'manage_give_settings',
275
			'give-updates',
276
			array( $this, 'render_page' )
277
		);
278
	}
279
280
	/**
281
	 * Get tottal updates count
282
	 *
283
	 * @since  1.8.12
284
	 * @access public
285
	 * @return int
286
	 */
287
	public function get_db_update_count() {
288
		return count( $this->get_updates( 'database', 'new' ) );
289
	}
290
291
292
	/**
293
	 * Render Give Updates page
294
	 *
295
	 * @since  1.8.12
296
	 * @access public
297
	 */
298
	public function render_page() {
299
		include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades.php';
300
	}
301
302
	/**
303
	 * Get addon update count.
304
	 *
305
	 * @since  1.8.12
306
	 * @access public
307
	 * @return int
308
	 */
309
	public function get_plugin_update_count() {
310
		return count( $this->get_updates( 'plugin' ) );
311
	}
312
313
	/**
314
	 * Get total update count
315
	 *
316
	 * @since  1.8.12
317
	 * @access public
318
	 *
319
	 * @return int
320
	 */
321
	public function get_update_count() {
322
		$db_update_count     = $this->get_db_update_count();
323
		$plugin_update_count = $this->get_plugin_update_count();
324
325
		return ( $db_update_count + $plugin_update_count );
326
	}
327
328
329
	/**
330
	 * Delete resume updates
331
	 *
332
	 * @since  1.8.12
333
	 * @access public
334
	 */
335
	public function __flush_resume_updates() {
336
		delete_option( 'give_doing_upgrade' );
337
		update_option( 'give_version', preg_replace( '/[^0-9.].*/', '', GIVE_VERSION ) );
338
339
		// Reset counter.
340
		self::$step = self::$percentage = 0;
341
		++ self::$update;
342
	}
343
344
	/**
345
	 *  Process give updates.
346
	 *
347
	 * @since  1.8.12
348
	 * @access public
349
	 */
350
	public function __give_ajax_updates() {
351
		// Check permission.
352
		if ( ! current_user_can( 'manage_give_settings' ) ) {
353
			$this->send_ajax_response(
354
				array(
355
					'message' => esc_html__( 'You do not have permission to do Give upgrades.', 'give' ),
356
				),
357
				'error'
358
			);
359
		}
360
361
		// Update timeout error.
362
		ignore_user_abort( true );
363
		if ( ! give_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
364
			@set_time_limit( 0 );
365
		}
366
367
		// Set params.
368
		self::$step   = absint( $_POST['step'] );
369
		self::$update = absint( $_POST['update'] );
370
371
		// Bailout: step and update must be positive and greater then zero.
372
		if ( ! self::$step ) {
373
			$this->send_ajax_response(
374
				array(
375
					'message'    => __( 'Error: please reload this page  and try again', 'give' ),
376
					'heading'    => '',
377
					'percentage' => 0,
378
				),
379
				'error'
380
			);
381
		}
382
383
		// Get updates.
384
		// $all_updates = $this->get_updates( 'database' );
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
385
		$updates = $this->get_updates( 'database', 'new' );
386
387
388
		// Bailout if we do not have nay updates.
389
		if ( empty( $updates ) ) {
390
			$this->send_ajax_response(
391
				array(
392
					'message'    => __( 'Database already up to date.', 'give' ),
393
					'heading'    => '',
394
					'percentage' => 0,
395
				),
396
				'success'
397
			);
398
		}
399
400
		// Process update.
401
		foreach ( $updates as $index => $update ) {
402
			// Check if update depend upon any other update.
403
			if ( ! empty( $update['depend'] ) && ! give_has_upgrade_completed( $update['depend'] ) ) {
404
				continue;
405
			}
406
407
			// Run update.
408
			if ( is_array( $update['callback'] ) ) {
409
				$update['callback'][0]->$update['callback'][1]();
410
			} else {
411
				$update['callback']();
412
			}
413
414
			// Check if current update completed or not.
415
			if ( give_has_upgrade_completed( $update['id'] ) ) {
416
				if ( 1 === count( $updates ) ) {
417
					$this->send_ajax_response(
418
						array(
419
							'message'    => __( 'Database updated successfully.', 'give' ),
420
							'heading'    => '',
421
							'percentage' => 0,
422
						),
423
						'success'
424
					);
425
				}
426
			}
427
428
			// Verify percentage.
429
			self::$percentage = ( 100 < self::$percentage ) ? 100 : self::$percentage;
430
431
			$doing_upgrade_args = array(
432
				'update_info' => $update,
433
				'step'        => ++ self::$step,
434
				'update'      => self::$update,
435
				'heading'     => sprintf( 'Update %s of {update_count}', self::$update ),
436
				'percentage'  => self::$percentage,
437
			);
438
439
			// Cache upgrade.
440
			update_option( 'give_doing_upgrade', $doing_upgrade_args );
441
442
			$this->send_ajax_response( $doing_upgrade_args );
443
		}
444
	}
445
446
	/**
447
	 * Send ajax response
448
	 *
449
	 * @since  1.8.12
450
	 * @access public
451
	 *
452
	 * @param        $data
453
	 * @param string $type
454
	 */
455
	public function send_ajax_response( $data, $type = '' ) {
456
		$default = array(
457
			'message'    => '',
458
			'heading'    => '',
459
			'percentage' => 0,
460
			'step'       => 0,
461
			'update'     => 0,
462
		);
463
464
		// Set data.
465
		$data = wp_parse_args( $data, $default );
466
467
		switch ( $type ) {
468
			case 'success':
469
				wp_send_json_success( $data );
470
				break;
471
472
			case 'error':
473
				wp_send_json_success( $data );
474
				break;
475
476
			default:
477
				wp_send_json( array( 'data' => $data ) );
478
				break;
479
		}
480
	}
481
482
483
	/**
484
	 * Resume updates
485
	 * @since  1.8.12
486
	 * @access public
487
	 *
488
	 * @return bool|int
489
	 */
490
	public function resume_updates() {
491
		$status = false;
492
493
		if ( $update = get_option( 'give_doing_upgrade' ) ) {
494
			$status = ! empty( $update['step'] ) ? $update['step'] : $status;
495
		}
496
497
		return $status;
498
	}
499
}
500
501
Give_Updates::get_instance()->setup();