Mini Shell
<?php
namespace Luracast\Restler\Format;
use Luracast\Restler\Data\Obj;
use Luracast\Restler\RestException;
use SimpleXMLElement;
use XMLWriter;
/**
* XML Markup Format for Restler Framework
*
* @category Framework
* @package Restler
* @subpackage format
* @author R.Arul Kumaran <arul@luracast.com>
* @copyright 2010 Luracast
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link http://luracast.com/products/restler/
*
*/
class XmlFormat extends Format
{
const MIME = 'application/xml';
const EXTENSION = 'xml';
// ==================================================================
//
// Properties related to reading/parsing/decoding xml
//
// ------------------------------------------------------------------
public static $importSettingsFromXml = false;
public static $parseAttributes = true;
public static $parseNamespaces = true;
public static $parseTextNodeAsProperty = true;
// ==================================================================
//
// Properties related to writing/encoding xml
//
// ------------------------------------------------------------------
public static $useTextNodeProperty = true;
public static $useNamespaces = true;
public static $cdataNames = array();
// ==================================================================
//
// Common Properties
//
// ------------------------------------------------------------------
public static $attributeNames = array();
public static $textNodeName = 'text';
public static $namespaces = array();
public static $namespacedProperties = array();
/**
* Default name for the root node.
*
* @var string $rootNodeName
*/
public static $rootName = 'response';
public static $defaultTagName = 'item';
/**
* When you decode an XML its structure is copied to the static vars
* we can use this function to echo them out and then copy paste inside
* our service methods
*
* @return string PHP source code to reproduce the configuration
*/
public static function exportCurrentSettings()
{
$s = 'XmlFormat::$rootName = "' . (self::$rootName) . "\";\n";
$s .= 'XmlFormat::$attributeNames = ' .
(var_export(self::$attributeNames, true)) . ";\n";
$s .= 'XmlFormat::$defaultTagName = "' .
self::$defaultTagName . "\";\n";
$s .= 'XmlFormat::$parseAttributes = ' .
(self::$parseAttributes ? 'true' : 'false') . ";\n";
$s .= 'XmlFormat::$parseNamespaces = ' .
(self::$parseNamespaces ? 'true' : 'false') . ";\n";
if (self::$parseNamespaces) {
$s .= 'XmlFormat::$namespaces = ' .
(var_export(self::$namespaces, true)) . ";\n";
$s .= 'XmlFormat::$namespacedProperties = ' .
(var_export(self::$namespacedProperties, true)) . ";\n";
}
return $s;
}
public function encode($data, $humanReadable = false)
{
$data = Obj::toArray($data);
$xml = new XMLWriter();
$xml->openMemory();
$xml->startDocument('1.0', $this->charset);
if ($humanReadable) {
$xml->setIndent(true);
$xml->setIndentString(' ');
}
static::$useNamespaces && isset(static::$namespacedProperties[static::$rootName])
?
$xml->startElementNs(
static::$namespacedProperties[static::$rootName],
static::$rootName,
static::$namespaces[static::$namespacedProperties[static::$rootName]]
)
:
$xml->startElement(static::$rootName);
if (static::$useNamespaces) {
foreach (static::$namespaces as $prefix => $ns) {
if (isset(static::$namespacedProperties[static::$rootName])
&& static::$namespacedProperties[static::$rootName] == $prefix
) {
continue;
}
$prefix = 'xmlns' . (empty($prefix) ? '' : ':' . $prefix);
$xml->writeAttribute($prefix, $ns);
}
}
$this->write($xml, $data, static::$rootName);
$xml->endElement();
return $xml->outputMemory();
}
public function write(XMLWriter $xml, $data, $parent)
{
$text = array();
if (is_array($data)) {
if (static::$useTextNodeProperty && isset($data[static::$textNodeName])) {
$text [] = $data[static::$textNodeName];
unset($data[static::$textNodeName]);
}
$attributes = array_flip(static::$attributeNames);
//make sure we deal with attributes first
$temp = array();
foreach ($data as $key => $value) {
if (isset($attributes[$key])) {
$temp[$key] = $data[$key];
unset($data[$key]);
}
}
$data = array_merge($temp, $data);
foreach ($data as $key => $value) {
if (is_numeric($key)) {
if (!is_array($value)) {
$text [] = $value;
continue;
}
$key = static::$defaultTagName;
}
$useNS = static::$useNamespaces
&& !empty(static::$namespacedProperties[$key])
&& false === strpos($key, ':');
if (is_array($value)) {
$useNS
? $xml->startElementNs(
static::$namespacedProperties[$key],
$key,
null
)
: $xml->startElement($key);
$this->write($xml, $value, $key);
$xml->endElement();
continue;
} elseif (is_bool($value)) {
$value = $value ? 'true' : 'false';
}
if (isset($attributes[$key])) {
$xml->writeAttribute($useNS ? static::$namespacedProperties[$key] . ':' . $key : $key, $value);
} else {
$useNS
?
$xml->startElementNs(
static::$namespacedProperties[$key],
$key,
null
)
: $xml->startElement($key);
$this->write($xml, $value, $key);
$xml->endElement();
}
}
} else {
$text [] = (string)$data;
}
if (!empty($text)) {
if (count($text) == 1) {
in_array($parent, static::$cdataNames)
? $xml->writeCdata(implode('', $text))
: $xml->text(implode('', $text));
} else {
foreach ($text as $t) {
$xml->writeElement(static::$textNodeName, $t);
}
}
}
}
public function decode($data)
{
try {
if ($data == '') {
return array();
}
libxml_use_internal_errors(true);
libxml_disable_entity_loader(true);
$xml = simplexml_load_string($data,
"SimpleXMLElement", LIBXML_NOBLANKS | LIBXML_NOCDATA | LIBXML_COMPACT);
if (false === $xml) {
$error = libxml_get_last_error();
throw new RestException(400, 'Malformed XML. '
. trim($error->message, "\r\n") . ' at line ' . $error->line);
}
libxml_clear_errors();
if (static::$importSettingsFromXml) {
static::$attributeNames = array();
static::$namespacedProperties = array();
static::$namespaces = array();
static::$rootName = $xml->getName();
$namespaces = $xml->getNamespaces();
if (count($namespaces)) {
$p = strpos($data, $xml->getName());
if ($p && $data[$p - 1] == ':') {
$s = strpos($data, '<') + 1;
$prefix = substr($data, $s, $p - $s - 1);
static::$namespacedProperties[static::$rootName] = $prefix;
}
}
}
$data = $this->read($xml);
if (count($data) == 1 && isset($data[static::$textNodeName])) {
$data = $data[static::$textNodeName];
}
return $data;
} catch (\RuntimeException $e) {
throw new RestException(400,
"Error decoding request. " . $e->getMessage());
}
}
public function read(SimpleXMLElement $xml, $namespaces = null)
{
$r = array();
$text = (string)$xml;
if (static::$parseAttributes) {
$attributes = $xml->attributes();
foreach ($attributes as $key => $value) {
if (static::$importSettingsFromXml
&& !in_array($key, static::$attributeNames)
) {
static::$attributeNames[] = $key;
}
$r[$key] = static::setType((string)$value);
}
}
$children = $xml->children();
foreach ($children as $key => $value) {
if ($key == static::$defaultTagName) {
$r[] = $this->read($value);
} elseif (isset($r[$key])) {
if (is_array($r[$key])) {
if ($r[$key] != array_values($r[$key])) {
$r[$key] = array($r[$key]);
}
} else {
$r[$key] = array($r[$key]);
}
$r[$key][] = $this->read($value, $namespaces);
} else {
$r[$key] = $this->read($value);
}
}
if (static::$parseNamespaces) {
if (is_null($namespaces)) {
$namespaces = $xml->getDocNamespaces(true);
}
foreach ($namespaces as $prefix => $ns) {
static::$namespaces[$prefix] = $ns;
if (static::$parseAttributes) {
$attributes = $xml->attributes($ns);
foreach ($attributes as $key => $value) {
if (isset($r[$key])) {
$key = "{$prefix}:$key";
}
if (static::$importSettingsFromXml
&& !in_array($key, static::$attributeNames)
) {
static::$namespacedProperties[$key] = $prefix;
static::$attributeNames[] = $key;
}
$r[$key] = static::setType((string)$value);
}
}
$children = $xml->children($ns);
foreach ($children as $key => $value) {
if (static::$importSettingsFromXml) {
static::$namespacedProperties[$key] = $prefix;
}
if (isset($r[$key])) {
if (is_array($r[$key])) {
if ($r[$key] != array_values($r[$key])) {
$r[$key] = array($r[$key]);
}
} else {
$r[$key] = array($r[$key]);
}
$r[$key][] = $this->read($value, $namespaces);
} else {
$r[$key] = $this->read($value, $namespaces);
}
}
}
}
if (empty($text) && $text !== '0') {
if (empty($r)) {
return null;
}
} else {
empty($r)
? $r = static::setType($text)
: (
static::$parseTextNodeAsProperty
? $r[static::$textNodeName] = static::setType($text)
: $r[] = static::setType($text)
);
}
return $r;
}
public static function setType($value)
{
if (empty($value) && $value !== '0') {
return null;
}
if ($value == 'true') {
return true;
}
if ($value == 'false') {
return true;
}
if (is_numeric($value)) {
return 0 + $value;
}
return $value;
}
}
Zerion Mini Shell 1.0