1 <?php
2 /**
3 * UIX Core
4 *
5 * @package ui
6 * @author David Cramer
7 * @license GPL-2.0+
8 * @link
9 * @copyright 2016 David Cramer
10 */
11 namespace uix\ui;
12
13 /**
14 * Core UIX abstract class.
15 *
16 * @package uix\ui
17 * @author David Cramer
18 */
19 abstract class uix{
20
21 /**
22 * The type of UI object
23 *
24 * @since 1.0.0
25 * @access public
26 * @var string
27 */
28 public $type = 'uix';
29
30 /**
31 * Config Structure of object
32 *
33 * @since 1.0.0
34 * @access public
35 * @var array
36 */
37 public $struct = array();
38
39 /**
40 * Set this object type assets
41 *
42 * @since 1.0.0
43 * @access public
44 * @var array
45 */
46 public $assets = array(
47 'script' => array(),
48 'style' => array()
49 );
50
51 /**
52 * object slug
53 * @access public
54 * @since 1.0.0
55 *
56 * @var string
57 */
58 public $slug;
59
60 /**
61 * array of child objects
62 *
63 * @since 1.0.0
64 * @access public
65 * @var array
66 */
67 public $child = array();
68
69 /**
70 * Objects parent
71 *
72 * @since 1.0.0
73 * @access public
74 * @var object/uix
75 */
76 public $parent;
77
78 /**
79 * List of attributes to apply to the wrapper element
80 *
81 * @since 1.0.0
82 * @access public
83 * @var array
84 */
85 public $attributes = array();
86
87 /**
88 * Base URL of this class
89 *
90 * @since 1.0.0
91 * @access protected
92 * @var string
93 */
94 protected $url;
95
96 /**
97 * List of core object scripts ( common scripts )
98 *
99 * @since 1.0.0
100 * @access protected
101 * @var array
102 */
103 protected $scripts = array();
104
105 /**
106 * List of core object styles ( common styles )
107 *
108 * @since 1.0.0
109 * @access protected
110 * @var array
111 */
112 protected $styles = array();
113
114 /**
115 * UIX constructor
116 *
117 * @since 1.0.0
118 * @access protected
119 * @param string $slug Object slug
120 * @param array $object Objects structure array
121 * @param uix $parent Parent UIX Object
122 */
123 protected function __construct( $slug, $object, $parent = null ) {
124
125 // set the slug
126 $this->slug = $slug;
127 // set the object
128 $this->struct = $object;
129 // set parent if given
130 $this->parent = $parent;
131 // Set the root URL for this plugin.
132 $this->set_url();
133 // do setup
134 $this->setup();
135 // Set required assets
136 $this->set_assets();
137 // start internal actions to allow for automating post init
138 $this->actions();
139
140 }
141
142 /**
143 * Autoload Children - Checks structure for nested structures
144 *
145 * @since 1.0.0
146 * @access public
147 */
148 public function setup(){
149
150 foreach ( $this->struct as $struct_key=>$sub_struct ){
151 if( is_array( $sub_struct ) && uix()->get_register_callback( $struct_key ) )
152 $this->process_child( $struct_key );
153 }
154 }
155
156
157 /**
158 * process type key child
159 *
160 * @since 1.0.0
161 * @access public
162 */
163 public function process_child( $type ){
164
165 if( isset( $this->struct[ $type ]['id'] ) ){
166 $this->{$type}( $this->struct[ $type ]['id'], $this->struct[ $type ] );
167 }else{
168
169 $this->process_children( $type );
170 }
171
172 }
173
174
175 /**
176 * Process all children under type key
177 *
178 * @since 1.0.0
179 * @access public
180 */
181 public function process_children( $type ){
182 $this->struct[ $type ] = array_filter( $this->struct[ $type ], 'is_array' );
183 foreach( $this->struct[ $type ] as $sub_slug => $sub_structure ){
184 if( !empty( $sub_structure['id'] ) )
185 $sub_slug = $sub_structure['id'];
186
187 $this->{$type}($sub_slug, $sub_structure);
188 }
189
190 }
191
192 /**
193 * All objects loaded - application method for finishing off loading objects
194 *
195 * @since 1.0.0
196 * @access public
197 */
198 public function init(){}
199
200 /**
201 * setup actions and hooks - ovveride to add specific hooks. use parent::actions() to keep admin head
202 *
203 * @since 1.0.0
204 * @access protected
205 */
206 protected function actions() {
207
208 // init uix after loaded
209 add_action( 'init', array( $this, 'init' ) );
210
211 // set location
212 $location = 'wp_print_styles';
213
214 if( is_admin() )
215 $location = 'admin_enqueue_scripts';
216
217 // init UIX headers
218 add_action( $location, array( $this, 'enqueue_core' ) );
219
220 }
221
222 /**
223 * Define core UIX styles - override to register core ( common styles for uix type )
224 *
225 * @since 1.0.0
226 * @access public
227 */
228 public function set_assets() {
229
230
231 if( !empty( $this->struct['style'] ) )
232 $this->assets['style'] = array_merge( $this->assets['style'], $this->struct['style'] );
233
234 if( !empty( $this->struct['script'] ) )
235 $this->assets['script'] = array_merge( $this->assets['script'], $this->struct['script'] );
236
237
238 }
239
240
241 /**
242 * uix object id
243 *
244 * @since 1.0.0
245 * @access public
246 * @return string The object ID
247 */
248 public function id(){
249 $id = 'uix-' . $this->slug;
250 if( !empty( $this->parent ) )
251 $id = $this->parent->id() . '-' . $this->slug;
252
253 return $id;
254 }
255
256
257 /**
258 * Register the UIX objects
259 *
260 * @since 1.0.0
261 * @access public
262 * @param string $slug Object slug
263 * @param array $object object structure array
264 * @return object|\uix object instance
265 */
266 public static function register( $slug, $object, $parent = null ) {
267 // get the current instance
268 $caller = get_called_class();
269 return new $caller( $slug, $object, $parent );
270 }
271
272
273 /**
274 * Magic caller for adding child objects
275 *
276 * @since 1.0.0
277 * @access public
278 * @param string $type Type of object to attempt to create
279 * @param array $args arguments for the caller
280 * @return UIX|null
281 */
282 public function __call( $type, $args ){
283 $init = uix()->get_register_callback( $type );
284 $child = null;
285 if( null !== $init ){
286 $this->sanitize_slug( $args[0] );
287 $args[] = $this;
288 $child = call_user_func_array( $init, $args );
289 if( null !== $child ){
290 $this->child[ $args[0] ] = $child;
291 }
292 }
293 return $child;
294 }
295
296 /**
297 * Create a slug for the object
298 *
299 * @since 1.0.0
300 * @param string $slug The slug to be checked and created
301 * @access private
302 */
303 private function sanitize_slug( &$slug ) {
304 $slug = sanitize_key( $slug );
305 if( '' === $slug )
306 $slug = count( $this->child );
307 }
308
309 /**
310 * enqueue core assets
311 *
312 * @since 1.0.0
313 * @access public
314 */
315 public function enqueue_core() {
316
317 // attempt to get a config
318 if( !$this->is_active() ){ return; }
319
320 // register uix core asset
321 wp_register_script( 'uix', $this->url . 'assets/js/core' . UIX_ASSET_DEBUG . '.js' );
322 wp_register_style( 'uix', $this->url . 'assets/css/core' . UIX_ASSET_DEBUG . '.css' );
323
324 // set assets . methods at before this point can set assets, after this not so much.
325 $this->set_assets();
326
327 /**
328 * do object initilisation
329 *
330 * @param object current uix instance
331 */
332 do_action( 'uix_admin_enqueue_scripts' . $this->type, $this );
333
334 // push assets to ui manager
335 uix()->set_assets( $this->assets );
336
337 // done enqueuing - dpo inline or manual enqueue.
338 $this->enqueue_active_assets();
339 }
340
341 /**
342 * runs after assets have been enqueued
343 *
344 * @since 1.0.0
345 * @access protected
346 */
347 protected function enqueue_active_assets(){}
348
349 /**
350 * Detects the root of the plugin folder and sets the URL
351 *
352 * @since 1.0.0
353 * @access public
354 */
355 public function set_url(){
356
357 $plugins_url = plugins_url();
358 $this_url = trim( substr( trailingslashit( plugin_dir_url( __FILE__ ) ), strlen( $plugins_url ) ), '/' );
359
360 if( false !== strpos( $this_url, '/') ){
361 $url_path = explode('/', $this_url );
362 // generic 3 path depth: classes/namespace/ui|data
363 array_splice( $url_path, count( $url_path ) - 3 );
364 $this_url = implode( '/', $url_path );
365 }
366 // setup the base URL
367 $this->url = trailingslashit( $plugins_url . '/' . $this_url );
368 }
369
370
371 /**
372 * Determin if a UIX object should be active for this screen
373 * Intended to be ovveridden
374 * @since 1.0.0
375 * @access public
376 */
377 public function is_active(){
378 if( !empty( $this->parent ) )
379 return $this->parent->is_active();
380
381 return true; // base is_active will result in true;
382 }
383
384 /**
385 * Base color helper
386 *
387 * @since 1.0.0
388 * @access public
389 */
390 protected function base_color(){
391 if( empty( $this->struct['base_color'] ) ){
392 if( !empty( $this->parent ) )
393 return $this->parent->base_color();
394 }else{
395 return $this->struct['base_color'];
396 }
397
398 return '#D84315';
399
400 }
401
402 /**
403 * Sets the wrappers attributes
404 *
405 * @since 1.0.0
406 * @access public
407 */
408 public function set_attributes(){
409
410 if( empty( $this->attributes[ 'id' ] ) )
411 $this->attributes[ 'id' ] = $this->id();
412
413 if( !empty( $this->struct['attributes'] ) )
414 $this->attributes = array_merge( $this->attributes, $this->struct['attributes'] );
415
416 }
417
418
419 /**
420 * Build Attributes for the input control
421 *
422 * @since 1.0.0
423 * @access public
424 * @return string Attributes string for applying to an element
425 */
426 public function build_attributes() {
427 // setup attributes
428 $this->set_attributes();
429
430 $attributes = array();
431 foreach( $this->attributes as $att => $value)
432 $attributes[] = sprintf( '%s="%s"', esc_html( $att ), esc_attr( $value ) );
433
434 return implode( ' ', $attributes );
435 }
436
437 /**
438 * Render the UIX object
439 *
440 * @since 1.0.0
441 * @access public
442 * @return string HTML of rendered object
443 */
444 abstract public function render();
445
446 /**
447 * Render the child objects
448 *
449 * @since 1.0.0
450 * @access public
451 * @return string|null
452 */
453 public function render_children(){
454 $output = null;
455 foreach ($this->child as $child)
456 $output .= $child->render();
457
458 return $output;
459 }
460
461
462 }