Completed
Pull Request — master (#107)
by Luca
04:57
created

MslsMetaBox::maybe_set_linked_post()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 31
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 17
nc 5
nop 1
dl 0
loc 31
rs 8.439
c 0
b 0
f 0
1
<?php
2
/**
3
 * MslsMetaBox
4
 * @author Dennis Ploetner <[email protected]>
5
 * @since 0.9.8
6
 */
7
8
/**
9
 * Meta box for the edit mode of the (custom) post types
10
 * @package Msls
11
 */
12
class MslsMetaBox extends MslsMain {
13
14
	/**
15
	 * Suggest
16
	 *
17
	 * Echo a JSON-ified array of posts of the given post-type and
18
	 * the requested search-term and then die silently
19
	 */
20
	public static function suggest() {
21
		$json = new MslsJson;
22
23
		if ( filter_has_var( INPUT_POST, 'blog_id' ) ) {
24
			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...
25
				filter_input( INPUT_POST, 'blog_id', FILTER_SANITIZE_NUMBER_INT )
26
			);
27
28
			$args = array(
29
				'post_status'    => get_post_stati( array( 'internal' => '' ) ),
30
				'posts_per_page' => 10,
31
			);
32
33
			if ( filter_has_var( INPUT_POST, 'post_type' ) ) {
34
				$args['post_type'] = sanitize_text_field(
35
					filter_input( INPUT_POST, 'post_type' )
36
				);
37
			}
38
39
			if ( filter_has_var( INPUT_POST, 's' ) ) {
40
				$args['s'] = sanitize_text_field(
41
					filter_input( INPUT_POST, 's' )
42
				);
43
			}
44
45
			/**
46
			 * Overrides the query-args for the suggest fields in the MetaBox
47
			 * @since 0.9.9
48
			 *
49
			 * @param array $args
50
			 */
51
			$args = (array) apply_filters( 'msls_meta_box_suggest_args', $args );
52
53
			$my_query = new WP_Query( $args );
54
			while ( $my_query->have_posts() ) {
55
				$my_query->the_post();
56
57
				/**
58
				 * Manipulates the WP_Post object before using it
59
				 * @since 0.9.9
60
				 *
61
				 * @param WP_Post $post
62
				 */
63
				$my_query->post = apply_filters( 'msls_meta_box_suggest_post', $my_query->post );
64
65
				if ( is_object( $my_query->post ) ) {
66
					$json->add( get_the_ID(), get_the_title() );
67
				}
68
			}
69
			wp_reset_postdata();
70
			restore_current_blog();
71
		}
72
		wp_die( $json->encode() );
73
	}
74
75
	/**
76
	 * Init
77
	 * @return MslsMetaBox
78
	 */
79
	public static function init() {
80
		$obj = new self();
81
		if ( ! MslsOptions::instance()->is_excluded() ) {
82
			add_action( 'add_meta_boxes', array( $obj, 'add' ) );
83
			add_action( 'save_post', array( $obj, 'set' ) );
84
			add_action( 'trashed_post', array( $obj, 'delete' ) );
85
		}
86
87
		return $obj;
88
	}
89
90
	/**
91
	 * Add
92
	 */
93
	public function add() {
94
		foreach ( MslsPostType::instance()->get() as $post_type ) {
95
			add_meta_box(
96
				'msls',
97
				__( 'Multisite Language Switcher', 'multisite-language-switcher' ),
98
				array(
99
					$this,
100
					(
101
					MslsOptions::instance()->activate_autocomplete ?
102
						'render_input' :
103
						'render_select'
104
					),
105
				),
106
				$post_type,
107
				'side',
108
				'high'
109
			);
110
		}
111
	}
112
113
	/**
114
	 * Render the classic select-box
115
	 * @uses selected
116
	 */
117
	public function render_select() {
118
		$blogs           = MslsBlogCollection::instance()->get();
119
		if ( $blogs ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $blogs of type 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...
120
			global $post;
121
122
			$type   = get_post_type( $post->ID );
123
			$mydata = new MslsOptionsPost( $post->ID );
124
125
			$this->maybe_set_linked_post( $mydata );
126
127
			$temp   = $post;
128
129
			wp_nonce_field( MSLS_PLUGIN_PATH, 'msls_noncename' );
130
131
			$lis = '';
132
133
			foreach ( $blogs as $blog ) {
134
				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...
135
136
				$language = $blog->get_language();
137
138
				$icon = MslsAdminIcon::create()
139
				                     ->set_language( $language )
140
				                     ->set_src( MslsOptions::instance()->get_flag_url( $language ) );
141
				if ( $mydata->has_value( $language ) ) {
142
					$icon->set_href( $mydata->$language );
143
				}
144
145
				$selects = '';
146
				$pto     = get_post_type_object( $type );
147
148
				if ( $pto->hierarchical ) {
149
					$args = array(
150
						'post_type'         => $type,
151
						'selected'          => $mydata->$language,
152
						'name'              => 'msls_input_' . $language,
153
						'show_option_none'  => ' ',
154
						'option_none_value' => 0,
155
						'sort_column'       => 'menu_order, post_title',
156
						'echo'              => 0,
157
					);
158
					/**
159
					 * Overrides the args for wp_dropdown_pages when using the HTML select in the MetaBox
160
					 * @since 1.0.5
161
					 *
162
					 * @param array $args
163
					 */
164
					$args = (array) apply_filters( 'msls_meta_box_render_select_hierarchical', $args );
165
166
					$selects .= wp_dropdown_pages( $args );
167
				} else {
168
					$options = '';
169
170
					$my_query = new WP_Query(
171
						array(
172
							'post_type'      => $type,
173
							'post_status'    => get_post_stati( array( 'internal' => '' ) ),
174
							'orderby'        => 'title',
175
							'order'          => 'ASC',
176
							'posts_per_page' => - 1,
177
							'fields'         => 'ids',
178
						)
179
					);
180
181
					if ( $my_query->have_posts() ) {
182
						foreach ( $my_query->posts as $my_id ) {
183
							$options .= sprintf(
184
								'<option value="%s" %s>%s</option>',
185
								$my_id,
186
								selected( $my_id, $mydata->$language, false ),
187
								get_the_title( $my_id )
188
							);
189
						}
190
					}
191
					$selects .= sprintf(
192
						'<select name="msls_input_%s"><option value="0"></option>%s</select>',
193
						$language,
194
						$options
195
					);
196
				}
197
198
				$lis .= sprintf(
199
					'<li><label for="msls_input_%s">%s</label>%s</li>',
200
					$language,
201
					$icon,
202
					$selects
203
				);
204
205
				restore_current_blog();
206
			}
207
			printf(
208
				'<ul>%s</ul><input type="submit" class="button-secondary" value="%s"/>',
209
				$lis,
210
				__( 'Update', 'multisite-language-switcher' )
211
			);
212
			$post = $temp;
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
213
		} else {
214
			printf(
215
				'<p>%s</p>',
216
				__( 'You should define at least another blog in a different language in order to have some benefit from this plugin!', 'multisite-language-switcher' )
217
			);
218
		}
219
	}
220
221
	/**
222
	 * Render the suggest input-field
223
	 */
224
	public function render_input() {
225
		$blogs = MslsBlogCollection::instance()->get();
226
227
		if ( $blogs ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $blogs of type 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...
228
			global $post;
229
230
			$post_type = get_post_type( $post->ID );
231
			$my_data   = new MslsOptionsPost( $post->ID );
232
			$temp      = $post;
233
			$items     = '';
234
235
			wp_nonce_field( MSLS_PLUGIN_PATH, 'msls_noncename' );
236
237
			foreach ( $blogs as $blog ) {
238
				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...
239
240
				$language = $blog->get_language();
241
				$flag_url = MslsOptions::instance()->get_flag_url( $language );
242
				$icon     = MslsAdminIcon::create()->set_language( $language )->set_src( $flag_url );
243
244
				$value = $title = '';
245
246
				if ( $my_data->has_value( $language ) ) {
247
					$icon->set_href( $my_data->$language );
248
					$value = $my_data->$language;
249
					$title = get_the_title( $value );
250
				}
251
252
				$items .= sprintf(
253
					'<li>
254
					<label for="msls_title_%1$s">%2$s</label>
255
					<input type="hidden" id="msls_id_%1$s" name="msls_input_%3$s" value="%4$s"/>
256
					<input class="msls_title" id="msls_title_%1$s" name="msls_title_%1$s" type="text" value="%5$s"/>
257
					</li>',
258
					$blog->userblog_id,
259
					$icon,
260
					$language,
261
					$value,
262
					$title
263
				);
264
265
				restore_current_blog();
266
			}
267
268
			$input_button = sprintf(
269
				'<input type="submit" class="button-secondary clear" value="%s"/>',
270
				__( 'Update', 'multisite-language-switcher' )
271
			);
272
273
			/**
274
			 * Returns the input button, return an empty string if you'ld like to hide the button
275
			 * @since 1.0.2
276
			 *
277
			 * @param string $input_button
278
			 */
279
			$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...
280
281
			printf(
282
				'<ul>%s</ul>
283
				<input type="hidden" name="msls_post_type" id="msls_post_type" value="%s"/>
284
				<input type="hidden" name="msls_action" id="msls_action" value="suggest_posts"/>
285
				%s',
286
				$items,
287
				$post_type,
288
				$input_button
289
			);
290
291
			$post = $temp;
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
292
		} else {
293
			printf(
294
				'<p>%s</p>',
295
				__( 'You should define at least another blog in a different language in order to have some benefit from this plugin!', 'multisite-language-switcher' )
296
			);
297
		}
298
	}
299
300
	/**
301
	 * Set
302
	 *
303
	 * @param int $post_id
304
	 */
305
	public function set( $post_id ) {
306
		if ( $this->is_autosave( $post_id ) || ! $this->verify_nonce() ) {
307
			return;
308
		}
309
310
		$capability = (
311
		'page' == filter_input( INPUT_POST, 'post_type', FILTER_SANITIZE_STRING ) ?
312
			'edit_page' :
313
			'edit_post'
314
		);
315
316
		if ( ! current_user_can( $capability, $post_id ) ) {
317
			return;
318
		}
319
320
		$this->save( $post_id, 'MslsOptionsPost' );
321
	}
322
323
	/**
324
	 * Sets the selected element in the data from the `$_GET` superglobal, if any.
325
	 * @param MslsOptionsPost $mydata
326
	 * @return MslsOptionsPost
327
	 */
328
	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...
329
		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...
330
			return $mydata;
331
		}
332
333
		$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...
334
335
		if ( isset( $mydata->{$origin_lang} ) ) {
336
			return $mydata;
337
		}
338
339
		$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...
340
341
		$origin_blog_id = MslsBlogCollection::instance()->get_blog_id( $origin_lang );
342
343
		if ( null === $origin_blog_id ) {
344
			return $mydata;
345
		}
346
347
		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...
348
		$origin_post = get_post( $origin_post_id );
349
		restore_current_blog();
350
351
		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...
352
			return $mydata;
353
		}
354
355
		$mydata->{$origin_lang} = $origin_post_id;
356
357
		return $mydata;
358
	}
359
}
360