Completed
Push — issues/1538 ( 1244f8...b170da )
by Ravinder
16:11
created

Give_Updates::__change_donations_label()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 4
nop 0
dl 0
loc 22
rs 8.6737
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 453.

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
		$updates = ! empty( self::$updates[ $update_type ] ) ? self::$updates[ $update_type ] : array();
109
110
		// Bailout.
111
		if ( empty( $updates ) ) {
112
			return $updates;
113
		}
114
115
		switch ( $status ) {
116
			case 'new':
117
				// Remove already completed updates.
118
119
				$completed_updates = give_get_completed_upgrades();
120
121
				if ( ! empty( $completed_updates ) ) {
122
					foreach ( $updates as $index => $update ) {
123
						if ( in_array( $update['id'], $completed_updates ) ) {
124
							unset( $updates[ $index ] );
125
						}
126
					}
127
					$updates = array_values( $updates );
128
				}
129
130
				break;
131
		}
132
133
		return $updates;
134
	}
135
136
137
	/**
138
	 * Get instance.
139
	 *
140
	 * @since
141
	 * @access static
142
	 * @return static
143
	 */
144
	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...
145
		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...
146
			self::$instance = new static();
147
		}
148
149
		return self::$instance;
150
	}
151
152
	/**
153
	 *
154
	 * Setup hook
155
	 *
156
	 * @since  1.8.12
157
	 * @access public
158
	 *
159
	 */
160
	public function setup_hooks() {
161
		add_action( 'admin_init', array( $this, '__change_donations_label' ), 9999 );
162
		add_action( 'admin_menu', array( $this, '__register_menu' ), 9999 );
163
		add_action( 'give_set_upgrade_completed', array( $this, '__flush_resume_updates' ), 9999 );
164
		add_action( 'wp_ajax_give_do_ajax_updates', array( $this, '__give_ajax_updates' ) );
165
	}
166
167
	/**
168
	 * Rename `Donations` menu title if updates exists
169
	 *
170
	 * @since  1.8.12
171
	 * @access public
172
	 */
173
	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...
174
		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...
175
		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...
176
177
		// Bailout.
178
		if ( empty( $menu ) || ! $this->get_update_count() ) {
179
			return;
180
		}
181
182
		foreach ( $menu as $index => $menu_item ) {
183
			if ( 'edit.php?post_type=give_forms' !== $menu_item[2] ) {
184
				continue;
185
			}
186
187
			$menu[ $index ][0] = sprintf(
188
				__( 'Donations <span class="update-plugins count-%1$d"><span class="plugin-count">%1$d</span></span>', 'give' ),
189
				$this->get_update_count()
190
			);
191
192
			break;
193
		}
194
	}
195
196
	/**
197
	 * Register updates menu
198
	 *
199
	 * @since  1.8.12
200
	 * @access public
201
	 */
202
	public function __register_menu() {
203
		// Bailout.
204
		if ( ! $this->get_update_count() ) {
205
			return;
206
		}
207
208
		//Upgrades
209
		add_submenu_page(
210
			'edit.php?post_type=give_forms',
211
			esc_html__( 'Give Updates', 'give' ),
212
			sprintf(
213
				'%1$s <span class="update-plugins count-%2$d"><span class="plugin-count">%2$d</span></span>',
214
				__( 'Updates', 'give' ),
215
				$this->get_update_count()
216
			),
217
			'manage_give_settings',
218
			'give-updates',
219
			array( $this, 'render_page' )
220
		);
221
	}
222
223
	/**
224
	 * Get tottal updates count
225
	 *
226
	 * @since  1.8.12
227
	 * @access public
228
	 * @return int
229
	 */
230
	public function get_db_update_count() {
231
		return count( $this->get_updates( 'database', 'new' ) );
232
	}
233
234
235
	/**
236
	 * Render Give Updates page
237
	 *
238
	 * @since  1.8.12
239
	 * @access public
240
	 */
241
	public function render_page() {
242
		include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades.php';
243
	}
244
245
	/**
246
	 * Get addon update count.
247
	 *
248
	 * @since  1.8.12
249
	 * @access public
250
	 * @return int
251
	 */
252
	public function get_plugin_update_count() {
253
		$addons         = give_get_plugins();
254
		$plugin_updates = get_plugin_updates();
255
		$update_counter = 0;
256
257
		foreach ( $addons as $key => $info ) {
258
			if ( 'active' != $info['Status'] || 'add-on' != $info['Type'] || empty( $plugin_updates[ $key ] ) ) {
259
				continue;
260
			}
261
262
			$update_counter ++;
263
		}
264
265
		return $update_counter;
266
	}
267
268
	/**
269
	 * Get total update count
270
	 *
271
	 * @since  1.8.12
272
	 * @access public
273
	 *
274
	 * @return int
275
	 */
276
	public function get_update_count() {
277
		$db_update_count     = $this->get_db_update_count();
278
		$plugin_update_count = $this->get_plugin_update_count();
279
280
		return ( $db_update_count + $plugin_update_count );
281
	}
