Passed
Push — master ( d94d90...6b2031 )
by Paul
02:54
created

MetaBox::validateUnknown()   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 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace GeminiLabs\Pollux;
4
5
use GeminiLabs\Pollux\Application;
6
use GeminiLabs\Pollux\Component;
7
use RecursiveArrayIterator;
8
use RecursiveIteratorIterator;
9
10
class MetaBox extends Component
11
{
12
	const CONDITIONS = [
13
		'class_exists', 'defined', 'function_exists', 'hook', 'is_front_page', 'is_home',
14
		'is_page_template', 'is_plugin_active', 'is_plugin_inactive',
15
	];
16
17
	/**
18
	 * @var array
19
	 */
20
	public $metaboxes = [];
21
22
	/**
23
	 * {@inheritdoc}
24
	 */
25
	public function init()
26
	{
27
		$this->normalize();
28
29
		add_filter( 'rwmb_show',       [$this, 'isVisible'], 10, 2 );
30
		add_filter( 'rwmb_meta_boxes', [$this, 'register'] );
31
	}
32
33
	/**
34
	 * @return bool
35
	 * @filter rwmb_show
36
	 */
37
	public function isVisible( $bool, array $metabox )
38
	{
39
		if( defined( 'DOING_AJAX' )
40
			|| !isset( $metabox['condition'] )
41
			|| !$this->hasPostType( $metabox )) {
42
			return $bool;
43
		}
44
		return $this->verifyMetaBoxCondition( $metabox['condition'] );
45
	}
46
47
	/**
48
	 * @return array
49
	 * @filter rwmb_meta_boxes
50
	 */
51
	public function register()
52
	{
53
		if( current_user_can( 'switch_themes' )) {
54
			$this->addInstructions();
55
		}
56
		$metaboxes = func_num_args()
57
			? $this->toArray( func_get_arg(0) )
58
			: [];
59
		return array_merge( $metaboxes, $this->metaboxes );
60
	}
61
62
	/**
63
	 * @return bool
64
	 */
65
	public function verifyMetaBoxCondition( array $conditions )
66
	{
67
		array_walk( $conditions, function( &$value, $key ) {
68
			$method = $this->app->buildMethodName( $key, 'validate' );
69
			$value = method_exists( $this, $method )
70
				? $this->$method( $value )
71
				: $this->validateUnknown( $key, $value );
72
		});
73
		return !in_array( false, $conditions );
74
	}
75
76
	/**
77
	 * @return void
78
	 */
79
	protected function addInstructions()
80
	{
81
		if( !count( array_filter( $this->metaboxes, function( $metabox ) {
82
			return $this->isVisible( false, $metabox );
83
		})))return;
84
		$this->metaboxes[] = [
85
			'id' => 'infodiv',
86
			'post_types' => $this->getPostTypes(),
87
			'title' => __( 'How to use in your theme', 'pollux' ),
88
			'context' => 'side',
89
			'priority' => 'low',
90
			'fields' => [[
91
				'slug' => '',
92
				'std' => $this->generateInstructions(),
93
				'type' => 'custom_html',
94
			]],
95
		];
96
	}
97
98
	/**
99
	 * @return string
100
	 */
101
	protected function generateInstructions()
102
	{
103
		return array_reduce( $this->getInstructions(), function( $html, $metabox ) {
104
			$fields = array_reduce( array_column( $metabox['fields'], 'slug' ), function( $html, $slug ) use( $metabox ) {
105
				$hook = sprintf( 'pollux/%s/instruction', $this->getClassname() );
106
				return $html . apply_filters( $hook, "PostMeta::get('{$slug}');", $slug, $metabox['slug'] ) . PHP_EOL;
107
			});
108
			return $html . sprintf( '<p><strong>%s</strong></p><pre class="my-sites nav-tab-active misc-pub-section">%s</pre>',
109
				$metabox['title'],
110
				$fields
111
			);
112
		});
113
	}
114
115
	/**
116
	 * @return array
117
	 */
118
	protected function getInstructions()
119
	{
120
		return array_filter( $this->metaboxes, function( $metabox ) {
121
			return $this->verifyMetaBoxCondition( $metabox['condition'] )
122
				&& $this->hasPostType( $metabox );
123
		});
124
	}
125
126
	/**
127
	 * @return int
128
	 */
129
	protected function getPostId()
130
	{
131
		if( !( $postId = filter_input( INPUT_GET, 'post' ))) {
132
			$postId = filter_input( INPUT_POST, 'post_ID' );
133
		}
134
		return intval( $postId );
135
	}
136
137
	/**
138
	 * @return array
139
	 */
140
	protected function getPostTypes()
141
	{
142
		return array_unique( iterator_to_array(
143
			new RecursiveIteratorIterator(
144
				new RecursiveArrayIterator( array_column( $this->metaboxes, 'post_types' ))
145
			),
146
			false
147
		));
148
	}
149
150
	/**
151
	 * @return bool
152
	 */
153
	protected function hasPostType( array $metabox )
154
	{
155
		if( !isset( $metabox['post_types'] )) {
156
			return true;
157
		}
158
		return in_array( get_post_type( $this->getPostId() ), $metabox['post_types'] );
159
	}
160
161
	/**
162
	 * {@inheritdoc}
163
	 */
164 View Code Duplication
	protected function normalize()
165
	{
166
		foreach( $this->app->config['meta_boxes'] as $id => $metabox ) {
167
			$defaults = [
168
				'condition' => [],
169
				'fields' => [],
170
				'id' => $id,
171
				'post_types' => [],
172
				'slug' => $id,
173
			];
174
			$this->metaboxes[] = $this->setDependencies(
175
				$this->normalizeThis( $metabox, $defaults, $id )
176
			);
177
		}
178
	}
179
180
	/**
181
	 * @param mixed $conditions
182
	 * @return array
183
	 */
184
	protected function normalizeCondition( $conditions )
185
	{
186
		$conditions = $this->toArray( $conditions );
187
		if( count( array_filter( array_keys( $conditions ), 'is_string' )) == 0 ) {
188
			foreach( $conditions as $key ) {
189
				$conditions[str_replace( '!', '', $key )] = substr( $key, 0, 1 ) == '!' ? 0 : 1;
190
			}
191
			$conditions = array_filter( $conditions, function( $key ) {
192
				return !is_numeric( $key );
193
			}, ARRAY_FILTER_USE_KEY );
194
		}
195
		$hook = sprintf( 'pollux/%s/conditions', $this->getClassname() );
196
		return array_intersect_key(
197
			$conditions,
198
			array_flip( apply_filters( $hook, static::CONDITIONS ))
199
		);
200
	}
201
202
	/**
203
	 * @param string $id
0 ignored issues
show
Bug introduced by
There is no parameter named $id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
204
	 * @param string $parentId
205
	 * @return string
206
	 */
207
	protected function normalizeDepends( $depends, array $data, $parentId )
208
	{
209
		return is_string( $depends ) && !empty( $depends )
210
			? $this->normalizeId( $depends, $data, $parentId )
211
			: '';
212
	}
213
214
	/**
215
	 * @return array
216
	 */
217
	protected function normalizeFields( array $fields, array $data, $parentId )
218
	{
219
		return array_map( function( $id, $field ) use( $parentId ) {
220
			$defaults =  [
221
				'attributes' => [],
222
				// 'condition' => [],
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% 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...
223
				'depends' => '',
224
				'id' => $id,
225
				'field_name' => '',
226
				'slug' => $id,
227
			];
228
			return $this->normalizeThis( $field, $defaults, $parentId );
229
		}, array_keys( $fields ), $fields );
230
	}
231
232
	/**
233
	 * @param string $id
234
	 * @param string $parentId
235
	 * @return string
236
	 */
237
	protected function normalizeId( $id, array $data, $parentId )
238
	{
239
		return apply_filters( 'pollux/prefix', Application::PREFIX ) . $id;
240
	}
241
242
	/**
243
	 * @param mixed $types
244
	 * @return array
245
	 */
246
	protected function normalizePostTypes( $types )
247
	{
248
		return $this->toArray( $types );
249
	}
250
251
	/**
252
	 * @return array
253
	 */
254
	protected function setDependencies( array $metabox )
255
	{
256
		$fields = &$metabox['fields'];
257
		$depends = array_column( $fields, 'depends' );
258
		array_walk( $depends, function( $value, $index ) use( &$fields ) {
259
			if( empty( $value ))return;
260
			$fields[$index]['attributes']['data-depends'] = $value;
261
		});
262
		return $metabox;
263
	}
264
265
	/**
266
	 * @param string $value
267
	 * @return bool
268
	 */
269
	protected function validateClassExists( $value )
270
	{
271
		return class_exists( $value );
272
	}
273
274
	/**
275
	 * @param string $value
276
	 * @return bool
277
	 */
278
	protected function validateDefined( $value )
279
	{
280
		return defined( $value );
281
	}
282
283
	/**
284
	 * @param string $value
285
	 * @return bool
286
	 */
287
	protected function validateFunctionExists( $value )
288
	{
289
		return function_exists( $value );
290
	}
291
292
	/**
293
	 * @param string $value
294
	 * @return bool
295
	 */
296
	protected function validateHook( $value )
297
	{
298
		return apply_filters( $value, true );
299
	}
300
301
	/**
302
	 * @param bool $value
303
	 * @return bool
304
	 */
305
	protected function validateIsFrontPage( $value )
306
	{
307
		return $value == ( $this->getPostId() == get_option( 'page_on_front' ));
308
	}
309
310
	/**
311
	 * @param bool $value
312
	 * @return bool
313
	 */
314
	protected function validateIsHome( $value )
315
	{
316
		return $value == ( $this->getPostId() == get_option( 'page_for_posts' ));
317
	}
318
319
	/**
320
	 * @param string $value
321
	 * @return bool
322
	 */
323
	protected function validateIsPageTemplate( $value )
324
	{
325
		return basename( get_page_template_slug( $this->getPostId() )) == $value;
326
	}
327
328
	/**
329
	 * @param string $value
330
	 * @return bool
331
	 */
332
	protected function validateIsPluginActive( $value )
333
	{
334
		return is_plugin_active( $value );
335
	}
336
337
	/**
338
	 * @param string $value
339
	 * @return bool
340
	 */
341
	protected function validateIsPluginInactive( $value )
342
	{
343
		return is_plugin_inactive( $value );
344
	}
345
346
	/**
347
	 * @param string $key
348
	 * @param mixed $value
349
	 * @return bool
350
	 */
351
	protected function validateUnknown( $key, $value )
352
	{
353
		return apply_filters( 'pollux/metabox/condition', true, $key, $value );
354
	}
355
}
356