3v4l.org

run code in 150+ php & hhvm versions
Bugs & Features
<?php /** * SETTINGS. * * Objects of class Settings are injected to factories * as initiators of various classes. * * Process: * - FUNCTIONS.PHP: Create object Settings(). * - FUNCTIONS.PHP: Set args by Settings:set(). * - FUNCTIONS.PHP: Create object Factory($settings). * - CLASS-FACTORY.PHP: Create functionality objects according to settings. * - CLASS-WORKER.PHP: Parent functionality. * * @author Petr Cibulka <cibulka.me@gmail.com> * @link http://cibulka.me * * @package Cibulka_Framework\Architecture * @since 1.0 * @version 1.0 * * @filesource */ // ---------------------------------------------------------------------------------- /** * SETTINGS CLASS. * * @used-by Factory() * @package Cibulka_Framework\Architecture * */ // ---------------------------------------------------------------------------------- class Settings { private $prefix = ''; private $spec = []; private $workers = []; /** * CONSTRUCTOR. * * Sets prefix. The rest is done by Settings::setters(); * * @param string $prefix Sets prefix for all chained classes. * */ function __construct($prefix) { $this->prefix = $prefix; } // -------------------------------------------------------------------------- /** * SETTER. * * Note: If unique worker needed, leave ID blank * => arg TYPE will act both like type of functionality AND unique ID. * * @param string $type Sets type of functionality. If class should be unique, acts as ID as well. * @param string $id * @param array $args Args are later validated by Worker(). * */ public function set($type,$id='',$args='') { /*ID*/ $id = $this->get_id($type,$id); if (!$id) { return false; } /*SPEC*/ $spec = $this->create_spec($type,$id,$args); /*VALIDATION & TRANSLATION*/ $v = new Validator(); try { // SPEC: Validation $v->spec_validate($type); // ARGS: Translation $v->args_translate($args,$type); // ARGS: Validation $v->args_validate($args,$type); } catch (Exception $e) { $message = $e->getMessage(); $line = $e->getLine(); $file = $e->getFile(); $trace = $e->getTrace(); ?> <table> <tr> <th colspan="2"><?php echo $message; ?></th> </tr><tr> <td>Line: <?php echo $line; ?></td> <td>File: <?php echo $file; ?></td>'; </tr><tr> </tr><tr> <td colspan="2">Trace: <?php echo $trace; ?></td> </tr> </table> <?php return false; } /*ARGS*/ $this->workers[$id]['type'] = $type; $this->workers[$id]['args'] = (!empty($args)) ? $args : array(); /*TEST*/ //helper::printr($this); } // -------------------------------------------------------------------------- private function get_id($type,$id) { $id = (!empty($id)) ? $id : $type; // Error // TODO: Create proper exception if (array_key_exists($id,$this->workers)) { $text = 'Worker with ID '.$id.' already exists.'; $error = new Error($this,$text); trigger_error(); return false; } return $id; } private function create_spec($type,$id,$args) { $spec_name = ucfirst($this->prefix).'_'.ucfirst($type).'_Spec'; // Initiate, if not already if (!array_key_exists($type, $this->spec)) { $this->spec[$type] = new $spec_name($type,$id); } return $spec_name; } // -------------------------------------------------------------------------- private function spec_validate($type) { $spec = $this->spec[$type]; foreach ($spec as $spec_term => $spec_row) { // Conflicting spec keys // req & def if (array_key_exists('req',$spec_row)) {} // wrong type to check if (!empty($spec_row['type'])) { $type = helper::str_to_array($spec_row['type']); $type_supported = array('boolean','integer','double','string','array','object','resource','null','file'); $type_unsupported = array_diff($type,$type_supported); if ($type_unsupported) { trigger_error('Unsupported type!'); return false; } } // wrong count if (!empty($spec_row['count'] && is_string($spec_row['count'])) { // max & min // range } } return true; } private function args_translate($args,$type) { $spec = $this->spec[$type]; foreach ($spec as $spec_term => $spec_row) { /*KEYS & DEF values*/ $spec_def_value = (!empty($property_row['def'])) ? $property_row['def'] : null; // SET if (!empty($this->args[$spec_term])) { continue; } else { $this->args[$spec_term] = $spec_def_value; } } return true; } private function args_validate($args,$type) { $spec = $this->spec[$type]->get_all(); /*SHOULD WE VALIDATE?*/ if (!$spec) { // ARGS disabled & Not set => ok if (empty($this->args)) { return; } // ARGS disabled & set => not ok else { trigger_error('ARGS are not allowed'); } } /*UNSUPPORTED SPEC*/ $args_terms_unsupported = array_diff_key($this->args, $spec); if ($args_terms_unsupported) { trigger_error('Unsupported keys: '.implode(', ', $args_terms_unsupported)); return false; } /*LOOP THROUGH SPEC*/ foreach ($spec as $spec_term => $spec_row) { $user_value = $this->args[$spec_term]; // ERROR: Required keys missing $req = $spec_row['req']; if ($req && empty($user_value)) { trigger_error('Required ARG '.$spec_term.' is empty.'); return false; } // CONTINUE if $user_val empty if (empty($user_value)) { continue; } // ERROR: Count if (!empty($spec_row['count'])) { $user_count = count(helper::str_to_array($user_value)); $count_error = $this->user_val_count($user_count,$spec_row['count']); if ($count_error) { trigger_error('Wrong count on '.$spec_term); } } // ERROR: TYPE: File if (!empty($spec_row['type']) && !is_array($spec_row['type']) && 'file' === $spec_row['type']) { // Escape type checking later $type_escape = true; // Error: File is not a string $user_value_is_string = is_string($user_value); if (!$user_value_is_string) { trigger_error('File must be string.'); return false; } // Error: File does not exist $file_exists = $this->check_file($user_value); if (!$file_exists) { trigger_error('File has weird SRC.'); return false; } } // ERROR: TYPE: Common types if (!empty($spec_row['type'] && !$type_escape) { $user_value_type_supported = in_array(gettype($user_value),helper::str_to_array($spec_types)); if (!$user_value_type_supported) { trigger_error('Value type is not supported'); return false; } } // ERROR: VALUES if (!empty($spec_row['vals'])) { $user_val_unsupported = array_diff(helper::str_to_array($user_val),$spec_val); if ($user_val_unsupported) { trigger_error('Value is unsupported'); return false; } } } return true; } } // ------------------------------------------------------------------------------ interface Spec_Interface { public function set($property,$key,$value=''); public function get($property); } interface Spec_Interface_Child { public function spec_set(); } abstract class Spec implements Spec_Interface { protected $worker = array( 'type' => '', 'id' => '' ); // -------------------------------------------------------------------------- function __construct($type,$id) { $this->worker['type'] = $type; $this->worker['id'] = $id; /*SPEC*/ // Sets default values & allowed values if (method_exists($this,'spec_set')) { try { // parent $this->spec_set(); // child if (method_exists($this,'spec_set_child')) { $this->spec_set_child(); } } catch (Exception $e) { } } } // -------------------------------------------------------------------------- // TODO: Exceptions function set($property,$spec_key,$value='') { $allowed_keys = array('def','vals'); if (!in_array($spec_key,$allowed_keys)) { trigger_error('TYPES accepted: '.implode(', ', $allowed_keys).'. Type provided: <b>'.$spec_key.'</b>.'); } if (property_exists($this,$property)) { $this->{$property}[$spec_key] = $value; } else { trigger_error('Property <b>'.$spec_key.'</b> is not supported.'); } } function get($property) { if (property_exists($this,$property)) { return $this->{$property}; } else { trigger_error('Property '.$property.' does not exist.'); } } function get_all() { return get_object_vars($this); } } abstract class Scripts_Spec extends Spec implements Spec_Interface_Child { protected $script_type = array( 'req' => true, 'num' => 1, 'vals' => array('wp','admin','login') ); protected $load = array( 'req' => false, 'num' => 1, 'type' => array('string','object'), 'vals' => array('post_edit') ); protected $autoload = array( 'req' => false, 'num' => 1, 'type' => 'boolean', 'def' => false ); protected $local = array( 'req' => false, 'num' => 1, 'type' => 'boolean', 'def' => true ); protected $id = array( 'req' => false, 'num' => 1, 'type' => 'string', 'def' => '' ); protected $src = array( 'req' => false, 'num' => 1, 'type' => 'string' ); protected $deps = array( 'req' => false, 'num' => '', 'type' => array('string','array') ); protected $ver = array( 'req' => false, 'num' => 1, 'type' => 'string' ); function spec_set() { // ID > Def: id of worker $this->set('id','def',$this->worker['id']); } } class Scripts_Js_Spec extends Scripts_Spec { } class Scripts_Css_Spec extends Scripts_Spec { } ?>
Output for 5.4.0 - 5.4.27
Parse error: syntax error, unexpected '&&' (T_BOOLEAN_AND), expecting ')' in /in/sqm0o on line 166
Process exited with code 255.
Output for 5.1.0 - 5.3.28
Parse error: syntax error, unexpected '[' in /in/sqm0o on line 41
Process exited with code 255.
Output for 5.0.0 - 5.0.5
Parse error: parse error, unexpected '[' in /in/sqm0o on line 41
Process exited with code 255.
Output for 4.4.2 - 4.4.9
Parse error: syntax error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in /in/sqm0o on line 40
Process exited with code 255.
Output for 4.3.0 - 4.3.1, 4.3.5 - 4.4.1
Parse error: parse error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in /in/sqm0o on line 40
Process exited with code 255.
Output for 4.3.2 - 4.3.4
Parse error: parse error, expecting `T_OLD_FUNCTION' or `T_FUNCTION' or `T_VAR' or `'}'' in /in/sqm0o on line 40
Process exited with code 255.