Passed
Push — master ( 3f789e...c58b71 )
by Brian
04:52
created

GetPaid_Admin_Setup_Wizard::display_current_step()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Setup Wizard Class
4
 *
5
 * Takes new users through some basic steps to setup GetPaid.
6
 *
7
 * @author      AyeCode
8
 * @category    Admin
9
 * @package     GetPaid/Admin
10
 * @version     2.4.0
11
 * @info        GetPaid Setup Wizard.
12
 */
13
defined( 'ABSPATH' ) || exit;
14
15
/**
16
 * GetPaid_Admin_Setup_Wizard class.
17
 */
18
class GetPaid_Admin_Setup_Wizard {
19
20
	/**
21
	 * @var string Current Step
22
	 */
23
	protected $step = '';
24
25
	/**
26
	 * @var string|false Previous Step
27
	 */
28
	protected $previous_step = '';
29
30
	/**
31
	 * @var string|false Next Step
32
	 */
33
	protected $next_step = '';
34
35
	/**
36
	 * @var array All available steps for the setup wizard 
37
	 */
38
	protected $steps = array();
39
40
	/**
41
	 * Class constructor.
42
	 *
43
	 * @since 2.4.0
44
	 */
45
	public function __construct() {
46
47
		if ( apply_filters( 'getpaid_enable_setup_wizard', true ) && wpinv_current_user_can_manage_invoicing() ) {
48
			add_action( 'admin_menu', array( $this, 'add_menu' ) );
49
			add_action( 'current_screen', array( $this, 'setup_wizard' ) );
50
		}
51
52
	}
53
54
	/**
55
	 * Add admin menus/screens.
56
	 *
57
	 * @since 2.4.0
58
	 */
59
	public function add_menu() {
60
		add_dashboard_page( '', '', wpinv_get_capability(), 'gp-setup', '' );
61
	}
62
63
	/**
64
	 * Sets up the setup wizard.
65
	 *
66
	 * @since 2.4.0
67
	 */
68
	public function setup_wizard() {
69
70
		if ( isset( $_GET['page'] ) && 'gp-setup' === $_GET['page'] ) {
71
			$this->setup_globals();
72
			$this->maybe_save_current_step();
73
			$this->display_wizard();
74
			exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
75
		}
76
77
	}
78
79
	/**
80
	 * Sets up class variables.
81
	 *
82
	 * @since 2.4.0
83
	 */
84
	protected function setup_globals() {
85
		$this->steps         = $this->get_setup_steps();
86
		$this->step          = $this->get_current_step();
87
		$this->previous_step = $this->get_previous_step();
88
		$this->next_step     = $this->get_next_step();
89
	}
90
91
	/**
92
	 * Saves the current step.
93
	 *
94
	 * @since 2.4.0
95
	 */
96
	protected function maybe_save_current_step() {
97
		if ( ! empty( $_POST['save_step'] ) && is_callable( $this->steps[ $this->step ]['handler'] ) ) {
98
			call_user_func( $this->steps[ $this->step ]['handler'], $this );
99
		}
100
	}
101
102
	/**
103
	 * Returns the setup steps.
104
	 *
105
	 * @since 2.4.0
106
	 * @return array
107
	 */
108
	protected function get_setup_steps() {
109
110
		$steps = array(
111
112
			'introduction'     => array(
113
				'name'    => __( 'Introduction', 'invoicing' ),
114
				'view'    => array( $this, 'setup_introduction' ),
115
				'handler' => '',
116
			),
117
118
			'business_details'             => array(
119
				'name'    => __( "Business Details", 'invoicing' ),
120
				'view'    => array( $this, 'setup_business' ),
121
				'handler' => array( $this, 'setup_business_save' ),
122
			),
123
124
			'currency' => array(
125
				'name'    => __( 'Currency', 'invoicing' ),
126
				'view'    => array( $this, 'setup_currency' ),
127
				'handler' => array( $this, 'setup_currency_save' ),
128
			),
129
130
			'payments'        => array(
131
				'name'    => __( 'Payment Gateways', 'invoicing' ),
132
				'view'    => array( $this, 'setup_payments' ),
133
				'handler' => array( $this, 'setup_payments_save' ),
134
			),
135
136
			'recommend'          => array(
137
				'name'    => __( 'Recommend', 'invoicing' ),
138
				'view'    => array( $this, 'setup_recommend' ),
139
				'handler' => array( $this, 'setup_recommend_save' ),
140
			),
141
142
			'next_steps'       => array(
143
				'name'    => __( 'Get Paid', 'invoicing' ),
144
				'view'    => array( $this, 'setup_ready' ),
145
				'handler' => '',
146
			),
147
148
		);
149
150
		return apply_filters( 'getpaid_setup_wizard_steps', $steps );
151
152
	}
153
154
	/**
155
	 * Returns the current step.
156
	 *
157
	 * @since 2.4.0
158
	 * @return string
159
	 */
160
	protected function get_current_step() {
161
		$step = isset( $_GET['step'] ) ? sanitize_key( $_GET['step'] ) : '';
162
		return ! empty( $step ) && in_array( $step, array_keys( $this->steps ) ) ? $step : current( array_keys( $this->steps ) );
163
	}
164
165
	/**
166
	 * Returns the previous step.
167
	 *
168
	 * @since 2.4.0
169
	 * @return string|false
170
	 */
171
	protected function get_previous_step() {
172
173
		$previous = false;
174
		$current  = $this->step;
175
		foreach ( array_keys( $this->steps ) as $step ) {
176
			if ( $current === $step ) {
177
				return $previous;
178
			}
179
180
			$previous = $step;
181
		}
182
183
		return false;
184
	}
185
186
	/**
187
	 * Returns the next step.
188
	 *
189
	 * @since 2.4.0
190
	 * @return string|false
191
	 */
192
	protected function get_next_step() {
193
194
		$on_current = false;
195
		$current    = $this->step;
196
		foreach ( array_keys( $this->steps ) as $step ) {
197
198
			if ( $on_current ) {
199
				return $step;
200
			}
201
202
			if ( $current === $step ) {
203
				return $on_current = true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $on_current = true returns the type true which is incompatible with the documented return type false|string.
Loading history...
Unused Code introduced by
The assignment to $on_current is dead and can be removed.
Loading history...
204
			}
205
206
		}
207
208
		return false;
209
	}
210
211
	/**
212
	 * Displays the setup wizard.
213
	 *
214
	 * @since 2.4.0
215
	 */
216
	public function display_wizard() {
217
		$this->display_header();
218
		$this->display_current_step();
219
		$this->display_footer();
220
	}
221
222
	/**
223
	 * Displays the Wizard Header.
224
	 *
225
	 * @since 2.0.0
226
	 */
227
	public function display_header() {
228
		$steps     = $this->steps;
229
		$current   = $this->step;
230
		$next_step = $this->next_step;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->next_step can also be of type boolean. However, the property $next_step is declared as type false|string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
231
		array_shift( $steps );
232
		include plugin_dir_path( __FILE__ ) . 'views/wizard-header.php';
233
	}
234
235
	/**
236
	 * Displays the content for the current step.
237
	 *
238
	 * @since 2.4.0
239
	 */
240
	public function display_current_step() {
241
		?>
242
			<div class="gp-setup-content rowx mw-100 text-center mb-3">
243
				<div class="col-12 col-md-5 m-auto">
244
					<?php call_user_func( $this->steps[ $this->step ]['view'], $this ); ?>
245
				</div>
246
			</div>
247
		<?php
248
	}
249
250
	/**
251
	 * Setup Wizard Footer.
252
	 *
253
	 * @since 2.4.0
254
	 */
255
	public function display_footer() {
256
		echo '</body></html>';
257
	}
258
259
	/**
260
	 * Introduction step.
261
	 *
262
	 * @since 2.0.0
263
	 */
264
	public function setup_introduction() {
265
		$next_url = $this->get_next_step_link();
266
		include plugin_dir_path( __FILE__ ) . 'views/wizard-introduction.php';
267
	}
268
269
	/**
270
	 * Get the URL for the next step's screen.
271
	 *
272
	 * @param string step   slug (default: current step)
0 ignored issues
show
Bug introduced by
The type step was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
273
	 *
274
	 * @return string       URL for next step if a next step exists.
275
	 *                      Admin URL if it's the last step.
276
	 *                      Empty string on failure.
277
	 * @since 3.0.0
278
	 */
279
	public function get_next_step_link( $step = '' ) {
280
		if ( ! $step ) {
281
			$step = $this->step;
282
		}
283
284
		$keys = array_keys( $this->steps );
285
		if ( end( $keys ) === $step ) {
286
			return admin_url();
287
		}
288
289
		$step_index = array_search( $step, $keys );
290
		if ( false === $step_index ) {
291
			return '';
292
		}
293
294
		return remove_query_arg('settings-updated', add_query_arg( 'step', $keys[ $step_index + 1 ] ));
295
	}
296
297
	/**
298
	 * Setup maps api.
299
	 *
300
	 * @since 2.0.0
301
	 */
302
	public function setup_business() {
303
		$next_url = $this->get_next_step_link();
304
		$wizard   = $this;
305
		$page     = 'wpinv_settings_general_main';
306
		$section  = 'wpinv_settings_general_main';
307
		include plugin_dir_path( __FILE__ ) . 'views/wizard-settings.php';
308
	}
309
310
	/**
311
	 * Default Location settings.
312
	 *
313
	 * @since 2.0.0
314
	 */
315
	public function setup_currency() {
316
		$next_url = $this->get_next_step_link();
317
		$wizard   = $this;
318
		$page     = 'wpinv_settings_general_currency_section';
319
		$section  = 'wpinv_settings_general_currency_section';
320
		include plugin_dir_path( __FILE__ ) . 'views/wizard-settings.php';
321
	}
322
323
	/**
324
	 * Installation of recommended plugins.
325
	 *
326
	 * @since 1.0.0
327
	 */
328
	public function setup_recommend() {
329
		$next_url            = $this->get_next_step_link();
330
		$recommended_plugins = self::get_recommend_wp_plugins();
331
		include plugin_dir_path( __FILE__ ) . 'views/wizard-plugins.php';
332
	}
333
334
	/**
335
	 * A list of recommended wp.org plugins.
336
	 * @return array
337
	 */
338
	public static function get_recommend_wp_plugins(){
339
		return array(
340
			'ayecode-connect' => array(
341
				'file'   => 'ayecode-connect/ayecode-connect.php',
342
				'url'    => 'https://wordpress.org/plugins/ayecode-connect/',
343
				'slug'   => 'ayecode-connect',
344
				'name'   => 'AyeCode Connect',
345
				'desc'   => __( 'Documentation and Support from within your WordPress admin.', 'geodirectory' ),
346
			),
347
			'invoicing-quotes' => array(
348
				'file'   => 'invoicing-quotes/wpinv-quote.php',
349
				'url'    => 'https://wordpress.org/plugins/invoicing-quotes/',
350
				'slug'   => 'invoicing-quotes',
351
				'name'   => 'Customer Quotes',
352
				'desc'   => __('Create & Send Quotes to Customers and have them accept and pay.','geodirectory'),
353
			),
354
			'userswp'    => array(
355
				'file'   => 'userswp/userswp.php',
356
				'url'    => 'https://wordpress.org/plugins/userswp/',
357
				'slug'   => 'userswp',
358
				'name'   => 'UsersWP',
359
				'desc'   => __('Frontend user login and registration as well as slick profile pages.','geodirectory'),
360
			),
361
		);
362
	}
363
364
	/**
365
	 * Dummy data save.
366
	 *
367
	 * This is done via ajax so we just pass onto the next step.
368
	 *
369
	 * @since 2.0.0
370
	 */
371
	public function setup_recommend_save() {
372
		check_admin_referer( 'gp-setup' );
373
		wp_redirect( esc_url_raw( $this->get_next_step_link() ) );
374
		exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
375
	}
376
377
	/**
378
	 * Dummy Data setup.
379
	 *
380
	 * @since 2.4.0
381
	 */
382
	public function setup_payments() {
383
		$next_url = $this->get_next_step_link();
384
		include plugin_dir_path( __FILE__ ) . 'views/wizard-gateways.php';
385
	}
386
387
	/**
388
	 * Dummy data save.
389
	 *
390
	 * This is done via ajax so we just pass onto the next step.
391
	 *
392
	 * @since 2.0.0
393
	 */
394
	public function setup_payments_save() {
395
		check_admin_referer( 'gp-setup' );
396
		wp_redirect( esc_url_raw( $this->get_next_step_link() ) );
397
		exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
398
	}
399
400
	/**
401
	 * Final step.
402
	 *
403
	 * @since 2.0.0
404
	 */
405
	public function setup_ready() {
406
		include plugin_dir_path( __FILE__ ) . 'views/wizard-thank-you.php';
407
	}
408
409
}
410
411
new GetPaid_Admin_Setup_Wizard();
412