/** * Cast a value according to the datatype property * * @param mixed $value * @param boolean $force Force casting and cast to type instead of datatype * @return mixed */ public function castValue($value, $force = null) { if ($value === null || $value === "") { return null; } if (!isset($this['type'])) { return $value; } $cast = null; $type = strtolower($force ? $this['type'] : $this['datatype']); switch ($type) { case 'children': $cast = (array) $value; break; case 'array': $cast = !is_array($value) && !empty($value) ? split_set(';', $value) : $value; break; case 'bool': case 'boolean': if ($force || $value == 0 || $value == 1) { $cast = (bool) $value; } else { $cast = $value; } break; case 'set': if (!is_int($value) && !preg_match('/^-?\\d*$/', $value)) { $value = split_set(';', $value); } if (is_array($value) && !empty($value) && is_string(reset($value))) { $opts = $this->getProperty('values'); if (!empty($opts)) { $intval = 0; if (!is_array($opts)) { $opts = split_set(';', $opts); } foreach ($opts as $val => $opt) { if (in_array($opt, $value)) { $intval += pow(2, $val); } } $value = $intval; } } if (is_array($value)) { $value = array_sum($value); } case 'bit': case 'tinyint': case 'smallint': case 'mediumint': case 'int': case 'integer': case 'bigint': if (is_string($value)) { $value = trim($value, '"'); } $cast = (int) $value; if (is_object($value) || is_array($value) || !is_int($value) && !preg_match('/^-?\\d*$/', $value)) { if ($force) { trigger_error("Field '{$this}': Value {$value} is cast to integer {$cast}", E_USER_NOTICE); } else { $cast = $value; } } break; case 'float': case 'double': case 'double precision': case 'real': case 'decimal': case 'dec': case 'fixed': if (is_string($value)) { $value = trim($value, '"'); } $matches = null; if (is_object($value) || is_array($value) || !is_float($value) && !preg_match('/^(-?\\d*)([\\.,]?)(\\d*)$/', $value, $matches) && $force) { trigger_error("Field '{$this}': Value {$value} is cast to float " . (double) $value, E_USER_NOTICE); } $cast = !empty($matches) ? $cast = (double) ($matches[1] . '.' . $matches[3]) : (!$force ? $value : (double) $value); break; case 'date': case 'datetime': if (is_int($value) || is_string($value) && ctype_digit($value)) { $date = new \DateTime(); $date->setTimestamp($value); $cast = $date->format('c'); } elseif (is_string($value) && preg_match('/^\\d{1,2}-\\d{1,2}-\\d{4}(\\s+\\d{1,2}:\\d{1,2}:\\d{1,2}\\d{1,2})?$/', $value, $matches)) { $date = \DateTime::createFromFormat('j-n-Y H:i:s', $value . ($matches[1] ? '' : ' 00:00:00')); if ($date) { $cast = $date->format('c'); } } if (empty($cast)) { $cast = $value; } break; case 'time': if (is_string($value) && preg_match('/^([0-1]\\d|2[0-3])\\:([0-5]\\d)/', $value, $matches)) { $cast = $matches[0]; } elseif ($force) { trigger_error("Field '{$this}': Value {$value} is not a valid time: set to NULL", E_USER_NOTICE); } else { $cast = $value; } break; default: if ($force) { $value = $this['datatype'] == 'array' ? $value = implode_set(';', $value) : (string) $value; } $cast = is_string($value) ? trim($value) : $value; } return $cast; }
/** * Class constructor. * * @param object|resource $native * @param array $settings Settings used to create connection */ public function __construct($native, $settings = array()) { $this->native = $native; if (isset($settings)) { $this->settings = $settings; } $config = array_chunk_assoc($this->settings, 'config'); $this->metadata = $config instanceof Config ? $config : Config::with($config, array('mapkey' => array('table_def' => "'#table'", 'field' => '@name', 'alias' => "'#alias:'.@name"))); if (isset($settings['metadata-cache'])) { $this->metadataCache = $settings['metadata-cache']; } if (isset($settings['log']) && load_class('Q\\Log')) { $this->log = $settings['log'] instanceof Logger ? $settings['log'] : Log::with($settings['log']); } elseif (class_exists('Q\\Log') && Log::db()->exists()) { $this->log = Log::db(); } if (isset($settings['log-columns'])) { $this->logColumns = is_string($settings['log-columns']) ? split_set(',', $settings['log-columns']) : (array) $settings['log-columns']; } }
/** * Extract the parameters from a DSN string. * The first item of the returned array is 'driver'=>driver, other items are arguments/properties. * * @param string $dsn * @return array */ function extract_dsn($dsn) { if (empty($dsn)) { return array(); } $options = array(); if (is_array($dsn)) { if (!isset($dsn['dsn']) && isset($dsn[0])) { $dsn['dsn'] = $dsn[0]; unset($dsn[0]); } if (isset($dsn['driver']) || !isset($dsn['dsn'])) { return $dsn; } $options = $dsn; $dsn = $dsn['dsn']; unset($options['dsn']); } $matches = null; if (!preg_match('/^([\\w-]+)\\:(.*)$/', $dsn, $matches)) { return array('driver' => $dsn); } return array('driver' => $matches[1]) + split_set(';', $matches[2]) + $options; }
/** * Set map for short options. * Add an '=' at the end of the long option to indicate the next argument is the value of the option. * * {@example Console::setOptMap(array('h'=>'help', 'q'=>'quiet', 'f'=>'file=');}} * * @param array $map array(shortopt=>longopt, ...) */ public static function setOptMap($map) { self::$opts = null; self::$args = null; self::$optmap = is_string($map) ? split_set(';', $map) : $map; }
/** * Returns a value for a node. * * @param SimpleXMLElement $node Convert a SimpleXMLElement into an array * @param string $map Uses option "map{$map}" * @param string $item Don't get the item from the map, but use this one * @return mixed */ protected function sxmlGetMapped(\SimpleXMLElement $node, $map = '', $item = null) { if (!isset($item)) { if (isset($this->_options["map{$map}"][$node->getName()])) { $item = $this->_options["map{$map}"][$node->getName()]; } elseif (isset($this->_options["map{$map}"]['*'])) { $item = $this->_options["map{$map}"]['*']; } else { return null; } } if (strpos($item, '.') !== false) { $items = split_set('.', $item, false); if (count($items) > 1) { $value = ''; foreach ($items as $item) { $value .= $this->sxmlGetMapped($node, null, $item); } return $value; } } if (($item[0] == '"' || $item[0] == "'") && preg_match('/^([\'"]).*\\1$/', $item)) { return substr($item, 1, -1); } if ($item[0] == '@') { $item = substr($item, 1); if (!isset($node[$item])) { trigger_error("Mapping of config node '" . $node->getName() . "' failed. Attribute '{$item}' was not found. (1)", E_USER_WARNING); return null; } return (string) $node[$item]; } if (!isset($node->{$item})) { trigger_error("Mapping of config node '" . $node->getName() . "' failed. Child node '{$item}' was not found.(2)", E_USER_WARNING); return null; } return $node->{$item}; }
/** * Get AUTH info from session data. */ protected function initInfo() { if (is_string($this->store)) { $this->store = extract_dsn($this->store); } switch ($this->store['driver']) { case 'none': $this->info = null; break; case 'session': session_start(); $this->info = isset($_SESSION['AUTH']) ? $_SESSION['AUTH'] : null; break; case 'cookie': $this->info = array_chunk_assoc($_COOKIE, 'AUTH', '_'); break; case 'request': $this->info = isset($_REQUEST['AUTH']) ? $_REQUEST['AUTH'] : null; break; case 'env': $this->info = split_set(';', unquote(getenv('AUTH'))); break; case 'http': $this->info = getenv('REMOTE_USER') ? array('username' => getenv('REMOTE_USER')) : null; break; case 'posix': $this->info = array('uid' => posix_getuid()); break; case 'posix_username': $this->info = array('username' => posix_getlogin()); break; default: throw new Exception("Invalid option '{$this->store['driver']}' specified for retrieving info."); } }
/** * Extract the connection parameters from a DSN string. * Returns array(driver, filters, props) * * @param string|array $dsn * @return array */ public static function extractDSN($dsn) { $args = array(); $filters = array(); $props = array(); $matches = null; // Extract DSN if (!is_string($dsn)) { $props = $dsn; $driver = strtolower(array_shift($props)); } elseif (strpos($dsn, '+') !== false && preg_match_all('/((?:\\"(?:[^\\"\\\\]++|\\\\.)++\\")|(?:\'(?:[^\'\\\\]++|\\\\.)++\')|[^\\+\\"\']++)++/', $dsn, $matches) >= 2) { $a = null; $driver = 'container'; $props = $matches[0]; $filters = null; foreach ($props as $i => $prop) { if (preg_match('/^\\s*(filter\\s*(?:\\[("(?:\\\\"|[^"])*")|(\'(?:\\\\\'|[^\'])*\'|[^\\]]+)\\]\\s*)?)=(.*)$/', $prop, $filters)) { parse_str($filters[1] . '=' . unquote(trim($filters[2])), $a); $filters = array_replace_recursive($filters, $a); unset($props[$i]); } } } else { $props = extract_dsn($dsn); $driver = strtolower(array_shift($props)); } // Get filters and properties from arguments if (isset($args['filter'])) { $filters = $args['filter']; unset($args['filter']); if (!is_array($filters)) { $filters = split_set(',', $filters); } } return array($driver, $filters, $props); }
/** * Factory; Create a new router. * * @param string|array $dsn Configuration options, may be serialized as assoc set (string) * @param array $options Configuration options (which do not appear in DSN) * @return Router */ public static function with($dsn, $options = array()) { if (get_called_class() == __CLASS__) { $dsn_options = is_string($dsn) ? extract_dsn($dsn) : $dsn; $options = (array) $dsn_options + (is_array($options) || $options instanceof \ArrayObject ? $options : array($options)); if (load_class('Q\\Config')) { $cfg_options = Config::i()->get('route' . (empty($options['driver']) ? '' : '.' . $options['driver'])); if ($cfg_options) { if (!is_array($cfg_options) && !$options instanceof \ArrayObject) { $cfg_options = split_set(';', $cfg_options); } $options += $cfg_options; if (isset($cfg_options['driver'])) { $options['driver'] = $cfg_options['driver']; } } } if (empty($options['driver'])) { throw new Exception("Unable to create Route object: No driver specified."); } if (!isset(self::$drivers[$options['driver']])) { throw new Exception("Unable to create Route object: Unknown driver '{$options['driver']}'"); } $class = self::$drivers[$options['driver']]; if (!load_class($class)) { throw new Exception("Unable to create {$class} object: Class does not exist."); } } else { $options = (is_array($dsn) ? $dsn : array($dsn)) + $options; $class = get_called_class(); } return new $class($options); }