Completed
Push — master ( ea28d3...1760c1 )
by Dennis
04:45
created

MslsAdmin::validate()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 21
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 4
nop 1
dl 0
loc 21
rs 9.3142
c 0
b 0
f 0
1
<?php
2
/**
3
 * MslsAdmin
4
 * @author Dennis Ploetner <[email protected]>
5
 * @since 0.9.8
6
 */
7
8
namespace lloc\Msls;
9
10
/**
11
 * Administration of the options
12
 * @package Msls
13
 */
14
class MslsAdmin extends MslsMain {
15
16
	/**
17
	 * Factory
18
	 *
19
	 * @codeCoverageIgnore
20
	 *
21
	 * @return MslsAdmin
22
	 */
23
	public static function init() {
24
		$options    = MslsOptions::instance();
25
		$collection = MslsBlogCollection::instance();
26
		$obj        = new static( $options, $collection );
27
28
		if ( current_user_can( 'manage_options' ) ) {
29
			$title = __( 'Multisite Language Switcher', 'multisite-language-switcher' );
30
			add_options_page( $title, $title, 'manage_options', $obj->get_menu_slug(), [ $obj, 'render' ] );
31
32
			add_action( 'admin_init', [ $obj, 'register' ] );
33
			add_action( 'admin_notices', [ $obj, 'has_problems' ] );
34
35
			add_filter( 'msls_admin_validate', [ $obj, 'set_blog_language' ] );
36
		}
37
38
		return $obj;
39
	}
40
41
	/**
42
	 * Let's do this simple
43
	 *
44
	 * @return string
45
	 */
46
	public function get_menu_slug() {
47
		return 'MslsAdmin';
48
	}
49
50
	/**
51
	 * Get's the link for the switcher-settings in the wp-admin
52
	 *
53
	 * @return string
54
	 */
55
	public function get_options_page_link() {
56
		return sprintf( '/options-general.php?page=%s', $this->get_menu_slug() );
57
	}
58
59
	/**
60
	 * You can use every method of the decorated object
61
	 *
62
	 * @param string $method
63
	 * @param mixed $args
64
	 *
65
	 * @return mixed
66
	 */
67
	public function __call( $method, $args ) {
68
		$parts = explode( '_', $method, 2 );
69
		if ( 2 == count( $parts ) ) {
70
			switch ( $parts[0] ) {
71
				case 'rewrite':
72
					return $this->render_rewrite( $parts[1] );
73
					break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
74
				case 'text':
75
					echo $this->render_input( $parts[1] );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
76
					break;
77
			}
78
		}
79
	}
80
81
	/**
82
	 * There is something wrong? Here comes the message...
83
	 * @return bool
84
	 */
85
	public function has_problems() {
86
		$message = '';
87
88
		if ( 1 == count( $this->options->get_available_languages() ) ) {
89
			$message = sprintf(
90
				__( 'There are no language files installed. You can <a href="%s">manually install some language files</a> or you could use a <a href="%s">plugin</a> to download these files automatically.' ),
91
				esc_url( 'http://codex.wordpress.org/Installing_WordPress_in_Your_Language#Manually_Installing_Language_Files' ),
92
				esc_url( 'http://wordpress.org/plugins/wp-native-dashboard/' )
93
			);
94
		} elseif ( $this->options->is_empty() ) {
95
			$message = sprintf(
96
				__( 'Multisite Language Switcher is almost ready. You must complete the configuration process</a>.' ),
97
				esc_url( admin_url( $this->get_options_page_link() ) )
98
			);
99
		}
100
101
		return MslsPlugin::message_handler( $message, 'updated fade' );
102
	}
103
104
	/**
105
	 * Render the options-page
106
	 * @codeCoverageIgnore
107
	 */
108
	public function render() {
109
		printf(
110
			'<div class="wrap"><div class="icon32" id="icon-options-general"><br/></div><h1>%s</h1>%s<br class="clear"/><form action="options.php" method="post"><p>%s</p>',
111
			__( 'Multisite Language Switcher Options', 'multisite-language-switcher' ),
112
			$this->subsubsub(),
113
			__( 'To achieve maximum flexibility, you have to configure each blog separately.', 'multisite-language-switcher' )
114
		);
115
116
		settings_fields( 'msls' );
117
		do_settings_sections( __CLASS__ );
118
119
		printf(
120
			'<p class="submit"><input name="Submit" type="submit" class="button-primary" value="%s" /></p></form></div>',
121
			( $this->options->is_empty() ? __( 'Configure', 'multisite-language-switcher' ) : __( 'Update', 'multisite-language-switcher' ) )
122
		);
123
	}
124
125
126
	/**
127
	 * Create a submenu which contains links to all blogs of the current user
128
	 * @return string
129
	 */
130
	public function subsubsub() {
131
		$arr = [];
132
133
		foreach ( $this->collection->get_plugin_active_blogs() as $blog ) {
134
			$arr[] = sprintf(
135
				'<a href="%s"%s>%s / %s</a>',
136
				get_admin_url( $blog->userblog_id, $this->get_options_page_link() ),
137
				( $blog->userblog_id == $this->collection->get_current_blog_id() ? ' class="current"' : '' ),
138
				$blog->blogname,
139
				$blog->get_description()
140
			);
141
		}
142
143
		return (
144
			empty( $arr ) ?
145
			'' :
146
			sprintf(
147
				'<ul class="subsubsub"><li>%s</li></ul>',
148
				implode( ' | </li><li>', $arr )
149
			)
150
		);
151
	}
152
153
	/**
154
	 * Register the form-elements
155
	 * @codeCoverageIgnore
156
	 */
157
	public function register() {
158
		register_setting( 'msls', 'msls', [ $this, 'validate' ] );
159
160
		add_settings_section( 'language_section', __( 'Language Settings', 'multisite-language-switcher' ), array(
161
			$this,
162
			'language_section'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
163
		), __CLASS__ );
164
		add_settings_section( 'main_section', __( 'Main Settings', 'multisite-language-switcher' ), array(
165
			$this,
166
			'main_section'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
167
		), __CLASS__ );
168
		add_settings_section( 'advanced_section', __( 'Advanced Settings', 'multisite-language-switcher' ), array(
169
			$this,
170
			'advanced_section'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
171
		), __CLASS__ );
172
173
		global $wp_rewrite;
174
		if ( $wp_rewrite->using_permalinks() ) {
175
			add_settings_section( 'rewrites_section', __( 'Rewrites Settings', 'multisite-language-switcher' ), array(
176
				$this,
177
				'rewrites_section'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
178
			), __CLASS__ );
179
		}
180
181
		/**
182
		 * Lets you add your own settings section
183
		 * @since 1.0
184
		 *
185
		 * @param string $page
186
		 */
187
		do_action( 'msls_admin_register', __CLASS__ );
188
	}
189
190
	/**
191
	 * Register the fields in the language_section
192
	 * @codeCoverageIgnore
193
	 */
194
	public function language_section() {
195
		add_settings_field( 'blog_language', __( 'Blog Language', 'multisite-language-switcher' ), array(
196
			$this,
197
			'blog_language'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
198
		), __CLASS__, 'language_section' );
199
200
		/**
201
		 * Lets you add your own field to the language section
202
		 * @since 1.0
203
		 *
204
		 * @param string $page
205
		 * @param string $section
206
		 */
207
		do_action( 'msls_admin_language_section', __CLASS__, 'language_section' );
208
	}
209
210
	/**
211
	 * Register the fields in the main_section
212
	 * @codeCoverageIgnore
213
	 */
214
	public function main_section() {
215
		add_settings_field( 'display', __( 'Display', 'multisite-language-switcher' ), array(
216
			$this,
217
			'display'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
218
		), __CLASS__, 'main_section' );
219
		add_settings_field( 'sort_by_description', __( 'Sort output by description', 'multisite-language-switcher' ), array(
220
			$this,
221
			'sort_by_description'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
222
		), __CLASS__, 'main_section' );
223
		add_settings_field( 'output_current_blog', __( 'Display link to the current language', 'multisite-language-switcher' ), array(
224
			$this,
225
			'output_current_blog'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
226
		), __CLASS__, 'main_section' );
227
		add_settings_field( 'only_with_translation', __( 'Show only links with a translation', 'multisite-language-switcher' ), array(
228
			$this,
229
			'only_with_translation'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
230
		), __CLASS__, 'main_section' );
231
		add_settings_field( 'description', __( 'Description', 'multisite-language-switcher' ), array(
232
			$this,
233
			'description'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
234
		), __CLASS__, 'main_section' );
235
		add_settings_field( 'before_output', __( 'Text/HTML before the list', 'multisite-language-switcher' ), array(
236
			$this,
237
			'text_before_output'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
238
		), __CLASS__, 'main_section' );
239
		add_settings_field( 'after_output', __( 'Text/HTML after the list', 'multisite-language-switcher' ), array(
240
			$this,
241
			'text_after_output'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
242
		), __CLASS__, 'main_section' );
243
		add_settings_field( 'before_item', __( 'Text/HTML before each item', 'multisite-language-switcher' ), array(
244
			$this,
245
			'text_before_item'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
246
		), __CLASS__, 'main_section' );
247
		add_settings_field( 'after_item', __( 'Text/HTML after each item', 'multisite-language-switcher' ), array(
248
			$this,
249
			'text_after_item'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
250
		), __CLASS__, 'main_section' );
251
		add_settings_field( 'content_filter', __( 'Add hint for available translations', 'multisite-language-switcher' ), array(
252
			$this,
253
			'content_filter'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
254
		), __CLASS__, 'main_section' );
255
		add_settings_field( 'content_priority', __( 'Hint priority', 'multisite-language-switcher' ), array(
256
			$this,
257
			'content_priority'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
258
		), __CLASS__, 'main_section' );
259
260
		/**
261
		 * Lets you add your own field to the main section
262
		 * @since 1.0
263
		 *
264
		 * @param string $page
265
		 * @param string $section
266
		 */
267
		do_action( 'msls_admin_main_section', __CLASS__, 'main_section' );
268
	}
269
270
	/**
271
	 * Register the fields in the advanced_section
272
	 * @codeCoverageIgnore
273
	 */
274
	public function advanced_section() {
275
		add_settings_field( 'activate_autocomplete', __( 'Activate experimental autocomplete inputs', 'multisite-language-switcher' ), array(
276
			$this,
277
			'activate_autocomplete'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
278
		), __CLASS__, 'advanced_section' );
279
		add_settings_field( 'image_url', __( 'Custom URL for flag-images', 'multisite-language-switcher' ), array(
280
			$this,
281
			'text_image_url'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
282
		), __CLASS__, 'advanced_section' );
283
		add_settings_field( 'reference_user', __( 'Reference user', 'multisite-language-switcher' ), array(
284
			$this,
285
			'reference_user'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
286
		), __CLASS__, 'advanced_section' );
287
		add_settings_field( 'exclude_current_blog', __( 'Exclude this blog from output', 'multisite-language-switcher' ), array(
288
			$this,
289
			'exclude_current_blog'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
290
		), __CLASS__, 'advanced_section' );
291
292
		/**
293
		 * Lets you add your own field to the advanced section
294
		 * @since 1.0
295
		 *
296
		 * @param string $page
297
		 * @param string $section
298
		 */
299
		do_action( 'msls_admin_advanced_section', __CLASS__, 'advanced_section' );
300
	}
301
302
	/**
303
	 * Register the fields in the rewrites_section
304
	 * @since 1.1
305
	 * @codeCoverageIgnore
306
	 */
307
	public function rewrites_section() {
308
		foreach ( get_post_types( [ 'public' => true ], 'objects' ) as $key => $object ) {
309
			$title = sprintf( __( '%s Slug', 'multisite-language-switcher' ), $object->label );
310
			add_settings_field( "rewrite_{$key}", $title, [ $this, "rewrite_{$key}" ], __CLASS__, 'rewrites_section' );
311
		}
312
313
		/**
314
		 * Lets you add your own field to the rewrites section
315
		 *
316
		 * @param string $page
317
		 * @param string $section
318
		 */
319
		do_action( 'msls_admin_rewrites_section', __CLASS__, 'rewrites_section' );
320
	}
321
322
	/**
323
	 * Shows the select-form-field 'blog_language'
324
	 */
325
	public function blog_language() {
326
		echo $this->render_select(
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
327
			'blog_language',
328
			$this->options->get_available_languages(),
329
			get_option( 'WPLANG', 'en_US' )
330
		);
331
	}
332
333
	/**
334
	 * Shows the select-form-field 'display'
335
	 */
336
	public function display() {
337
		echo $this->render_select(
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
338
			'display',
339
			MslsLink::get_types_description(),
340
			$this->options->display
341
		);
342
	}
343
344
	/**
345
	 * Shows the select-form-field 'reference_user'
346
	 */
347
	public function reference_user() {
348
		$users = array();
349
350
		foreach ( $this->collection->get_users() as $user ) {
351
			$users[ $user->ID ] = $user->user_nicename;
352
		}
353
354
		echo $this->render_select( 'reference_user', $users, $this->options->reference_user );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
355
	}
356
357
	/**
358
	 * render
359
	 *
360
	 * You can decide if you want to activate the experimental autocomplete
361
	 * input fields in the backend instead of the traditional select-menus.
362
	 */
363
	public function activate_autocomplete() {
364
		echo $this->render_checkbox( 'activate_autocomplete' );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
365
	}
366
367
	/**
368
	 * Show sort_by_description-field
369
	 *
370
	 * You can decide that the ouput will be sorted by the description. If not
371
	 * the output will be sorted by the language-code.
372
	 */
373
	public function sort_by_description() {
374
		echo $this->render_checkbox( 'sort_by_description' );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
375
	}
376
377
	/**
378
	 * Exclude the current blog
379
	 *
380
	 * You can exclude a blog explicitly. All your settings will be safe but the
381
	 * plugin will ignore this blog while this option is active.
382
	 */
383
	public function exclude_current_blog() {
384
		echo $this->render_checkbox( 'exclude_current_blog' );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
385
	}
386
387
	/**
388
	 * Show only a link  if a translation is available
389
	 *
390
	 * Some user requested this feature. Shows only links to available
391
	 * translations.
392
	 */
393
	public function only_with_translation() {
394
		echo $this->render_checkbox( 'only_with_translation' );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
395
	}
396
397
	/**
398
	 * Show a link to the current blog
399
	 *
400
	 * Some user requested this feature. If active the plugin will place also a
401
	 * link to the current blog.
402
	 */
403
	public function output_current_blog() {
404
		echo $this->render_checkbox( 'output_current_blog' );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
405
	}
406
407
	/**
408
	 * The description for the current blog
409
	 *
410
	 * The language will be used ff there is no description.
411
	 */
412
	public function description() {
413
		echo $this->render_input( 'description', '40' );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
414
	}
415
416
	/**
417
	 * The output can be placed after the_content
418
	 */
419
	public function content_filter() {
420
		echo $this->render_checkbox( 'content_filter' );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
421
	}
422
423
	/**
424
	 * If the output in the_content is active you can set the priority too
425
	 *
426
	 * Default is 10. But may be there are other plugins active and you run into
427
	 * trouble. So you can decide a higher (from 1) or a lower (to 100) priority
428
	 * for the output
429
	 */
430
	public function content_priority() {
431
		$temp     = array_merge( range( 1, 10 ), [ 20, 50, 100 ] );
432
		$arr      = array_combine( $temp, $temp );
433
		$selected = (
434
			empty( $this->options->content_priority ) ?
435
			10 :
436
			$this->options->content_priority
437
		);
438
439
		echo $this->render_select( 'content_priority', $arr, $selected );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
440
	}
441
442
	/**
443
	 * Rewrites slugs for registered post types
444
	 *
445
	 * @param string $key
446
	 */
447
	public function render_rewrite( $key ) {
448
		$rewrite = get_post_type_object( $key )->rewrite;
449
450
		$value = '';
451
		if ( true === $rewrite ) {
452
			$value = $key;
453
		} elseif ( ! empty( $rewrite['slug'] ) ) {
454
			$value = $rewrite['slug'];
455
		}
456
457
		echo $this->render_input( "rewrite_{$key}", 30, $value, true );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
458
	}
459
460
	/**
461
	 * Render form-element (checkbox)
462
	 *
463
	 * @param string $key Name and ID of the form-element
464
	 *
465
	 * @return string
466
	 */
467
	public function render_checkbox( $key ) {
468
		return sprintf(
469
			'<input type="checkbox" id="%1$s" name="msls[%1$s]" value="1" %2$s/>',
470
			$key,
471
			checked( 1, $this->options->$key, false )
472
		);
473
	}
474
475
	/**
476
	 * Render form-element (text-input)
477
	 *
478
	 * @param string $key Name and ID of the form-element
479
	 * @param string $size Size-attribute of the input-field
480
	 * @param string $default
481
	 * @param bool $readonly
482
	 *
483
	 * @return string
484
	 */
485
	public function render_input( $key, $size = '30', $default = '', $readonly = false ) {
486
		return sprintf(
487
			'<input id="%1$s" name="msls[%1$s]" value="%2$s" size="%3$s"%4$s/>',
488
			$key,
489
			esc_attr( ! empty( $this->options->$key ) ? $this->options->$key : $default ),
490
			$size,
491
			$readonly ? ' readonly="readonly"' : ''
492
		);
493
	}
494
495
	/**
496
	 * Render form-element (select)
497
	 * @uses selected
498
	 *
499
	 * @param string $key Name and ID of the form-element
500
	 * @param array $arr Options as associative array
501
	 * @param string $selected Values which should be selected
502
	 *
503
	 * @return string
504
	 */
505
	public function render_select( $key, array $arr, $selected = '' ) {
506
		$options = [];
507
508
		foreach ( $arr as $value => $description ) {
509
			$options[] = sprintf(
510
				'<option value="%s" %s>%s</option>',
511
				$value,
512
				selected( $value, $selected, false ),
513
				$description
514
			);
515
		}
516
517
		return sprintf(
518
			'<select id="%1$s" name="msls[%1$s]">%2$s</select>',
519
			$key,
520
			implode( '', $options )
521
		);
522
	}
523
524
	/**
525
	 * Validates input before saving it
526
	 *
527
	 * @param array $arr Values of the submitted form
528
	 *
529
	 * @return array Validated input
530
	 */
531
	public function validate( array $arr ) {
532
		/**
533
		 * Returns custom filtered input array
534
		 * @since 1.0
535
		 *
536
		 * @param array $arr
537
		 */
538
		$arr = apply_filters( 'msls_admin_validate', $arr );
539
540
		$arr['display'] = (
541
		isset( $arr['display'] ) ?
542
			(int) $arr['display'] :
543
			0
544
		);
545
546
		if ( isset( $arr['image_url'] ) ) {
547
			$arr['image_url'] = rtrim( esc_attr( $arr['image_url'] ), '/' );
548
		}
549
550
		return $arr;
551
	}
552
553
	/**
554
	 * Filter which sets the global blog language
555
	 *
556
	 * @param array $arr
557
	 *
558
	 * @return array
559
	 */
560
	public function set_blog_language( array $arr ) {
561
		if ( isset( $arr['blog_language'] ) ) {
562
			$blog_language = ( 'en_US' === $arr['blog_language'] ) ? '' : $arr['blog_language'];
563
			update_option( 'WPLANG', $blog_language );
564
			unset( $arr['blog_language'] );
565
		}
566
567
		return $arr;
568
	}
569
570
}
571