XML_XUL
[ class tree: XML_XUL ] [ index: XML_XUL ] [ all elements ]

Source for file Element.php

Documentation is available at Element.php

  1. <?PHP
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 5                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2002 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Stephan Schmidt <schst@php.net>                             |
  17. // +----------------------------------------------------------------------+
  18. // $Id$
  19.  
  20. require_once 'XML/Util2.php';
  21. require_once 'XML/XUL/Exception.php';
  22.  
  23. /**
  24.  * XML/XUL/Element.php
  25.  *
  26.  * Base class for all elements
  27.  *
  28.  * @package  XML_XUL
  29.  * @author   Stephan Schmidt <schst@php.net>
  30.  */
  31.  
  32. /**
  33.  * unknown element
  34.  */ 
  35. define('XML_XUL_ERROR_ELEMENT_NOT_FOUND'150);
  36.  
  37. /**
  38.  * unknown attribute
  39.  */ 
  40. define('XML_XUL_ERROR_ATTRIBUTE_UNKNOWN'200);
  41.  
  42. /**
  43.  * attribute is no integer
  44.  */ 
  45. define('XML_XUL_ERROR_ATTRIBUTE_NO_INTEGER'201);
  46.  
  47. /**
  48.  * attribute is no integer
  49.  */ 
  50. define('XML_XUL_ERROR_ATTRIBUTE_NO_BOOLEAN'202);
  51.  
  52. /**
  53.  * attribute contains invalid value
  54.  */ 
  55. define('XML_XUL_ERROR_ATTRIBUTE_INVALID_VALUE'203);
  56.  
  57. /**
  58.  * XML/XUL/Element.php
  59.  *
  60.  * Base class for all elements
  61.  *
  62.  * @package  XML_XUL
  63.  * @author   Stephan Schmidt <schst@php.net>
  64.  */
  65. {
  66.    /**
  67.     * element name
  68.     *
  69.     * @access public
  70.     * @var  string 
  71.     */
  72.     var $elementName;
  73.  
  74.    /**
  75.     * namespace for XUL elements
  76.     *
  77.     * @access private
  78.     * @var  string 
  79.     */
  80.     var $_ns;
  81.  
  82.    /**
  83.     * namespace for HTML elements
  84.     *
  85.     * @access private
  86.     * @var    string 
  87.     */
  88.     var $_htmlNs = null;
  89.  
  90.    /**
  91.     * attributes of the element
  92.     *
  93.     * @access   public
  94.     * @var      array 
  95.     */
  96.     var $attributes   =   array();
  97.  
  98.    /**
  99.     * childNodes of the element
  100.     *
  101.     * @access   public
  102.     * @var      array 
  103.     */
  104.     var $childNodes   =   array();
  105.  
  106.    /**
  107.     * cdata of the element
  108.     *
  109.     * @access   public
  110.     * @var      string 
  111.     */
  112.     var $cdata;
  113.  
  114.    /**
  115.     * stores a reference to the document that created the
  116.     * element
  117.     *
  118.     * @access   private
  119.     * @var      object XML_XUL_Document 
  120.     */
  121.     var $_doc;
  122.  
  123.    /**
  124.     * indicates whether the element is the root element
  125.     *
  126.     * @access   public
  127.     * @var      boolean 
  128.     */
  129.     var $isRoot = false;
  130.  
  131.    /**
  132.     * common attributes
  133.     *
  134.     * These attributes are supported by all elements
  135.     *
  136.     * @access   private
  137.     * @var      array 
  138.     */
  139.     var $_commonAttribs = array(
  140.                                 'align' => array(
  141.                                                    'required' => false,
  142.                                                    'type'     => 'enum',
  143.                                                    'values'   => array'baseline''center''end''start''stretch' )
  144.                                                 ),
  145.                                 'allowevents' => array(
  146.                                                    'required' => false,
  147.                                                    'type'     => 'boolean',
  148.                                                 ),
  149.                                 'class' => array(
  150.                                                    'required' => false,
  151.                                                    'type'     => 'string',
  152.                                                 ),
  153.                                 'collapsed' => array(
  154.                                                    'required' => false,
  155.                                                    'type'     => 'boolean',
  156.                                                 ),
  157.                                 'container' => array(
  158.                                                    'required' => false,
  159.                                                    'type'     => 'boolean',
  160.                                                 ),
  161.                                 'containment' => array(
  162.                                                    'required' => false,
  163.                                                    'type'     => 'string',
  164.                                                 ),
  165.                                 'context' => array(
  166.                                                    'required' => false,
  167.                                                    'type'     => 'string',
  168.                                                 ),
  169.                                 'datasources' => array(
  170.                                                    'required' => false,
  171.                                                    'type'     => 'string',
  172.                                                 ),
  173.                                 'debug' => array(
  174.                                                    'required' => false,
  175.                                                    'type'     => 'string',
  176.                                                 ),
  177.                                 'dir' => array(
  178.                                                    'required' => false,
  179.                                                    'type'     => 'enum',
  180.                                                    'values'   => array'normal''reverse' )
  181.                                                 ),
  182.                                 'empty' => array(
  183.                                                    'required' => false,
  184.                                                    'type'     => 'boolean',
  185.                                                 ),
  186.                                 'equalsize' => array(
  187.                                                    'required' => false,
  188.                                                    'type'     => 'enum',
  189.                                                    'values'   => array'alwyys''never' )
  190.                                                 ),
  191.                                 'flex' => array(
  192.                                                    'required' => false,
  193.                                                    'type'     => 'string',
  194.                                                 ),
  195.                                 'flexgroup' => array(
  196.                                                    'required' => false,
  197.                                                    'type'     => 'int',
  198.                                                 ),
  199.                                 'height' => array(
  200.                                                    'required' => false,
  201.                                                    'type'     => 'string',
  202.                                                 ),
  203.                                 'hidden' => array(
  204.                                                    'required' => false,
  205.                                                    'type'     => 'boolean',
  206.                                                 ),
  207.                                 'id' => array(
  208.                                                    'required' => false,
  209.                                                    'type'     => 'string',
  210.                                                 ),
  211.                                 'insertafter' => array(
  212.                                                    'required' => false,
  213.                                                    'type'     => 'string',
  214.                                                 ),
  215.                                 'insertbefore' => array(
  216.                                                    'required' => false,
  217.                                                    'type'     => 'string',
  218.                                                 ),
  219.                                 'left' => array(
  220.                                                    'required' => false,
  221.                                                    'type'     => 'string',
  222.                                                 ),
  223.                                 'maxheight' => array(
  224.                                                    'required' => false,
  225.                                                    'type'     => 'string',
  226.                                                 ),
  227.                                 'maxwidth' => array(
  228.                                                    'required' => false,
  229.                                                    'type'     => 'string',
  230.                                                 ),
  231.                                 'minheight' => array(
  232.                                                    'required' => false,
  233.                                                    'type'     => 'string',
  234.                                                 ),
  235.                                 'minwidth' => array(
  236.                                                    'required' => false,
  237.                                                    'type'     => 'string',
  238.                                                 ),
  239.                                 'observes' => array(
  240.                                                    'required' => false,
  241.                                                    'type'     => 'string',
  242.                                                 ),
  243.                                 'ordinal' => array(
  244.                                                    'required' => false,
  245.                                                    'type'     => 'int',
  246.                                                 ),
  247.                                 'orient' => array(
  248.                                                    'required' => false,
  249.                                                    'type'     => 'enum',
  250.                                                    'values'   => array'vertical''horizontal' )
  251.                                                 ),
  252.                                 'pack' => array(
  253.                                                    'required' => false,
  254.                                                    'type'     => 'enum',
  255.                                                    'values'   => array'center''start''end' )
  256.                                                 ),
  257.                                 'persist' => array(
  258.                                                    'required' => false,
  259.                                                    'type'     => 'string',
  260.                                                 ),
  261.                                 'position' => array(
  262.                                                    'required' => false,
  263.                                                    'type'     => 'string',
  264.                                                 ),
  265.                                 'ref' => array(
  266.                                                    'required' => false,
  267.                                                    'type'     => 'string',
  268.                                                 ),
  269.                                 'style' => array(
  270.                                                    'required' => false,
  271.                                                    'type'     => 'string',
  272.                                                 ),
  273.                                 'template' => array(
  274.                                                    'required' => false,
  275.                                                    'type'     => 'string',
  276.                                                 ),
  277.                                 'tooltip' => array(
  278.                                                    'required' => false,
  279.                                                    'type'     => 'string',
  280.                                                 )
  281.                                 );
  282.     
  283.    /**
  284.     * flag to indicate whether xml entities should be replaced
  285.     *
  286.     * @access   public
  287.     * @var      boolean 
  288.     */
  289.     var $replaceEntities = true;
  290.     
  291.    /**
  292.     * constructor
  293.     *
  294.     * @access   public
  295.     * @param    array   attributes of the element
  296.     * @param    string  cdata of the element (used by caption, et al)
  297.     * @param    boolean autobuild flag
  298.     */
  299.     function __construct$attributes = array()$cdata = null$autoBuild = true )
  300.     {
  301.         $this->attributes = $attributes;
  302.         $this->cdata      = $cdata;
  303.     }
  304.  
  305.    /**
  306.     * set the reference to the document
  307.     *
  308.     * @access   public
  309.     * @param    object XML_XUL_Document     document
  310.     */
  311.     function setDocument$doc )
  312.     {
  313.         $this->_doc      $doc;
  314.     }
  315.  
  316.    /**
  317.     * set the namespace
  318.     *
  319.     * @access   public
  320.     * @param    string 
  321.     */
  322.     function setNamespace$ns )
  323.     {
  324.         $this->_ns $ns;
  325.     }
  326.  
  327.    /**
  328.     * set the namespace for XHTML element
  329.     *
  330.     * @access   public
  331.     * @param    string 
  332.     */
  333.     function setHtmlNamespace$ns )
  334.     {
  335.         $this->_htmlNs $ns;
  336.     }
  337.  
  338.    /**
  339.     * get the element's id
  340.     *
  341.     * @access   public
  342.     * @return   string  id of the element
  343.     */
  344.     function getId()
  345.     {
  346.         if (isset($this->attributes['id'])) {
  347.             return $this->attributes['id'];
  348.         }
  349.         return false;
  350.     }
  351.  
  352.    /**
  353.     * get the element's tag name
  354.     *
  355.     * @access   public
  356.     * @return   string  tag name of the element
  357.     */
  358.     function getElementname()
  359.     {
  360.         return $this->elementName;
  361.     }
  362.  
  363.    /**
  364.     * sets cdata of the element
  365.     *
  366.     * @access public
  367.     * @param    string  data
  368.     */
  369.     function setCData$data )
  370.     {
  371.         $this->cdata = $data;
  372.     }
  373.  
  374.    /**
  375.     * sets several attributes at once
  376.     *
  377.     * @access public
  378.     * @param    array  attributes
  379.     */
  380.     function setAttributes$attribs )
  381.     {
  382.         $this->attributes = array_merge($this->attributes$attribs);
  383.     }
  384.  
  385.    /**
  386.     * set an attribute
  387.     *
  388.     * @access public
  389.     * @param    string  attribute name
  390.     * @param    mixed   attribute value
  391.     */
  392.     function setAttribute$name$value )
  393.     {
  394.         $this->attributes[$name$value;
  395.     }
  396.     
  397.    /**
  398.     * get an attribute
  399.     *
  400.     * @access public
  401.     * @param    string  attribute name
  402.     * @return   mixed   attribute value
  403.     */
  404.     function getAttribute$name )
  405.     {
  406.         if (isset($this->attributes[$name])) {
  407.             return $this->attributes[$name];
  408.         }
  409.         return false;
  410.     }
  411.     
  412.    /**
  413.     * add a child object
  414.     *
  415.     * @access   public
  416.     * @param    object 
  417.     */
  418.     function appendChild$obj )
  419.     {
  420.         $this->childNodes[$obj;
  421.     }
  422.  
  423.    /**
  424.     * create a string representation of the element
  425.     *
  426.     * This is just an alias for serialize()
  427.     *
  428.     * @access public
  429.     * @return string string representation of the element and all of its childNodes
  430.     */
  431.     function toXML()
  432.     {
  433.         return $this->serialize();
  434.     }
  435.     
  436.    /**
  437.     * serialize the element
  438.     *
  439.     * @access public
  440.     * @return string string representation of the element and all of its childNodes
  441.     */
  442.     function serialize()
  443.     {
  444.         $util = new XML_Util2();
  445.         $content '';
  446.         
  447.         if (empty($this->_ns)) {
  448.             $el $this->elementName;
  449.         else {
  450.             $el sprintf'%s:%s'$this->_ns$this->elementName);
  451.         }
  452.  
  453.         if (empty($this->childNodes) ) {
  454.             if ($this->cdata !== null{
  455.                 $content $this->cdata;
  456.                 if ($this->replaceEntities{
  457.                     $content $util->replaceEntities($content);
  458.                 }
  459.             }
  460.         else {
  461.             $cnt count($this->childNodes);
  462.             for ($i=0; $i<$cnt$i++{
  463.                 $content .= $this->childNodes[$i]->serialize();
  464.             }
  465.         }
  466.         
  467.         if ($this->isRoot{
  468.             $nsUri 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
  469.             if ($this->_htmlNs != null{
  470.                 $this->attributes['xmlns:'.$this->_htmlNs'http://www.w3.org/1999/xhtml';
  471.             }
  472.         else {
  473.             $nsUri = null;
  474.         }
  475.         
  476.         return $util->createTag(
  477.                                     $el,
  478.                                     $this->attributes,
  479.                                     $content,
  480.                                     $nsUri,
  481.                                     false
  482.                                 );
  483.     }
  484.  
  485.    /**
  486.     * clone the element
  487.     *
  488.     * This method will return a copy of the element
  489.     * without the id and the childNodes
  490.     *
  491.     * @access   public
  492.     * @param    boolean     whether children should be cloned, too.
  493.     * @return   object XML_XUL_Element 
  494.     */
  495.     function cloneElement$recursive = false )
  496.     {
  497.         $atts $this->attributes;
  498.         unset($atts['id']);
  499.         
  500.         $copy $this->_doc->createElement($this->elementName$atts$this->cdata);
  501.         if ($recursive !== true{
  502.             return $copy;
  503.         }
  504.         /**
  505.          * copy child nodes
  506.          */
  507.         $cnt count($this->childNodes);
  508.         for ($i = 0; $i $cnt$i++{
  509.             $copy->appendChild$this->childNodes[$i]->cloneElement$recursive ) );
  510.         }
  511.         return $copy;
  512.     }
  513.  
  514.    /**
  515.     * get an element by its id
  516.     *
  517.     * You should not need to call this method directly
  518.     *
  519.     * @access   public
  520.     * @param    string  id
  521.     * @return   object XML_XUL_Element or false if the element does not exist
  522.     */
  523.     function getElementById($id)
  524.     {
  525.         if ($this->getId(== $id{
  526.             return $this;
  527.         }
  528.         
  529.         $cnt count($this->childNodes);
  530.         
  531.         if ($cnt==0{
  532.             return false;
  533.         }
  534.  
  535.         for ($i=0; $i<$cnt$i++{
  536.             $result $this->childNodes[$i]->getElementById($id);
  537.             if ($result === false{
  538.                 continue;
  539.             }
  540.             return $result;
  541.         }
  542.         return false;
  543.     }
  544.  
  545.    /**
  546.     * get a nodelist of elements by their tagname
  547.     *
  548.     * @access   public
  549.     * @param    string  id
  550.     * @return   array   array containing XML_XUL_Element objects
  551.     */
  552.     function getElementsByTagname($tagname)
  553.     {
  554.         $nodeList = array();
  555.         if ($this->elementName == $tagname{
  556.             $nodeList[$this;
  557.         }
  558.  
  559.         $cnt count($this->childNodes);
  560.  
  561.         if ($cnt==0{
  562.             return $nodeList;
  563.         }
  564.  
  565.         for ($i=0; $i<$cnt$i++{
  566.             $tmp $this->childNodes[$i]->getElementsByTagname($tagname);
  567.             $cnt2 count($tmp);
  568.             for($j=0; $j<$cnt2$j++{
  569.                 $nodeList[$tmp[$j];
  570.             }
  571.         }
  572.         return $nodeList;
  573.     }
  574.  
  575.    /**
  576.     * validate the element's attributes
  577.     *
  578.     * Uses the definitions of common attributes as well as the
  579.     * attribute definitions of the element.
  580.     *
  581.     * @access   public
  582.     * @return   boolean     true on success
  583.     * @throws XML_XUL_Exception
  584.     */
  585.     function validateAttributes()
  586.     {
  587.         foreach ($this->attributes as $name => $value{
  588.  
  589.             if (isset($this->_commonAttribs[$name])) {
  590.                 $def    =   $this->_commonAttribs[$name];
  591.             elseif (isset($this->_attribDefs[$name])) {
  592.                 $def    =   $this->_attribDefs[$name];
  593.             else {
  594.                 throw new XML_XUL_Exception('Unknown attribute '.$name.'.'XML_XUL_ERROR_ATTRIBUTE_UNKNOWN);
  595.             }
  596.  
  597.             switch ($def['type']{
  598.                 /**
  599.                  * must be a string
  600.                  */
  601.                 case 'string':
  602.                     continue;
  603.                     break;
  604.                 /**
  605.                  * must be an integer
  606.                  */
  607.                 case 'int':
  608.                 case 'integer':
  609.                     if (!preg_match($value)) {
  610.                         throw new XML_XUL_Exception('Attribute \''.$name.'\' must be integer.'XML_XUL_ERROR_ATTRIBUTE_NO_INTEGER);
  611.                     }
  612.                     break;
  613.                 /**
  614.                  * enumerated value
  615.                  */
  616.                 case 'enum':
  617.                     if (!in_array($value$def['values'])) {
  618.                         throw new XML_XUL_Exception('Attribute \''.$name.'\' must be one of '.implode(', '$def['values']).'.'XML_XUL_ERROR_ATTRIBUTE_INVALID_VALUE);
  619.                     }
  620.                     break;
  621.                 /**
  622.                  * boolean value
  623.                  */
  624.                 case 'boolean':
  625.                     if ($value != 'true' && $value != 'false'{
  626.                         throw new XML_XUL_Exception('Attribute \''.$name.'\' must be one either \'true\' or \'false\'.'XML_XUL_ERROR_ATTRIBUTE_NO_BOOLEAN);
  627.                     }
  628.                     break;
  629.             }
  630.         }
  631.         return true;
  632.     }
  633.  
  634.    /**
  635.     * get the first child of the element
  636.     *
  637.     * If the element has no childNodes, null will be returned.
  638.     *
  639.     * @access   public
  640.     * @return   object XML_XUL_Element 
  641.     */
  642.     function firstChild()
  643.     {
  644.         if (isset($this->childNodes[0])) {
  645.             return $this->childNodes[0];
  646.         }
  647.         $child = null;
  648.         return $child;
  649.     }
  650.  
  651.    /**
  652.     * get last first child of the element
  653.     *
  654.     * If the element has no childNodes, null will be returned.
  655.     *
  656.     * @access   public
  657.     * @return   object XML_XUL_Element 
  658.     */
  659.     function lastChild()
  660.     {
  661.         $cnt count($this->childNodes);
  662.         if ($cnt > 0{
  663.             return $this->childNodes[($cnt-1)];
  664.         }
  665.         $child = null;
  666.         return $child;
  667.     }
  668.  
  669.    /**
  670.     * add a description element
  671.     *
  672.     * This can be used by a lot of elements,
  673.     * thus it has been placed in the base class.
  674.     *
  675.     * @access   public
  676.     * @param    string  text for the description
  677.     * @param    array   additional attributes
  678.     * @return   object XML_XUL_Element_Description 
  679.     * @see      XML_XUL_Element_Description
  680.     */
  681.     function addDescription($text$atts = array())
  682.     {
  683.         $desc $this->_doc->createElement('Description'$atts$text);
  684.         $this->appendChild($desc);
  685.         return $desc;
  686.     }
  687.  
  688.    /**
  689.     * get a debug info about the element as
  690.     * string.
  691.     *
  692.     * Use this instead of a print_r on the tree.
  693.     *
  694.     * @access   public
  695.     * @param    integer     nesting depth, no need to pass this
  696.     * @return   string 
  697.     */
  698.     function getDebug$indent ''$last = false )
  699.     {
  700.         $name $this->getElementName();
  701.         $id   $this->getId();
  702.         if ($id !== false{
  703.             $name .= " [id=$id]";
  704.         }
  705.         
  706.         if ($last{
  707.             $debug   sprintf("%s   +-%s\n"$indent$name);
  708.             $indent .= '      ';
  709.         else {
  710.             $debug   sprintf("%s   +-%s\n"$indent$name);
  711.             $indent .= '   |  ';
  712.        }
  713.         
  714.         if (!empty($this->attributes)) {
  715.             $debug .= sprintf("%s+-attributes:\n"$indent);
  716.             foreach ($this->attributes as $key => $value{
  717.                 $debug .= sprintf("%s|   %s => %s\n"$indent$key$value);
  718.             }
  719.         }
  720.  
  721.         if (!empty($this->cdata)) {
  722.             $debug .= sprintf("%s+-cdata: %s\n"$indent$this->cdata);
  723.         else {
  724.             $debug .= sprintf("%s+-cdata: null\n"$indent);
  725.         }
  726.         
  727.         if (!empty($this->childNodes)) {
  728.             $debug .= sprintf("%s+-childNodes:\n"$indent);
  729.             for ($i = 0; $i<count($this->childNodes)$i++{
  730.                 if ($i == (count($this->childNodes)-1)) {
  731.                     $debug .= $this->childNodes[$i]->getDebug($indenttrue);
  732.                 else {
  733.                     $debug .= $this->childNodes[$i]->getDebug($indent);
  734.                 }
  735.             }
  736.         }
  737.         if (!$last{
  738.             $debug .= sprintf("%s\n"$indent);
  739.         }
  740.         return $debug;
  741.     }
  742. }

Documentation generated on Mon, 11 Mar 2019 15:49:51 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.