/gforge/plugins/wiki/www/lib/XmlElement.php
PHP | 645 lines | 554 code | 36 blank | 55 comment | 45 complexity | 48870bb3e35783784a9123ea5a013880 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception
- <?php rcs_id('$Id: XmlElement.php,v 1.38 2005/10/10 19:36:09 rurban Exp $');
- /**
- * Code for writing XML.
- * @package Markup
- * @author: Jeff Dairiki,
- * Reini Urban (php5 tricks)
- *
- * WARNING: This module is very php5 sensitive.
- * Fixed for 1.3.9 and 1.3.11.
- * With allow_call_time_pass_reference clean fixes.
- */
- /**
- * A sequence of (zero or more) XmlElements (possibly interspersed with
- * plain strings (CDATA).
- */
- class XmlContent
- {
- function XmlContent (/* ... */) {
- $this->_content = array();
- $this->_pushContent_array(func_get_args());
- }
- function pushContent ($arg /*, ...*/) {
- if (func_num_args() > 1)
- $this->_pushContent_array(func_get_args());
- elseif (is_array($arg))
- $this->_pushContent_array($arg);
- else
- $this->_pushContent($arg);
- }
- function _pushContent_array ($array) {
- foreach ($array as $item) {
- if (is_array($item))
- $this->_pushContent_array($item);
- else
- $this->_pushContent($item);
- }
- }
- function _pushContent ($item) {
- if (strtolower(get_class($item)) == 'xmlcontent')
- array_splice($this->_content, count($this->_content), 0,
- $item->_content);
- else
- $this->_content[] = $item;
- }
- function unshiftContent ($arg /*, ...*/) {
- if (func_num_args() > 1)
- $this->_unshiftContent_array(func_get_args());
- elseif (is_array($arg))
- $this->_unshiftContent_array($arg);
- else
- $this->_unshiftContent($arg);
- }
- function _unshiftContent_array ($array) {
- foreach (array_reverse($array) as $item) {
- if (is_array($item))
- $this->_unshiftContent_array($item);
- else
- $this->_unshiftContent($item);
- }
- }
- function _unshiftContent ($item) {
- if (strtolower(get_class($item)) == 'xmlcontent')
- array_splice($this->_content, 0, 0, $item->_content);
- else
- array_unshift($this->_content, $item);
- }
-
- function getContent () {
- return $this->_content;
- }
- function setContent ($arg /* , ... */) {
- $this->_content = array();
- $this->_pushContent_array(func_get_args());
- }
- function printXML () {
- foreach ($this->_content as $item) {
- if (is_object($item)) {
- if (method_exists($item, 'printXML'))
- $item->printXML();
- elseif (method_exists($item, 'asXML'))
- echo $item->asXML();
- elseif (method_exists($item, 'asString'))
- echo $this->_quote($item->asString());
- else
- printf("==Object(%s)==", get_class($item));
- }
- else
- echo $this->_quote((string) $item);
- }
- }
- function asXML () {
- $xml = '';
- foreach ($this->_content as $item) {
- if (is_object($item)) {
- if (method_exists($item, 'asXML'))
- $xml .= $item->asXML();
- elseif (method_exists($item, 'asString'))
- $xml .= $this->_quote($item->asString());
- else
- $xml .= sprintf("==Object(%s)==", get_class($item));
- }
- else
- $xml .= $this->_quote((string) $item);
- }
- return $xml;
- }
- function asPDF () {
- $pdf = '';
- foreach ($this->_content as $item) {
- if (is_object($item)) {
- if (method_exists($item, 'asPDF'))
- $pdf .= $item->asPDF();
- elseif (method_exists($item, 'asString'))
- $pdf .= $this->_quote($item->asString());
- else
- $pdf .= sprintf("==Object(%s)==", get_class($item));
- }
- else
- $pdf .= $this->_quote((string) $item);
- }
- return $pdf;
- }
- function asString () {
- $val = '';
- foreach ($this->_content as $item) {
- if (is_object($item)) {
- if (method_exists($item, 'asString'))
- $val .= $item->asString();
- else
- $val .= sprintf("==Object(%s)==", get_class($item));
- }
- else
- $val .= (string) $item;
- }
- return trim($val);
- }
- /**
- * See if element is empty.
- *
- * Empty means it has no content.
- * @return bool True if empty.
- */
- function isEmpty () {
- if (empty($this->_content))
- return true;
- foreach ($this->_content as $x) {
- if (is_string($x) ? strlen($x) : !empty($x))
- return false;
- }
- return true;
- }
-
- function _quote ($string) {
- if (!$string) return $string;
- if (check_php_version(4,1) and isset($GLOBALS['charset']))
- return htmlspecialchars($string, ENT_COMPAT, $GLOBALS['charset']);
- else
- return htmlspecialchars($string);
- }
- };
- /**
- * An XML element.
- *
- * @param $tagname string Tag of html element.
- */
- class XmlElement extends XmlContent
- {
- function XmlElement ($tagname /* , $attr_or_content , ...*/) {
- //FIXME: php5 incompatible
- $this->XmlContent();
- $this->_init(func_get_args());
- }
- function _init ($args) {
- if (!is_array($args))
- $args = func_get_args();
- assert(count($args) >= 1);
- //assert(is_string($args[0]));
- $this->_tag = array_shift($args);
-
- if ($args && is_array($args[0]))
- $this->_attr = array_shift($args);
- else {
- $this->_attr = array();
- if ($args && $args[0] === false)
- array_shift($args);
- }
- $this->setContent($args);
- }
-
- /** Methods only needed for XmlParser,
- * to be fully compatible to perl Html::Element
- */
- // doesn't yet work with php5 as __destruct()
- function _destruct () {
- if ($this->hasChildren()) {
- foreach ($this->getChildren() as $node) {
- $node->_destruct();
- }
- }
- unset($this->_tag);
- unset($this->_attr);
- unset($this->_content);
- }
-
- function getChildren () {
- return $this->_children;
- }
- function hasChildren () {
- return !empty($this->_children);
- }
- /* End XmlParser Methods
- */
- function getTag () {
- return $this->_tag;
- }
-
- function setAttr ($attr, $value = false) {
- if (is_array($attr)) {
- assert($value === false);
- foreach ($attr as $a => $v) {
- $this->_attr[strtolower($a)] = $v;
- //$this->set($a, $v);
- }
- return;
- }
- assert(is_string($attr));
-
- if ($value === false) {
- unset($this->_attr[$attr]);
- }
- else {
- if (is_bool($value))
- $value = $attr;
- $this->_attr[$attr] = (string) $value;
- }
- if ($attr == 'class')
- unset($this->_classes);
- }
- function getAttr ($attr) {
- if ($attr == 'class')
- $this->_setClasses();
- if (isset($this->_attr[strtolower($attr)]))
- return $this->_attr[strtolower($attr)];
- else
- return false;
- }
- function _getClasses() {
- if (!isset($this->_classes)) {
- $this->_classes = array();
- if (isset($this->_attr['class'])) {
- $classes = explode(' ', (string) $this->_attr['class']);
- foreach ($classes as $class) {
- $class = trim($class);
- if ($class)
- $this->_classes[$class] = $class;
- }
- }
- }
- return $this->_classes;
- }
- function _setClasses() {
- if (isset($this->_classes)) {
- if ($this->_classes)
- $this->_attr['class'] = join(' ', $this->_classes);
- else
- unset($this->_attr['class']);
- }
- }
- /**
- * Manipulate the elements CSS class membership.
- *
- * This adds or remove an elements membership
- * in a give CSS class.
- *
- * @param $class string
- *
- * @param $in_class bool
- * If true (the default) the element is added to class $class.
- * If false, the element is removed from the class.
- */
- function setInClass($class, $in_class=true) {
- $this->_getClasses();
- $class = trim($class);
- if ($in_class)
- $this->_classes[$class] = $class;
- else
- unset($this->_classes[$class]);
- }
- /**
- * Is element in a given (CSS) class?
- *
- * This checks for the presence of a particular class in the
- * elements 'class' attribute.
- *
- * @param $class string The class to check for.
- * @return bool True if the element is a member of $class.
- */
- function inClass($class) {
- $this->_parseClasses();
- return isset($this->_classes[trim($class)]);
- }
- function startTag() {
- $start = "<" . $this->_tag;
- $this->_setClasses();
- foreach ($this->_attr as $attr => $val) {
- if (is_bool($val)) {
- if (!$val)
- continue;
- $val = $attr;
- }
- $qval = str_replace("\"", '"', $this->_quote((string)$val));
- $start .= " $attr=\"$qval\"";
- }
- $start .= ">";
- return $start;
- }
- function emptyTag() {
- return substr($this->startTag(), 0, -1) . "/>";
- }
-
- function endTag() {
- return "</$this->_tag>";
- }
-
-
- function printXML () {
- if ($this->isEmpty())
- echo $this->emptyTag();
- else {
- echo $this->startTag();
- // FIXME: The next two lines could be removed for efficiency
- if (!$this->hasInlineContent())
- echo "\n";
- XmlContent::printXML();
- echo "</$this->_tag>";
- }
- if (!$this->isInlineElement())
- echo "\n";
- }
- function asXML () {
- if ($this->isEmpty()) {
- $xml = $this->emptyTag();
- }
- else {
- $xml = $this->startTag();
- // FIXME: The next two lines could be removed for efficiency
- if (!$this->hasInlineContent())
- $xml .= "\n";
- $xml .= XmlContent::asXML();
- $xml .= "</$this->_tag>";
- }
- if (!$this->isInlineElement())
- $xml .= "\n";
- return $xml;
- }
- /**
- * Can this element have inline content?
- *
- * This is a hack, but is probably the best one can do without
- * knowledge of the DTD...
- */
- function hasInlineContent () {
- // This is a hack.
- if (empty($this->_content))
- return true;
- if (is_object($this->_content[0]))
- return false;
- return true;
- }
-
- /**
- * Is this element part of inline content?
- *
- * This is a hack, but is probably the best one can do without
- * knowledge of the DTD...
- */
- function isInlineElement () {
- return false;
- }
-
- };
- class RawXml {
- function RawXml ($xml_text) {
- $this->_xml = $xml_text;
- }
- function printXML () {
- echo $this->_xml;
- }
- function asXML () {
- return $this->_xml;
- }
- function isEmpty () {
- return empty($this->_xml);
- }
- }
- class FormattedText {
- function FormattedText ($fs /* , ... */) {
- if ($fs !== false) {
- $this->_init(func_get_args());
- }
- }
- function _init ($args) {
- $this->_fs = array_shift($args);
- // PHP's sprintf doesn't support variable width specifiers,
- // like sprintf("%*s", 10, "x"); --- so we won't either.
- $m = array();
- if (! preg_match_all('/(?<!%)%(\d+)\$/x', $this->_fs, $m)) {
- $this->_args = $args;
- }
- else {
- // Format string has '%2$s' style argument reordering.
- // PHP doesn't support this.
- if (preg_match('/(?<!%)%[- ]?\d*[^- \d$]/x', $this->_fs)) // $fmt
- // literal variable name substitution only to keep locale
- // strings uncluttered
- trigger_error(sprintf(_("Can't mix '%s' with '%s' type format strings"),
- '%1\$s','%s'), E_USER_WARNING);
-
- $this->_fs = preg_replace('/(?<!%)%\d+\$/x', '%', $this->_fs);
- $this->_args = array();
- foreach($m[1] as $argnum) {
- if ($argnum < 1 || $argnum > count($args))
- trigger_error(sprintf("%s: argument index out of range",
- $argnum), E_USER_WARNING);
- $this->_args[] = $args[$argnum - 1];
- }
- }
- }
- function asXML () {
- // Not all PHP's have vsprintf, so...
- $args[] = XmlElement::_quote((string)$this->_fs);
- foreach ($this->_args as $arg)
- $args[] = AsXML($arg);
- return call_user_func_array('sprintf', $args);
- }
- function printXML () {
- // Not all PHP's have vsprintf, so...
- $args[] = XmlElement::_quote((string)$this->_fs);
- foreach ($this->_args as $arg)
- $args[] = AsXML($arg);
- call_user_func_array('printf', $args);
- }
- function asString() {
- $args[] = $this->_fs;
- foreach ($this->_args as $arg)
- $args[] = AsString($arg);
- return call_user_func_array('sprintf', $args);
- }
- }
- /**
- * PHP5 compatibility
- * Error[2048]: Non-static method XmlContent::_quote() should not be called statically
- */
- function XmlContent_quote ($string) {
- if (!$string) return $string;
- if (check_php_version(4,1) and isset($GLOBALS['charset']))
- return htmlspecialchars($string, ENT_COMPAT, $GLOBALS['charset']);
- else
- return htmlspecialchars($string);
- }
- function PrintXML ($val /* , ... */ ) {
- if (func_num_args() > 1) {
- foreach (func_get_args() as $arg)
- PrintXML($arg);
- }
- elseif (is_object($val)) {
- if (method_exists($val, 'printXML'))
- $val->printXML();
- elseif (method_exists($val, 'asXML')) {
- echo $val->asXML();
- }
- elseif (method_exists($val, 'asString'))
- echo XmlContent_quote($val->asString());
- else
- printf("==Object(%s)==", get_class($val));
- }
- elseif (is_array($val)) {
- // DEPRECATED:
- // Use XmlContent objects instead of arrays for collections of XmlElements.
- trigger_error("Passing arrays to PrintXML() is deprecated: (" . AsXML($val, true) . ")",
- E_USER_NOTICE);
- foreach ($val as $x)
- PrintXML($x);
- }
- else
- echo (string)XmlContent_quote((string)$val);
- }
- function AsXML ($val /* , ... */) {
- static $nowarn;
- if (func_num_args() > 1) {
- $xml = '';
- foreach (func_get_args() as $arg)
- $xml .= AsXML($arg);
- return $xml;
- }
- elseif (is_object($val)) {
- if (method_exists($val, 'asXML'))
- return $val->asXML();
- elseif (method_exists($val, 'asString'))
- return XmlContent_quote($val->asString());
- else
- return sprintf("==Object(%s)==", get_class($val));
- }
- elseif (is_array($val)) {
- // DEPRECATED:
- // Use XmlContent objects instead of arrays for collections of XmlElements.
- if (empty($nowarn)) {
- $nowarn = true;
- trigger_error("Passing arrays to AsXML() is deprecated: (" . AsXML($val) . ")",
- E_USER_NOTICE);
- unset($nowarn);
- }
- $xml = '';
- foreach ($val as $x)
- $xml .= AsXML($x);
- return $xml;
- }
- else
- return XmlContent_quote((string)$val);
- }
- function AsString ($val) {
- if (func_num_args() > 1) {
- $str = '';
- foreach (func_get_args() as $arg)
- $str .= AsString($arg);
- return $str;
- }
- elseif (is_object($val)) {
- if (method_exists($val, 'asString'))
- return $val->asString();
- else
- return sprintf("==Object(%s)==", get_class($val));
- }
- elseif (is_array($val)) {
- // DEPRECATED:
- // Use XmlContent objects instead of arrays for collections of XmlElements.
- trigger_error("Passing arrays to AsString() is deprecated", E_USER_NOTICE);
- $str = '';
- foreach ($val as $x)
- $str .= AsString($x);
- return $str;
- }
-
- return (string) $val;
- }
- function fmt ($fs /* , ... */) {
- $s = new FormattedText(false);
- $args = func_get_args();
- $args[0] = _($args[0]);
- $s->_init($args);
- return $s;
- }
- // $Log: XmlElement.php,v $
- // Revision 1.38 2005/10/10 19:36:09 rurban
- // fix comment
- //
- // Revision 1.37 2005/01/25 07:04:27 rurban
- // case-sensitive for php5
- //
- // Revision 1.36 2004/12/06 19:49:56 rurban
- // enable action=remove which is undoable and seeable in RecentChanges: ADODB ony for now.
- // renamed delete_page to purge_page.
- // enable action=edit&version=-1 to force creation of a new version.
- // added BABYCART_PATH config
- // fixed magiqc in adodb.inc.php
- // and some more docs
- //
- // Revision 1.35 2004/11/21 11:59:18 rurban
- // remove final \n to be ob_cache independent
- //
- // Revision 1.34 2004/10/12 13:13:19 rurban
- // php5 compatibility (5.0.1 ok)
- //
- // Revision 1.33 2004/07/02 09:55:58 rurban
- // more stability fixes: new DISABLE_GETIMAGESIZE if your php crashes when loading LinkIcons: failing getimagesize in old phps; blockparser stabilized
- //
- // Revision 1.32 2004/06/20 15:30:05 rurban
- // get_class case-sensitivity issues
- //
- // Revision 1.31 2004/06/20 14:42:54 rurban
- // various php5 fixes (still broken at blockparser)
- //
- // (c-file-style: "gnu")
- // Local Variables:
- // mode: php
- // tab-width: 8
- // c-basic-offset: 4
- // c-hanging-comment-ender-p: nil
- // indent-tabs-mode: nil
- // End:
- ?>