282
283
284
	/**
285
	 * Delete resume updates
286
	 *
287
	 * @since  1.8.12
288
	 * @access public
289
	 */
290
	public function __flush_resume_updates() {
291
		delete_option( 'give_doing_upgrade' );
292
		update_option( 'give_version', preg_replace( '/[^0-9.].*/', '', GIVE_VERSION ) );
293
294
		// Reset counter.
295
		self::$step = self::$percentage = 0;
296
		++ self::$update;
297
	}
298
299
	/**
300
	 *  Process give updates.
301
	 *
302
	 * @todo   : add dependency update logic
303
	 *
304
	 * @since  1.8.12
305
	 * @access public
306
	 */
307
	public function __give_ajax_updates() {
308
		// Check permission.
309
		if ( ! current_user_can( 'manage_give_settings' ) ) {
310
			$this->send_ajax_response(
311
				array(
312
					'message' => esc_html__( 'You do not have permission to do Give upgrades.', 'give' ),
313
				),
314
				'error'
315
			);
316
		}
317
318
		// Update timeout error.
319
		ignore_user_abort( true );
320
		if ( ! give_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
321
			@set_time_limit( 0 );
322
		}
323
324
		// Set params.
325
		self::$step   = absint( $_POST['step'] );
326
		self::$update = absint( $_POST['update'] );
327
328
		// Bailout: step and update must be positive and greater then zero.
329
		if ( ! self::$step ) {
330
			$this->send_ajax_response(
331
				array(
332
					'message'    => __( 'Error: please reload this page  and try again', 'give' ),
333
					'heading'    => '',
334
					'percentage' => 0,
335
				),
336
				'error'
337
			);
338
		}
339
340
		// Get updates.
341
		// $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...
342
		$updates = $this->get_updates( 'database', 'new' );
343
344
345
		// Bailout if we do not have nay updates.
346
		if ( empty( $updates ) ) {
347
			$this->send_ajax_response(
348
				array(
349
					'message'    => __( 'Database already up to date.', 'give' ),
350
					'heading'    => '',
351
					'percentage' => 0,
352
				),
353
				'success'
354
			);
355
		}
356
357
		// Process update.
358
		foreach ( $updates as $index => $update ) {
359
			// Run update.
360
			if ( is_array( $update['callback'] ) ) {
361
				$update['callback'][0]->$update['callback'][1]();
362
			} else {
363
				$update['callback']();
364
			}
365
366
			// Check if current update completed or not.
367
			if ( give_has_upgrade_completed( $update['id'] ) ) {
368
				if ( 1 === count( $updates ) ) {
369
					$this->send_ajax_response(
370
						array(
371
							'message'    => __( 'Database updated successfully.', 'give' ),
372
							'heading'    => '',
373
							'percentage' => 0,
374
						),
375
						'success'
376
					);
377
				}
378
			}
379
380
			// Verify percentage.
381
			self::$percentage = ( 100 < self::$percentage ) ? 100 : self::$percentage;
382
383
			$doing_upgrade_args = array(
384
				'update_info' => $update,
385
				'step'        => ++ self::$step,
386
				'update'      => self::$update,
387
				'heading'     => sprintf( 'Update %s of {update_count}', self::$update ),
388
				'percentage'  => self::$percentage,
389
			);
390
391
			// Cache upgrade.
392
			update_option( 'give_doing_upgrade', $doing_upgrade_args );
393
394
			$this->send_ajax_response( $doing_upgrade_args );
395
		}
396
	}
397
398
	/**
399
	 * Send ajax response
400
	 *
401
	 * @since  1.8.12
402
	 * @access public
403
	 *
404
	 * @param        $data
405
	 * @param string $type
406
	 */
407
	public function send_ajax_response( $data, $type = '' ) {
408
		$default = array(
409
			'message'    => '',
410
			'heading'    => '',
411
			'percentage' => 0,
412
			'step'       => 0,
413
			'update'     => 0,
414
		);
415
416
		// Set data.
417
		$data = wp_parse_args( $data, $default );
418
419
		switch ( $type ) {
420
			case 'success':
421
				wp_send_json_success( $data );
422
				break;
423
424
			case 'error':
425
				wp_send_json_success( $data );
426
				break;
427
428
			default:
429
				wp_send_json( array( 'data' => $data ) );
430
				break;
431
		}
432
	}
433
434
435
	/**
436
	 * Resume updates
437
	 * @since  1.8.12
438
	 * @access public
439
	 *
440
	 * @return bool|int
441
	 */
442
	public function resume_updates() {
443
		$status = false;
444
445
		if ( $update = get_option( 'give_doing_upgrade' ) ) {
446
			$status = ! empty( $update['step'] ) ? $update['step'] : $status;
447
		}
448
449
		return $status;
450
	}
451
}
452
453
Give_Updates::get_instance()->setup_hooks();