/** * This method iterates over each record in the file, yielding each item to the procedure function. * * @access public * @param callable $procedure the procedure function to be used * @throws Throwable\Parse\Exception indicates that an invalid record was * encountered */ public function each(callable $procedure) { $self = $this; IO\FileReader::read($this->file, function ($reader, $data, $index) use($self, $procedure) { $line = trim($data); if (strlen($line) > 0) { if ($index == 0 && $self->bom) { $line = preg_replace('/^' . pack('H*', 'EFBBBF') . '/', '', $line); } $query_string = parse_url($line, PHP_URL_QUERY); $properties = array(); parse_str($query_string, $properties); if (!empty($properties)) { $source_encoding = $self->encoder !== null ? call_user_func($self->encoder . "::getEncoding", $properties) : $self->encoding[0]; $target_encoding = $self->encoding[1]; foreach ($properties as $key => &$value) { $value = urldecode($value); $value = Core\Data\Charset::encode($value, $source_encoding, $target_encoding); $type = isset($self->schema[$key]) ? $self->schema[$key] : 'string'; $value = Core\Convert::changeType($value, $type); $record = new Common\Mutable\HashMap(); $record->putEntry($key, $value); $procedure($record); } } } }); }
/** * This method adds a value to the query string. * * @access public * @param string $key the key to be used * @param mixed $value the value to be added * @return string the query string segment */ public function addValue($key, $value) { if (!Core\Data\Undefined::instance()->__equals($value)) { $field = preg_replace('/\\[[^\\]]*\\]/', '[]', $key); $type = isset($this->metadata['schema'][$field]) ? $this->metadata['schema'][$field] : 'string'; $value = Core\Convert::changeType($value, $type); $value = Core\Convert::toString($value); $value = Core\Data\Charset::encode($value, $this->metadata['encoding'][0], $this->metadata['encoding'][1]); $value = urlencode($value); return $key . '=' . $value; } return null; }
/** * This method returns an object matching the description specified by the element. * * @access public * @param Spring\Object\Parser $parser a reference to the parser * @param \SimpleXMLElement $element the element to be parsed * @return mixed an object matching the description * specified by the element * @throws Throwable\Parse\Exception indicates that a problem occurred * when parsing */ public function getObject(Spring\Object\Parser $parser, \SimpleXMLElement $element) { $children = $parser->getElementChildren($element, null); if (!empty($children)) { $value = ''; foreach ($children as $child) { $name = $parser->getElementPrefixedName($child); switch ($name) { case 'spring:null': $value = $parser->getObjectFromElement($child); break; default: throw new Throwable\Parse\Exception('Unable to process Spring XML. Tag ":tag" has invalid child node ":child"', array(':tag' => 'value', ':child' => $name)); break; } } if (is_string($value)) { return Core\Data\Charset::encode($value, $parser->getEncoding($parser->getResource()), Core\Data\Charset::UTF_8_ENCODING); } return $value; } else { $attributes = $element->attributes(); $value = dom_import_simplexml($element)->textContent; if (isset($attributes['type'])) { $type = $parser->valueOf($attributes['type']); if (!$parser->isPrimitiveType($type)) { throw new Throwable\Parse\Exception('Unable to process Spring XML. Expected a valid primitive type, but got ":type".', array(':type' => $type)); } $value = Core\Convert::changeType($value, $type); } if (is_string($value)) { $attributes = $element->attributes('xml', true); if (isset($attributes['space'])) { $space = $parser->valueOf($attributes['space']); if (!$parser->isSpacePreserved($space)) { throw new Throwable\Parse\Exception('Unable to process Spring XML. Expected a valid space token, but got ":token".', array(':token' => $space)); } } else { $value = trim($value); } } if (is_string($value)) { return Core\Data\Charset::encode($value, $parser->getEncoding($parser->getResource()), Core\Data\Charset::UTF_8_ENCODING); } return $value; } }
/** * This method recursively adds each entry as a property. * * @access protected * @param string &$buffer the string buffer * @param string $key the key to be used * @param mixed $value the value to be added */ protected function addProperty(&$buffer, $key, $value) { if (!is_array($value)) { if ($value == null || is_object($value) && $value instanceof Core\Data\Undefined) { $buffer .= $key . '=' . ''; } else { $type = isset($this->metadata['schema'][$key]) ? $this->metadata['schema'][$key] : 'string'; $datum = Core\Convert::changeType($value, $type); $datum = Core\Convert::toString($datum); $datum = Core\Data\Charset::encode($datum, $this->metadata['encoding'][0], $this->metadata['encoding'][1]); $buffer .= $key . '=' . $datum; } $buffer .= $this->metadata['eol']; } else { foreach ($value as $k => $v) { $this->addProperty($buffer, $key . '.' . Core\Convert::toString($k), $v); } } }
/** * This method renders the data for the writer. * * @access public * @return string the data as string * @throws \Exception indicates a problem occurred * when generating the template */ public function render() { $metadata = $this->metadata; $declaration = $metadata['declaration'] ? Core\Data\XML::declaration($metadata['encoding'][1], $metadata['standalone']) . $metadata['eol'] : ''; if (!empty($metadata['template'])) { $file = new IO\File($metadata['template']); $mustache = new \Mustache_Engine(array('loader' => new \Mustache_Loader_FilesystemLoader($file->getFilePath()), 'escape' => function ($string) use($metadata) { $string = Core\Data\Charset::encode($string, $metadata['encoding'][0], $metadata['encoding'][1]); $string = Core\Data\XML::entities($string); return $string; })); ob_start(); try { echo $declaration; echo $mustache->render($file->getFileName(), $this->data); } catch (\Exception $ex) { ob_end_clean(); throw $ex; } $template = ob_get_clean(); if (!empty($metadata['minify'])) { $template = Minify\XML::minify($template, $metadata['minify']); } return $template; } else { ob_start(); try { $document = new \DOMDocument(); $document->formatOutput = true; $this->toXML($document, $document, $this->data); echo $declaration; echo $document->saveXML(); } catch (\Exception $ex) { ob_end_clean(); throw $ex; } $template = ob_get_clean(); return $template; } }
/** * This method adds a dictionary of nodes to the DOM structure. * * @access protected * @param \SimpleXMLElement $root a reference to the root node * @param \SimpleXMLElement $node a reference to the current node * @param mixed $data the data to be added to the node * @param string $xmlns the xml namespace to be used */ protected function addDictionary(&$root, &$node, &$data, $xmlns) { foreach ($data as $name => $value) { $type = $value !== null ? gettype($value) : 'NULL'; switch ($type) { case 'array': $child = $node->addChild($name, null, $xmlns); if (static::isDictionary($value)) { $this->addDictionary($root, $child, $value, $xmlns); } else { $this->addArray($root, $child, $value, $xmlns); } break; case 'object': if ($value instanceof Core\Data\Undefined) { // do nothing } break; case 'NULL': $child = $node->addChild($name, null, $xmlns); $child->addAttribute('xsi:nil', 'true', 'http://www.w3.org/2001/XMLSchema-instance'); break; default: $datum = Core\Convert::toString($value); $datum = Core\Data\Charset::encode($datum, $this->metadata['encoding'][0], $this->metadata['encoding'][1]); $datum = SOAP\Data\XML::entities($datum); $node->addChild($name, $datum, $xmlns); break; } } }
/** * This method adds a "value" node to the DOM structure. * * @access protected * @param \SimpleXMLElement $root a reference to the root node * @param \SimpleXMLElement $node a reference to the current node * @param mixed $data the data to be added to the node * @param string $type the type of data */ protected function addValue($root, $node, $data, $type) { switch ($type) { case 'boolean': $value = !$data ? 'false' : 'true'; $child = $node->addChild('value', $value); $child->addAttribute('type', 'boolean'); break; case 'integer': case 'double': $child = $node->addChild('value', $data); $child->addAttribute('type', $type); break; case 'string': case 'unknown type': default: $value = '' . $data; $value = Core\Data\Charset::encode($value, $this->encoding[0], $this->encoding[1]); $value = Spring\Data\XML::entities($value); $child = $node->addChild('value', $value); $child->addAttribute('type', 'string'); if (strlen(trim($value)) < strlen($value)) { $child->addAttribute('xml:space', 'preserve', 'http://www.w3.org/XML/1998/namespace'); } break; } }
/** * This method serializes a value. * * @access protected * @param mixed $value the value to be serialized * @return string the serialized key */ protected function getSerializedValue($value) { $type = gettype($value); switch ($type) { case 'array': $array = 'array(' . $this->metadata['eol']; foreach ($value as $k => $v) { $array .= $this->getSerializedKey($k) . ' => ' . $this->getSerializedValue($v) . ',' . $this->metadata['eol']; } $array .= ')'; return $array; case 'NULL': return 'null'; case 'object': if ($value instanceof Core\Data\Undefined) { return '\\Unicity\\Core\\Data\\Undefined::instance()'; } return 'null'; case 'boolean': case 'double': case 'integer': return Core\Convert::toString($value); case 'string': case 'resource': case 'unknown type': default: $value = Core\Convert::toString($value); $value = Core\Data\Charset::encode($value, $this->metadata['encoding'][0], $this->metadata['encoding'][1]); return "'" . addslashes($value) . "'"; } }
/** * This method iterates over each record in the file, yielding each item to the procedure function. * * @access public * @param callable $procedure the procedure function to be used * @throws Throwable\Parse\Exception indicates that an invalid record was * encountered */ public function each(callable $procedure) { $self = $this; $headers = array(); IO\FileReader::read($this->file, function ($reader, $data, $index) use($self, $procedure, &$headers) { $line = trim($data); if (strlen($line) > 0) { if ($index == 0) { if ($self->bom) { $line = preg_replace('/^' . pack('H*', 'EFBBBF') . '/', '', $line); } $headers = str_getcsv($line, $self->delimiter, $self->enclosure, $self->escape); $headers = array_map('trim', $headers); if ($self->key_case !== null) { switch ($self->key_case) { case CASE_LOWER: $headers = array_map('strtolower', $headers); break; case CASE_UPPER: $headers = array_map('strtoupper', $headers); break; } } } else { $record = str_getcsv($line, $self->delimiter, $self->enclosure, $self->escape); if (!is_array($record)) { throw new Throwable\Runtime\Exception('Failed to process record. Expected an array, but got ":type".', array(':type' => gettype($record))); } $record = array_combine($headers, $record); if ($self->strict_mapping && count($headers) != count($record)) { throw new Throwable\Runtime\Exception('Failed to process record. Headers could not be mapped properly.'); } $source_encoding = $self->encoder !== null ? call_user_func($self->encoder . "::getEncoding", $record) : $self->encoding[0]; $target_encoding = $self->encoding[1]; foreach ($record as $key => &$value) { $value = Core\Data\Charset::encode($value, $source_encoding, $target_encoding); if ($self->strip_invalid_chars) { $value = $self->removeNonUTF8Characters($value); } $type = isset($self->schema[$key]) ? $self->schema[$key] : 'string'; $value = Core\Convert::changeType($value, $type); } $map = new Common\Mutable\HashMap($record); if ($self->filter === null || call_user_func_array(array($self->filter, 'isQualified'), array($map))) { $procedure($map); } } } }); }
/** * This method formats an array of values using CSV conventions. * * @access public * @static * @param array $fields the values to be formatted * @param string $delimiter the delimiter to be used * @param string $enclosure the enclosure to be used * @param string $escape the escape character to be used * @param string $eol the end-of-line character to be used * @param array $encoding the character set encoding to be used * @return string the formatted string * * @see http://php.net/manual/en/function.fputcsv.php#77866 */ public static function format(array $fields, $delimiter = ',', $enclosure = '"', $escape = '\\', $eol = "\n", array $encoding = null) { $buffer = ''; if (empty($encoding)) { $encoding = array(Core\Data\Charset::UTF_8_ENCODING, Core\Data\Charset::UTF_8_ENCODING); } foreach ($fields as $field) { $value = Core\Data\Charset::encode($field, $encoding[0], $encoding[1]); if ($enclosure != '' && (strpos($value, $delimiter) !== false || strpos($value, $enclosure) !== false || strpos($value, "\n") !== false || strpos($value, "\r") !== false || strpos($value, "\t") !== false || strpos($value, ' ') !== false)) { $literal = $enclosure; $escaped = 0; $length = strlen($value); for ($i = 0; $i < $length; $i++) { if ($value[$i] == $escape) { $escaped = 1; } else { if (!$escaped && $value[$i] == $enclosure) { $literal .= $enclosure; } else { $escaped = 0; } } $literal .= $value[$i]; } $literal .= $enclosure; $buffer .= $literal . $delimiter; } else { $buffer .= Core\Convert::toString($value) . $delimiter; } } $buffer = substr($buffer, 0, -1) . $eol; return $buffer; }
/** * This method returns the first value associated with the specified object. * * @access public * @static * @param mixed $value the object to be processed * @param string $source_encoding the source encoding * @param string $target_encoding the target encoding * @return mixed the value that was wrapped by * the object */ public static function valueOf($value, $source_encoding = 'UTF-8', $target_encoding = 'UTF-8') { $flags = defined('ENT_XML1') ? ENT_QUOTES | ENT_XML1 : ENT_QUOTES; if (is_array($value) || is_object($value)) { $array = (array) $value; if (isset($array[0])) { $buffer = $array[0]; if (is_string($buffer)) { $buffer = Core\Data\Charset::encode($buffer, $source_encoding, $target_encoding); } $buffer = html_entity_decode($buffer, $flags, $target_encoding); return $buffer; } } $buffer = $value; if (is_string($buffer)) { $buffer = Core\Data\Charset::encode($buffer, $source_encoding, $target_encoding); } $buffer = html_entity_decode($buffer, $flags, $target_encoding); return $buffer; }
/** * This method parses a "string" node. * * @access protected * @param \DOMElement $node a reference to the "string" node * @return \Unicity\Common\String the value as a string */ protected function parseStringElement(\DOMElement $node) { $value = $node->textContent; $value = Core\Convert::toString($value); $value = Core\Data\XML::toUnicodeString($value); $value = Core\Data\Charset::encode($value, $this->metadata['encoding'][0], $this->metadata['encoding'][1]); $string = new Common\String($value); return $string; }