mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 19:38:26 +00:00
683 lines
15 KiB
PHP
683 lines
15 KiB
PHP
|
<?php
|
||
|
/* SVN FILE: $Id$ */
|
||
|
|
||
|
/**
|
||
|
* XML handling for Cake.
|
||
|
*
|
||
|
* The methods in these classes enable the datasources that use XML to work.
|
||
|
*
|
||
|
* PHP versions 4 and 5
|
||
|
*
|
||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||
|
* Copyright (c) 2005, Cake Software Foundation, Inc.
|
||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||
|
* Las Vegas, Nevada 89104
|
||
|
*
|
||
|
* Licensed under The MIT License
|
||
|
* Redistributions of files must retain the above copyright notice.
|
||
|
*
|
||
|
* @filesource
|
||
|
* @copyright Copyright (c) 2005, Cake Software Foundation, Inc.
|
||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||
|
* @package cake
|
||
|
* @subpackage cake.cake.libs
|
||
|
* @since CakePHP v .0.10.3.1400
|
||
|
* @version $Revision$
|
||
|
* @modifiedby $LastChangedBy$
|
||
|
* @lastmodified $Date$
|
||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* XML handling.
|
||
|
*
|
||
|
* Operations on XML data.
|
||
|
*
|
||
|
* @package cake
|
||
|
* @subpackage cake.cake.libs
|
||
|
* @since CakePHP v .0.10.3.1400
|
||
|
*/
|
||
|
class XML extends XMLNode
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
* Resource handle to XML parser.
|
||
|
*
|
||
|
* @var resource
|
||
|
*/
|
||
|
var $__parser;
|
||
|
|
||
|
/**
|
||
|
* File handle to XML indata file.
|
||
|
*
|
||
|
* @var resource
|
||
|
*/
|
||
|
var $__file;
|
||
|
|
||
|
/**
|
||
|
* Raw XML string data (for loading purposes)
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
var $__rawData = null;
|
||
|
|
||
|
/**
|
||
|
* XML document header
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
var $__header = null;
|
||
|
|
||
|
/**
|
||
|
* XML document version
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
var $version = '1.0';
|
||
|
|
||
|
/**
|
||
|
* XML document encoding
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
var $encoding = 'UTF-8';
|
||
|
|
||
|
/**
|
||
|
* Constructor. Sets up the XML parser with options, gives it this object as
|
||
|
* its XML object, and sets some variables.
|
||
|
*
|
||
|
* @param string $input
|
||
|
*/
|
||
|
function __construct($input = null, $options = array())
|
||
|
{
|
||
|
parent::__construct('root');
|
||
|
$this->__parser = xml_parser_create_ns();
|
||
|
|
||
|
xml_set_object($this->__parser, $this);
|
||
|
xml_parser_set_option($this->__parser, XML_OPTION_CASE_FOLDING, 0);
|
||
|
xml_parser_set_option($this->__parser, XML_OPTION_SKIP_WHITE, 1);
|
||
|
|
||
|
$this->childNodes = array();
|
||
|
|
||
|
if($input != null)
|
||
|
{
|
||
|
$this->load($input);
|
||
|
}
|
||
|
|
||
|
foreach ($options as $key => $val)
|
||
|
{
|
||
|
switch ($key)
|
||
|
{
|
||
|
case 'version':
|
||
|
$this->version = $val;
|
||
|
break;
|
||
|
case 'encoding':
|
||
|
$this->encoding = $val;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initialize XML object from a given XML string. Returns false on error.
|
||
|
*
|
||
|
* @param string $in
|
||
|
* @return boolean Success
|
||
|
*/
|
||
|
function load($in)
|
||
|
{
|
||
|
$this->__rawData = null;
|
||
|
$this->header = null;
|
||
|
|
||
|
if(strstr($in, "<"))
|
||
|
{
|
||
|
// Input is raw xml data
|
||
|
$this->__rawData = $in;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Input is an xml file
|
||
|
if(strpos($in, '://') || file_exists($in))
|
||
|
{
|
||
|
$this->__rawData = @file_get_contents($in);
|
||
|
if ($this->__rawData == null)
|
||
|
{
|
||
|
$this->error("XML file $in is empty or could not be read (possible permissions error).");
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$this->error("XML file $in does not exist");
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return $this->parse();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Parses and creates XML nodes from the __rawData property.
|
||
|
*
|
||
|
* @see load()
|
||
|
*
|
||
|
*/
|
||
|
function parse()
|
||
|
{
|
||
|
$this->header = trim(r(a('<'.'?', '?'.'>'), a('', ''), substr(trim($this->__rawData), 0, strpos($this->__rawData, "\n"))));
|
||
|
|
||
|
xml_parse_into_struct($this->__parser, $this->__rawData, $vals);
|
||
|
$xml = new XMLNode();
|
||
|
|
||
|
$count = count($vals);
|
||
|
for ($i = 0; $i < $count; $i++)
|
||
|
{
|
||
|
$data = $vals[$i];
|
||
|
switch($data['type'])
|
||
|
{
|
||
|
case "open" :
|
||
|
$tmpXML = new XMLNode();
|
||
|
$tmpXML->name = $data['tag'];
|
||
|
if(isset($data['value']))
|
||
|
{
|
||
|
$tmpXML->value = $data['value'];
|
||
|
}
|
||
|
if(isset($data['attributes']))
|
||
|
{
|
||
|
$tmpXML->attributes = $data['attributes'];
|
||
|
}
|
||
|
|
||
|
$tmpXML->__parentNode =& $xml;
|
||
|
$ct = count($xml->childNodes);
|
||
|
$xml->childNodes[$ct] = $tmpXML;
|
||
|
$xml =& $xml->childNodes[$ct];
|
||
|
break;
|
||
|
|
||
|
case "close" :
|
||
|
$xml =& $xml->parentNode();
|
||
|
break;
|
||
|
|
||
|
case "complete" :
|
||
|
$tmpXML = new XMLNode();
|
||
|
$tmpXML->name = $data['tag'];
|
||
|
if(isset($data['value']))
|
||
|
{
|
||
|
$tmpXML->value = $data['value'];
|
||
|
}
|
||
|
if(isset($data['attributes']))
|
||
|
{
|
||
|
$tmpXML->attributes = $data['attributes'];
|
||
|
}
|
||
|
|
||
|
$tmpXML->__parentNode =& $xml;
|
||
|
$xml->childNodes[] = $tmpXML;
|
||
|
break;
|
||
|
case 'cdata':
|
||
|
if (is_string($xml->value))
|
||
|
{
|
||
|
$xml->value = a($xml->value, $data['value']);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$xml->value[] = $data['value'];
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
$this->childNodes =& $xml->childNodes;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a string representation of the XML object
|
||
|
*
|
||
|
* @param boolean $header Whether to include the XML header with the document (defaults to true)
|
||
|
* @return string XML data
|
||
|
*/
|
||
|
function compose($header = true)
|
||
|
{
|
||
|
$header = '<'.'?'.$this->header.' ?'.'>'."\n";
|
||
|
if (!$this->hasChildNodes() && !$header)
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
elseif (!$this->hasChildNodes())
|
||
|
{
|
||
|
return $header;
|
||
|
}
|
||
|
|
||
|
$data = $this->childNodes[0]->__toString();
|
||
|
if ($header)
|
||
|
{
|
||
|
return $header.$data;
|
||
|
}
|
||
|
return $data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* If DEBUG is on, this method echoes an error message.
|
||
|
*
|
||
|
* @param string $msg Error message
|
||
|
* @param integer $code Error code
|
||
|
* @param integer $line Line in file
|
||
|
*/
|
||
|
function error($msg, $code = 0, $line = 0)
|
||
|
{
|
||
|
if(DEBUG)
|
||
|
{
|
||
|
echo $msg . " " . $code . " " . $line;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a string with a textual description of the error code, or FALSE if no description was found.
|
||
|
*
|
||
|
* @param integer $code
|
||
|
* @return string Error message
|
||
|
*/
|
||
|
function getError($code)
|
||
|
{
|
||
|
$r = @xml_error_string($code);
|
||
|
return $r;
|
||
|
}
|
||
|
|
||
|
// Overridden functions from superclass
|
||
|
|
||
|
/**
|
||
|
* Enter description here...
|
||
|
*
|
||
|
* @return unknown
|
||
|
*/
|
||
|
function &nextSibling()
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Enter description here...
|
||
|
*
|
||
|
* @return null
|
||
|
*/
|
||
|
function &previousSibling()
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Enter description here...
|
||
|
*
|
||
|
* @return null
|
||
|
*/
|
||
|
function &parentNode()
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
function __destruct()
|
||
|
{
|
||
|
if (is_resource($this->__parser))
|
||
|
{
|
||
|
xml_parser_free($this->__parser);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* XML node.
|
||
|
*
|
||
|
* Single XML node in an XML tree.
|
||
|
*
|
||
|
* @package cake
|
||
|
* @subpackage cake.cake.libs
|
||
|
* @since CakePHP v .0.10.3.1400
|
||
|
*/
|
||
|
class XMLNode extends Object
|
||
|
{
|
||
|
/**
|
||
|
* Name of node
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
var $name = null;
|
||
|
|
||
|
/**
|
||
|
* Value of node
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
var $value;
|
||
|
|
||
|
/**
|
||
|
* Attributes on this node
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
var $attributes = array();
|
||
|
|
||
|
/**
|
||
|
* This node's children
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
var $childNodes = array();
|
||
|
|
||
|
/**
|
||
|
* Reference to parent node.
|
||
|
*
|
||
|
* @var XMLNode
|
||
|
*/
|
||
|
var $__parentNode = null;
|
||
|
|
||
|
/**
|
||
|
* Constructor.
|
||
|
*
|
||
|
* @param string $name Node name
|
||
|
*/
|
||
|
function __construct($name = null)
|
||
|
{
|
||
|
$this->name = $name;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a copy of self.
|
||
|
*
|
||
|
* @return XMLNode
|
||
|
*/
|
||
|
function cloneNode()
|
||
|
{
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Append given node as a child.
|
||
|
*
|
||
|
* @param XMLNode $child
|
||
|
*/
|
||
|
function &appendChild(&$child)
|
||
|
{
|
||
|
if (is_object($child))
|
||
|
{
|
||
|
$this->childNodes[] =& $child;
|
||
|
}
|
||
|
elseif (is_string($child))
|
||
|
{
|
||
|
$attr = array();
|
||
|
if (func_num_args() >= 2 && is_array(func_get_arg(1)))
|
||
|
{
|
||
|
$attr = func_get_arg(1);
|
||
|
}
|
||
|
$tmp = new XMLNode();
|
||
|
$tmp->name = $child;
|
||
|
$tmp->attributes = $attr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns first child node, or null if empty.
|
||
|
*
|
||
|
* @return XMLNode
|
||
|
*/
|
||
|
function &firstChild()
|
||
|
{
|
||
|
if(isset($this->childNodes[0]))
|
||
|
{
|
||
|
return $this->childNodes[0];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns last child node, or null if empty.
|
||
|
*
|
||
|
* @return XMLNode
|
||
|
*/
|
||
|
function &lastChild()
|
||
|
{
|
||
|
if(count($this->childNodes) > 0)
|
||
|
{
|
||
|
return $this->childNodes[count($this->childNodes) - 1];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns child node with given ID.
|
||
|
*
|
||
|
* @param string $id Name of childnode
|
||
|
* @return XMLNode
|
||
|
*
|
||
|
*/
|
||
|
function &getChild($id)
|
||
|
{
|
||
|
if(is_int($id))
|
||
|
{
|
||
|
if(isset($this->childNodes[$id]))
|
||
|
{
|
||
|
return $this->childNodes[$id];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
elseif(is_string($id))
|
||
|
{
|
||
|
for($i = 0; $i < count($this->childNodes); $i++)
|
||
|
{
|
||
|
if($this->childNodes[$i]->name == $id)
|
||
|
{
|
||
|
return $this->childNodes[$i];
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets a list of childnodes with the given tag name.
|
||
|
*
|
||
|
* @param string $name Tag name of child nodes
|
||
|
* @return array An array of XMLNodes with the given tag name
|
||
|
*/
|
||
|
function getChildren($name)
|
||
|
{
|
||
|
$nodes = array();
|
||
|
$count = count($this->childNodes);
|
||
|
for($i = 0; $i < $count; $i++)
|
||
|
{
|
||
|
if($this->childNodes[$i]->name == $name)
|
||
|
{
|
||
|
$nodes[] =& $this->childNodes[$i];
|
||
|
}
|
||
|
}
|
||
|
return $nodes;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets a reference to the next child node in the list of this node's parent
|
||
|
*
|
||
|
* @return XMLNode A reference to the XMLNode object
|
||
|
*/
|
||
|
function &nextSibling()
|
||
|
{
|
||
|
$count = count($this->__parentNode->childNodes);
|
||
|
for ($i = 0; $i < $count; $i++)
|
||
|
{
|
||
|
if ($this->__parentNode->childNodes === $this)
|
||
|
{
|
||
|
if ($i >= $count - 1 || !isset($this->__parentNode->childNodes[$i + 1]))
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
return $this->__parentNode->childNodes[$i + 1];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets a reference to the previous child node in the list of this node's parent
|
||
|
*
|
||
|
* @return XMLNode A reference to the XMLNode object
|
||
|
*/
|
||
|
function &previousSibling()
|
||
|
{
|
||
|
$count = count($this->__parentNode->childNodes);
|
||
|
for ($i = 0; $i < $count; $i++)
|
||
|
{
|
||
|
if ($this->__parentNode->childNodes === $this)
|
||
|
{
|
||
|
if ($i == 0 || !isset($this->__parentNode->childNodes[$i - 1]))
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
return $this->__parentNode->childNodes[$i - 1];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns parent node.
|
||
|
*
|
||
|
* @return XMLNode
|
||
|
*/
|
||
|
function &parentNode()
|
||
|
{
|
||
|
return $this->__parentNode;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if this structure has child nodes.
|
||
|
*
|
||
|
* @return boolean
|
||
|
*/
|
||
|
function hasChildNodes()
|
||
|
{
|
||
|
if(is_array($this->childNodes) && count($this->childNodes) > 0)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns this XML structure as a string.
|
||
|
*
|
||
|
* @return string String representation of the XML structure.
|
||
|
*/
|
||
|
function toString()
|
||
|
{
|
||
|
$d = '';
|
||
|
if($this->name != '')
|
||
|
{
|
||
|
$d .= '<' . $this->name;
|
||
|
if(is_array($this->attributes) && count($this->attributes) > 0)
|
||
|
{
|
||
|
foreach($this->attributes as $key => $val)
|
||
|
{
|
||
|
$d .= " $key=\"$val\"";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(!$this->hasChildNodes() && empty($this->value))
|
||
|
{
|
||
|
if($this->name != '')
|
||
|
{
|
||
|
$d .= " />\n";
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if($this->name != '')
|
||
|
{
|
||
|
$d .= ">";
|
||
|
}
|
||
|
if($this->hasChildNodes())
|
||
|
{
|
||
|
if (is_string($this->value) || empty($this->value))
|
||
|
{
|
||
|
if (!empty($this->value))
|
||
|
{
|
||
|
$d .= $this->value;
|
||
|
}
|
||
|
$count = count($this->childNodes);
|
||
|
|
||
|
for($i = 0; $i < $count; $i++)
|
||
|
{
|
||
|
$d .= $this->childNodes[$i]->toString();
|
||
|
}
|
||
|
}
|
||
|
elseif (is_array($this->value))
|
||
|
{
|
||
|
$count = count($this->value);
|
||
|
for($i = 0; $i < $count; $i++)
|
||
|
{
|
||
|
$d .= $this->value[$i];
|
||
|
if (isset($this->childNodes[$i]))
|
||
|
{
|
||
|
$d .= $this->childNodes[$i]->toString();
|
||
|
}
|
||
|
}
|
||
|
$count = count($this->childNodes);
|
||
|
if ($i < $count)
|
||
|
{
|
||
|
for ($i = $i; $i < $count; $i++)
|
||
|
{
|
||
|
$d .= $this->childNodes[$i]->toString();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (is_string($this->value))
|
||
|
{
|
||
|
$d .= $this->value;
|
||
|
}
|
||
|
|
||
|
if($this->name != '')
|
||
|
{
|
||
|
$d .= "</" . $this->name . ">\n";
|
||
|
}
|
||
|
}
|
||
|
return $d;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns data from toString when this object is converted to a string.
|
||
|
*
|
||
|
* @return string String representation of this structure.
|
||
|
*/
|
||
|
function __toString()
|
||
|
{
|
||
|
return $this->toString();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Magic method. Deletes the parentNode. Also deletes this node's children,
|
||
|
* if given the $recursive parameter.
|
||
|
*
|
||
|
* @param boolean $recursive
|
||
|
*/
|
||
|
function __killParent($recursive = true)
|
||
|
{
|
||
|
unset($this->__parentNode);
|
||
|
if($recursive && $this->hasChildNodes())
|
||
|
{
|
||
|
for($i = 0; $i < count($this->childNodes); $i++)
|
||
|
{
|
||
|
$this->childNodes[$i]->__killParent(true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
?>
|