/** * @param array $set array to be managed */ public function __construct($type, $set = null) { if (is_callable($type)) { $this->type = $type; } else { if (!string::isString($type)) { throw new \InvalidArgumentException('invalid type specifier'); } else { $this->type = trim(_S($type)->asUtf8); } } if (func_num_args() > 1) { parent::__construct($this->filterByType($set, false)); } else { parent::__construct(); } }
/** * Detects if provided string contains valid class name. * * This check is testing syntactical validity, only. It doesn't check * whether related class actually exists or not. * * @param string $name class name to check * @return boolean true on a valid class name, false otherwise */ public static function isValidClassName(&$name) { if (string::isString($name)) { $name = trim($name); return preg_match('/^([a-z_][a-z0-9_]*\\\\)*[a-z_][a-z0-9_]*$/i', $name); } return false; }
/** * Recursively converts provided value to XML thread. * * @param mixed $set data to convert * @param string $indent indentation to use on value * @param string $name name used to wrap around converted data * @return string XML notation of provided data */ protected static function array2Xml($set, $indent = null, $name = 'root') { $name = _S($name)->asUtf8; if (!xml::isValidName($name)) { throw new \UnexpectedValueException('invalid element name cannot be converted to XML'); } if (is_array($set)) { // there are subordinated elements to be converted into XML nodes // // collect hash-like and set-like elements separately $separateName = $sameName = array(); foreach ($set as $subName => $sub) { if (ctype_digit(trim($subName))) { $sameName[] = static::array2Xml($sub, $indent, $name); } else { $separateName[$subName] = static::array2Xml($sub, "{$indent} ", $subName); } } // exclude to have both sorts of elements (as it can't be mapped into XML notation) if (count($separateName) && count($sameName)) { throw new \UnexpectedValueException('unsupported state of mixing hash-like and set-like array in converting to XML'); } // convert elements to XML if (count($separateName)) { return "{$indent}<{$name}>\n" . implode('', $separateName) . "{$indent}</{$name}>\n"; } else { if (count($sameName)) { // prevent multiple root nodes here if (strval($indent) === '') { if (count($set) > 1) { throw new \UnexpectedValueException('cannot convert array with multiple root elements into XML'); } } return implode('', $sameName); } else { // support empty elements return "{$indent}<{$name}/>\n"; } } } else { // it's a leaf node // -> convert to element containing single text element if (string::isString($set)) { $set = _S($set)->asUtf8; } else { $set = data::asAutoTypable($set); } return "{$indent}<{$name}>{$set}</{$name}>\n"; } }
/** * Converts provided value to best matching type according to actual value. * * This method is parsing a provided string for containing an integer, * decimal or special string for marking boolean values. Any non-string * value is passed as is. * * @param mixed $value value to convert optionally * @param string $type name of type to prefer * @return mixed provided or converted value */ public static function autoType($value, $type = null) { if (string::isString($value)) { $type = strtolower(trim($type)); if ($type === 'string') { return $value; } if (strtolower(trim($value)) == 'null') { return null; } if ($type === 'integer' || preg_match('/^[+-]?\\d+$/', trim($value)) || $type === 'integer') { return intval($value); } if (is_numeric($value)) { return doubleval($value); } // due to different locale is_numeric() probably won't detect // non-localized decimals if (preg_match('/^(([+-]?)\\d+)(\\.(\\d+))?$/', trim($value), $matches)) { return doubleval($matches[1]) + "{$matches['2']}1" * doubleval($matches[4]) * pow(10, -strlen($matches[4])); } if ($type === 'double') { return doubleval($value); } if (preg_match('/^(o(ff|n)|true|false|yes|no)$/i', trim($value), $matches)) { return in_array(strtolower($matches[1]), array('on', 'yes', 'true')); } if ($type === 'boolean') { return in_array(strtolower(trim($value)), array('on', 'yes', 'true')); } if (preg_match('/^=\\?8bit\\?B\\?(.+)\\?=$/i', $value, $matches)) { return static::autotype(unserialize(base64_decode($matches[1])), $type); } } return $value; }