Completed
Push — develop ( 35270b...3f50dc )
by David
01:42
created

repeat::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 1
cp 0
crap 2
rs 10
1
<?php
2
/**
3
 * UIX repeat
4
 *
5
 * @package   ui
6
 * @author    David Cramer
7
 * @license   GPL-2.0+
8
 * @link
9
 * @copyright 2016 David Cramer
10
 */
11
12
namespace uix\ui;
13
14
/**
15
 * A repetable container for repeatable areas.
16
 *
17
 * @since 1.0.0
18
 * @see   \uix\uix
19
 */
20
class repeat extends panel {
21
22
	/**
23
	 * The type of object
24
	 *
25
	 * @since  1.0.0
26
	 * @access public
27
	 * @var      string
28
	 */
29
	public $type = 'repeat';
30
31
	/**
32
	 * The instance of this object
33
	 *
34
	 * @since  1.0.0
35
	 * @access public
36
	 * @var      int|string
37
	 */
38
	public $instance = 0;
39
40
	/**
41
	 * total instances of this object
42
	 *
43
	 * @since  1.0.0
44
	 * @access public
45
	 * @var      int|string
46
	 */
47
	public $instances = 0;
48
49
	/**
50
	 * The templates to render in the footer
51
	 *
52
	 * @since  1.0.0
53
	 * @access public
54
	 * @var      string
55
	 */
56
	public $templates = null;
57
58
	/**
59
	 * Button Label
60
	 *
61
	 * @since  1.0.0
62
	 * @access public
63
	 * @var      string
64
	 */
65
	public $button_label;
66
67
68
	/**
69
	 * Setup and prepare data.
70
	 *
71
	 * @since  1.0.0
72
	 * @access public
73
	 */
74
	public function setup() {
75
		parent::setup();
76
	}
77
	/**
78
	 * All objects loaded - application method for finishing off loading objects
79
	 *
80
	 * @since  1.0.0
81
	 * @access public
82
	 */
83
	public function init() {
84
		$this->prepare_data();
85
	}
86
	/**
87
	 * Define core repeat styles ans scripts
88
	 *
89
	 * @since  1.0.0
90
	 * @access public
91
	 */
92
	public function set_assets() {
93
94
		$this->assets['script'][ $this->type ] = $this->url . 'assets/js/' . $this->type . UIX_ASSET_DEBUG . '.js';
95
		$this->assets['style'][ $this->type ]  = $this->url . 'assets/css/' . $this->type . UIX_ASSET_DEBUG . '.css';
96
97
		parent::set_assets();
98
99
	}
100
101
	/**
102
	 * Prepares Data for extraction and saving
103
	 *
104
	 * @since  1.0.0
105
	 * @see    \uix\uix
106
	 * @access public
107
	 */
108
	public function prepare_data() {
109
		$submit_data = uix()->request_vars( 'post' );
110
		if ( ! empty( $submit_data ) ) {
111
112
			$parent = $this->parent;
0 ignored issues
show
Unused Code introduced by
$parent is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
113
114
			$id = $this->id();
0 ignored issues
show
Unused Code introduced by
$id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
115
			$instances = array_filter( array_keys( $submit_data ), [
116
				$this,
117
				'compare_var_key',
118
			] );
119
120
			$instances = array_map( [
121
				$this,
122
				'build_instance_count',
123
			], $instances );
124
			$instances = array_unique( $instances );
125
			$this->push_instance_setup( $instances );
126
127
		}
128
		$this->instance = 0; // reset instance;
129
	}
130
131
	/**
132
	 * Sets the data for all children
133
	 *
134
	 * @since  1.0.0
135
	 * @access public
136
	 */
137
	public function set_data( $data ) {
138
139
		$this->instance = 0;
140
141
		foreach ( (array) $data as $instance => $instance_data ) {
142
			// Check that the data is a repeat item.
143
			if ( is_int( $instance ) ) {
144
				foreach ( $this->child as $child ) {
145
					$child->set_data( $instance_data );
146
				}
147
				$this->instance ++;
148
			}
149
150
		}
151
		$this->instances = $this->instance;
152
		$this->instance  = 0;
153
154
	}
155
156
	/**
157
	 * Render the complete section
158
	 *
159
	 * @since  1.0.0
160
	 * @access public
161
	 * @return string|null HTML of rendered repeatable
162
	 */
163
	public function render() {
164
165
		add_action( 'admin_footer', [
166
			$this,
167
			'render_repeatable_script',
168
		] );
169
		add_action( 'wp_footer', [ $this, 'render_repeatable_script' ] );
170
171
		$output = '<div data-instance="{{json this}}" data-uix-template="' . esc_attr( $this->id() ) . '" ' . $this->build_attributes() . '>';
172
		$output .= $this->render_instances();
173
		$output .= '</div>';
174
175
		$output .= $this->render_repeatable_more();
176
177
		return $output;
178
	}
179
180
	/**
181
	 * uix object id
182
	 *
183
	 * @since  1.0.0
184
	 * @access public
185
	 * @return string The object ID
186
	 */
187
	public function id() {
188
189
		return parent::id() . '-' . $this->instance;
190
	}
191
192
	/**
193
	 * Render each instance from data
194
	 *
195
	 * @since  1.0.0
196
	 * @access private
197
	 * @return string|null HTML of rendered instances
198
	 */
199
	private function render_instances() {
200
		$data   = $this->get_data();
201
		$output = null;
202
		$data   = array_filter( $data );
203
204
		foreach ( (array) $data as $instance_id ) {
205
			if ( ! isset( $this->struct['active'] ) ) {
206
				$this->struct['active'] = 'true';
207
			}
208
209
			$output .= $this->render_repeatable();
210
211
			$this->instance ++;
212
213
		}
214
215
		return $output;
216
	}
217
218
	/**
219
	 * Sets the data for all children
220
	 *
221
	 * @since  1.0.0
222
	 * @access public
223
	 */
224
	public function get_data() {
225
226
		//if ( empty( $this->data ) ) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% 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...
227
			return $this->set_instance_data();
228
		//}
229
230
		return $this->data;
0 ignored issues
show
Unused Code introduced by
return $this->data; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
231
232
	}
233
234
	/**
235
	 * @return array
236
	 */
237
	public function set_instance_data() {
238
		$data           = [];
239
		$this->instance = 0;
240
		while ( $this->instance < $this->instances ) {
241
242
			if ( ! isset( $data[ $this->instance ] ) ) {
243
				$data[ $this->instance ] = [];
244
			}
245
246
			if ( null !== $this->get_instance_data() ) {
247
				$data[ $this->instance ] += $this->get_instance_data();
248
			}
249
250
			$this->instance ++;
251
		}
252
		$this->instance = 0;
253
254
		return $data;
255
	}
256
257
	/**
258
	 * @return array
259
	 */
260
	public function get_instance_data() {
261
		$data = [];
262
		foreach ( $this->child as $child ) {
263
			if ( method_exists( $child, 'get_data' ) ) {
264
				if ( null !== $child->get_data() ) {
265
					$data += $child->get_data();
266
				}
267
			}
268
		}
269
270
		return $data;
271
	}
272
273
	/**
274
	 * Render the internal section
275
	 *
276
	 * @since  1.0.0
277
	 * @access public
278
	 * @param bool $reset Flag to indicate reset repeatbles.
279
	 * @return string|null HTML of rendered object
280
	 */
281
	public function render_repeatable( $reset = false ) {
282
283
		$output = '<div class="uix-repeat">';
284
		$output .= $this->render_template();
285
		if ( ! empty( $this->child ) ) {
286
			$output .= $this->render_children( $reset );
287
		}
288
289
		$output .= '<button type="button" class="button button-small uix-remover"><span class="dashicons dashicons-no"></span></button> </div>';
290
291
		return $output;
292
293
	}
294
295
	/**
296
	 * Render the child objects
297
	 *
298
	 * @since  1.0.0
299
	 * @access public
300
	 * @param bool $reset Flag to reset the instances of child repeatables.
301
	 * @return string|null
302
	 */
303
	public function render_children( $reset = false ) {
304
		$output = null;
305
		foreach ( $this->child as $child ) {
306
			if ( true === $reset && 'repeat' === $child->type ) {
307
				$child->instances = 0;
308
			}
309
			if( 'repeat' === $child->type && $reset === false ){
310
				$id = 1;
0 ignored issues
show
Unused Code introduced by
$id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
311
			}
312
			$output .= $child->render();
313
		}
314
315
		return $output;
316
	}
317
318
	/**
319
	 * Render the add more button and template
320
	 *
321
	 * @since  1.0.0
322
	 * @access public
323
	 * @return string|null HTML of rendered object
324
	 */
325
	public function render_repeatable_more() {
326
327
		$label = __( 'Add Another', 'uix' );
328
329
		if ( ! empty( $this->struct['label'] ) ) {
330
			$label = $this->struct['label'];
331
		}
332
333
		$this->instance  = '{{_inst_}}';
334
		$this->templates = $this->render_repeatable( true );
335
		$this->instance  = 0;
336
		$output          = '<div class="repeatable-footer"><button type="button" class="button" data-uix-repeat="' . esc_attr( $this->id() ) . '">' . esc_html( $label ) . '</button></div>';
337
338
		return $output;
339
340
	}
341
342
	/**
343
	 * Render the script footer template
344
	 *
345
	 * @since  1.0.0
346
	 * @see    \uix\ui\uix
347
	 * @access public
348
	 */
349
	public function render_repeatable_script() {
350
		$output = null;
351
		if ( ! empty( $this->templates ) ) {
352
			$output .= '<script type="text/html" id="' . esc_attr( $this->id() ) . '-tmpl">';
353
			$output .= $this->templates;
354
			$output .= '</script>';
355
		}
356
357
		echo $output;
358
	}
359
360
	/**
361
	 * Enqueues specific tabs assets for the active pages
362
	 *
363
	 * @since  1.0.0
364
	 * @access protected
365
	 */
366
	protected function set_active_styles() {
367
368
		parent::set_active_styles();
369
		$style = '#' . $this->id() . ' .uix-repeat{ box-shadow: 1px 0 0 ' . $this->base_color() . ' inset, -37px 0 0 #f5f5f5 inset, -38px 0 0 #ddd inset, 0 2px 3px rgba(0, 0, 0, 0.05); };';
370
		uix_share()->set_active_styles( $style );
371
	}
372
373
	/**
374
	 * Compares the key of submitted fields to match instances
375
	 *
376
	 * @since  1.0.0
377
	 * @see    \uix\uix
378
	 * @access private
379
	 *
380
	 * @param string $key Key to compare
381
	 *
382
	 * @return bool
383
	 */
384
	private function compare_var_key( $key ) {
385
		$id_parts = $this->id_base_parts();
386
		$compare  = implode( '-', $id_parts ) . '-';
387
		$current  = substr( $key, 0, strlen( $compare ) );
388
		$this_id = $this->id();
0 ignored issues
show
Unused Code introduced by
$this_id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
389
		return $current == $compare;
390
	}
391
392
	/**
393
	 * Breaks apart the ID to get the base parts without the instance number
394
	 *
395
	 * @access private
396
	 * @return array
397
	 */
398
	private function id_base_parts() {
399
		$id_parts = explode( '-', $this->id() );
400
		array_pop( $id_parts );
401
402
		return $id_parts;
403
	}
404
405
	/**
406
	 * Pushes the children to initilize setup in order to capture the instance
407
	 * data
408
	 *
409
	 * @access private
410
	 *
411
	 * @param $instances
412
	 */
413
	private function push_instance_setup( $instances ) {
414
415
		$this->instances = count( $instances );
416
		$this->instance = 0;
417
		while ( $this->instance < $this->instances ) {
418
			if ( ! isset( $this->data[ $this->instance ] ) ) {
419
				$this->data[ $this->instance ] = [];
420
			}
421
			$id = $this->id();
0 ignored issues
show
Unused Code introduced by
$id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
422
			foreach ( $this->child as $child ) {
423
				$child->setup();
424
				$this->data[ $this->instance ] += $child->get_data();
425
			}
426
			$this->instance++;
427
		}
428
	}
429
430
	/**
431
	 * Removes the instance number from the submission key
432
	 *
433
	 * @access private
434
	 *
435
	 * @param $key
436
	 *
437
	 * @return int
438
	 */
439
	private function build_instance_count( $key ) {
440
		$key_parts = explode( '-', $key );
441
		$id_parts  = $this->id_base_parts();
442
443
		return (int) $key_parts[ count( $id_parts ) ];
444
	}
445
446
447
}
448