TRUE, I_Proto::DI_MAIN => '__main', I_Proto::DI_CLASS => [], I_Proto::DI_DELEGATE => [], I_Proto::DI_FILTER => [], I_Proto::DI_METHOD => [], I_Proto::DI_OBSERVER => [], I_Proto::DI_METHOD_PROTO => [], I_Proto::DI_SIGNAL => [], I_Proto::DI_TO => [ 'string' => 'toString', 'array' => 'toArray' ] ]; protected $__initConfig = []; public function __construct(array $__options = []) { $__boot = [ I_Proto::PROP_DEFINE_DEFAULTS => [ I_Boot::ON_LOOKUP => function(array $c, $n, array $l) { array_walk($l, function($v, $p) use (&$c, $n) { $c[$p] = $this->Core_Proto_T_Boot_handleLookup($p, $n, $c) + [ I_Proto::DEFAULT_VALUE => $v ]; $value = &$c[$p][I_Proto::DEFAULT_VALUE]; if(isset($value) && is_array($value) && is_array($v) && in_array($p, ['class'])) // I_Object namespaces $value = $this->extend(TRUE, $v, $value); }); return $c; }, I_Boot::ON_INIT => function(array $c) { array_walk($c, function($s, $p) { $this->__initConfig[$p] = $s[I_Proto::DEFAULT_VALUE]; }); return $c; } ], I_Proto::PROP_DEFINE_ASP => [ I_Boot::ON_LOOKUP => function(array $c, $n, array $l) { $d = [ I_Proto::ASP_TYPE_DEF => [I_Proto::ASP_FN_PRFX_SET, I_Proto::ASP_FN_PRFX_RESTORE], I_Proto::ASP_TYPE_OBJ => [I_Proto::ASP_FN_PRFX_SET, I_Proto::ASP_FN_PRFX_RESTORE], I_Proto::ASP_TYPE_ARR => [I_Proto::ASP_FN_PRFX_SET, I_Proto::ASP_FN_PRFX_RESTORE, I_Proto::ASP_FN_PRFX_ADD, I_Proto::ASP_FN_PRFX_REMOVE, I_Proto::ASP_FN_PRFX_CLEAR], ]; array_walk($l, function($v, $p) use (&$c, $n, $d) { if(is_integer($p)) { $p = $v; $v = TRUE; } $c[$p] = $this->Core_Proto_T_Boot_handleLookup($p, $n, $c) + [ I_Proto::ASP_AVAIL => $a = is_string($u = is_bool($v) ? I_Proto::ASP_TYPE_DEF : $v) ? isset($d[$u]) ? $d[$u] : explode('|', $u) : $u, I_Proto::ASP_USE => !isset($a[0]) ? isset($d[$u]) ? $d[$u][0] : I_Proto::ASP_FN_PRFX_SET : $a[0], I_Proto::ASP_HANDLE => is_string($v) ? TRUE : $v ]; }); return $c; }, I_Boot::ON_COMPLETE => function(array $c) { array_walk($c, function(&$s, $p) { if(FALSE === $s[I_Boot::EXISTS] || FALSE === $s[I_Proto::ASP_HANDLE]) return; array_walk($s[I_Proto::ASP_AVAIL], function($a) use (&$s, $p) { $m = String::insert(I_Proto::TPL_ASP_FN_NAME, [ 'aspFnPrfx' => Inflector::camelize($a), 'propertyName' => Inflector::camelize($p)]); $s += [I_Proto::ASP_ACCESS_ALL.$a => $m]; $s += [(($e = method_exists($this, $m)) ? I_Proto::ASP_ACCESS_ASP : I_Proto::ASP_ACCESS_DIR).$a => ($e ? $m : $p)]; }); }); return $c; } ], I_Proto::PROP_DEFINE_CONFIGURABLE => [ I_Boot::ON_LOOKUP => function(array $c, $n, array $l) { array_walk($l, function($v, $p) use (&$c, $n) { if(is_integer($p)) { $p = $v; $v = FALSE; } $c[$p] = $this->Core_Proto_T_Boot_handleLookup($p, $n, $c) + [ I_Proto::CONFIG_HANDLE => $v ]; }); return $c; } ] ]; $__init = isset($__options[I_Proto::DI_BOOT_INIT]) && is_callable($__options[I_Proto::DI_BOOT_INIT]) ? function($p, $v) use ($__options) { $__options[I_Proto::DI_BOOT_INIT]($p, $v, self::$__Core_Proto_T_Boot_Static[get_called_class()]); } : function($p, $v) { $a = self::$__Core_Proto_T_Boot_Static[get_called_class()][I_Proto::PROP_DEFINE_ASP]; if(!isset($a[$p])) return $this->$p = $v; $s = $a[$p]; if(FALSE === $s[I_Proto::ASP_HANDLE]) return $this->$p = $v; $u = &$s[I_Proto::ASP_USE]; if(!isset($u)) throw new Exception('The default handle is "set". No handler found.'); $d = &$s[I_Proto::ASP_ACCESS_DIR.$u]; $m = &$s[I_Proto::ASP_ACCESS_ASP.$u]; if(isset($d)) return $this->$p = $v; if(isset($m)) return $this->$m($v); $m = I_Proto::ASP_ACCESS_ASP.$u; throw new Exception('Setter {:m} not avail.', compact('m')); }; $__exec = isset($__options[I_Proto::DI_BOOT_EXEC]) && is_callable($__options[I_Proto::DI_BOOT_EXEC]) ? function() use ($__init, $__options) { $__options[I_Proto::DI_BOOT_EXEC]($__init, self::$__Core_Proto_T_Boot_Static[get_called_class()]); $this->__initConfig[I_Proto::DI_RUN] = TRUE; unset($this->__initConfig[I_Proto::DI_BOOT_EXEC]); } : function() use ($__init) { $_ = self::$__Core_Proto_T_Boot_Static[get_called_class()]; $c = $_[I_Proto::PROP_DEFINE_CONFIGURABLE]; $d = $_[I_Proto::PROP_DEFINE_DEFAULTS]; $i = &$this->__initConfig; $t = []; array_walk($d, function($s, $p) use (&$t) { if(FALSE === $s[I_Boot::EXISTS]) return; $t[$p] = &$s[I_Proto::DEFAULT_VALUE]; }); array_walk($c, function($s, $p) use (&$i, &$t) { if(FALSE === isset($i[$p])) return; $value = $i[$p]; if(FALSE === $s[I_Boot::EXISTS]) return; switch(TRUE): case is_array($value) && is_array($this->$p): switch($s[I_Boot::CONFIG_HANDLE]): case I_Proto::CONFIG_HANDLE_ARR_ADD: $value = $this->$p + $value; break; case I_Proto::CONFIG_HANDLE_ARR_EXTEND: $value = $this->extend($this->$p, $value); break; case I_Proto::CONFIG_HANDLE_ARR_MERGE: $value = array_merge($this->$p, $value); break; case I_Proto::CONFIG_HANDLE_ARR_RECURSIVE: $value = $this->extend(TRUE, $this->$p, $value); break; endswitch; break; case is_string($value) && is_string($this->$p): switch($s[I_Boot::CONFIG_HANDLE]): case I_Proto::CONFIG_HANDLE_STR_APPEND: $value = $this->$p.$value; break; case I_Proto::CONFIG_HANDLE_STR_PREPEND: $value = $value.$this->$p; break; endswitch; break; endswitch; $t[$p] = &$value; }); array_walk($t, function(&$v, $p) use (&$i, $__init) { unset($i[$p]); $__init($p, $v); }); $this->__initConfig[I_Proto::DI_RUN] = TRUE; unset($this->__initConfig[I_Proto::DI_BOOT_EXEC]); }; $this->Core_Proto_T_Boot_emit ( $this->extend(TRUE, (isset($__options[I_Proto::DI_BOOT_LOAD]) ? $__options[I_Proto::DI_BOOT_LOAD] : []), $__boot) ); unset($__options[I_Proto::DI_BOOT_LOAD]); unset($__options[I_Proto::DI_BOOT_EXEC]); unset($__options[I_Proto::DI_BOOT_INIT]); $this->__initConfig = $this->extend(TRUE, $this->__initConfig, self::$__defaultOptions, $__options); TRUE === $this->__initConfig[I_Proto::DI_RUN] ? $__exec() : $this->__initConfig[I_Proto::DI_BOOT_EXEC] = $__exec; unset($__boot); unset($__init); unset($__exec); } public function run() { if(isset($this->__initConfig[I_Proto::DI_BOOT_EXEC])) $this->__initConfig[I_Proto::DI_BOOT_EXEC](); return $this; } public function propertySet($property, $value) { $_ = self::$__Core_Proto_T_Boot_Static[get_called_class()]; $c = $_[I_Proto::PROP_DEFINE_CONFIGURABLE]; if(!isset($c[$property])) throw new Exception('{:property} is not public.', compact('property')); $this->$property = $value; return $this; } public function extend() { $a = func_get_args(); $t = $a[0]; $i = 1; $l = count($a); $r = FALSE; if(is_bool($t)) { $r = $t; $t = isset($a[1]) ? $a[1] : []; $i = 2; } if(FALSE === is_array($t) && FALSE === is_object($t) && FALSE === is_string($t)) $t = []; if($l === $i) { $t = $this; --$i; } for( ; $i < $l; $i++) { if(NULL === ($o = $a[$i])) continue; foreach($o as $p => $v) { switch(TRUE): case is_array($t): $t[$p] = (TRUE === $r && is_array($v) && isset($t[$p]) && is_array($t[$p])) ? $this->extend($r, $t[$p], $v) : $v; break; case is_object($t): $t->$p = (TRUE === $r && is_array($v) && isset($t->$p) && is_array($t->$p)) ? $this->extend($r, $t->$p, $v) : $v; break; case is_string($t): if(FALSE === class_exists($t)) throw new Exception('Class {:t} not found.', compact('t')); if(FALSE === property_exists($t, $p)) throw new Exception('Property {:t}::${:p} not found.', compact('t', 'p')); $t::$$p = (TRUE === $r && is_array($v) && is_array($t::${$p})) ? $this->extend($r, $t::$$p, $v) : $v; break; default: throw new Exception('Target not writable.'); endswitch; } } return $t; } public function dump() { return self::$__Core_Proto_T_Boot_Static; } }