Completed
Push — master ( 5463c4...6a0df7 )
by David
10:12 queued 06:51
created

Wordlift_Admin_Settings_Page::get_instance()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Pages: Admin Settings.
4
 *
5
 * Handles the WordLift admin settings page.
6
 *
7
 * @since      3.11.0
8
 * @package    Wordlift
9
 * @subpackage Wordlift/admin
10
 */
11
12
/**
13
 * Define the {@link Wordlift_Admin_Settings_Page} class.
14
 *
15
 * @since      3.11.0
16
 * @package    Wordlift
17
 * @subpackage Wordlift/admin
18
 */
19
class Wordlift_Admin_Settings_Page extends Wordlift_Admin_Page {
20
21
	/**
22
	 * A singleton instance of the Notice service.
23
	 *
24
	 * @since 3.2.0
25
	 * @access private
26
	 * @var \Wordlift_Notice_Service $instance A singleton instance of the Notice service.
27
	 */
28
	private static $instance;
29
30
	/**
31
	 * A {@link Wordlift_Entity_Service} instance.
32
	 *
33
	 * @since  3.11.0
34
	 * @access private
35
	 * @var \Wordlift_Entity_Service $entity_service A {@link Wordlift_Entity_Service} instance.
36
	 */
37
	private $entity_service;
38
39
	/**
40
	 * A {@link Wordlift_Configuration_Service} instance.
41
	 *
42
	 * @since  3.11.0
43
	 * @access private
44
	 * @var \Wordlift_Configuration_Service $configuration_service A {@link Wordlift_Configuration_Service} instance.
45
	 */
46
	private $configuration_service;
47
48
	/**
49
	 * A {@link Wordlift_Admin_Input_Element} element renderer.
50
	 *
51
	 * @since  3.11.0
52
	 * @access private
53
	 * @var \Wordlift_Admin_Input_Element $input_element An {@link Wordlift_Admin_Input_Element} element renderer.
54
	 */
55
	private $input_element;
56
57
	/**
58
	 * A {@link Wordlift_Admin_Radio_Input_Element} element renderer.
59
	 *
60
	 * @since  3.13.0
61
	 * @access protected
62
	 * @var \Wordlift_Admin_Radio_Input_Element $radio_input_element A {@link Wordlift_Admin_Radio_Input_Element} element renderer.
63
	 */
64
	private $radio_input_element;
65
66
	/**
67
	 * A {@link Wordlift_Admin_Language_Select_Element} element renderer.
68
	 *
69
	 * @since  3.11.0
70
	 * @access private
71
	 * @var \Wordlift_Admin_Language_Select_Element $language_select_element A {@link Wordlift_Admin_Language_Select_Element} element renderer.
72
	 */
73
	private $language_select_element;
74
75
	/**
76
	 * A {@link Wordlift_Admin_Publisher_Element} element renderer.
77
	 *
78
	 * @since  3.11.0
79
	 * @access private
80
	 * @var \Wordlift_Admin_Publisher_Element $publisher_element A {@link Wordlift_Admin_Publisher_Element} element renderer.
81
	 */
82
	private $publisher_element;
83
84
	/**
85
	 * Create a {@link Wordlift_Admin_Settings_Page} instance.
86
	 *
87
	 * @since 3.11.0
88
	 *
89
	 * @param \Wordlift_Configuration_Service         $configuration_service
90
	 * @param \Wordlift_Entity_Service                $entity_service
91
	 * @param \Wordlift_Admin_Input_Element           $input_element
92
	 * @param \Wordlift_Admin_Language_Select_Element $language_select_element
93
	 * @param \Wordlift_Admin_Publisher_Element       $publisher_element
94
	 * @param \Wordlift_Admin_Radio_Input_Element     $radio_input_element
95
	 */
96
	function __construct( $configuration_service, $entity_service, $input_element, $language_select_element, $publisher_element, $radio_input_element ) {
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...
97
98
		$this->configuration_service = $configuration_service;
99
		$this->entity_service        = $entity_service;
100
101
		// Set a reference to the UI elements.
102
		$this->input_element           = $input_element;
103
		$this->radio_input_element     = $radio_input_element;
104
		$this->language_select_element = $language_select_element;
105
		$this->publisher_element       = $publisher_element;
106
107
		self::$instance = $this;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this of type this<Wordlift_Admin_Settings_Page> is incompatible with the declared type object<Wordlift_Notice_Service> of property $instance.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
108
	}
109
110
	/**
111
	 * Get the singleton instance of the Notice service.
112
	 *
113
	 * @since 3.14.0
114
	 * @return \Wordlift_Admin_Settings_Page The singleton instance of the settings page service.
115
	 */
116
	public static function get_instance() {
117
118
		return self::$instance;
119
	}
120
121
	/**
122
	 * @inheritdoc
123
	 */
124
	function get_parent_slug() {
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...
125
126
		return 'wl_admin_menu';
127
	}
128
129
	/**
130
	 * @inheritdoc
131
	 */
132
	function get_capability() {
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...
133
134
		return 'manage_options';
135
	}
136
137
	/**
138
	 * @inheritdoc
139
	 */
140
	function get_page_title() {
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...
141
142
		return 'WorldLift Settings';
143
	}
144
145
	/**
146
	 * @inheritdoc
147
	 */
148
	function get_menu_title() {
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...
149
150
		return 'Settings';
151
	}
152
153
	/**
154
	 * @inheritdoc
155
	 */
156
	function get_menu_slug() {
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...
157
158
		return 'wl_configuration_admin_menu';
159
	}
160
161
	/**
162
	 * @inheritdoc
163
	 */
164
	function get_partial_name() {
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...
165
166
		return 'wordlift-admin-settings-page.php';
167
	}
168
169
	/**
170
	 * @inheritdoc
171
	 */
172
	public function enqueue_scripts() {
173
174
		// Enqueue the media scripts to be used for the publisher's logo selection.
175
		wp_enqueue_media();
176
177
		// JavaScript required for the settings page.
178
		// @todo: try to move to the `wordlift-admin.bundle.js`.
179
		wp_enqueue_script( 'wordlift-admin-settings-page', plugin_dir_url( dirname( __FILE__ ) ) . 'admin/js/wordlift-admin-settings-page.bundle.js', array( 'wp-util' ) );
180
181
	}
182
183
	/**
184
	 * Configure all the configuration parameters.
185
	 *
186
	 * Called by the *admin_init* hook.
187
	 *
188
	 * @since 3.11.0
189
	 */
190
	function admin_init() {
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...
191
192
		// Register WordLift's general settings, providing our own sanitize callback
193
		// which will also check whether the user filled the WL Publisher form.
194
		register_setting(
195
			'wl_general_settings',
196
			'wl_general_settings',
197
			array( $this, 'sanitize_callback', )
198
		);
199
200
		// Add the general settings section.
201
		add_settings_section(
202
			'wl_general_settings_section', // ID used to identify this section and with which to register options.
203
			'',                            // Section header.
204
			'',                            // Callback used to render the description of the section.
205
			'wl_general_settings'          // Page on which to add this section of options.
206
		);
207
208
		$key_args = array(
209
			'id'          => 'wl-key',
210
			'name'        => 'wl_general_settings[' . Wordlift_Configuration_Service::KEY . ']',
211
			'value'       => $this->configuration_service->get_key(),
212
			'description' => _x( 'Insert the <a href="https://www.wordlift.io/blogger">WordLift Key</a> you received via email.', 'wordlift' ),
213
		);
214
215
		// Set the class for the key field based on the validity of the key.
216
		// Class should be "untouched" for an empty (virgin) value, "valid"
217
		// if the key is valid, or "invalid" otherwise.
218
		$validation_service = new Wordlift_Key_Validation_Service();
219
220
		if ( empty( $key_args['value'] ) ) {
221
			$key_args['css_class'] = 'untouched';
222
		} elseif ( $validation_service->is_valid( $key_args['value'] ) ) {
223
			$key_args['css_class'] = 'valid';
224
		} else {
225
			$key_args['css_class'] = 'invalid';
226
		}
227
228
		// Add the `key` field.
229
		add_settings_field(
230
			'wl-key',                                       // Element id used to identify the field throughout the theme.
231
			_x( 'WordLift Key', 'wordlift' ),               // The label to the left of the option interface element.
232
			// The name of the function responsible for rendering the option interface.
233
			array( $this->input_element, 'render', ),
234
			'wl_general_settings',                          // The page on which this option will be displayed.
235
			'wl_general_settings_section',                  // The name of the section to which this field belongs.
236
			$key_args                                       // The array of arguments to pass to the callback. In this case, just a description.
237
		);
238
239
		// Entity Base Path input.
240
		$entity_base_path_args = array(
241
			// The array of arguments to pass to the callback. In this case, just a description.
242
			'id'          => 'wl-entity-base-path',
243
			'name'        => 'wl_general_settings[' . Wordlift_Configuration_Service::ENTITY_BASE_PATH_KEY . ']',
244
			'value'       => $this->configuration_service->get_entity_base_path(),
245
			'description' => sprintf( _x( 'All new pages created with WordLift, will be stored inside your internal vocabulary. You can customize the url pattern of these pages in the field above. Check our <a href="%s">FAQs</a> if you need more info.', 'wordlift' ), 'https://wordlift.io/wordlift-user-faqs/#10-why-and-how-should-i-customize-the-url-of-the-entity-pages-created-in-my-vocabulary' ),
246
		);
247
248
		$entity_base_path_args['readonly'] = 0 < $this->entity_service->count();
249
250
		// Add the `wl_entity_base_path` field.
251
		add_settings_field(
252
			'wl-entity-base-path',                                // ID used to identify the field throughout the theme
253
			_x( 'Entity Base Path', 'wordlift' ),                 // The label to the left of the option interface element
254
			// The name of the function responsible for rendering the option interface
255
			array( $this->input_element, 'render', ),
256
			'wl_general_settings',                                // The page on which this option will be displayed
257
			'wl_general_settings_section',                        // The name of the section to which this field belongs
258
			$entity_base_path_args
259
		);
260
261
		// Add the `language_name` field.
262
		add_settings_field(
263
			'wl-site-language',
264
			_x( 'Site Language', 'wordlift' ),
265
			array( $this->language_select_element, 'render' ),
266
			'wl_general_settings',
267
			'wl_general_settings_section',
268
			array(
269
				// The array of arguments to pass to the callback. In this case, just a description.
270
				'id'          => 'wl-site-language',
271
				'name'        => 'wl_general_settings[' . Wordlift_Configuration_Service::LANGUAGE . ']',
272
				'value'       => $this->configuration_service->get_language_code(),
273
				'description' => __( 'Each WordLift Key can be used only in one language. Pick yours.', 'wordlift' ),
274
			)
275
		);
276
277
		// Add the `publisher` field.
278
		add_settings_field(
279
			'wl-publisher-id',
280
			_x( 'Publisher', 'wordlift' ),
281
			array( $this->publisher_element, 'render' ),
282
			'wl_general_settings',
283
			'wl_general_settings_section',
284
			array(
285
				'id'   => 'wl-publisher-id',
286
				'name' => 'wl_general_settings[' . Wordlift_Configuration_Service::PUBLISHER_ID . ']',
287
			)
288
		);
289
290
		// Add the `link by default` field.
291
		add_settings_field(
292
			'wl-link-by-default',
293
			_x( 'Link by Default', 'wordlift' ),
294
			array( $this->radio_input_element, 'render' ),
295
			'wl_general_settings',
296
			'wl_general_settings_section',
297
			array(
298
				'id'          => 'wl-link-by-default',
299
				'name'        => 'wl_general_settings[' . Wordlift_Configuration_Service::LINK_BY_DEFAULT . ']',
300
				'value'       => $this->configuration_service->is_link_by_default() ? 'yes' : 'no',
301
				'description' => _x( 'Whether to link entities by default or not. This setting applies to all the entities.', 'wordlift' ),
302
			)
303
		);
304
305
	}
306
307
	/**
308
	 * Sanitize the configuration settings to be stored.
309
	 *
310
	 * If a new entity is being created for the publisher, create it and set The
311
	 * publisher setting.
312
	 *
313
	 * @since 3.11.0
314
	 *
315
	 * @param array $input The configuration settings array.
316
	 *
317
	 * @return array The sanitized input array.
318
	 */
319
	function sanitize_callback( $input ) {
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...
Coding Style introduced by
sanitize_callback 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...
320
321
		// Check whether a publisher name has been set.
322
		if ( isset( $_POST['wl_publisher'] ) && ! empty( $_POST['wl_publisher']['name'] ) ) {
323
			$name         = $_POST['wl_publisher']['name'];
324
			$type         = $_POST['wl_publisher']['type'];
325
			$thumbnail_id = $_POST['wl_publisher']['thumbnail_id'] ?: null;
326
327
			// Set the type URI, either http://schema.org/Person or http://schema.org/Organization.
328
			$type_uri = sprintf( 'http://schema.org/%s', 'organization' === $type ? 'Organization' : 'Person' );
329
330
			// Create an entity for the publisher and assign it to the input
331
			// parameter which WordPress automatically saves into the settings.
332
			$input['publisher_id'] = $this->entity_service->create( $name, $type_uri, $thumbnail_id, 'publish' );
333
		}
334
335
		return $input;
336
	}
337
338
}
339