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

MslsMetaBox::render_select()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 103
Code Lines 67

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 67
nc 8
nop 0
dl 0
loc 103
rs 6.4589
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * MslsMetaBox
4
 * @author Dennis Ploetner <[email protected]>
5
 * @since 0.9.8
6
 */
7
8
namespace lloc\Msls;
9
10
/**
11
 * Meta box for the edit mode of the (custom) post types
12
 * @package Msls
13
 */
14
class MslsMetaBox extends MslsMain {
15
16
	/**
17
	 * Suggest
18
	 *
19
	 * Echo a JSON-ified array of posts of the given post-type and
20
	 * the requested search-term and then die silently
21
	 */
22
	public static function suggest() {
23
		$json = new MslsJson;
24
25
		if ( filter_has_var( INPUT_POST, 'blog_id' ) ) {
26
			switch_to_blog(
0 ignored issues
show
introduced by
switch_to_blog is not something you should ever need to do in a VIP theme context. Instead use an API (XML-RPC, REST) to interact with other sites if needed.
Loading history...
27
				filter_input( INPUT_POST, 'blog_id', FILTER_SANITIZE_NUMBER_INT )
28
			);
29
30
			$args = array(
31
				'post_status'    => get_post_stati( [ 'internal' => '' ] ),
32
				'posts_per_page' => 10,
33
			);
34
35
			if ( filter_has_var( INPUT_POST, 'post_type' ) ) {
36
				$args['post_type'] = sanitize_text_field(
37
					filter_input( INPUT_POST, 'post_type' )
38
				);
39
			}
40
41
			if ( filter_has_var( INPUT_POST, 's' ) ) {
42
				$args['s'] = sanitize_text_field(
43
					filter_input( INPUT_POST, 's' )
44
				);
45
			}
46
47
			/**
48
			 * Overrides the query-args for the suggest fields in the MetaBox
49
			 * @since 0.9.9
50
			 *
51
			 * @param array $args
52
			 */
53
			$args = (array) apply_filters( 'msls_meta_box_suggest_args', $args );
54
55
			$my_query = new \WP_Query( $args );
56
			while ( $my_query->have_posts() ) {
57
				$my_query->the_post();
58
59
				/**
60
				 * Manipulates the WP_Post object before using it
61
				 * @since 0.9.9
62
				 *
63
				 * @param \WP_Post $post
64
				 */
65
				$my_query->post = apply_filters( 'msls_meta_box_suggest_post', $my_query->post );
66
67
				if ( is_object( $my_query->post ) ) {
68
					$json->add( get_the_ID(), get_the_title() );
69
				}
70
			}
71
			wp_reset_postdata();
72
			restore_current_blog();
73
		}
74
		wp_die( $json->encode() );
75
	}
76
77
	/**
78
	 * Init
79
	 *
80
	 * @codeCoverageIgnore
81
	 *
82
	 * @return MslsMetaBox
83
	 */
84
	public static function init() {
85
		$options    = MslsOptions::instance();
86
		$collection = MslsBlogCollection::instance();
87
		$obj        = new static( $options, $collection );
88
89
		if ( ! $options->is_excluded() ) {
90
			add_action( 'add_meta_boxes', [ $obj, 'add' ] );
91
			add_action( 'save_post', [ $obj, 'set' ] );
92
			add_action( 'trashed_post', [ $obj, 'delete' ] );
93
		}
94
95
		return $obj;
96
	}
97
98
	/**
99
	 * Add
100
	 */
101
	public function add() {
102
		foreach ( MslsPostType::instance()->get() as $post_type ) {
103
			add_meta_box(
104
				'msls',
105
				__( 'Multisite Language Switcher', 'multisite-language-switcher' ),
106
				[
107
					$this,
108
					(
109
					MslsOptions::instance()->activate_autocomplete ?
110
						'render_input' :
111
						'render_select'
112
					),
113
				],
114
				$post_type,
115
				'side',
116
				'high'
117
			);
118
		}
119
	}
120
121
	/**
122
	 * Render the classic select-box
123
	 * @uses selected
124
	 */
125
	public function render_select() {
126
		$blogs = $this->collection->get();
127
		if ( $blogs ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $blogs of type lloc\Msls\MslsBlog[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
128
			global $post;
129
130
			$type   = get_post_type( $post->ID );
131
			$mydata = new MslsOptionsPost( $post->ID );
132
133
			$this->maybe_set_linked_post( $mydata );
134
135
			$temp   = $post;
136
137
			wp_nonce_field( MSLS_PLUGIN_PATH, 'msls_noncename' );
138
139
			$lis = '';
140
141
			foreach ( $blogs as $blog ) {
142
				switch_to_blog( $blog->userblog_id );
0 ignored issues
show
introduced by
switch_to_blog is not something you should ever need to do in a VIP theme context. Instead use an API (XML-RPC, REST) to interact with other sites if needed.
Loading history...
143
144
				$language = $blog->get_language();
145
146
				$icon = MslsAdminIcon::create()
147
				                     ->set_language( $language )
148
				                     ->set_src( MslsOptions::instance()->get_flag_url( $language ) );
149
				if ( $mydata->has_value( $language ) ) {
150
					$icon->set_href( $mydata->$language );
151
				}
152
153
				$selects = '';
154
				$pto     = get_post_type_object( $type );
155
156
				if ( $pto->hierarchical ) {
157
					$args = array(
158
						'post_type'         => $type,
159
						'selected'          => $mydata->$language,
160
						'name'              => 'msls_input_' . $language,
161
						'show_option_none'  => ' ',
162
						'option_none_value' => 0,
163
						'sort_column'       => 'menu_order, post_title',
164
						'echo'              => 0,
165
					);
166
					/**
167
					 * Overrides the args for wp_dropdown_pages when using the HTML select in the MetaBox
168
					 * @since 1.0.5
169
					 *
170
					 * @param array $args
171
					 */
172
					$args = (array) apply_filters( 'msls_meta_box_render_select_hierarchical', $args );
173
174
					$selects .= wp_dropdown_pages( $args );
175
				} else {
176
					$options = '';
177
178
					$my_query = new \WP_Query(
179
						array(
180
							'post_type'      => $type,
181
							'post_status'    => get_post_stati( [ 'internal' => '' ] ),
182
							'orderby'        => 'title',
183
							'order'          => 'ASC',
184
							'posts_per_page' => - 1,
185
							'fields'         => 'ids',
186
						)
187
					);
188
189
					if ( $my_query->have_posts() ) {
190
						foreach ( $my_query->posts as $my_id ) {
191
							$options .= sprintf(
192
								'<option value="%s" %s>%s</option>',
193
								$my_id,
194
								selected( $my_id, $mydata->$language, false ),
195
								get_the_title( $my_id )
196
							);
197
						}
198
					}
199
					$selects .= sprintf(
200
						'<select name="msls_input_%s"><option value="0"></option>%s</select>',
201
						$language,
202
						$options
203
					);
204
				}
205
206
				$lis .= sprintf(
207
					'<li><label for="msls_input_%s">%s</label>%s</li>',
208
					$language,
209
					$icon,
210
					$selects
211
				);
212
213
				restore_current_blog();
214
			}
215
			printf(
216
				'<ul>%s</ul><input type="submit" class="button-secondary" value="%s"/>',
217
				$lis,
218
				__( 'Update', 'multisite-language-switcher' )
219
			);
220
			$post = $temp;
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
221
		} else {
222
			printf(
223
				'<p>%s</p>',
224
				__( 'You should define at least another blog in a different language in order to have some benefit from this plugin!', 'multisite-language-switcher' )
225
			);
226
		}
227
	}
228
229
	/**
230
	 * Render the suggest input-field
231
	 */
232
	public function render_input() {
233
		$blogs = $this->collection->get();
234
235
		if ( $blogs ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $blogs of type lloc\Msls\MslsBlog[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
236
			global $post;
237
238
			$post_type = get_post_type( $post->ID );
239
			$my_data   = new MslsOptionsPost( $post->ID );
240
241
			$this->maybe_set_linked_post( $my_data );
242
243
			$temp      = $post;
244
			$items     = '';
245
246
			wp_nonce_field( MSLS_PLUGIN_PATH, 'msls_noncename' );
247
248
			foreach ( $blogs as $blog ) {
249
				switch_to_blog( $blog->userblog_id );
0 ignored issues
show
introduced by
switch_to_blog is not something you should ever need to do in a VIP theme context. Instead use an API (XML-RPC, REST) to interact with other sites if needed.
Loading history...
250
251
				$language = $blog->get_language();
252
				$flag_url = MslsOptions::instance()->get_flag_url( $language );
253
				$icon     = MslsAdminIcon::create()->set_language( $language )->set_src( $flag_url );
254
255
				$value = $title = '';
256
257
				if ( $my_data->has_value( $language ) ) {
258
					$icon->set_href( $my_data->$language );
259
					$value = $my_data->$language;
260
					$title = get_the_title( $value );
261
				}
262
263
				$items .= sprintf(
264
					'<li>
265
					<label for="msls_title_%1$s">%2$s</label>
266
					<input type="hidden" id="msls_id_%1$s" name="msls_input_%3$s" value="%4$s"/>
267
					<input class="msls_title" id="msls_title_%1$s" name="msls_title_%1$s" type="text" value="%5$s"/>
268
					</li>',
269
					$blog->userblog_id,
270
					$icon,
271
					$language,
272
					$value,
273
					$title
274
				);
275
276
				restore_current_blog();
277
			}
278
279
			$input_button = sprintf(
280
				'<input type="submit" class="button-secondary clear" value="%s"/>',
281
				__( 'Update', 'multisite-language-switcher' )
282
			);
283
284
			/**
285
			 * Returns the input button, return an empty string if you'ld like to hide the button
286
			 * @since 1.0.2
287
			 *
288
			 * @param string $input_button
289
			 */
290
			$input_button = ( string ) apply_filters( 'msls_meta_box_render_input_button', $input_button );
0 ignored issues
show
introduced by
Cast statements must not contain whitespace; expected "(string)" but found "( string )"
Loading history...
291
292
			printf(
293
				'<ul>%s</ul>
294
				<input type="hidden" name="msls_post_type" id="msls_post_type" value="%s"/>
295
				<input type="hidden" name="msls_action" id="msls_action" value="suggest_posts"/>
296
				%s',
297
				$items,
298
				$post_type,
299
				$input_button
300
			);
301
302
			$post = $temp;
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
303
		} else {
304
			printf(
305
				'<p>%s</p>',
306
				__( 'You should define at least another blog in a different language in order to have some benefit from this plugin!', 'multisite-language-switcher' )
307
			);
308
		}
309
	}
310
311
	/**
312
	 * Set
313
	 *
314
	 * @param int $post_id
315
	 */
316
	public function set( $post_id ) {
317
		if ( $this->is_autosave( $post_id ) || ! $this->verify_nonce() ) {
318
			return;
319
		}
320
321
		$capability = (
322
		'page' == filter_input( INPUT_POST, 'post_type', FILTER_SANITIZE_STRING ) ?
323
			'edit_page' :
324
			'edit_post'
325
		);
326
327
		if ( ! current_user_can( $capability, $post_id ) ) {
328
			return;
329
		}
330
331
		$this->save( $post_id, MslsOptionsPost::class );
332
	}
333
334
	/**
335
	 * Sets the selected element in the data from the `$_GET` superglobal, if any.
336
	 * @param MslsOptionsPost $mydata
337
	 * @return MslsOptionsPost
338
	 */
339
	public function maybe_set_linked_post( MslsOptionsPost $mydata ) {
0 ignored issues
show
Coding Style introduced by
maybe_set_linked_post 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...
340
		if ( ! isset( $_GET['msls_id'], $_GET['msls_lang'] ) ) {
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
341
			return $mydata;
342
		}
343
344
		$origin_lang = trim( $_GET['msls_lang'] );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
345
346
		if ( isset( $mydata->{$origin_lang} ) ) {
347
			return $mydata;
348
		}
349
350
		$origin_post_id = (int) $_GET['msls_id'];
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
351
352
		$origin_blog_id = $this->collection->get_blog_id( $origin_lang );
353
354
		if ( null === $origin_blog_id ) {
355
			return $mydata;
356
		}
357
358
		switch_to_blog( $origin_blog_id );
0 ignored issues
show
introduced by
switch_to_blog is not something you should ever need to do in a VIP theme context. Instead use an API (XML-RPC, REST) to interact with other sites if needed.
Loading history...
359
		$origin_post = get_post( $origin_post_id );
360
		restore_current_blog();
361
362
		if ( ! $origin_post instanceof \WP_Post ) {
0 ignored issues
show
Bug introduced by
The class WP_Post does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
363
			return $mydata;
364
		}
365
366
		$mydata->{$origin_lang} = $origin_post_id;
367
368
		return $mydata;
369
	}
370
}
371