FluentDOM Package
Current file: /tmp/FluentDOM/FluentDOM/Core.php
Legend: executed not executed dead code

  Coverage
  Classes Functions / Methods Lines
Total
0.00%0.00%
0.00% 0 / 1
97.62%97.62%
97.62% 41 / 42
99.74%99.74%
99.74% 387 / 388
 
FluentDOMCore
0.00%0.00%
0.00% 0 / 1
97.62%97.62%
97.62% 41 / 42
99.74%99.74%
99.74% 387 / 388
 public function __construct()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 2 / 2
 public function load($source, $contentType = 'text/xml')
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 28 / 28
 protected function _initLoaders()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 17 / 17
 public function setLoaders($loaders)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 6 / 6
 protected function _setContentType($value)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 20 / 20
 public function __get($name)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 11 / 11
 public function __set($name, $value)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 12 / 12
 public function __isset($name)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 7 / 7
 public function __toString()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 7 / 7
 public function item($position)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 public function formatOutput($contentType = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 13 / 13
 public function getIterator()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function count()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function offsetSet($offset, $value)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function offsetExists($offset)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function offsetUnset($offset)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function offsetGet($offset)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function spawn()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 4 / 4
 public function push($elements, $ignoreTextNodes = FALSE)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 19 / 19
 public function unique(array $array)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 26 / 26
 protected function _uniqueSort()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 2 / 2
 public function evaluate($expr, DOMNode $context = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 public function namespaces(array $namespaces = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 9 / 9
 protected function _xpath()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 16 / 16
 protected function _match($expr, $context = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 protected function _test($expr, $context = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 7 / 7
 protected function _inList($node)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 5 / 5
 protected function _isQName($name)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 8 / 8
 protected function _isNCName($name, $offset = 0, $length = 0)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 25 / 25
 protected function _isNode($node, $ignoreTextNodes = FALSE)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 10 / 10
 protected function _isNodeList($elements)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 7 / 7
 protected function _isCallback($callback, $allowGlobalFunctions, $silent)
0.00%0.00%
0.00% 0 / 1
92.86%92.86%
92.86% 13 / 14
 protected function _getContentFragment($content, $includeTextNodes = TRUE, $limit = 0)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 15 / 15
 protected function _getContentNodes($content, $includeTextNodes = TRUE, $limit = 0)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 26 / 26
 protected function _getContentElement($content)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 4 / 4
 protected function _getTargetNodes($selector)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 7 / 7
 protected function _getContextNodes($selector)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 protected function _getInnerXml($node)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 10 / 10
 protected function _removeNodes($selector)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 9 / 9
 protected function _getHandler()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 protected function _applyContentToNodes($targetNodes, $content, $handler)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 19 / 19
 protected function _executeEasySetter($easySetter, $node, $index, $value)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 4 / 4


       1                 : <?php                                                                                               
       2                 : /**                                                                                                 
       3                 : * FluentDOMCore implements the core and interface functions for FluentDOM                           
       4                 : *                                                                                                   
       5                 : * @version $Id: Core.php 441 2010-04-16 18:24:08Z subjective $                                      
       6                 : * @license http://www.opensource.org/licenses/mit-license.php The MIT License                       
       7                 : * @copyright Copyright (c) 2009 Bastian Feder, Thomas Weinert                                       
       8                 : *                                                                                                   
       9                 : * @tutorial FluentDOM.pkg                                                                           
      10                 : * @package FluentDOM                                                                                
      11                 : */                                                                                                  
      12                 :                                                                                                     
      13                 : /**                                                                                                 
      14                 : * Include the external iterator class.                                                              
      15                 : */                                                                                                  
      16                 : require_once(dirname(__FILE__).'/Iterator.php');                                                    
      17                 : /**                                                                                                 
      18                 : * Include the loader interface.                                                                     
      19                 : */                                                                                                  
      20                 : require_once(dirname(__FILE__).'/Loader.php');                                                      
      21                 : /**                                                                                                 
      22                 : * Include the handler class.                                                                        
      23                 : */                                                                                                  
      24                 : require_once(dirname(__FILE__).'/Handler.php');                                                     
      25                 :                                                                                                     
      26                 : /**                                                                                                 
      27                 : * FluentDOMCore implements the core and interface functions for FluentDOM                           
      28                 : *                                                                                                   
      29                 : * @property string $contentType Output type - text/xml or text/html                                 
      30                 : * @property-read integer $length The amount of elements found by selector.                          
      31                 : * @property-read DOMDocument $document Internal DOMDocument object                                  
      32                 : * @property-read DOMXPath $xpath Internal XPath object                                              
      33                 : *                                                                                                   
      34                 : * @package FluentDOM                                                                                
      35                 : */                                                                                                  
      36                 : class FluentDOMCore implements IteratorAggregate, Countable, ArrayAccess {                          
      37                 :                                                                                                     
      38                 :   /**                                                                                               
      39                 :   * Associated DOMDocument object.                                                                  
      40                 :   * @var DOMDocument $_document                                                                     
      41                 :   */                                                                                                
      42                 :   protected $_document = NULL;                                                                      
      43                 :                                                                                                     
      44                 :   /**                                                                                               
      45                 :   * XPath object used to execute selectors                                                          
      46                 :   * @var DOMXPath $_xpath                                                                           
      47                 :   */                                                                                                
      48                 :   protected $_xpath = NULL;                                                                         
      49                 :                                                                                                     
      50                 :   /**                                                                                               
      51                 :   * List of namespaces to be registered for xpath expressions                                       
      52                 :   * @var array                                                                                      
      53                 :   */                                                                                                
      54                 :   protected $_namespaces = array();                                                                 
      55                 :                                                                                                     
      56                 :   /**                                                                                               
      57                 :   * Use document context for expression (not selected nodes).                                       
      58                 :   * @var boolean $_useDocumentContext                                                               
      59                 :   */                                                                                                
      60                 :   protected $_useDocumentContext = TRUE;                                                            
      61                 :                                                                                                     
      62                 :   /**                                                                                               
      63                 :   * Content type for output (xml, text/xml, html, text/html).                                       
      64                 :   * @var string $_contentType                                                                       
      65                 :   */                                                                                                
      66                 :   protected $_contentType = 'text/xml';                                                             
      67                 :                                                                                                     
      68                 :   /**                                                                                               
      69                 :   * Parent FluentDOM object (previous selection in chain).                                          
      70                 :   * @var FluentDOM $_parent                                                                         
      71                 :   */                                                                                                
      72                 :   protected $_parent = NULL;                                                                        
      73                 :                                                                                                     
      74                 :   /**                                                                                               
      75                 :   * Seleted element and text nodes                                                                  
      76                 :   * @var array $_array                                                                              
      77                 :   */                                                                                                
      78                 :   protected $_array = array();                                                                      
      79                 :                                                                                                     
      80                 :   /**                                                                                               
      81                 :   * Document loader list.                                                                           
      82                 :   *                                                                                                 
      83                 :   * @see _initLoaders                                                                               
      84                 :   * @see _setLoader                                                                                 
      85                 :   *                                                                                                 
      86                 :   * @var array $_loaders                                                                            
      87                 :   */                                                                                                
      88                 :   protected $_loaders = NULL;                                                                       
      89                 :                                                                                                     
      90                 :   /**                                                                                               
      91                 :   * Constructor                                                                                     
      92                 :   *                                                                                                 
      93                 :   * @return FluentDOM                                                                               
      94                 :   */                                                                                                
      95                 :   public function __construct() {                                                                   
      96              18 :     $this->_document = new DOMDocument();                                                           
      97              18 :   }                                                                                                 
      98                 :                                                                                                     
      99                 :   /**                                                                                               
     100                 :   * Load a $source. The type of the source depends on the loaders. If no explicit loaders are set   
     101                 :   * FluentDOM will use a set of default loaders for xml/html and DOM.                               
     102                 :   *                                                                                                 
     103                 :   * @param mixed $source                                                                            
     104                 :   * @param string $contentType optional, default value 'text/xml'                                   
     105                 :   */                                                                                                
     106                 :   public function load($source, $contentType = 'text/xml') {                                        
     107              10 :     $this->_array = array();                                                                        
     108              10 :     $this->_setContentType($contentType);                                                           
     109              10 :     if ($source instanceof FluentDOMCore) {                                                         
     110               2 :       $this->_useDocumentContext = FALSE;                                                           
     111               2 :       $this->_document = $source->document;                                                         
     112               2 :       $this->_xpath = $source->_xpath;                                                              
     113               2 :       $this->_contentType = $source->_contentType;                                                  
     114               2 :       $this->_parent = $source;                                                                     
     115               2 :       return $this;                                                                                 
     116                 :     } else {                                                                                        
     117               9 :       $this->_parent = NULL;                                                                        
     118               9 :       $this->_initLoaders();                                                                        
     119               9 :       foreach ($this->_loaders as $loader) {                                                        
     120               9 :         if ($loaded = $loader->load($source, $this->_contentType)) {                                
     121               8 :           if ($loaded instanceof DOMDocument) {                                                     
     122               5 :             $this->_useDocumentContext = TRUE;                                                      
     123               5 :             $this->_document = $loaded;                                                             
     124               8 :           } elseif (is_array($loaded) &&                                                            
     125               3 :                     isset($loaded[0]) &&                                                            
     126               3 :                     isset($loaded[1]) &&                                                            
     127               3 :                     $loaded[0] instanceof DOMDocument &&                                            
     128               3 :                     is_array($loaded[1])) {                                                         
     129               3 :             $this->_document = $loaded[0];                                                          
     130               3 :             $this->push($loaded[1]);                                                                
     131               3 :             $this->_useDocumentContext = FALSE;                                                     
     132               3 :           }                                                                                         
     133               8 :           return $this;                                                                             
     134                 :         }                                                                                           
     135               3 :       }                                                                                             
     136               1 :       throw new InvalidArgumentException('Invalid source object.');                                 
     137                 :     }                                                                                               
     138                 :     return $this;                                                                                   
     139                 :   }                                                                                                 
     140                 :                                                                                                     
     141                 :   /**                                                                                               
     142                 :   * Initialize default loaders if they are not already initialized                                  
     143                 :   *                                                                                                 
     144                 :   * @return void                                                                                    
     145                 :   */                                                                                                
     146                 :   protected function _initLoaders() {                                                               
     147               6 :     if (!is_array($this->_loaders)) {                                                               
     148               3 :       $path = dirname(__FILE__).'/';                                                                
     149               3 :       include_once($path.'/Loader/DOMNode.php');                                                    
     150               3 :       include_once($path.'/Loader/DOMDocument.php');                                                
     151               3 :       include_once($path.'/Loader/StringXML.php');                                                  
     152               3 :       include_once($path.'/Loader/FileXML.php');                                                    
     153               3 :       include_once($path.'/Loader/StringHTML.php');                                                 
     154               3 :       include_once($path.'/Loader/FileHTML.php');                                                   
     155               3 :       $this->_loaders = array(                                                                      
     156               3 :         new FluentDOMLoaderDOMNode(),                                                               
     157               3 :         new FluentDOMLoaderDOMDocument(),                                                           
     158               3 :         new FluentDOMLoaderStringXML(),                                                             
     159               3 :         new FluentDOMLoaderFileXML(),                                                               
     160               3 :         new FluentDOMLoaderStringHTML(),                                                            
     161               3 :         new FluentDOMLoaderFileHTML(),                                                              
     162                 :       );                                                                                            
     163               3 :     }                                                                                               
     164               6 :   }                                                                                                 
     165                 :                                                                                                     
     166                 :   /**                                                                                               
     167                 :   * Define own loading handlers                                                                     
     168                 :   *                                                                                                 
     169                 :   * @example iniloader/iniToXML.php Usage Example: Own loader object                                
     170                 :   * @param $loaders                                                                                 
     171                 :   * @return FluentDOM                                                                               
     172                 :   */                                                                                                
     173                 :   public function setLoaders($loaders) {                                                            
     174               5 :     foreach ($loaders as $loader) {                                                                 
     175               5 :       if (!($loader instanceof FluentDOMLoader)) {                                                  
     176               1 :         throw new InvalidArgumentException('Array contains invalid loader object');                 
     177                 :       }                                                                                             
     178               4 :     }                                                                                               
     179               4 :     $this->_loaders = $loaders;                                                                     
     180               4 :     return $this;                                                                                   
     181                 :   }                                                                                                 
     182                 :                                                                                                     
     183                 :   /**                                                                                               
     184                 :   * Setter for FluentDOM::_contentType property                                                     
     185                 :   *                                                                                                 
     186                 :   * @param string $value                                                                            
     187                 :   * @return void                                                                                    
     188                 :   */                                                                                                
     189                 :   protected function _setContentType($value) {                                                      
     190              15 :     switch (strtolower($value)) {                                                                   
     191              15 :     case 'xml' :                                                                                    
     192              15 :     case 'application/xml' :                                                                        
     193              15 :     case 'text/xml' :                                                                               
     194               9 :       $newContentType = 'text/xml';                                                                 
     195               9 :       break;                                                                                        
     196               7 :     case 'html' :                                                                                   
     197               7 :     case 'text/html' :                                                                              
     198               6 :       $newContentType = 'text/html';                                                                
     199               6 :       break;                                                                                        
     200               1 :     default :                                                                                       
     201               1 :       throw new UnexpectedValueException('Invalid content type value');                             
     202              15 :     }                                                                                               
     203              14 :     if ($this->_contentType != $newContentType) {                                                   
     204               6 :       $this->_contentType = $newContentType;                                                        
     205               6 :       if (isset($this->_parent)) {                                                                  
     206               1 :         $this->_parent->contentType = $newContentType;                                              
     207               1 :       }                                                                                             
     208               6 :     }                                                                                               
     209              14 :   }                                                                                                 
     210                 :                                                                                                     
     211                 :   /**                                                                                               
     212                 :   * implement dynamic properties using magic methods                                                
     213                 :   *                                                                                                 
     214                 :   * @param string $name                                                                             
     215                 :   * @return mixed                                                                                   
     216                 :   */                                                                                                
     217                 :   public function __get($name) {                                                                    
     218                 :     switch ($name) {                                                                                
     219              11 :     case 'contentType' :                                                                            
     220               1 :       return $this->_contentType;                                                                   
     221              10 :     case 'document' :                                                                               
     222               7 :       return $this->_document;                                                                      
     223               5 :     case 'length' :                                                                                 
     224               1 :       return count($this->_array);                                                                  
     225               4 :     case 'xpath' :                                                                                  
     226               3 :       return $this->_xpath();                                                                       
     227               1 :     default :                                                                                       
     228               1 :       return NULL;                                                                                  
     229               1 :     }                                                                                               
     230                 :   }                                                                                                 
     231                 :                                                                                                     
     232                 :   /**                                                                                               
     233                 :   * block changes of dynamic readonly property length                                               
     234                 :   *                                                                                                 
     235                 :   * @param string $name                                                                             
     236                 :   * @param mixed $value                                                                             
     237                 :   * @return void                                                                                    
     238                 :   */                                                                                                
     239                 :   public function __set($name, $value) {                                                            
     240                 :     switch ($name) {                                                                                
     241              15 :     case 'contentType' :                                                                            
     242              11 :       $this->_setContentType($value);                                                               
     243               9 :       break;                                                                                        
     244               4 :     case 'document' :                                                                               
     245               4 :     case 'length' :                                                                                 
     246               4 :     case 'xpath' :                                                                                  
     247               3 :       throw new BadMethodCallException('Can not set readonly value.');                              
     248               1 :     default :                                                                                       
     249               1 :       $this->$name = $value;                                                                        
     250               1 :       break;                                                                                        
     251               1 :     }                                                                                               
     252              10 :   }                                                                                                 
     253                 :                                                                                                     
     254                 :   /**                                                                                               
     255                 :   * support isset for dynamic properties length and document                                        
     256                 :   *                                                                                                 
     257                 :   * @param string $name                                                                             
     258                 :   * @return boolean                                                                                 
     259                 :   */                                                                                                
     260                 :   public function __isset($name) {                                                                  
     261                 :     switch ($name) {                                                                                
     262               5 :     case 'length' :                                                                                 
     263               5 :     case 'xpath' :                                                                                  
     264               5 :     case 'contentType' :                                                                            
     265               3 :       return TRUE;                                                                                  
     266               2 :     case 'document' :                                                                               
     267               1 :       return isset($this->_document);                                                               
     268                 :     }                                                                                               
     269               1 :     return FALSE;                                                                                   
     270                 :   }                                                                                                 
     271                 :                                                                                                     
     272                 :                                                                                                     
     273                 :   /**                                                                                               
     274                 :   * Return the XML output of the internal dom document                                              
     275                 :   *                                                                                                 
     276                 :   * @return string                                                                                  
     277                 :   */                                                                                                
     278                 :   public function __toString() {                                                                    
     279               3 :     switch ($this->_contentType) {                                                                  
     280               3 :     case 'html' :                                                                                   
     281               3 :     case 'text/html' :                                                                              
     282               1 :       return $this->_document->saveHTML();                                                          
     283               2 :     default :                                                                                       
     284               2 :       return $this->_document->saveXML();                                                           
     285               2 :     }                                                                                               
     286                 :   }                                                                                                 
     287                 :                                                                                                     
     288                 :   /**                                                                                               
     289                 :   * The item() method is used to access elements in the node list,                                  
     290                 :   * like in a DOMNodelist.                                                                          
     291                 :   *                                                                                                 
     292                 :   * @param integer $position                                                                        
     293                 :   * @return DOMNode                                                                                 
     294                 :   */                                                                                                
     295                 :   public function item($position) {                                                                 
     296               2 :     if (isset($this->_array[$position])) {                                                          
     297               1 :       return $this->_array[$position];                                                              
     298                 :     }                                                                                               
     299               1 :     return NULL;                                                                                    
     300                 :   }                                                                                                 
     301                 :                                                                                                     
     302                 :   /**                                                                                               
     303                 :   * Formats the current document, resets internal node array and other properties.                  
     304                 :   *                                                                                                 
     305                 :   * The document is saved and reloaded, all variables with DOMNodes                                 
     306                 :   * of this document will get invalid.                                                              
     307                 :   *                                                                                                 
     308                 :   * @return FluentDOM                                                                               
     309                 :   */                                                                                                
     310                 :   public function formatOutput($contentType = NULL) {                                               
     311               2 :     if (isset($contentType)) {                                                                      
     312               1 :       $this->_setContentType($contentType);                                                         
     313               1 :     }                                                                                               
     314               2 :     $this->_array = array();                                                                        
     315               2 :     $this->_position = 0;                                                                           
     316               2 :     $this->_useDocumentContext = TRUE;                                                              
     317               2 :     $this->_parent = NULL;                                                                          
     318               2 :     $this->_document->preserveWhiteSpace = FALSE;                                                   
     319               2 :     $this->_document->formatOutput = TRUE;                                                          
     320               2 :     if (!empty($this->_document->documentElement)) {                                                
     321               2 :       $this->_document->loadXML($this->_document->saveXML());                                       
     322               2 :     }                                                                                               
     323               2 :     return $this;                                                                                   
     324                 :   }                                                                                                 
     325                 :                                                                                                     
     326                 :   /*                                                                                                
     327                 :   * Interface - IteratorAggregate                                                                   
     328                 :   */                                                                                                
     329                 :                                                                                                     
     330                 :   /**                                                                                               
     331                 :   * Get an iterator for this object.                                                                
     332                 :   *                                                                                                 
     333                 :   * @example interfaces/Iterator.php Usage Example: Iterator Interface                              
     334                 :   * @example interfaces/RecursiveIterator.php Usage Example: Recursive Iterator Interface           
     335                 :   * @return FluentDOMIterator                                                                       
     336                 :   */                                                                                                
     337                 :   public function getIterator() {                                                                   
     338               2 :     return new FluentDOMIterator($this);                                                            
     339                 :   }                                                                                                 
     340                 :                                                                                                     
     341                 :   /*                                                                                                
     342                 :   * Interface - Countable                                                                           
     343                 :   */                                                                                                
     344                 :                                                                                                     
     345                 :   /**                                                                                               
     346                 :   * Get element count (Countable interface)                                                         
     347                 :   *                                                                                                 
     348                 :   * @example interfaces/Countable.php Usage Example: Countable Interface                            
     349                 :   * @return integer                                                                                 
     350                 :   */                                                                                                
     351                 :   public function count() {                                                                         
     352               2 :     return count($this->_array);                                                                    
     353                 :   }                                                                                                 
     354                 :                                                                                                     
     355                 :   /*                                                                                                
     356                 :   * Interface - ArrayAccess                                                                         
     357                 :   */                                                                                                
     358                 :                                                                                                     
     359                 :   /**                                                                                               
     360                 :   * If somebody tries to modify the internal array throw an exception.                              
     361                 :   *                                                                                                 
     362                 :   * @example interfaces/ArrayAccess.php Usage Example: ArrayAccess Interface                        
     363                 :   * @param integer $offset                                                                          
     364                 :   * @param mixed $value                                                                             
     365                 :   * @return void                                                                                    
     366                 :   */                                                                                                
     367                 :   public function offsetSet($offset, $value) {                                                      
     368               1 :     throw new BadMethodCallException('List is read only');                                          
     369                 :   }                                                                                                 
     370                 :                                                                                                     
     371                 :   /**                                                                                               
     372                 :   * Check if index exists in internal array                                                         
     373                 :   *                                                                                                 
     374                 :   * @example interfaces/ArrayAccess.php Usage Example: ArrayAccess Interface                        
     375                 :   * @param integer $offset                                                                          
     376                 :   * @return boolean                                                                                 
     377                 :   */                                                                                                
     378                 :   public function offsetExists($offset) {                                                           
     379               2 :     return isset($this->_array[$offset]);                                                           
     380                 :   }                                                                                                 
     381                 :                                                                                                     
     382                 :   /**                                                                                               
     383                 :   * If somebody tries to remove an element from the internal array throw an exception.              
     384                 :   *                                                                                                 
     385                 :   * @example interfaces/ArrayAccess.php Usage Example: ArrayAccess Interface                        
     386                 :   * @param integer $offset                                                                          
     387                 :   * @return void                                                                                    
     388                 :   */                                                                                                
     389                 :   public function offsetUnset($offset) {                                                            
     390               1 :     throw new BadMethodCallException('List is read only');                                          
     391                 :   }                                                                                                 
     392                 :                                                                                                     
     393                 :   /**                                                                                               
     394                 :   * Get element from internal array                                                                 
     395                 :   *                                                                                                 
     396                 :   * @example interfaces/ArrayAccess.php Usage Example: ArrayAccess Interface                        
     397                 :   * @param integer $offset                                                                          
     398                 :   * @return DOMNode|NULL                                                                            
     399                 :   */                                                                                                
     400                 :   public function offsetGet($offset) {                                                              
     401               1 :     return isset($this->_array[$offset]) ? $this->_array[$offset] : NULL;                           
     402                 :   }                                                                                                 
     403                 :                                                                                                     
     404                 :   /*                                                                                                
     405                 :   * Core functions                                                                                  
     406                 :   */                                                                                                
     407                 :                                                                                                     
     408                 :   /**                                                                                               
     409                 :   * Create a new instance of the same class with $this as the parent. This is used for the chaining.
     410                 :   *                                                                                                 
     411                 :   * @return FluentDOM                                                                               
     412                 :   */                                                                                                
     413                 :   public function spawn() {                                                                         
     414               2 :     $className = get_class($this);                                                                  
     415               2 :     $result = new $className();                                                                     
     416               2 :     $result->_namespaces = $this->_namespaces;                                                      
     417               2 :     return $result->load($this);                                                                    
     418                 :   }                                                                                                 
     419                 :                                                                                                     
     420                 :   /**                                                                                               
     421                 :   * Push new element(s) an the internal element list                                                
     422                 :   *                                                                                                 
     423                 :   * @uses _inList                                                                                   
     424                 :   * @param DOMNode|DOMNodeList|FluentDOM $elements                                                  
     425                 :   * @param boolean $ignoreTextNodes ignore text nodes                                               
     426                 :   * @return void                                                                                    
     427                 :   */                                                                                                
     428                 :   public function push($elements, $ignoreTextNodes = FALSE) {                                       
     429               8 :     if ($this->_isNode($elements, $ignoreTextNodes)) {                                              
     430               2 :       $elements = array($elements);                                                                 
     431               2 :     }                                                                                               
     432               8 :     if ($this->_isNodeList($elements)) {                                                            
     433               7 :       foreach ($elements as $index => $node) {                                                      
     434               7 :         if ($this->_isNode($node, $ignoreTextNodes)) {                                              
     435               7 :           if ($node->ownerDocument === $this->_document) {                                          
     436               5 :             $this->_array[] = $node;                                                                
     437               5 :           } else {                                                                                  
     438               2 :             throw new OutOfBoundsException(                                                         
     439               2 :               sprintf(                                                                              
     440               2 :                 'Node #%d is not a part of this document', $index                                   
     441               2 :               )                                                                                     
     442               2 :             );                                                                                      
     443                 :           }                                                                                         
     444               5 :         }                                                                                           
     445               5 :       }                                                                                             
     446               6 :     } elseif (!is_null($elements)) {                                                                
     447               1 :       throw new InvalidArgumentException('Invalid elements variable.');                             
     448                 :     }                                                                                               
     449               5 :   }                                                                                                 
     450                 :                                                                                                     
     451                 :   /**                                                                                               
     452                 :   * Sorts an array of DOM nodes based on document position, in place, with the duplicates removed.  
     453                 :   * Note that this only works on arrays of DOM nodes, not strings or numbers.                       
     454                 :   *                                                                                                 
     455                 :   * @param array $array array of DOM nodes                                                          
     456                 :   * @return array                                                                                   
     457                 :   */                                                                                                
     458                 :   public function unique(array $array) {                                                            
     459               5 :     $sortable = array();                                                                            
     460               5 :     $unsortable = array();                                                                          
     461               5 :     foreach ($array as $node) {                                                                     
     462               5 :       if (!($node instanceof DOMNode)) {                                                            
     463               2 :         throw new InvalidArgumentException(                                                         
     464               2 :           sprintf(                                                                                  
     465               2 :             'Array must only contain dom nodes, found "%s".',                                       
     466               2 :             is_object($node) ? get_class($node) : gettype($node)                                    
     467               2 :           )                                                                                         
     468               2 :         );                                                                                          
     469                 :       }                                                                                             
     470               3 :       if (isset($node->parentNode) ||                                                               
     471               3 :           $node === $node->ownerDocument->documentElement) {                                        
     472               2 :         $position = (integer)$this->_xpath()->evaluate('count(preceding::node())', $node);          
     473                 :         /* use the document position as index, ignore duplicates */                                 
     474               2 :         if (!isset($sortable[$position])) {                                                         
     475               2 :           $sortable[$position] = $node;                                                             
     476               2 :         }                                                                                           
     477               2 :       } else {                                                                                      
     478               2 :         $hash = spl_object_hash($node);                                                             
     479                 :         /* use the object hash as index, ignore duplicates */                                       
     480               2 :         if (!isset($unsortable[$hash])) {                                                           
     481               2 :           $unsortable[$hash] = $node;                                                               
     482               2 :         }                                                                                           
     483                 :       }                                                                                             
     484               3 :     }                                                                                               
     485               3 :     ksort($sortable, SORT_NUMERIC);                                                                 
     486               3 :     $result = array_values($sortable);                                                              
     487               3 :     array_splice($result, count($result), 0, array_values($unsortable));                            
     488               3 :     return $result;                                                                                 
     489                 :   }                                                                                                 
     490                 :                                                                                                     
     491                 :   /**                                                                                               
     492                 :   * Sorts the selected nodes, with the duplicates removed.                                          
     493                 :   *                                                                                                 
     494                 :   * @uses FluentDOMCore::unique                                                                     
     495                 :   *                                                                                                 
     496                 :   * @param array $array array of DOM nodes                                                          
     497                 :   * @return array                                                                                   
     498                 :   */                                                                                                
     499                 :   protected function _uniqueSort() {                                                                
     500               1 :     $this->_array = $this->unique($this->_array);                                                   
     501               1 :   }                                                                                                 
     502                 :                                                                                                     
     503                 :   /**                                                                                               
     504                 :   * Gives access to an xpath evaluate on the current document                                       
     505                 :   *                                                                                                 
     506                 :   * @param string $expr                                                                             
     507                 :   * @param DOMNode $context                                                                         
     508                 :   */                                                                                                
     509                 :   public function evaluate($expr, DOMNode $context = NULL) {                                        
     510               2 :     if (isset($context)) {                                                                          
     511               1 :       return $this->_xpath()->evaluate($expr, $context);                                            
     512                 :     } else {                                                                                        
     513               1 :       return $this->_xpath()->evaluate($expr);                                                      
     514                 :     }                                                                                               
     515                 :   }                                                                                                 
     516                 :                                                                                                     
     517                 :   /**                                                                                               
     518                 :   * Register namespaces and or get namespaces                                                       
     519                 :   *                                                                                                 
     520                 :   * @param array $namespaces If this parameter is empty the current namespaces are returned         
     521                 :   * @return array|FluentDOMCore                                                                     
     522                 :   */                                                                                                
     523                 :   public function namespaces(array $namespaces = NULL) {                                            
     524               3 :     if (is_null($namespaces)) {                                                                     
     525               1 :       return $this->_namespaces;                                                                    
     526                 :     }                                                                                               
     527               3 :     foreach ($namespaces as $prefix => $uri) {                                                      
     528               3 :       if ($this->_isNCName($prefix)) {                                                              
     529               3 :         $this->_xpath()->registerNamespace($prefix, $uri);                                          
     530               3 :         $this->_namespaces[$prefix] = $uri;                                                         
     531               3 :       }                                                                                             
     532               3 :     }                                                                                               
     533               3 :     return $this;                                                                                   
     534                 :   }                                                                                                 
     535                 :                                                                                                     
     536                 :   /**                                                                                               
     537                 :   * Get a XPath object associated with the internal DOMDocument and register                        
     538                 :   * default namespaces from the document element if availiable.                                     
     539                 :   *                                                                                                 
     540                 :   * @return DOMXPath                                                                                
     541                 :   */                                                                                                
     542                 :   protected function _xpath() {                                                                     
     543               4 :     if (empty($this->_xpath) || $this->_xpath->document !== $this->_document) {                     
     544               4 :       $this->_xpath = new DOMXPath($this->_document);                                               
     545               4 :       foreach ($this->_namespaces as $prefix => $uri) {                                             
     546               1 :         $this->_xpath->registerNamespace($prefix, $uri);                                            
     547               4 :       }                                                                                             
     548               4 :       if ($this->_document->documentElement) {                                                      
     549               4 :         $uri = $this->_document->documentElement->lookupnamespaceURI('_');                          
     550               4 :         if (!isset($uri)) {                                                                         
     551               4 :           $uri = $this->_document->documentElement->lookupnamespaceURI(NULL);                       
     552               4 :           if (isset($uri)) {                                                                        
     553               2 :             $this->_xpath->registerNamespace('_', $uri);                                            
     554               2 :           }                                                                                         
     555               4 :         }                                                                                           
     556               4 :       }                                                                                             
     557               4 :     }                                                                                               
     558               4 :     return $this->_xpath;                                                                           
     559                 :   }                                                                                                 
     560                 :                                                                                                     
     561                 :   /**                                                                                               
     562                 :   * Match XPath expression agains context and return matched elements.                              
     563                 :   *                                                                                                 
     564                 :   * @param string $expr                                                                             
     565                 :   * @param DOMNode $context optional, default value NULL                                            
     566                 :   * @return DOMNodeList                                                                             
     567                 :   */                                                                                                
     568                 :   protected function _match($expr, $context = NULL) {                                               
     569               3 :     if (isset($context)) {                                                                          
     570               1 :       return $this->_xpath()->query($expr, $context);                                               
     571                 :     } else {                                                                                        
     572               2 :       return $this->_xpath()->query($expr);                                                         
     573                 :     }                                                                                               
     574                 :   }                                                                                                 
     575                 :                                                                                                     
     576                 :   /**                                                                                               
     577                 :   * Test xpath expression against context and return true/false                                     
     578                 :   *                                                                                                 
     579                 :   * @param string $expr                                                                             
     580                 :   * @param DOMNode $context optional, default value NULL                                            
     581                 :   * @return boolean                                                                                 
     582                 :   */                                                                                                
     583                 :   protected function _test($expr, $context = NULL) {                                                
     584               2 :     if (isset($context)) {                                                                          
     585               1 :       $check = $this->_xpath()->evaluate($expr, $context);                                          
     586               1 :     } else {                                                                                        
     587               1 :       $check = $this->_xpath()->evaluate($expr);                                                    
     588                 :     }                                                                                               
     589               2 :     if ($check instanceof DOMNodeList) {                                                            
     590               1 :       return $check->length > 0;                                                                    
     591                 :     } else {                                                                                        
     592               1 :       return (bool)$check;                                                                          
     593                 :     }                                                                                               
     594                 :   }                                                                                                 
     595                 :                                                                                                     
     596                 :   /**                                                                                               
     597                 :   * Check if object is already in internal list                                                     
     598                 :   *                                                                                                 
     599                 :   * @param DOMNode $node                                                                            
     600                 :   * @return boolean                                                                                 
     601                 :   */                                                                                                
     602                 :   protected function _inList($node) {                                                               
     603               2 :     foreach ($this->_array as $compareNode) {                                                       
     604               2 :       if ($compareNode === $node) {                                                                 
     605               1 :         return TRUE;                                                                                
     606                 :       }                                                                                             
     607               1 :     }                                                                                               
     608               1 :     return FALSE;                                                                                   
     609                 :   }                                                                                                 
     610                 :                                                                                                     
     611                 :   /**                                                                                               
     612                 :   * Validate string as qualified node name                                                          
     613                 :   *                                                                                                 
     614                 :   * @param string $name                                                                             
     615                 :   * @return boolean                                                                                 
     616                 :   */                                                                                                
     617                 :   protected function _isQName($name) {                                                              
     618               6 :     if (empty($name)) {                                                                             
     619               1 :       throw new UnexpectedValueException('Invalid QName: QName is empty.');                         
     620               5 :     } elseif (FALSE !== ($position = strpos($name, ':'))) {                                         
     621               2 :       $this->_isNCName($name, 0, $position);                                                        
     622               2 :       $this->_isNCName($name, $position + 1);                                                       
     623               2 :       return TRUE;                                                                                  
     624                 :     }                                                                                               
     625               3 :     $this->_isNCName($name);                                                                        
     626               3 :     return TRUE;                                                                                    
     627                 :   }                                                                                                 
     628                 :                                                                                                     
     629                 :   /**                                                                                               
     630                 :   * Validate string as qualified node name part (namespace or local name)                           
     631                 :   *                                                                                                 
     632                 :   * @param string $name full QName                                                                  
     633                 :   * @param integer $offset Offset of NCName part in QName                                           
     634                 :   * @param integer $length Length of NCName part in QName                                           
     635                 :   * @return boolean                                                                                 
     636                 :   */                                                                                                
     637                 :   protected function _isNCName($name, $offset = 0, $length = 0) {                                   
     638                 :     $nameStartChar =                                                                                
     639                 :        'A-Z_a-z'.                                                                                   
     640               9 :        '\\x{C0}-\\x{D6}\\x{D8}-\\x{F6}\\x{F8}-\\x{2FF}\\x{370}-\\x{37D}'.                           
     641               9 :        '\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}'.                                  
     642               9 :        '\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}'.                                 
     643               9 :        '\\x{FDF0}-\\x{FFFD}\\x{10000}-\\x{EFFFF}';                                                  
     644                 :     $nameChar =                                                                                     
     645                 :        $nameStartChar.                                                                              
     646               9 :        '\\.\\d\\x{B7}\\x{300}-\\x{36F}\\x{203F}-\\x{2040}';                                         
     647               9 :     if ($length > 0) {                                                                              
     648               1 :       $namePart = substr($name, $offset, $length);                                                  
     649               9 :     } elseif ($offset > 0) {                                                                        
     650               4 :       $namePart = substr($name, $offset);                                                           
     651               4 :     } else {                                                                                        
     652               4 :       $namePart = $name;                                                                            
     653                 :     }                                                                                               
     654               9 :     if (empty($namePart)) {                                                                         
     655               1 :       throw new UnexpectedValueException(                                                           
     656               1 :         'Invalid QName "'.$name.'": Missing QName part.'                                            
     657               1 :       );                                                                                            
     658               8 :     } elseif (preg_match('([^'.$nameChar.'-])u', $namePart, $match, PREG_OFFSET_CAPTURE)) {         
     659                 :       //invalid bytes and whitespaces                                                               
     660               1 :       $position = (int)$match[0][1];                                                                
     661               1 :       throw new UnexpectedValueException(                                                           
     662               1 :         'Invalid QName "'.$name.'": Invalid character at index '.($offset + $position).'.'          
     663               1 :       );                                                                                            
     664               7 :     } elseif (preg_match('(^[^'.$nameStartChar.'])u', $namePart)) {                                 
     665                 :       //first char is a little more limited                                                         
     666               1 :       throw new UnexpectedValueException(                                                           
     667               1 :         'Invalid QName "'.$name.'": Invalid character at index '.$offset.'.'                        
     668               1 :       );                                                                                            
     669                 :     }                                                                                               
     670               6 :     return TRUE;                                                                                    
     671                 :   }                                                                                                 
     672                 :                                                                                                     
     673                 :   /**                                                                                               
     674                 :   * Check if the DOMNode is DOMElement or DOMText with content                                      
     675                 :   *                                                                                                 
     676                 :   * @param DOMNode $node                                                                            
     677                 :   * @param boolean $ignoreTextNodes                                                                 
     678                 :   * @return boolean                                                                                 
     679                 :   */                                                                                                
     680                 :   protected function _isNode($node, $ignoreTextNodes = FALSE) {                                     
     681               6 :     if (is_object($node)) {                                                                         
     682               6 :       if ($node instanceof DOMElement) {                                                            
     683               4 :         return TRUE;                                                                                
     684               3 :       } elseif ($node instanceof DOMText) {                                                         
     685               2 :         if (!$ignoreTextNodes &&                                                                    
     686               2 :             !$node->isWhitespaceInElementContent()) {                                               
     687               1 :           return TRUE;                                                                              
     688                 :         }                                                                                           
     689               1 :       }                                                                                             
     690               2 :     }                                                                                               
     691               4 :     return FALSE;                                                                                   
     692                 :   }                                                                                                 
     693                 :                                                                                                     
     694                 :   /**                                                                                               
     695                 :   * Check if $elements is a iterateable node list                                                   
     696                 :   *                                                                                                 
     697                 :   * @param DOMNodeList|DOMDocumentFragment|Iterator|IteratorAggregate|array $list                   
     698                 :   * @return boolean                                                                                 
     699                 :   */                                                                                                
     700                 :   protected function _isNodeList($elements) {                                                       
     701               5 :     if ($elements instanceof DOMNodeList ||                                                         
     702               5 :         $elements instanceof DOMDocumentFragment ||                                                 
     703               5 :         $elements instanceof Iterator ||                                                            
     704               5 :         $elements instanceof IteratorAggregate ||                                                   
     705               5 :         is_array($elements)) {                                                                      
     706               4 :       return TRUE;                                                                                  
     707                 :     }                                                                                               
     708               1 :     return FALSE;                                                                                   
     709                 :   }                                                                                                 
     710                 :                                                                                                     
     711                 :   /**                                                                                               
     712                 :   * check if parameter is a valid callback function                                                 
     713                 :   *                                                                                                 
     714                 :   * @param callback $callback                                                                       
     715                 :   * @param boolean $allowGlobalFunctions                                                            
     716                 :   * @param boolean $silent (no InvalidArgumentException)                                            
     717                 :   * @return boolean                                                                                 
     718                 :   */                                                                                                
     719                 :   protected function _isCallback($callback, $allowGlobalFunctions, $silent) {                       
     720               6 :     if ($callback instanceof Closure) {                                                             
     721               0 :       return TRUE;                                                                                  
     722               6 :     } elseif (is_string($callback) &&                                                               
     723               4 :               $allowGlobalFunctions &&                                                              
     724               6 :               function_exists($callback)) {                                                         
     725               1 :       return is_callable($callback);                                                                
     726               5 :     } elseif (is_array($callback) &&                                                                
     727               2 :               count($callback) == 2 &&                                                              
     728               1 :               (is_object($callback[0]) || is_string($callback[0])) &&                               
     729               5 :               is_string($callback[1])) {                                                            
     730               1 :       return is_callable($callback);                                                                
     731               4 :     } elseif ($silent) {                                                                            
     732               3 :       return FALSE;                                                                                 
     733                 :     } else {                                                                                        
     734               1 :       throw new InvalidArgumentException('Invalid callback argument');                              
     735                 :     }                                                                                               
     736                 :   }                                                                                                 
     737                 :                                                                                                     
     738                 :   /**                                                                                               
     739                 :   * Convert a given content xml string into and array of nodes                                      
     740                 :   *                                                                                                 
     741                 :   * @param string $content                                                                          
     742                 :   * @param boolean $includeTextNodes                                                                
     743                 :   * @param integer $limit                                                                           
     744                 :   * @return array                                                                                   
     745                 :   */                                                                                                
     746                 :   protected function _getContentFragment($content, $includeTextNodes = TRUE, $limit = 0) {          
     747               5 :     $result = array();                                                                              
     748               5 :     $fragment = $this->_document->createDocumentFragment();                                         
     749               5 :     if ($fragment->appendXML($content)) {                                                           
     750               4 :       for ($i = $fragment->childNodes->length - 1; $i >= 0; $i--) {                                 
     751               4 :         $element = $fragment->childNodes->item($i);                                                 
     752               4 :         if ($element instanceof DOMElement ||                                                       
     753               4 :             ($includeTextNodes && $this->_isNode($element))) {                                      
     754               4 :           array_unshift($result, $element);                                                         
     755               4 :           $element->parentNode->removeChild($element);                                              
     756               4 :         }                                                                                           
     757               4 :       }                                                                                             
     758               4 :       if ($limit > 0 && count($result) >= $limit) {                                                 
     759               1 :         return array_slice($result, 0, $limit);                                                     
     760                 :       }                                                                                             
     761               3 :       return $result;                                                                               
     762                 :     } else {                                                                                        
     763               1 :       throw new UnexpectedValueException('Invalid document fragment');                              
     764                 :     }                                                                                               
     765                 :   }                                                                                                 
     766                 :                                                                                                     
     767                 :   /**                                                                                               
     768                 :   * Convert a given content into and array of nodes                                                 
     769                 :   *                                                                                                 
     770                 :   * @param string|array|DOMElement|DOMText|Iterator $content                                        
     771                 :   * @param boolean $includeTextNodes                                                                
     772                 :   * @param integer $limit                                                                           
     773                 :   * @return array                                                                                   
     774                 :   */                                                                                                
     775                 :   protected function _getContentNodes($content, $includeTextNodes = TRUE, $limit = 0) {             
     776              10 :     $result = array();                                                                              
     777              10 :     if ($content instanceof DOMElement) {                                                           
     778               1 :       $result = array($content);                                                                    
     779              10 :     } elseif ($includeTextNodes && $this->_isNode($content)) {                                      
     780               1 :       $result = array($content);                                                                    
     781               9 :     } elseif (is_string($content)) {                                                                
     782               2 :       $result = $this->_getContentFragment($content, $includeTextNodes, $limit);                    
     783               8 :     } elseif ($this->_isNodeList($content)) {                                                       
     784               5 :       foreach ($content as $element) {                                                              
     785               5 :         if ($element instanceof DOMElement ||                                                       
     786               5 :             ($includeTextNodes && $this->_isNode($element))) {                                      
     787               5 :           $result[] = $element;                                                                     
     788               5 :           if ($limit > 0 && count($result) >= $limit) {                                             
     789               1 :             break;                                                                                  
     790                 :           }                                                                                         
     791               4 :         }                                                                                           
     792               5 :       }                                                                                             
     793               5 :     } else {                                                                                        
     794               1 :       throw new InvalidArgumentException('Invalid content parameter');                              
     795                 :     }                                                                                               
     796               9 :     if (empty($result)) {                                                                           
     797               1 :       throw new UnexpectedValueException('No element found');                                       
     798                 :     } else {                                                                                        
     799                 :       //if a node is not in the current document import it                                          
     800               8 :       foreach ($result as $index => $node) {                                                        
     801               8 :         if ($node->ownerDocument !== $this->_document) {                                            
     802               1 :           $result[$index] = $this->_document->importNode($node, TRUE);                              
     803               1 :         }                                                                                           
     804               8 :       }                                                                                             
     805                 :     }                                                                                               
     806               8 :     return $result;                                                                                 
     807                 :   }                                                                                                 
     808                 :                                                                                                     
     809                 :   /**                                                                                               
     810                 :   * Convert $content to a DOMElement. If $content contains several elements use the first.          
     811                 :   *                                                                                                 
     812                 :   * @param string|array|DOMElement|DOMNodeList|Iterator $content                                    
     813                 :   * @return DOMElement                                                                              
     814                 :   */                                                                                                
     815                 :   protected function _getContentElement($content) {                                                 
     816               2 :     if ($content instanceof DOMElement) {                                                           
     817               1 :       return $content;                                                                              
     818                 :     } else {                                                                                        
     819               1 :       $contentNodes = $this->_getContentNodes($content, FALSE, 1);                                  
     820               1 :       return $contentNodes[0];                                                                      
     821                 :     }                                                                                               
     822                 :   }                                                                                                 
     823                 :                                                                                                     
     824                 :   /**                                                                                               
     825                 :   * Get the target nodes from a given $selector.                                                    
     826                 :   *                                                                                                 
     827                 :   * A string will be used as XPath expression.                                                      
     828                 :   *                                                                                                 
     829                 :   * @param string|array|DOMNode|DOMNodeList|Iterator $selector                                      
     830                 :   * @return array                                                                                   
     831                 :   */                                                                                                
     832                 :   protected function _getTargetNodes($selector) {                                                   
     833               5 :     if ($this->_isNode($selector)) {                                                                
     834               1 :       return array($selector);                                                                      
     835               4 :     } elseif (is_string($selector)) {                                                               
     836               2 :       return $this->_match($selector);                                                              
     837               3 :     } elseif ($this->_isNodeList($selector)) {                                                      
     838               2 :       return $selector;                                                                             
     839                 :     } else {                                                                                        
     840               1 :       throw new InvalidArgumentException('Invalid selector');                                       
     841                 :     }                                                                                               
     842                 :   }                                                                                                 
     843                 :                                                                                                     
     844                 :   /*                                                                                                
     845                 :   * the context is the target of a selector or the current selection                                
     846                 :   *                                                                                                 
     847                 :   * @param string|array|DOMNode|DOMNodeList|Iterator $selector                                      
     848                 :   * @return unknown_type                                                                            
     849                 :   */                                                                                                
     850                 :   protected function _getContextNodes($selector) {                                                  
     851               2 :     if (is_null($selector)) {                                                                       
     852               1 :       return $this->_array;                                                                         
     853                 :     } else {                                                                                        
     854               1 :       return $this->_getTargetNodes($selector);                                                     
     855                 :     }                                                                                               
     856                 :   }                                                                                                 
     857                 :                                                                                                     
     858                 :   /**                                                                                               
     859                 :   * Get the inner xml of a given node or in other words the xml of all children.                    
     860                 :   * @param DOMElement $node                                                                         
     861                 :   * @return string                                                                                  
     862                 :   */                                                                                                
     863                 :   protected function _getInnerXml($node) {                                                          
     864               2 :     $result = '';                                                                                   
     865               2 :     if ($node instanceof DOMElement) {                                                              
     866               1 :       foreach ($node->childNodes as $childNode) {                                                   
     867               1 :         if ($this->_isNode($childNode)) {                                                           
     868               1 :           $result .= $this->_document->saveXML($childNode);                                         
     869               1 :         }                                                                                           
     870               1 :       }                                                                                             
     871               2 :     } elseif ($node instanceof DOMText) {                                                           
     872               1 :       return $node->textContent;                                                                    
     873                 :     }                                                                                               
     874               1 :     return $result;                                                                                 
     875                 :   }                                                                                                 
     876                 :                                                                                                     
     877                 :   /**                                                                                               
     878                 :   * Remove nodes from document tree                                                                 
     879                 :   *                                                                                                 
     880                 :   * @param string|array|DOMNode|DOMNodeList|Iterator $selector                                      
     881                 :   * @return array $result removed nodes                                                             
     882                 :   */                                                                                                
     883                 :   protected function _removeNodes($selector) {                                                      
     884               2 :     $targetNodes = $this->_getTargetNodes($selector);                                               
     885               2 :     $result = array();                                                                              
     886               2 :     foreach ($targetNodes as $node) {                                                               
     887               2 :       if ($node instanceof DOMNode &&                                                               
     888               2 :           isset($node->parentNode)) {                                                               
     889               2 :         $result[] = $node->parentNode->removeChild($node);                                          
     890               2 :       }                                                                                             
     891               2 :     }                                                                                               
     892               2 :     return $result;                                                                                 
     893                 :   }                                                                                                 
     894                 :                                                                                                     
     895                 :   /**                                                                                               
     896                 :   * Get the class/object providing the handler functions                                            
     897                 :   *                                                                                                 
     898                 :   * @return string|object                                                                           
     899                 :   */                                                                                                
     900                 :   protected function _getHandler() {                                                                
     901               2 :     return 'FluentDOMHandler';                                                                      
     902                 :   }                                                                                                 
     903                 :                                                                                                     
     904                 :   /**                                                                                               
     905                 :   * Use a handler callback to apply a content argument to each node $targetNodes. The content       
     906                 :   * argument can be an easy setter function                                                         
     907                 :   *                                                                                                 
     908                 :   * @param array|DOMNodeList $targetNodes                                                           
     909                 :   * @param string|array|DOMElement|DOMText|DOMNodeList|Iterator|callback|Closure $content           
     910                 :   * @param callback|Closure $handler                                                                
     911                 :   */                                                                                                
     912                 :   protected function _applyContentToNodes($targetNodes, $content, $handler) {                       
     913               3 :     $result = array();                                                                              
     914               3 :     $isEasySetterFunction = $this->_isCallback($content, FALSE, TRUE);                              
     915               3 :     if (!$isEasySetterFunction) {                                                                   
     916               2 :       $contentNodes = $this->_getContentNodes($content);                                            
     917               2 :     }                                                                                               
     918               3 :     foreach ($targetNodes as $index => $node) {                                                     
     919               3 :       if ($isEasySetterFunction) {                                                                  
     920               1 :         $contentNodes = $this->_executeEasySetter(                                                  
     921               1 :           $content, $node, $index, $this->_getInnerXml($node)                                       
     922               1 :         );                                                                                          
     923               1 :       }                                                                                             
     924               3 :       if (!empty($contentNodes)) {                                                                  
     925               3 :         $resultNodes = call_user_func($handler, $node, $contentNodes);                              
     926               3 :         if (is_array($resultNodes)) {                                                               
     927               3 :           $result = array_merge($result, $resultNodes);                                             
     928               3 :         }                                                                                           
     929               3 :       }                                                                                             
     930               3 :     }                                                                                               
     931               3 :     return $result;                                                                                 
     932                 :   }                                                                                                 
     933                 :                                                                                                     
     934                 :   /**                                                                                               
     935                 :   * Execute the easy setter function for a node and return the new elements                         
     936                 :   *                                                                                                 
     937                 :   * @param callback|Closure $easySetter                                                             
     938                 :   * @param DOMNode $node                                                                            
     939                 :   * @param integer $index                                                                           
     940                 :   * @param string $value                                                                            
     941                 :   * @return array                                                                                   
     942                 :   */                                                                                                
     943                 :   protected function _executeEasySetter($easySetter, $node, $index, $value) {                       
     944               2 :     $contentData = call_user_func($easySetter, $node, $index, $value);                              
     945               2 :     if (!empty($contentData)) {                                                                     
     946               1 :       return $this->_getContentNodes($contentData);                                                 
     947                 :     }                                                                                               
     948               1 :     return array();                                                                                 
     949                 :   }                                                                                                 

Generated by PHPUnit 3.4.12 and Xdebug 2.0.5 using PHP 5.2.13 at Sun Sep 26 1:00:19 CEST 2010.