Completed
Push — master ( 159d3b...c30b21 )
by David
02:37
created

Wordlift_Admin_Setup::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 3
dl 0
loc 25
rs 8.8571
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 29 and the first side effect is on line 16.

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
 * Admin UI: Wordlift_Admin_Install_Wizard
4
 *
5
 * The {@link Wordlift_Admin_Install_Wizard} class handles WL's installation wizard by checking whether WL is configured
6
 * and, if not, displays a notice with a link to the configuration wizard.
7
 *
8
 * @link       https://wordlift.io
9
 *
10
 * @package    Wordlift
11
 * @subpackage Wordlift/admin
12
 * @since      3.9.0
13
 */
14
15
if ( ! defined( 'ABSPATH' ) ) {
16
	exit;
17
}
18
19
/**
20
 * The install wizard.
21
 *
22
 * Methods to track and implement the various steps of the install wizard
23
 * which is triggered on dirst install of the plugin (when there are no settings)
24
 *
25
 * @package    Wordlift
26
 * @subpackage Wordlift/admin
27
 * @author     WordLift <[email protected]>
28
 */
29
class Wordlift_Admin_Setup {
30
31
	/**
32
	 * A {@link Wordlift_Configuration_Service} instance.
33
	 *
34
	 * @since  3.9.0
35
	 * @access private
36
	 * @var Wordlift_Configuration_Service A {@link Wordlift_Configuration_Service} instance.
37
	 */
38
	private $configuration_service;
39
40
	/**
41
	 * A {@link Wordlift_Key_Validation_Service} instance.
42
	 *
43
	 * @since  3.9.0
44
	 * @access private
45
	 * @var Wordlift_Key_Validation_Service A {@link Wordlift_Key_Validation_Service} instance.
46
	 */
47
	private $key_validation_service;
48
49
	/**
50
	 * A {@link Wordlift_Entity_Service} instance.
51
	 *
52
	 * @since  3.9.0
53
	 * @access private
54
	 * @var Wordlift_Entity_Service $entity_service A {@link Wordlift_Entity_Service} instance.
55
	 */
56
	private $entity_service;
57
58
	/**
59
	 * Initialize the class and set its properties.
60
	 *
61
	 * @since    3.9.0
62
	 *
63
	 * @param Wordlift_Configuration_Service  $configuration_service  A {@link Wordlift_Configuration_Service} instance.
64
	 * @param Wordlift_Key_Validation_Service $key_validation_service A {@link Wordlift_Key_Validation_Service} instance.
65
	 * @param Wordlift_Entity_Service         $entity_service         A {@link Wordlift_Entity_Service} instance.
66
	 */
67
	public function __construct( $configuration_service, $key_validation_service, $entity_service ) {
68
69
		// Set a reference to the configuration service.
70
		$this->configuration_service = $configuration_service;
71
72
		// Set a reference to the key validation service.
73
		$this->key_validation_service = $key_validation_service;
74
75
		// Set a reference to the entity service.
76
		$this->entity_service = $entity_service;
77
78
		// Hook to some WP's events:
79
		// When WP is loaded check whether the user decided to skip the set-up, i.e. don't show us even if WL is not set up.
80
		add_action( 'wp_loaded', array( $this, 'hide_notices' ) );
81
82
		// Hook to `admin_menu` in order to add our own setup wizard page.
83
		add_action( 'admin_menu', array( $this, 'admin_menu' ) );
84
85
		// Triggered when the user accesses the admin area, we decide whether to show our own wizard.
86
		add_action( 'admin_init', array( $this, 'show_page' ) );
87
88
		// Hook to `admin_notices` to display our notices.
89
		add_action( 'admin_notices', array( $this, 'admin_notices' ) );
90
91
	}
92
93
	/**
94
	 * Hook to `admin_init` and redirect to WordLift's setup page if the `_wl_activation_redirect` transient flag is set.
95
	 *
96
	 * @since 3.9.0
97
	 */
98
	public function admin_init() {
0 ignored issues
show
Coding Style introduced by
admin_init uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
99
100
		// If the `_wl_activation_redirect` is set, the redirect to the setup page.
101
		if ( get_transient( '_wl_activation_redirect' ) ) {
102
			delete_transient( '_wl_activation_redirect' );
103
104
			// If the user asked to skip the wizard then comply.
105
			if ( $this->configuration_service->is_skip_wizard() ) {
106
				return;
107
			}
108
109
			// If we're already on the page or the user doesn't have permissions, return.
110
			if ( ( ! empty( $_GET['page'] ) && 'wl-setup' === $_GET['page'] ) || is_network_admin() || isset( $_GET['activate-multi'] ) || ! current_user_can( 'manage_options' ) ) {
111
				return;
112
			}
113
114
			// Finally redirect to the setup page.
115
			wp_safe_redirect( admin_url( 'index.php?page=wl-setup' ) );
116
117
			exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method admin_init() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
118
		}
119
120
	}
121
122
	/**
123
	 * Generate an admin notice suggesting to start the wizard if there is no configuration.
124
	 *
125
	 * @since    3.9.0
126
	 */
127
	public function admin_notices() {
128
129
		// Use `wl_configuration_get_key` to check whether WL's key is set and that the user didn't disable the wizard.
130
		if ( '' === $this->configuration_service->get_key() && ! $this->configuration_service->is_skip_wizard() ) { ?>
131
			<div id="wl-message" class="updated">
132
				<p><?php esc_html_e( 'Welcome to WordLift &#8211; You&lsquo;re almost ready to start', 'wordlift' ); ?></p>
133
				<p class="submit"><a href="<?php echo esc_url( admin_url( 'admin.php?page=wl-setup' ) ); ?>"
134
				                     class="button-primary"><?php esc_html_e( 'Run the Setup Wizard', 'wordlift' ); ?></a>
135
					<a class="button-secondary skip"
136
					   href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wl-hide-notice', 'install' ), 'wordlift_hide_notices_nonce', '_wl_notice_nonce' ) ); ?>"><?php esc_html_e( 'Skip Setup', 'wordlift' ); ?></a>
137
				</p>
138
			</div>
139
		<?php }
140
141
	}
142
143
	/**
144
	 * Handle hiding the wizard notices by user request
145
	 *
146
	 * @since    3.9.0
147
	 */
148
	public function hide_notices() {
0 ignored issues
show
Coding Style introduced by
hide_notices uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
149
150
		// If it's not a `wl-hide-notice` or the nonce is not set, return.
151
		if ( ! isset( $_GET['wl-hide-notice'], $_GET['_wl_notice_nonce'] ) ) {
152
			return;
153
		}
154
155
		// If the nonce is invalid, return an error.
156
		if ( ! wp_verify_nonce( $_GET['_wl_notice_nonce'], 'wordlift_hide_notices_nonce' ) ) {
157
			wp_die( __( 'Action failed. Please refresh the page and retry.', 'wordlift' ) );
158
		}
159
160
		// If the user doesn't have the right privileges, return an error.
161
		if ( ! current_user_can( 'manage_options' ) ) {
162
			wp_die( __( 'Cheatin&#8217; huh?', 'wordlift' ) );
163
		}
164
165
		// Store a flag telling to skip the wizard.
166
		$this->configuration_service->set_skip_wizard( TRUE );
167
168
	}
169
170
	/**
171
	 * Register the wizard page to be able to access it
172
	 *
173
	 * @since    3.9.0
174
	 */
175
	public function admin_menu() {
176
177
		// @todo: find another way to do this, since this is adding an empty space in WP's dashboard menu.
178
		add_dashboard_page( '', '', 'manage_options', 'wl-setup', '' );
179
180
	}
181
182
	/**
183
	 * Displays the wizard page
184
	 *
185
	 * @since    3.9.0
186
	 */
187
	public function show_page() {
0 ignored issues
show
Coding Style introduced by
show_page uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
show_page uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
188
189
		// First check if we are in the wizard page at all, if not do nothing.
190
		if ( empty( $_GET['page'] ) || 'wl-setup' !== $_GET['page'] ) {
191
			return;
192
		}
193
194
		// If it's a POST and the `wl-save-configuration` action is set, save the configuration.
195
		if ( isset( $_POST['action'] ) && 'wl-save-configuration' === $_POST['action'] ) {
196
197
			// Check the nonce and the user capabilities.
198
			check_admin_referer( 'wl-save-configuration' );
199
200
			// Check if the user has the right privileges.
201
			if ( ! current_user_can( 'manage_options' ) ) {
202
				wp_die( __( 'Sorry, you do not have a permission to save the settings', 'wordlift' ) );
203
			}
204
205
			// Save the configuration.
206
			$this->save_configuration( $_POST );
207
208
			// Redirect to the admin's page.
209
			wp_redirect( admin_url() );
210
211
			exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method show_page() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
212
		}
213
214
		include plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/wordlift-admin-setup.php';
215
216
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method show_page() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
217
	}
218
219
	/**
220
	 * Save WordLift's configuration using the provided parameters.
221
	 *
222
	 * @since 3.9.0
223
	 *
224
	 * @param array $params An array of configuration parameters.
225
	 */
226
	private function save_configuration( $params ) {
227
228
		// We have the following parameters:
229
		// `key`, holding WL's key,
230
		// `vocabulary`, holding the vocabulary path,
231
		// `language`, with the language code (e.g. `en`),
232
		// `user_type`, the user type either `personal` or `company`,
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
233
		// `name`, with the `personal` or `company`'s name,
234
		// `logo`, the attachment id for the `personal` or `company` entity.
235
236
		// Store the key:
237
		$this->configuration_service->set_key( $params['key'] );
238
239
		// Store the vocabulary path:
240
		$this->configuration_service->set_entity_base_path( $params['vocabulary'] );
241
242
		// Store the site's language:
243
		$this->configuration_service->set_language_code( $params['language'] );
244
245
		// Set the type URI, either http://schema.org/Person or http://schema.org/Organization.
246
		$type_uri = sprintf( 'http://schema.org/%s', 'organization' === $params['user_type'] ? 'Organization' : 'Person' );
247
248
		// Create an entity for the publisher.
249
		$publisher_post_id = $this->entity_service->create( $params['name'], $type_uri, $params['logo'], 'publish' );
250
251
		// Store the publisher entity post id in the configuration.
252
		$this->configuration_service->set_publisher_id( $publisher_post_id );
253
254
		flush_rewrite_rules(); // Needed because of possible change to the entity base path.
255
256
	}
257
258
}
259