FluentDOM Package
Current file: /fluentdom/releases/release_3.0/FluentDOM.php
Legend: executed not executed dead code

  Coverage
  Classes Functions / Methods Lines
Total
0.00%0.00%
0.00% 0 / 1
98.77%98.77%
98.77% 80 / 81
99.89%99.89%
99.89% 879 / 880
 
FluentDOM
0.00%0.00%
0.00% 0 / 1
98.75%98.75%
98.75% 79 / 80
99.89%99.89%
99.89% 875 / 876
 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
 private 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% 6 / 6
 public function __call($name, $arguments)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 8 / 8
 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 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
 private function _spawn()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 private function _xpath()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 13 / 13
 private function _match($expr, $context = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 private function _test($expr, $context)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 4 / 4
 private function _push($elements, $unique = FALSE)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 24 / 24
 private function _inList($node)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 5 / 5
 private function _isQName($name)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 9 / 9
 private function _isNCName($name, $offset = 0)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 19 / 19
 private function _isNode($node)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 8 / 8
 protected function _isCallback($callback)
0.00%0.00%
0.00% 0 / 1
90.91%90.91%
90.91% 10 / 11
 private function _getContentNodes($content, $includeTextNodes = TRUE, $limit = 0)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 41 / 41
 private function _getTargetNodes($selector)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 10 / 10
 private function _removeNodes($selector)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 9 / 9
 private function _getContentElement($content)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 4 / 4
 public function each($function)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 6 / 6
 public function formatOutput($contentType = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 11 / 11
 public function eq($position)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 5 / 5
 public function filter($expr)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 13 / 13
 public function is($expr)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 4 / 4
 public function map($function)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 20 / 20
 public function not($expr)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 13 / 13
 public function slice($start, $end = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 10 / 10
 public function add($expr)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 9 / 9
 public function children($expr = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 12 / 12
 public function find($expr, $useDocumentContext = FALSE)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 9 / 9
 public function next($expr = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 13 / 13
 public function nextAll($expr = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 13 / 13
 public function parent()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 7 / 7
 public function parents($expr = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 11 / 11
 public function prev($expr = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 13 / 13
 public function prevAll($expr = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 13 / 13
 public function siblings($expr = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 14 / 14
 public function closest($expr)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 10 / 10
 public function andSelf()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 4 / 4
 public function end()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 public function xml($xml = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 20 / 20
 public function text($text = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 10 / 10
 public function append($content)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function appendTo($selector)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function prepend($content)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function prependTo($selector)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 private function _insertChild($content, $first)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 22 / 22
 private function _insertChildTo($selector, $first)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 19 / 19
 public function after($content)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 16 / 16
 public function before($content)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 15 / 15
 public function insertAfter($selector)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 18 / 18
 public function insertBefore($selector)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 17 / 17
 private function _wrap($elements, $content)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 22 / 22
 public function wrap($content)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 public function wrapAll($content)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 41 / 41
 public function wrapInner($content)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 11 / 11
 public function replaceWith($content)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 12 / 12
 public function replaceAll($selector)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 16 / 16
 private function _emptyNodes()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 7 / 7
 public function remove($expr = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 9 / 9
 public function node($content)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 private function _cloneNodes()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 5 / 5
 public function attr($attribute, $value = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 39 / 39
 public function removeAttr($name)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 23 / 23
 public function addClass($class)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function hasClass($class)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 9 / 9
 public function removeClass($class)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function toggleClass($class, $switch = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 31 / 31
Functions
  
   
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 0 / 0
 function FluentDOM($source = NULL, $contentType = 'text/xml')
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 4 / 4


       1                 : <?php                                                                                                    
       2                 : /**                                                                                                      
       3                 : * FluentDOM implements a jQuery like replacement for DOMNodeList                                         
       4                 : *                                                                                                        
       5                 : * @version $Id: FluentDOM.php 353 2009-11-17 20:13:20Z 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__).'/FluentDOM/Iterator.php');                                               
      17                 : /**                                                                                                      
      18                 : * Include the loader interface.                                                                          
      19                 : */                                                                                                       
      20                 : require_once(dirname(__FILE__).'/FluentDOM/Loader.php');                                                 
      21                 :                                                                                                          
      22                 : /**                                                                                                      
      23                 : * Function to create a new FluentDOM instance and loads data into it if                                  
      24                 : * a valid $source is provided.                                                                           
      25                 : *                                                                                                        
      26                 : * @param mixed $source                                                                                   
      27                 : * @param string $contentType optional, default value 'text/xml'                                          
      28                 : * @access public                                                                                         
      29                 : * @return FluentDOM                                                                                      
      30                 : */                                                                                                       
      31                 : function FluentDOM($source = NULL, $contentType = 'text/xml') {                                          
      32               2 :   $result = new FluentDOM();                                                                             
      33               2 :   if (isset($source)) {                                                                                  
      34               1 :     return $result->load($source, $contentType);                                                         
      35                 :   } else {                                                                                               
      36               1 :     return $result;                                                                                      
      37                 :   }                                                                                                      
      38                 : }                                                                                                        
      39                 :                                                                                                          
      40                 : /**                                                                                                      
      41                 : * FluentDOM implements a jQuery like replacement for DOMNodeList                                         
      42                 : *                                                                                                        
      43                 : * @property string $contentType Output type - text/xml or text/html                                      
      44                 : * @property-read integer $length The amount of elements found by selector.                               
      45                 : * @property-read DOMDocument $document Internal DOMDocument object                                       
      46                 : * @property-read DOMXPath $xpath Internal XPath object                                                   
      47                 : *                                                                                                        
      48                 : * @method bool empty() Remove all child nodes from the set of matched elements.                          
      49                 : * @method DOMDocument clone() Clone matched DOM Elements and select the clones.                          
      50                 : *                                                                                                        
      51                 : * @package FluentDOM                                                                                     
      52                 : */                                                                                                       
      53                 : class FluentDOM implements IteratorAggregate, Countable, ArrayAccess {                                   
      54                 :                                                                                                          
      55                 :   /**                                                                                                    
      56                 :   * Associated DOMDocument object.                                                                       
      57                 :   * @var DOMDocument                                                                                     
      58                 :   * @access private                                                                                      
      59                 :   */                                                                                                     
      60                 :   private $_document = NULL;                                                                             
      61                 :                                                                                                          
      62                 :   /**                                                                                                    
      63                 :   * XPath object used to execute selectors                                                               
      64                 :   * @var DOMXPath                                                                                        
      65                 :   * @access private                                                                                      
      66                 :   */                                                                                                     
      67                 :   private $_xpath = NULL;                                                                                
      68                 :                                                                                                          
      69                 :   /**                                                                                                    
      70                 :   * Use document context for expression (not selected nodes).                                            
      71                 :   * @var boolean                                                                                         
      72                 :   * @access private                                                                                      
      73                 :   */                                                                                                     
      74                 :   private $_useDocumentContext = TRUE;                                                                   
      75                 :                                                                                                          
      76                 :   /**                                                                                                    
      77                 :   * Content type for output (xml, text/xml, html, text/html).                                            
      78                 :   * @var string                                                                                          
      79                 :   * @access private                                                                                      
      80                 :   */                                                                                                     
      81                 :   private $_contentType = 'text/xml';                                                                    
      82                 :                                                                                                          
      83                 :   /**                                                                                                    
      84                 :   * Parent FluentDOM object (previous selection in chain).                                               
      85                 :   * @var FluentDOM                                                                                       
      86                 :   * @access private                                                                                      
      87                 :   */                                                                                                     
      88                 :   private $_parent = NULL;                                                                               
      89                 :                                                                                                          
      90                 :   /**                                                                                                    
      91                 :   * Seleted element and text nodes                                                                       
      92                 :   * @var array                                                                                           
      93                 :   * @access protected                                                                                    
      94                 :   */                                                                                                     
      95                 :   protected $_array = array();                                                                           
      96                 :                                                                                                          
      97                 :   /**                                                                                                    
      98                 :   * Document loader list.                                                                                
      99                 :   *                                                                                                      
     100                 :   * @see _initLoaders                                                                                    
     101                 :   * @see _setLoader                                                                                      
     102                 :   *                                                                                                      
     103                 :   * @var array                                                                                           
     104                 :   * @access private                                                                                      
     105                 :   */                                                                                                     
     106                 :   private $_loaders = NULL;                                                                              
     107                 :                                                                                                          
     108                 :   /**                                                                                                    
     109                 :   * Constructor                                                                                          
     110                 :   *                                                                                                      
     111                 :   * @access public                                                                                       
     112                 :   * @return FluentDOM                                                                                    
     113                 :   */                                                                                                     
     114                 :   public function __construct() {                                                                        
     115             157 :     $this->_document = new DOMDocument();                                                                
     116             157 :   }                                                                                                      
     117                 :                                                                                                          
     118                 :   /**                                                                                                    
     119                 :   * Load a $source. The type of the source depends on the loaders. If no explicit loaders are set        
     120                 :   * FluentDOM will use a set of default loaders for xml/html and DOM.                                    
     121                 :   *                                                                                                      
     122                 :   * @param mixed $source                                                                                 
     123                 :   * @param string $contentType optional, default value 'text/xml'                                        
     124                 :   * @access public                                                                                       
     125                 :   */                                                                                                     
     126                 :   public function load($source, $contentType = 'text/xml') {                                             
     127             134 :     $this->_array = array();                                                                             
     128             134 :     $this->_setContentType($contentType);                                                                
     129             134 :     if ($source instanceof FluentDOM) {                                                                  
     130             121 :       $this->_useDocumentContext = FALSE;                                                                
     131             121 :       $this->_document = $source->document;                                                              
     132             121 :       $this->_xpath = $source->_xpath;                                                                   
     133             121 :       $this->_contentType = $source->_contentType;                                                       
     134             121 :       $this->_parent = $source;                                                                          
     135             121 :       return $this;                                                                                      
     136                 :     } else {                                                                                             
     137             131 :       $this->_parent = NULL;                                                                             
     138             131 :       $this->_initLoaders();                                                                             
     139             131 :       foreach ($this->_loaders as $loader) {                                                             
     140             131 :         if ($loaded = $loader->load($source, $this->_contentType)) {                                     
     141             130 :           if ($loaded instanceof DOMDocument) {                                                          
     142             127 :             $this->_useDocumentContext = TRUE;                                                           
     143             127 :             $this->_document = $loaded;                                                                  
     144             130 :           } elseif (is_array($loaded) &&                                                                 
     145               6 :                     isset($loaded[0]) &&                                                                 
     146               6 :                     isset($loaded[1]) &&                                                                 
     147               6 :                     $loaded[0] instanceof DOMDocument &&                                                 
     148               6 :                     is_array($loaded[1])) {                                                              
     149               6 :             $this->_document = $loaded[0];                                                               
     150               6 :             $this->_push($loaded[1]);                                                                    
     151               6 :             $this->_useDocumentContext = FALSE;                                                          
     152               6 :           }                                                                                              
     153             130 :           return $this;                                                                                  
     154                 :         }                                                                                                
     155               2 :       }                                                                                                  
     156               1 :       throw new InvalidArgumentException('Invalid source object.');                                      
     157                 :     }                                                                                                    
     158                 :     return $this;                                                                                        
     159                 :   }                                                                                                      
     160                 :                                                                                                          
     161                 :   /**                                                                                                    
     162                 :   * Initialize default loaders if they are not already initialized                                       
     163                 :   *                                                                                                      
     164                 :   * @access protected                                                                                    
     165                 :   * @return void                                                                                         
     166                 :   */                                                                                                     
     167                 :   protected function _initLoaders() {                                                                    
     168             131 :     if (!is_array($this->_loaders)) {                                                                    
     169               6 :       $path = dirname(__FILE__).'/FluentDOM';                                                            
     170               6 :       include_once($path.'/Loader/DOMNode.php');                                                         
     171               6 :       include_once($path.'/Loader/DOMDocument.php');                                                     
     172               6 :       include_once($path.'/Loader/StringXML.php');                                                       
     173               6 :       include_once($path.'/Loader/FileXML.php');                                                         
     174               6 :       include_once($path.'/Loader/StringHTML.php');                                                      
     175               6 :       include_once($path.'/Loader/FileHTML.php');                                                        
     176               6 :       $this->_loaders = array(                                                                           
     177               6 :         new FluentDOMLoaderDOMNode(),                                                                    
     178               6 :         new FluentDOMLoaderDOMDocument(),                                                                
     179               6 :         new FluentDOMLoaderStringXML(),                                                                  
     180               6 :         new FluentDOMLoaderFileXML(),                                                                    
     181               6 :         new FluentDOMLoaderStringHTML(),                                                                 
     182               6 :         new FluentDOMLoaderFileHTML(),                                                                   
     183                 :       );                                                                                                 
     184               6 :     }                                                                                                    
     185             131 :   }                                                                                                      
     186                 :                                                                                                          
     187                 :   /**                                                                                                    
     188                 :   * Define own loading handlers                                                                          
     189                 :   *                                                                                                      
     190                 :   * @example iniloader/iniToXML.php Usage Example: Own loader object                                     
     191                 :   * @param $loaders                                                                                      
     192                 :   * @access public                                                                                       
     193                 :   * @return FluentDOM                                                                                    
     194                 :   */                                                                                                     
     195                 :   public function setLoaders($loaders) {                                                                 
     196             129 :     foreach ($loaders as $loader) {                                                                      
     197             129 :       if (!($loader instanceof FluentDOMLoader)) {                                                       
     198               1 :         throw new InvalidArgumentException('Array contains invalid loader object');                      
     199                 :       }                                                                                                  
     200             128 :     }                                                                                                    
     201             128 :     $this->_loaders = $loaders;                                                                          
     202             128 :     return $this;                                                                                        
     203                 :   }                                                                                                      
     204                 :                                                                                                          
     205                 :   /**                                                                                                    
     206                 :   * Setter for FluentDOM::_contentType property                                                          
     207                 :   *                                                                                                      
     208                 :   * @param string $value                                                                                 
     209                 :   * @access private                                                                                      
     210                 :   * @return void                                                                                         
     211                 :   */                                                                                                     
     212                 :   private function _setContentType($value) {                                                             
     213             143 :     switch (strtolower($value)) {                                                                        
     214             143 :     case 'xml' :                                                                                         
     215             143 :     case 'application/xml' :                                                                             
     216             143 :     case 'text/xml' :                                                                                    
     217             137 :       $newContentType = 'text/xml';                                                                      
     218             137 :       break;                                                                                             
     219               7 :     case 'html' :                                                                                        
     220               7 :     case 'text/html' :                                                                                   
     221               6 :       $newContentType = 'text/html';                                                                     
     222               6 :       break;                                                                                             
     223               1 :     default :                                                                                            
     224               1 :       throw new UnexpectedValueException('Invalid content type value');                                  
     225             143 :     }                                                                                                    
     226             142 :     if ($this->_contentType != $newContentType) {                                                        
     227               6 :       $this->_contentType = $newContentType;                                                             
     228               6 :       if (isset($this->_parent)) {                                                                       
     229               1 :         $this->_parent->contentType = $newContentType;                                                   
     230               1 :       }                                                                                                  
     231               6 :     }                                                                                                    
     232             142 :   }                                                                                                      
     233                 :                                                                                                          
     234                 :   /**                                                                                                    
     235                 :   * implement dynamic properties using magic methods                                                     
     236                 :   *                                                                                                      
     237                 :   * @param string $name                                                                                  
     238                 :   * @access public                                                                                       
     239                 :   * @return mixed                                                                                        
     240                 :   */                                                                                                     
     241                 :   public function __get($name) {                                                                         
     242                 :     switch ($name) {                                                                                     
     243             136 :     case 'contentType' :                                                                                 
     244               8 :       return $this->_contentType;                                                                        
     245             128 :     case 'document' :                                                                                    
     246             125 :       return $this->_document;                                                                           
     247              16 :     case 'length' :                                                                                      
     248              13 :       return count($this->_array);                                                                       
     249               3 :     case 'xpath' :                                                                                       
     250               2 :       return $this->_xpath();                                                                            
     251               1 :     default :                                                                                            
     252               1 :       return NULL;                                                                                       
     253               1 :     }                                                                                                    
     254                 :   }                                                                                                      
     255                 :                                                                                                          
     256                 :   /**                                                                                                    
     257                 :   * block changes of dynamic readonly property length                                                    
     258                 :   *                                                                                                      
     259                 :   * @param string $name                                                                                  
     260                 :   * @param mixed $value                                                                                  
     261                 :   * @access public                                                                                       
     262                 :   * @return void                                                                                         
     263                 :   */                                                                                                     
     264                 :   public function __set($name, $value) {                                                                 
     265                 :     switch ($name) {                                                                                     
     266              18 :     case 'contentType' :                                                                                 
     267              10 :       $this->_setContentType($value);                                                                    
     268               9 :       break;                                                                                             
     269               9 :     case 'document' :                                                                                    
     270               9 :     case 'length' :                                                                                      
     271               9 :     case 'xpath' :                                                                                       
     272               3 :       throw new BadMethodCallException('Can not set readonly value.');                                   
     273               6 :     default :                                                                                            
     274               6 :       $this->$name = $value;                                                                             
     275               6 :       break;                                                                                             
     276               6 :     }                                                                                                    
     277              14 :   }                                                                                                      
     278                 :                                                                                                          
     279                 :   /**                                                                                                    
     280                 :   * support isset for dynamic properties length and document                                             
     281                 :   *                                                                                                      
     282                 :   * @param string $name                                                                                  
     283                 :   * @access public                                                                                       
     284                 :   * @return boolean                                                                                      
     285                 :   */                                                                                                     
     286                 :   public function __isset($name) {                                                                       
     287                 :     switch ($name) {                                                                                     
     288               4 :     case 'length' :                                                                                      
     289               4 :     case 'xpath' :                                                                                       
     290               2 :       return TRUE;                                                                                       
     291               2 :     case 'document' :                                                                                    
     292               1 :       return isset($this->_document);                                                                    
     293                 :     }                                                                                                    
     294               1 :     return FALSE;                                                                                        
     295                 :   }                                                                                                      
     296                 :                                                                                                          
     297                 :   /**                                                                                                    
     298                 :   * declaring an empty() or clone() method will crash the parser so we use some magic                    
     299                 :   *                                                                                                      
     300                 :   * @param string $name                                                                                  
     301                 :   * @param array $arguments                                                                              
     302                 :   * @access public                                                                                       
     303                 :   * @return mixed                                                                                        
     304                 :   */                                                                                                     
     305                 :   public function __call($name, $arguments) {                                                            
     306               3 :     switch (strtolower($name)) {                                                                         
     307               3 :     case 'empty' :                                                                                       
     308               1 :       return $this->_emptyNodes();                                                                       
     309               2 :     case 'clone' :                                                                                       
     310               1 :       return $this->_cloneNodes();                                                                       
     311               1 :     default :                                                                                            
     312               1 :       throw new BadMethodCallException('Unknown method '.get_class($this).'::'.$name);                   
     313               1 :     }                                                                                                    
     314                 :   }                                                                                                      
     315                 :                                                                                                          
     316                 :   /**                                                                                                    
     317                 :   * Return the XML output of the internal dom document                                                   
     318                 :   *                                                                                                      
     319                 :   * @access public                                                                                       
     320                 :   * @return string                                                                                       
     321                 :   */                                                                                                     
     322                 :   public function __toString() {                                                                         
     323              52 :     switch ($this->_contentType) {                                                                       
     324              52 :     case 'html' :                                                                                        
     325              52 :     case 'text/html' :                                                                                   
     326               2 :       return $this->_document->saveHTML();                                                               
     327              50 :     default :                                                                                            
     328              50 :       return $this->_document->saveXML();                                                                
     329              50 :     }                                                                                                    
     330                 :   }                                                                                                      
     331                 :                                                                                                          
     332                 :   /**                                                                                                    
     333                 :   * The item() method is used to access elements in the node list,                                       
     334                 :   * like in a DOMNodelist.                                                                               
     335                 :   *                                                                                                      
     336                 :   * @param integer $position                                                                             
     337                 :   * @access public                                                                                       
     338                 :   * @return DOMNode                                                                                      
     339                 :   */                                                                                                     
     340                 :   public function item($position) {                                                                      
     341              17 :     if (isset($this->_array[$position])) {                                                               
     342              16 :       return $this->_array[$position];                                                                   
     343                 :     }                                                                                                    
     344              11 :     return NULL;                                                                                         
     345                 :   }                                                                                                      
     346                 :                                                                                                          
     347                 :   /*                                                                                                     
     348                 :   * Interface - IteratorAggregate                                                                        
     349                 :   */                                                                                                     
     350                 :                                                                                                          
     351                 :   /**                                                                                                    
     352                 :   * Get an iterator for this object.                                                                     
     353                 :   *                                                                                                      
     354                 :   * @example interfaces/Iterator.php Usage Example: Iterator Interface                                   
     355                 :   * @example interfaces/RecursiveIterator.php Usage Example: Recursive Iterator Interface                
     356                 :   * @return FluentDOMIterator                                                                            
     357                 :   */                                                                                                     
     358                 :   public function getIterator() {                                                                        
     359              11 :     return new FluentDOMIterator($this);                                                                 
     360                 :   }                                                                                                      
     361                 :                                                                                                          
     362                 :   /*                                                                                                     
     363                 :   * Interface - Countable                                                                                
     364                 :   */                                                                                                     
     365                 :                                                                                                          
     366                 :   /**                                                                                                    
     367                 :   * Get element count (Countable interface)                                                              
     368                 :   *                                                                                                      
     369                 :   * @example interfaces/Countable.php Usage Example: Countable Interface                                 
     370                 :   * @access public                                                                                       
     371                 :   * @return integer                                                                                      
     372                 :   */                                                                                                     
     373                 :   public function count() {                                                                              
     374               6 :     return count($this->_array);                                                                         
     375                 :   }                                                                                                      
     376                 :                                                                                                          
     377                 :   /*                                                                                                     
     378                 :   * Interface - ArrayAccess                                                                              
     379                 :   */                                                                                                     
     380                 :                                                                                                          
     381                 :   /**                                                                                                    
     382                 :   * If somebody tries to modify the internal array throw an exception.                                   
     383                 :   *                                                                                                      
     384                 :   * @example interfaces/ArrayAccess.php Usage Example: ArrayAccess Interface                             
     385                 :   * @param integer $offset                                                                               
     386                 :   * @param mixed $value                                                                                  
     387                 :   * @access public                                                                                       
     388                 :   * @return void                                                                                         
     389                 :   */                                                                                                     
     390                 :   public function offsetSet($offset, $value) {                                                           
     391               1 :     throw new BadMethodCallException('List is read only');                                               
     392                 :   }                                                                                                      
     393                 :                                                                                                          
     394                 :   /**                                                                                                    
     395                 :   * Check if index exists in internal array                                                              
     396                 :   *                                                                                                      
     397                 :   * @example interfaces/ArrayAccess.php Usage Example: ArrayAccess Interface                             
     398                 :   * @param integer $offset                                                                               
     399                 :   * @access public                                                                                       
     400                 :   * @return boolean                                                                                      
     401                 :   */                                                                                                     
     402                 :   public function offsetExists($offset) {                                                                
     403               1 :     return isset($this->_array[$offset]);                                                                
     404                 :   }                                                                                                      
     405                 :                                                                                                          
     406                 :   /**                                                                                                    
     407                 :   * If somebody tries to remove an element from the internal array throw an exception.                   
     408                 :   *                                                                                                      
     409                 :   * @example interfaces/ArrayAccess.php Usage Example: ArrayAccess Interface                             
     410                 :   * @param integer $offset                                                                               
     411                 :   * @access public                                                                                       
     412                 :   * @return void                                                                                         
     413                 :   */                                                                                                     
     414                 :   public function offsetUnset($offset) {                                                                 
     415               1 :     throw new BadMethodCallException('List is read only');                                               
     416                 :   }                                                                                                      
     417                 :                                                                                                          
     418                 :   /**                                                                                                    
     419                 :   * Get element from internal array                                                                      
     420                 :   *                                                                                                      
     421                 :   * @example interfaces/ArrayAccess.php Usage Example: ArrayAccess Interface                             
     422                 :   * @param $offset                                                                                       
     423                 :   * @access public                                                                                       
     424                 :   * @return void                                                                                         
     425                 :   */                                                                                                     
     426                 :   public function offsetGet($offset) {                                                                   
     427              12 :     return isset($this->_array[$offset]) ? $this->_array[$offset] : NULL;                                
     428                 :   }                                                                                                      
     429                 :                                                                                                          
     430                 :   /*                                                                                                     
     431                 :   * Core functions                                                                                       
     432                 :   */                                                                                                     
     433                 :                                                                                                          
     434                 :   /**                                                                                                    
     435                 :   * Create a new instance of the same class with $this as the parent. This is used for the chaining.     
     436                 :   *                                                                                                      
     437                 :   * @access private                                                                                      
     438                 :   * @return  FluentDOM                                                                                   
     439                 :   */                                                                                                     
     440                 :   private function _spawn() {                                                                            
     441             121 :     $className = get_class($this);                                                                       
     442             121 :     $result = new $className();                                                                          
     443             121 :     return $result->load($this);                                                                         
     444                 :   }                                                                                                      
     445                 :                                                                                                          
     446                 :   /**                                                                                                    
     447                 :   * Get a XPath object associated with the internal DOMDocument and register                             
     448                 :   * default namespaces from the document element if availiable.                                          
     449                 :   *                                                                                                      
     450                 :   * @access private                                                                                      
     451                 :   * @return DOMXPath                                                                                     
     452                 :   */                                                                                                     
     453                 :   private function _xpath() {                                                                            
     454             115 :     if (empty($this->_xpath) || $this->_xpath->document != $this->_document) {                           
     455             115 :       $this->_xpath = new DOMXPath($this->_document);                                                    
     456             115 :       if ($this->_document->documentElement) {                                                           
     457             115 :         $uri = $this->_document->documentElement->lookupnamespaceURI('_');                               
     458             115 :         if (!isset($uri)) {                                                                              
     459             115 :           $uri = $this->_document->documentElement->lookupnamespaceURI(NULL);                            
     460             115 :           if (isset($uri)) {                                                                             
     461               1 :             $this->_xpath->registerNamespace('_', $uri);                                                 
     462               1 :           }                                                                                              
     463             115 :         }                                                                                                
     464             115 :       }                                                                                                  
     465             115 :     }                                                                                                    
     466             115 :     return $this->_xpath;                                                                                
     467                 :   }                                                                                                      
     468                 :                                                                                                          
     469                 :   /**                                                                                                    
     470                 :   * Match XPath expression agains context and return matched elements.                                   
     471                 :   *                                                                                                      
     472                 :   * @param string $expr                                                                                  
     473                 :   * @param DOMElement $context optional, default value NULL                                              
     474                 :   * @access private                                                                                      
     475                 :   * @return DOMNodeList                                                                                  
     476                 :   */                                                                                                     
     477                 :   private function _match($expr, $context = NULL) {                                                      
     478             114 :     if (isset($context)) {                                                                               
     479              12 :       return $this->_xpath()->query($expr, $context);                                                    
     480                 :     } else {                                                                                             
     481             114 :       return $this->_xpath()->query($expr);                                                              
     482                 :     }                                                                                                    
     483                 :   }                                                                                                      
     484                 :                                                                                                          
     485                 :   /**                                                                                                    
     486                 :   * Test xpath expression against context and return true/false                                          
     487                 :   *                                                                                                      
     488                 :   * @param string $expr                                                                                  
     489                 :   * @param DOMElement $context optional, default value NULL                                              
     490                 :   * @access private                                                                                      
     491                 :   * @return boolean                                                                                      
     492                 :   */                                                                                                     
     493                 :   private function _test($expr, $context) {                                                              
     494               8 :     $check = $this->_xpath()->evaluate($expr, $context);                                                 
     495               8 :     if ($check instanceof DOMNodeList) {                                                                 
     496               2 :       return $check->length > 0;                                                                         
     497                 :     } else {                                                                                             
     498               6 :       return (bool)$check;                                                                               
     499                 :     }                                                                                                    
     500                 :   }                                                                                                      
     501                 :                                                                                                          
     502                 :   /**                                                                                                    
     503                 :   * Push new element(s) an the internal element list                                                     
     504                 :   *                                                                                                      
     505                 :   * @uses _inList                                                                                        
     506                 :   * @param DOMElement|DOMNodeList|FluentDOM $elements                                                    
     507                 :   * @param boolean $unique ignore duplicates                                                             
     508                 :   * @access private                                                                                      
     509                 :   * @return void                                                                                         
     510                 :   */                                                                                                     
     511                 :   private function _push($elements, $unique = FALSE) {                                                   
     512             122 :     if ($this->_isNode($elements)) {                                                                     
     513              49 :       if ($elements->ownerDocument === $this->_document) {                                               
     514              48 :         if (!$unique || !$this->_inList($elements, $this->_array)) {                                     
     515              48 :           $this->_array[] = $elements;                                                                   
     516              48 :         }                                                                                                
     517              48 :       } else {                                                                                           
     518               1 :         throw new OutOfBoundsException('Node is not a part of this document');                           
     519                 :       }                                                                                                  
     520             122 :     } elseif ($elements instanceof DOMNodeList ||                                                        
     521              28 :               $elements instanceof DOMDocumentFragment ||                                                
     522              28 :               $elements instanceof Iterator ||                                                           
     523              28 :               $elements instanceof IteratorAggregate ||                                                  
     524             120 :               is_array($elements)) {                                                                     
     525             120 :       foreach ($elements as $node) {                                                                     
     526             118 :         if ($this->_isNode($node)) {                                                                     
     527             118 :           if ($node->ownerDocument === $this->_document) {                                               
     528             118 :             if (!$unique || !$this->_inList($node, $this->_array)) {                                     
     529             118 :               $this->_array[] = $node;                                                                   
     530             118 :             }                                                                                            
     531             118 :           } else {                                                                                       
     532               1 :             throw new OutOfBoundsException('Node is not a part of this document');                       
     533                 :           }                                                                                              
     534             118 :         }                                                                                                
     535             120 :       }                                                                                                  
     536             120 :     }                                                                                                    
     537             122 :   }                                                                                                      
     538                 :                                                                                                          
     539                 :   /**                                                                                                    
     540                 :   * Check if object is already in internal list                                                          
     541                 :   *                                                                                                      
     542                 :   * @param DOMElement $node                                                                              
     543                 :   * @access private                                                                                      
     544                 :   * @return boolean                                                                                      
     545                 :   */                                                                                                     
     546                 :   private function _inList($node) {                                                                      
     547              14 :     foreach ($this->_array as $compareNode) {                                                            
     548               9 :       if ($compareNode === $node) {                                                                      
     549               3 :         return TRUE;                                                                                     
     550                 :       }                                                                                                  
     551              14 :     }                                                                                                    
     552              14 :     return FALSE;                                                                                        
     553                 :   }                                                                                                      
     554                 :                                                                                                          
     555                 :   /**                                                                                                    
     556                 :   * Validate string as qualified node name                                                               
     557                 :   *                                                                                                      
     558                 :   * @param string $name                                                                                  
     559                 :   * @access private                                                                                      
     560                 :   * @return boolean                                                                                      
     561                 :   */                                                                                                     
     562                 :   private function _isQName($name) {                                                                     
     563              22 :     if (empty($name)) {                                                                                  
     564               1 :       throw new UnexpectedValueException('Invalid QName: QName is empty.');                              
     565              21 :     } elseif (FALSE !== strpos($name, ':')) {                                                            
     566               6 :       list($namespace, $localName) = explode(':', $name, 2);                                             
     567               6 :       $this->_isNCName($namespace);                                                                      
     568               4 :       $this->_isNCName($localName, strlen($namespace));                                                  
     569               1 :       return TRUE;                                                                                       
     570                 :     }                                                                                                    
     571              15 :     $this->_isNCName($name);                                                                             
     572              14 :     return TRUE;                                                                                         
     573                 :   }                                                                                                      
     574                 :                                                                                                          
     575                 :   /**                                                                                                    
     576                 :   * Validate string as qualified node name part (namespace or local name)                                
     577                 :   *                                                                                                      
     578                 :   * @param string $name                                                                                  
     579                 :   * @param integer $offset index offset for excpetion messages                                           
     580                 :   * @access private                                                                                      
     581                 :   * @return boolean                                                                                      
     582                 :   */                                                                                                     
     583                 :   private function _isNCName($name, $offset = 0) {                                                       
     584                 :     $nameStartChar =                                                                                     
     585                 :        'A-Z_a-z'.                                                                                        
     586              21 :        '\\x{C0}-\\x{D6}\\x{D8}-\\x{F6}\\x{F8}-\\x{2FF}\\x{370}-\\x{37D}'.                                
     587              21 :        '\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}'.                                       
     588              21 :        '\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}'.                                      
     589              21 :        '\\x{FDF0}-\\x{FFFD}\\x{10000}-\\x{EFFFF}';                                                       
     590                 :     $nameChar =                                                                                          
     591                 :        $nameStartChar.                                                                                   
     592              21 :        '\\.\\d\\x{B7}\\x{300}-\\x{36F}\\x{203F}-\\x{2040}';                                              
     593              21 :     if (empty($name)) {                                                                                  
     594               2 :       throw new UnexpectedValueException(                                                                
     595               2 :         'Invalid QName "'.$name.'": Missing QName part.'                                                 
     596               2 :       );                                                                                                 
     597              20 :     } elseif (preg_match('([^'.$nameChar.'])u', $name, $match, PREG_OFFSET_CAPTURE)) {                   
     598                 :       //invalid bytes and whitespaces                                                                    
     599               1 :       $position = (int)$match[0][1];                                                                     
     600               1 :       throw new UnexpectedValueException(                                                                
     601               1 :         'Invalid QName "'.$name.'": Invalid character at index '.($offset + $position).'.'               
     602               1 :       );                                                                                                 
     603              20 :     } elseif (preg_match('(^[^'.$nameStartChar.'-])u', $name)) {                                         
     604                 :       //first char is a little more limited                                                              
     605               3 :       throw new UnexpectedValueException(                                                                
     606               3 :         'Invalid QName "'.$name.'": Invalid character at .index '.$offset.'.'                            
     607               3 :       );                                                                                                 
     608                 :     }                                                                                                    
     609              18 :     return TRUE;                                                                                         
     610                 :   }                                                                                                      
     611                 :                                                                                                          
     612                 :   /**                                                                                                    
     613                 :   * Check if the DOMNode is DOMElement or DOMText with content                                           
     614                 :   *                                                                                                      
     615                 :   * @param DOMNode $node                                                                                 
     616                 :   * @access private                                                                                      
     617                 :   * @return boolean                                                                                      
     618                 :   */                                                                                                     
     619                 :   private function _isNode($node) {                                                                      
     620             124 :     if (is_object($node)) {                                                                              
     621             122 :       if ($node instanceof DOMElement) {                                                                 
     622             118 :         return TRUE;                                                                                     
     623             115 :       } elseif ($node instanceof DOMText &&                                                              
     624             115 :                 !$node->isWhitespaceInElementContent()) {                                                
     625              13 :         return TRUE;                                                                                     
     626                 :       }                                                                                                  
     627             114 :     }                                                                                                    
     628             122 :     return FALSE;                                                                                        
     629                 :   }                                                                                                      
     630                 :                                                                                                          
     631                 :   /**                                                                                                    
     632                 :   * check if parameter is a valid callback function                                                      
     633                 :   *                                                                                                      
     634                 :   * @param callback $callback                                                                            
     635                 :   * @access protected                                                                                    
     636                 :   * @return boolean                                                                                      
     637                 :   */                                                                                                     
     638                 :   protected function _isCallback($callback) {                                                            
     639              10 :     if ($callback instanceof Closure) {                                                                  
     640               0 :       return TRUE;                                                                                       
     641              10 :     } elseif (is_string($callback) &&                                                                    
     642              10 :               function_exists($callback)) {                                                              
     643               5 :       return is_callable($callback);                                                                     
     644               5 :     } elseif (is_array($callback) &&                                                                     
     645               3 :               count($callback) == 2 &&                                                                   
     646               3 :               (is_object($callback[0]) || is_string($callback[0])) &&                                    
     647               5 :               is_string($callback[1])) {                                                                 
     648               3 :       return is_callable($callback);                                                                     
     649                 :     } else {                                                                                             
     650               2 :       throw new BadFunctionCallException('Invalid callback argument');                                   
     651                 :     }                                                                                                    
     652                 :   }                                                                                                      
     653                 :                                                                                                          
     654                 :   /**                                                                                                    
     655                 :   * Convert a given content into and array of nodes                                                      
     656                 :   *                                                                                                      
     657                 :   * @param string|array|DOMNode|Iterator $content                                                        
     658                 :   * @param boolean $includeTextNodes                                                                     
     659                 :   * @param integer $limit                                                                                
     660                 :   * @access private                                                                                      
     661                 :   * @return array                                                                                        
     662                 :   */                                                                                                     
     663                 :   private function _getContentNodes($content, $includeTextNodes = TRUE, $limit = 0) {                    
     664              30 :     $result = array();                                                                                   
     665              30 :     if ($content instanceof DOMElement) {                                                                
     666               1 :       $result = array($content);                                                                         
     667              30 :     } elseif ($includeTextNodes && $this->_isNode($content)) {                                           
     668               2 :       $result = array($content);                                                                         
     669              29 :     } elseif (is_string($content)) {                                                                     
     670              20 :       $fragment = $this->_document->createDocumentFragment();                                            
     671              20 :       if ($fragment->appendXML($content)) {                                                              
     672              19 :         foreach ($fragment->childNodes as $element) {                                                    
     673              19 :           if ($element instanceof DOMElement ||                                                          
     674              19 :               ($includeTextNodes && $this->_isNode($element))) {                                         
     675              19 :             $element->parentNode->removeChild($element);                                                 
     676              19 :             $result[] = $element;                                                                        
     677              19 :             if ($limit > 0 && count($result) >= $limit) {                                                
     678               7 :               break;                                                                                     
     679                 :             }                                                                                            
     680              12 :           }                                                                                              
     681              19 :         }                                                                                                
     682              19 :         return $result;                                                                                  
     683                 :       } else {                                                                                           
     684               1 :         throw new UnexpectedValueException('Invalid document fragment');                                 
     685                 :       }                                                                                                  
     686               7 :     } elseif ($content instanceof DOMNodeList ||                                                         
     687               6 :               $content instanceof Iterator ||                                                            
     688               6 :               $content instanceof IteratorAggregate ||                                                   
     689               7 :               is_array($content)) {                                                                      
     690               5 :       foreach ($content as $element) {                                                                   
     691               4 :         if ($element instanceof DOMElement ||                                                            
     692               4 :             ($includeTextNodes && $this->_isNode($element))) {                                           
     693               4 :           $result[] = $element;                                                                          
     694               4 :           if ($limit > 0 && count($result) >= $limit) {                                                  
     695               2 :             break;                                                                                       
     696                 :           }                                                                                              
     697               2 :         }                                                                                                
     698               5 :       }                                                                                                  
     699               5 :     } else {                                                                                             
     700               2 :       throw new InvalidArgumentException('Invalid content parameter');                                   
     701                 :     }                                                                                                    
     702               8 :     if (empty($result)) {                                                                                
     703               1 :       throw new UnexpectedValueException('No element found');                                            
     704                 :     } else {                                                                                             
     705                 :       //if a node is not in the current document import it                                               
     706               7 :       foreach ($result as $index => $node) {                                                             
     707               7 :         if ($node->ownerDocument !== $this->_document) {                                                 
     708               1 :           $result[$index] = $this->_document->importNode($node, TRUE);                                   
     709               1 :         }                                                                                                
     710               7 :       }                                                                                                  
     711                 :     }                                                                                                    
     712               7 :     return $result;                                                                                      
     713                 :   }                                                                                                      
     714                 :                                                                                                          
     715                 :   /**                                                                                                    
     716                 :   * Get the target nodes from a given $selector.                                                         
     717                 :   *                                                                                                      
     718                 :   * A string will be used as XPath expression.                                                           
     719                 :   *                                                                                                      
     720                 :   * @param string|array|DOMNode|DOMNodeList|FluentDOM $selector                                          
     721                 :   * @return unknown_type                                                                                 
     722                 :   */                                                                                                     
     723                 :   private function _getTargetNodes($selector) {                                                          
     724              13 :     if ($this->_isNode($selector)) {                                                                     
     725               1 :       return array($selector);                                                                           
     726              13 :     } elseif (is_string($selector)) {                                                                    
     727              10 :       return $this->_match($selector);                                                                   
     728              13 :     } elseif (is_array($selector) ||                                                                     
     729               7 :               $selector instanceof Iterator ||                                                           
     730               7 :               $selector instanceof IteratorAggregate ||                                                  
     731              13 :               $selector instanceof DOMNodeList) {                                                        
     732              12 :       return $selector;                                                                                  
     733                 :     } else {                                                                                             
     734               1 :       throw new InvalidArgumentException('Invalid selector');                                            
     735                 :     }                                                                                                    
     736                 :   }                                                                                                      
     737                 :                                                                                                          
     738                 :   /**                                                                                                    
     739                 :   * Remove nodes from document tree                                                                      
     740                 :   *                                                                                                      
     741                 :   * @param string|array|DOMNode|DOMNodeList|FluentDOM $selector                                          
     742                 :   * @access private                                                                                      
     743                 :   * @return array removed nodes                                                                          
     744                 :   */                                                                                                     
     745                 :   private function _removeNodes($selector) {                                                             
     746              12 :     $targetNodes = $this->_getTargetNodes($selector);                                                    
     747              12 :     $result = array();                                                                                   
     748              12 :     foreach ($targetNodes as $node) {                                                                    
     749              12 :       if ($node instanceof DOMNode &&                                                                    
     750              12 :           isset($node->parentNode)) {                                                                    
     751              12 :         $result[] = $node->parentNode->removeChild($node);                                               
     752              12 :       }                                                                                                  
     753              12 :     }                                                                                                    
     754              12 :     return $result;                                                                                      
     755                 :   }                                                                                                      
     756                 :                                                                                                          
     757                 :   /**                                                                                                    
     758                 :   * Convert $content to a DOMElement. If $content contains several elements use the first.               
     759                 :   *                                                                                                      
     760                 :   * @param string|array|DOMNode|Iterator $content                                                        
     761                 :   * @access private                                                                                      
     762                 :   * @return DOMElement                                                                                   
     763                 :   */                                                                                                     
     764                 :   private function _getContentElement($content) {                                                        
     765              11 :     if ($content instanceof DOMElement) {                                                                
     766               1 :       return $content;                                                                                   
     767                 :     } else {                                                                                             
     768              10 :       $contentNodes = $this->_getContentNodes($content, FALSE, 1);                                       
     769               9 :       return $contentNodes[0];                                                                           
     770                 :     }                                                                                                    
     771                 :   }                                                                                                      
     772                 :                                                                                                          
     773                 :   /*                                                                                                     
     774                 :   * Object Accessors                                                                                     
     775                 :   */                                                                                                     
     776                 :                                                                                                          
     777                 :   /**                                                                                                    
     778                 :   * Execute a function within the context of every matched element.                                      
     779                 :   *                                                                                                      
     780                 :   * @param callback $function                                                                            
     781                 :   * @access public                                                                                       
     782                 :   * @return FluentDOM                                                                                    
     783                 :   */                                                                                                     
     784                 :   public function each($function) {                                                                      
     785               3 :     if ($this->_isCallback($function)) {                                                                 
     786               2 :       foreach ($this->_array as $index => $node) {                                                       
     787               2 :         call_user_func($function, $node, $index);                                                        
     788               2 :       }                                                                                                  
     789               2 :     }                                                                                                    
     790               2 :     return $this;                                                                                        
     791                 :   }                                                                                                      
     792                 :                                                                                                          
     793                 :   /**                                                                                                    
     794                 :   * Formats the current document, resets internal node array and other properties.                       
     795                 :   *                                                                                                      
     796                 :   * The document is saved and reloaded, all variables with DOMNodes                                      
     797                 :   * of this document will get invalid.                                                                   
     798                 :   *                                                                                                      
     799                 :   * @access public                                                                                       
     800                 :   * @return FluentDOM                                                                                    
     801                 :   */                                                                                                     
     802                 :   public function formatOutput($contentType = NULL) {                                                    
     803               5 :     if (isset($contentType)) {                                                                           
     804               1 :       $this->_setContentType($contentType);                                                              
     805               1 :     }                                                                                                    
     806               5 :     $this->_array = array();                                                                             
     807               5 :     $this->_position = 0;                                                                                
     808               5 :     $this->_useDocumentContext = TRUE;                                                                   
     809               5 :     $this->_parent = NULL;                                                                               
     810               5 :     $this->_document->preserveWhiteSpace = FALSE;                                                        
     811               5 :     $this->_document->formatOutput = TRUE;                                                               
     812               5 :     $this->_document->loadXML($this->_document->saveXML());                                              
     813               5 :     return $this;                                                                                        
     814                 :   }                                                                                                      
     815                 :                                                                                                          
     816                 :   /*                                                                                                     
     817                 :   * Traversing - Filtering                                                                               
     818                 :   */                                                                                                     
     819                 :                                                                                                          
     820                 :   /**                                                                                                    
     821                 :   * Reduce the set of matched elements to a single element.                                              
     822                 :   *                                                                                                      
     823                 :   * @example eq.php Usage Example: FluentDOM::eq()                                                       
     824                 :   * @param integer $position Element index (start with 0)                                                
     825                 :   * @access public                                                                                       
     826                 :   * @return FluentDOM                                                                                    
     827                 :   */                                                                                                     
     828                 :   public function eq($position) {                                                                        
     829               5 :     $result = $this->_spawn();                                                                           
     830               5 :     if (isset($this->_array[$position])) {                                                               
     831               5 :       $result->_push($this->_array[$position]);                                                          
     832               5 :     }                                                                                                    
     833               5 :     return $result;                                                                                      
     834                 :   }                                                                                                      
     835                 :                                                                                                          
     836                 :   /**                                                                                                    
     837                 :   * Removes all elements from the set of matched elements that do not match                              
     838                 :   * the specified expression(s).                                                                         
     839                 :   *                                                                                                      
     840                 :   * @example filter-expr.php Usage Example: FluentDOM::filter() with XPath expression                    
     841                 :   * @example filter-fn.php Usage Example: FluentDOM::filter() with Closure                               
     842                 :   * @param string|callback $expr XPath expression or callback function                                   
     843                 :   * @access public                                                                                       
     844                 :   * @return FluentDOM                                                                                    
     845                 :   */                                                                                                     
     846                 :   public function filter($expr) {                                                                        
     847               2 :     $result = $this->_spawn();                                                                           
     848               2 :     foreach ($this->_array as $index => $node) {                                                         
     849               2 :       $check = TRUE;                                                                                     
     850               2 :       if (is_string($expr)) {                                                                            
     851               1 :         $check = $this->_test($expr, $node, $index);                                                     
     852               2 :       } elseif ($this->_isCallback($expr)) {                                                             
     853               1 :         $check = call_user_func($expr, $node, $index);                                                   
     854               1 :       }                                                                                                  
     855               2 :       if ($check) {                                                                                      
     856               2 :         $result->_push($node);                                                                           
     857               2 :       }                                                                                                  
     858               2 :     }                                                                                                    
     859               2 :     return $result;                                                                                      
     860                 :   }                                                                                                      
     861                 :                                                                                                          
     862                 :   /**                                                                                                    
     863                 :   * Checks the current selection against an expression and returns true,                                 
     864                 :   * if at least one element of the selection fits the given expression.                                  
     865                 :   *                                                                                                      
     866                 :   * @example is.php Usage Example: FluentDOM::is()                                                       
     867                 :   * @param string $expr XPath expression                                                                 
     868                 :   * @access public                                                                                       
     869                 :   * @return boolean                                                                                      
     870                 :   */                                                                                                     
     871                 :   public function is($expr) {                                                                            
     872               2 :     foreach ($this->_array as $node) {                                                                   
     873               1 :       return $this->_test($expr, $node);                                                                 
     874               1 :     }                                                                                                    
     875               1 :     return FALSE;                                                                                        
     876                 :   }                                                                                                      
     877                 :                                                                                                          
     878                 :   /**                                                                                                    
     879                 :   * Translate a set of elements in the FluentDOM object into                                             
     880                 :   * another set of values in an array (which may, or may not contain elements).                          
     881                 :   *                                                                                                      
     882                 :   * If the callback function returns an array each element of the array will be added to the             
     883                 :   * result array. All other variable types are put directly into the result array.                       
     884                 :   *                                                                                                      
     885                 :   * @example map.php Usage Example: FluentDOM::map()                                                     
     886                 :   * @param callback $function                                                                            
     887                 :   * @access public                                                                                       
     888                 :   * @return array                                                                                        
     889                 :   */                                                                                                     
     890                 :   public function map($function) {                                                                       
     891               4 :     $result = array();                                                                                   
     892               4 :     foreach ($this->_array as $index => $node) {                                                         
     893               4 :       if ($this->_isCallback($function)) {                                                               
     894               3 :         $mapped = call_user_func($function, $node, $index);                                              
     895               3 :       }                                                                                                  
     896               3 :       if ($mapped === NULL) {                                                                            
     897               1 :         continue;                                                                                        
     898               3 :       } elseif ($mapped instanceof DOMNodeList ||                                                        
     899               3 :                 $mapped instanceof Iterator ||                                                           
     900               3 :                 $mapped instanceof IteratorAggregate ||                                                  
     901               3 :                 is_array($mapped)) {                                                                     
     902               1 :         foreach ($mapped as $element) {                                                                  
     903               1 :           if ($element !== NULL) {                                                                       
     904               1 :             $result[] = $element;                                                                        
     905               1 :           }                                                                                              
     906               1 :         }                                                                                                
     907               1 :       } else {                                                                                           
     908               3 :         $result[] = $mapped;                                                                             
     909                 :       }                                                                                                  
     910               3 :     }                                                                                                    
     911               3 :     return $result;                                                                                      
     912                 :   }                                                                                                      
     913                 :                                                                                                          
     914                 :   /**                                                                                                    
     915                 :   * Removes elements matching the specified expression from the set of matched elements.                 
     916                 :   *                                                                                                      
     917                 :   * @example not.php Usage Example: FluentDOM::not()                                                     
     918                 :   * @param string|callback $expr XPath expression or callback function                                   
     919                 :   * @access public                                                                                       
     920                 :   * @return FluentDOM                                                                                    
     921                 :   */                                                                                                     
     922                 :   public function not($expr) {                                                                           
     923               2 :     $result = $this->_spawn();                                                                           
     924               2 :     foreach ($this->_array as $index => $node) {                                                         
     925               2 :       $check = FALSE;                                                                                    
     926               2 :       if (is_string($expr)) {                                                                            
     927               1 :         $check = $this->_test($expr, $node, $index);                                                     
     928               2 :       } elseif ($this->_isCallback($expr)) {                                                             
     929               1 :         $check = call_user_func($expr, $node, $index);                                                   
     930               1 :       }                                                                                                  
     931               2 :       if (!$check) {                                                                                     
     932               2 :         $result->_push($node);                                                                           
     933               2 :       }                                                                                                  
     934               2 :     }                                                                                                    
     935               2 :     return $result;                                                                                      
     936                 :   }                                                                                                      
     937                 :                                                                                                          
     938                 :   /**                                                                                                    
     939                 :   * Selects a subset of the matched elements.                                                            
     940                 :   *                                                                                                      
     941                 :   * @example slice.php Usage Example: FluentDOM::slice()                                                 
     942                 :   * @param integer $start                                                                                
     943                 :   * @param integer $end                                                                                  
     944                 :   * @access public                                                                                       
     945                 :   * @return FluentDOM                                                                                    
     946                 :   */                                                                                                     
     947                 :   public function slice($start, $end = NULL) {                                                           
     948               4 :     $result = $this->_spawn();                                                                           
     949               4 :     if ($end === NULL) {                                                                                 
     950               1 :       $result->_push(array_slice($this->_array, $start));                                                
     951               4 :     } elseif ($end < 0) {                                                                                
     952               1 :       $result->_push(array_slice($this->_array, $start, $end));                                          
     953               3 :     } elseif ($end > $start) {                                                                           
     954               1 :       $result->_push(array_slice($this->_array, $start, $end - $start));                                 
     955               1 :     } else {                                                                                             
     956               1 :       $result->_push(array_slice($this->_array, $end, $start - $end));                                   
     957                 :     }                                                                                                    
     958               4 :     return $result;                                                                                      
     959                 :   }                                                                                                      
     960                 :                                                                                                          
     961                 :   /*                                                                                                     
     962                 :   * Traversing - Finding                                                                                 
     963                 :   */                                                                                                     
     964                 :                                                                                                          
     965                 :   /**                                                                                                    
     966                 :   * Adds more elements, matched by the given expression, to the set of matched elements.                 
     967                 :   *                                                                                                      
     968                 :   * @example add.php Usage Examples: FluentDOM::add()                                                    
     969                 :   * @param string $expr XPath expression                                                                 
     970                 :   * @access public                                                                                       
     971                 :   * @return FluentDOM                                                                                    
     972                 :   */                                                                                                     
     973                 :   public function add($expr) {                                                                           
     974               5 :     $result = $this->_spawn();                                                                           
     975               5 :     $result->_push($this->_array);                                                                       
     976               5 :     if (is_object($expr)) {                                                                              
     977               3 :       $result->_push($expr);                                                                             
     978               3 :     } elseif (isset($this->_parent)) {                                                                   
     979               1 :       $result->_push($this->_parent->find($expr));                                                       
     980               1 :     } else {                                                                                             
     981               1 :       $result->_push($this->find($expr));                                                                
     982                 :     }                                                                                                    
     983               3 :     return $result;                                                                                      
     984                 :   }                                                                                                      
     985                 :                                                                                                          
     986                 :   /**                                                                                                    
     987                 :   * Get a set of elements containing all of the unique immediate                                         
     988                 :   * children of each of the matched set of elements.                                                     
     989                 :   *                                                                                                      
     990                 :   * @example children.php Usage Examples: FluentDOM::children()                                          
     991                 :   * @param string $expr XPath expression                                                                 
     992                 :   * @access public                                                                                       
     993                 :   * @return FluentDOM                                                                                    
     994                 :   */                                                                                                     
     995                 :   public function children($expr = NULL) {                                                               
     996               3 :     $result = $this->_spawn();                                                                           
     997               3 :     foreach ($this->_array as $node) {                                                                   
     998               3 :       if (empty($expr)) {                                                                                
     999               2 :         $result->_push($node->childNodes, TRUE);                                                         
    1000               2 :       } else {                                                                                           
    1001               1 :         foreach ($node->childNodes as $childNode) {                                                      
    1002               1 :           if ($this->_test($expr, $childNode)) {                                                         
    1003               1 :             $result->_push($childNode, TRUE);                                                            
    1004               1 :           }                                                                                              
    1005               1 :         }                                                                                                
    1006                 :       }                                                                                                  
    1007               3 :     }                                                                                                    
    1008               3 :     return $result;                                                                                      
    1009                 :   }                                                                                                      
    1010                 :                                                                                                          
    1011                 :   /**                                                                                                    
    1012                 :   * Searches for descendent elements that match the specified expression.                                
    1013                 :   *                                                                                                      
    1014                 :   * @example find.php Usage Example: FluentDOM::find()                                                   
    1015                 :   * @param string $expr XPath expression                                                                 
    1016                 :   * @param boolean $useDocumentContext ignore current node list                                          
    1017                 :   * @access public                                                                                       
    1018                 :   * @return FluentDOM                                                                                    
    1019                 :   */                                                                                                     
    1020                 :   public function find($expr, $useDocumentContext = FALSE) {                                             
    1021             113 :     $result = $this->_spawn();                                                                           
    1022             113 :     if ($useDocumentContext ||                                                                           
    1023             113 :         $this->_useDocumentContext) {                                                                    
    1024             113 :       $result->_push($this->_match($expr));                                                              
    1025             113 :     } else {                                                                                             
    1026               4 :       foreach ($this->_array as $contextNode) {                                                          
    1027               4 :         $result->_push($this->_match($expr, $contextNode));                                              
    1028               4 :       }                                                                                                  
    1029                 :     }                                                                                                    
    1030             113 :     return $result;                                                                                      
    1031                 :   }                                                                                                      
    1032                 :                                                                                                          
    1033                 :   /**                                                                                                    
    1034                 :   * Get a set of elements containing the unique next siblings of each of the                             
    1035                 :   * given set of elements.                                                                               
    1036                 :   *                                                                                                      
    1037                 :   * @example next.php Usage Example: FluentDOM::next()                                                   
    1038                 :   * @param string $expr XPath expression                                                                 
    1039                 :   * @access public                                                                                       
    1040                 :   * @return FluentDOM                                                                                    
    1041                 :   */                                                                                                     
    1042                 :   public function next($expr = NULL) {                                                                   
    1043               1 :     $result = $this->_spawn();                                                                           
    1044               1 :     foreach ($this->_array as $node) {                                                                   
    1045               1 :       $next = $node->nextSibling;                                                                        
    1046               1 :       while ($next instanceof DOMNode && !$this->_isNode($next)) {                                       
    1047               1 :         $next = $next->nextSibling;                                                                      
    1048               1 :       }                                                                                                  
    1049               1 :       if (!empty($next)) {                                                                               
    1050               1 :         if (empty($expr) || $this->_test($expr, $next)) {                                                
    1051               1 :           $result->_push($next, TRUE);                                                                   
    1052               1 :         }                                                                                                
    1053               1 :       }                                                                                                  
    1054               1 :     }                                                                                                    
    1055               1 :     return $result;                                                                                      
    1056                 :   }                                                                                                      
    1057                 :                                                                                                          
    1058                 :   /**                                                                                                    
    1059                 :   * Find all sibling elements after the current element.                                                 
    1060                 :   *                                                                                                      
    1061                 :   * @example nextAll.php Usage Example: FluentDOM::nextAll()                                             
    1062                 :   * @param string $expr XPath expression                                                                 
    1063                 :   * @access public                                                                                       
    1064                 :   * @return FluentDOM                                                                                    
    1065                 :   */                                                                                                     
    1066                 :   public function nextAll($expr = NULL) {                                                                
    1067               1 :     $result = $this->_spawn();                                                                           
    1068               1 :     foreach ($this->_array as $node) {                                                                   
    1069               1 :       $next = $node->nextSibling;                                                                        
    1070               1 :       while ($next instanceof DOMNode) {                                                                 
    1071               1 :         if ($this->_isNode($next)) {                                                                     
    1072               1 :           if (empty($expr) || $this->_test($expr, $next)) {                                              
    1073               1 :             $result->_push($next, TRUE);                                                                 
    1074               1 :           }                                                                                              
    1075               1 :         }                                                                                                
    1076               1 :         $next = $next->nextSibling;                                                                      
    1077               1 :       }                                                                                                  
    1078               1 :     }                                                                                                    
    1079               1 :     return $result;                                                                                      
    1080                 :   }                                                                                                      
    1081                 :                                                                                                          
    1082                 :   /**                                                                                                    
    1083                 :   * Get a set of elements containing the unique parents of the matched set of elements.                  
    1084                 :   *                                                                                                      
    1085                 :   * @example parent.php Usage Example: FluentDOM::parent()                                               
    1086                 :   * @access public                                                                                       
    1087                 :   * @return FluentDOM                                                                                    
    1088                 :   */                                                                                                     
    1089                 :   public function parent() {                                                                             
    1090               1 :     $result = $this->_spawn();                                                                           
    1091               1 :     foreach ($this->_array as $node) {                                                                   
    1092               1 :       if (isset($node->parentNode)) {                                                                    
    1093               1 :         $result->_push($node->parentNode, TRUE);                                                         
    1094               1 :       }                                                                                                  
    1095               1 :     }                                                                                                    
    1096               1 :     return $result;                                                                                      
    1097                 :   }                                                                                                      
    1098                 :                                                                                                          
    1099                 :   /**                                                                                                    
    1100                 :   * Get a set of elements containing the unique ancestors of the matched set of elements.                
    1101                 :   *                                                                                                      
    1102                 :   * @example parents.php Usage Example: FluentDOM::parents()                                             
    1103                 :   * @param string $expr XPath expression                                                                 
    1104                 :   * @access public                                                                                       
    1105                 :   * @return FluentDOM                                                                                    
    1106                 :   */                                                                                                     
    1107                 :   public function parents($expr = NULL) {                                                                
    1108               1 :     $result = $this->_spawn();                                                                           
    1109               1 :     foreach ($this->_array as $node) {                                                                   
    1110               1 :       $parents = $this->_match('ancestor::*', $node);                                                    
    1111               1 :       for ($i = $parents->length - 1; $i >= 0; --$i) {                                                   
    1112               1 :         $parentNode = $parents->item($i);                                                                
    1113               1 :         if (empty($expr) || $this->_test($expr, $parentNode)) {                                          
    1114               1 :           $result->_push($parentNode, TRUE);                                                             
    1115               1 :         }                                                                                                
    1116               1 :       }                                                                                                  
    1117               1 :     }                                                                                                    
    1118               1 :     return $result;                                                                                      
    1119                 :   }                                                                                                      
    1120                 :                                                                                                          
    1121                 :   /**                                                                                                    
    1122                 :   * Get a set of elements containing the unique previous siblings of each of the matched set of elements.
    1123                 :   *                                                                                                      
    1124                 :   * @example prev.php Usage Example: FluentDOM::prev()                                                   
    1125                 :   * @param string $expr XPath expression                                                                 
    1126                 :   * @access public                                                                                       
    1127                 :   * @return FluentDOM                                                                                    
    1128                 :   */                                                                                                     
    1129                 :   public function prev($expr = NULL) {                                                                   
    1130               3 :     $result = $this->_spawn();                                                                           
    1131               3 :     foreach ($this->_array as $node) {                                                                   
    1132               3 :       $previous = $node->previousSibling;                                                                
    1133               3 :       while ($previous instanceof DOMNode && !$this->_isNode($previous)) {                               
    1134               3 :         $previous = $previous->previousSibling;                                                          
    1135               3 :       }                                                                                                  
    1136               3 :       if (!empty($previous)) {                                                                           
    1137               3 :         if (empty($expr) || $this->_test($expr, $previous)) {                                            
    1138               3 :           $result->_push($previous, TRUE);                                                               
    1139               3 :         }                                                                                                
    1140               3 :       }                                                                                                  
    1141               3 :     }                                                                                                    
    1142               3 :     return $result;                                                                                      
    1143                 :   }                                                                                                      
    1144                 :                                                                                                          
    1145                 :   /**                                                                                                    
    1146                 :   * Find all sibling elements in front of the current element.                                           
    1147                 :   *                                                                                                      
    1148                 :   * @example prevAll.php Usage Example: FluentDOM::prevAll()                                             
    1149                 :   * @param string $expr XPath expression                                                                 
    1150                 :   * @access public                                                                                       
    1151                 :   * @return FluentDOM                                                                                    
    1152                 :   */                                                                                                     
    1153                 :   public function prevAll($expr = NULL) {                                                                
    1154               1 :     $result = $this->_spawn();                                                                           
    1155               1 :     foreach ($this->_array as $node) {                                                                   
    1156               1 :       $previous = $node->previousSibling;                                                                
    1157               1 :       while ($previous instanceof DOMNode) {                                                             
    1158               1 :         if ($this->_isNode($previous)) {                                                                 
    1159               1 :           if (empty($expr) || $this->_test($expr, $previous)) {                                          
    1160               1 :             $result->_push($previous, TRUE);                                                             
    1161               1 :           }                                                                                              
    1162               1 :         }                                                                                                
    1163               1 :         $previous = $previous->previousSibling;                                                          
    1164               1 :       }                                                                                                  
    1165               1 :     }                                                                                                    
    1166               1 :     return $result;                                                                                      
    1167                 :   }                                                                                                      
    1168                 :                                                                                                          
    1169                 :   /**                                                                                                    
    1170                 :   * Get a set of elements containing all of the unique siblings of each of the                           
    1171                 :   * matched set of elements.                                                                             
    1172                 :   *                                                                                                      
    1173                 :   * @example siblings.php Usage Example: FluentDOM::siblings()                                           
    1174                 :   * @param string $expr XPath expression                                                                 
    1175                 :   * @access public                                                                                       
    1176                 :   * @return FluentDOM                                                                                    
    1177                 :   */                                                                                                     
    1178                 :   public function siblings($expr = NULL) {                                                               
    1179               1 :     $result = $this->_spawn();                                                                           
    1180               1 :     foreach ($this->_array as $node) {                                                                   
    1181               1 :       if (isset($node->parentNode)) {                                                                    
    1182               1 :         foreach ($node->parentNode->childNodes as $childNode) {                                          
    1183               1 :           if ($this->_isNode($childNode) &&                                                              
    1184               1 :               $childNode !== $node) {                                                                    
    1185               1 :             if (empty($expr) || $this->_test($expr, $childNode)) {                                       
    1186               1 :               $result->_push($childNode, TRUE);                                                          
    1187               1 :             }                                                                                            
    1188               1 :           }                                                                                              
    1189               1 :         }                                                                                                
    1190               1 :       }                                                                                                  
    1191               1 :     }                                                                                                    
    1192               1 :     return $result;                                                                                      
    1193                 :   }                                                                                                      
    1194                 :                                                                                                          
    1195                 :   /**                                                                                                    
    1196                 :   * Get a set of elements containing the closest parent element that matches the specified               
    1197                 :   * selector, the starting element included.                                                             
    1198                 :   *                                                                                                      
    1199                 :   * @example closest.php Usage Example: FluentDOM::closest()                                             
    1200                 :   * @param string $expr XPath expression                                                                 
    1201                 :   * @return FluentDOM                                                                                    
    1202                 :   */                                                                                                     
    1203                 :   public function closest($expr) {                                                                       
    1204               2 :     $result = $this->_spawn();                                                                           
    1205               2 :     foreach ($this->_array as $node) {                                                                   
    1206               2 :       while (isset($node)) {                                                                             
    1207               2 :         if ($this->_test($expr, $node)) {                                                                
    1208               2 :           $result->_push($node, TRUE);                                                                   
    1209               2 :           break;                                                                                         
    1210                 :         }                                                                                                
    1211               2 :         $node = $node->parentNode;                                                                       
    1212               2 :       }                                                                                                  
    1213               2 :     }                                                                                                    
    1214               2 :     return $result;                                                                                      
    1215                 :   }                                                                                                      
    1216                 :                                                                                                          
    1217                 :   /*                                                                                                     
    1218                 :   * Traversing - Chaining                                                                                
    1219                 :   */                                                                                                     
    1220                 :                                                                                                          
    1221                 :   /**                                                                                                    
    1222                 :   * Add the previous selection to the current selection.                                                 
    1223                 :   *                                                                                                      
    1224                 :   * @access public                                                                                       
    1225                 :   * @return FluentDOM                                                                                    
    1226                 :   */                                                                                                     
    1227                 :   public function andSelf() {                                                                            
    1228               2 :     $result = $this->_spawn();                                                                           
    1229               2 :     $result->_push($this->_array);                                                                       
    1230               2 :     $result->_push($this->_parent);                                                                      
    1231               2 :     return $result;                                                                                      
    1232                 :   }                                                                                                      
    1233                 :                                                                                                          
    1234                 :   /**                                                                                                    
    1235                 :   * Revert the most recent traversing operation,                                                         
    1236                 :   * changing the set of matched elements to its previous state.                                          
    1237                 :   *                                                                                                      
    1238                 :   * @access public                                                                                       
    1239                 :   * @return FluentDOM                                                                                    
    1240                 :   */                                                                                                     
    1241                 :   public function end() {                                                                                
    1242               1 :     if ($this->_parent instanceof FluentDOM) {                                                           
    1243               1 :       return $this->_parent;                                                                             
    1244                 :     } else {                                                                                             
    1245               1 :       return $this;                                                                                      
    1246                 :     }                                                                                                    
    1247                 :   }                                                                                                      
    1248                 :                                                                                                          
    1249                 :   /*                                                                                                     
    1250                 :   * Manipulation - Changing Contents                                                                     
    1251                 :   */                                                                                                     
    1252                 :                                                                                                          
    1253                 :   /**                                                                                                    
    1254                 :   * Get or set the xml contents of the first matched element.                                            
    1255                 :   *                                                                                                      
    1256                 :   * @example xml.php Usage Example: FluentDOM::xml()                                                     
    1257                 :   * @param string $xml XML fragment                                                                      
    1258                 :   * @access public                                                                                       
    1259                 :   * @return string|FluentDOM                                                                             
    1260                 :   */                                                                                                     
    1261                 :   public function xml($xml = NULL) {                                                                     
    1262               2 :     if (isset($xml)) {                                                                                   
    1263               1 :       if (!empty($xml)) {                                                                                
    1264               1 :         $fragment = $this->_document->createDocumentFragment();                                          
    1265               1 :         if ($fragment->appendXML($xml)) {                                                                
    1266               1 :           foreach ($this->_array as $node) {                                                             
    1267               1 :             $node->nodeValue = '';                                                                       
    1268               1 :             $node->appendChild($fragment->cloneNode(TRUE));                                              
    1269               1 :           }                                                                                              
    1270               1 :         }                                                                                                
    1271               1 :       }                                                                                                  
    1272               1 :       return $this;                                                                                      
    1273                 :     } else {                                                                                             
    1274               1 :       $result = '';                                                                                      
    1275               1 :       if (isset($this->_array[0])) {                                                                     
    1276               1 :         foreach ($this->_array[0]->childNodes as $childNode) {                                           
    1277               1 :           if ($this->_isNode($childNode)) {                                                              
    1278               1 :             $result .= $this->_document->saveXML($childNode);                                            
    1279               1 :           }                                                                                              
    1280               1 :         }                                                                                                
    1281               1 :       }                                                                                                  
    1282               1 :       return $result;                                                                                    
    1283                 :     }                                                                                                    
    1284                 :   }                                                                                                      
    1285                 :                                                                                                          
    1286                 :   /**                                                                                                    
    1287                 :   * Get the combined text contents of all matched elements or                                            
    1288                 :   * set the text contents of all matched elements.                                                       
    1289                 :   *                                                                                                      
    1290                 :   * @example text.php Usage Example: FluentDOM::text()                                                   
    1291                 :   * @param string $text                                                                                  
    1292                 :   * @access public                                                                                       
    1293                 :   * @return string|FluentDOM                                                                             
    1294                 :   */                                                                                                     
    1295                 :   public function text($text = NULL) {                                                                   
    1296               4 :     if (isset($text)) {                                                                                  
    1297               2 :       foreach ($this->_array as $node) {                                                                 
    1298               2 :         $node->nodeValue = $text;                                                                        
    1299               2 :       }                                                                                                  
    1300               2 :       return $this;                                                                                      
    1301                 :     } else {                                                                                             
    1302               2 :       $result = '';                                                                                      
    1303               2 :       foreach ($this->_array as $node) {                                                                 
    1304               2 :         $result .= $node->textContent;                                                                   
    1305               2 :       }                                                                                                  
    1306               2 :       return $result;                                                                                    
    1307                 :     }                                                                                                    
    1308                 :   }                                                                                                      
    1309                 :                                                                                                          
    1310                 :   /*                                                                                                     
    1311                 :   * Manipulation - Inserting Inside                                                                      
    1312                 :   */                                                                                                     
    1313                 :                                                                                                          
    1314                 :   /**                                                                                                    
    1315                 :   * Append content to the inside of every matched element.                                               
    1316                 :   *                                                                                                      
    1317                 :   * @example append.php Usage Example: FluentDOM::append()                                               
    1318                 :   * @param string|array|DOMNode|Iterator $content DOMNode or DOMNodeList or xml fragment string          
    1319                 :   * @access public                                                                                       
    1320                 :   * @return FluentDOM                                                                                    
    1321                 :   */                                                                                                     
    1322                 :   public function append($content) {                                                                     
    1323               8 :     return $this->_insertChild($content, FALSE);                                                         
    1324                 :   }                                                                                                      
    1325                 :                                                                                                          
    1326                 :   /**                                                                                                    
    1327                 :   * Append all of the matched elements to another, specified, set of elements.                           
    1328                 :   * Returns all of the inserted elements.                                                                
    1329                 :   *                                                                                                      
    1330                 :   * @example appendTo.php Usage Example: FluentDOM::appendTo()                                           
    1331                 :   * @param string|array|DOMNode|DOMNodeList|FluentDOM $selector                                          
    1332                 :   * @access public                                                                                       
    1333                 :   * @return FluentDOM                                                                                    
    1334                 :   */                                                                                                     
    1335                 :   public function appendTo($selector) {                                                                  
    1336               1 :     return $this->_insertChildTo($selector, FALSE);                                                      
    1337                 :   }                                                                                                      
    1338                 :                                                                                                          
    1339                 :   /**                                                                                                    
    1340                 :   * Prepend content to the inside of every matched element.                                              
    1341                 :   *                                                                                                      
    1342                 :   * @example prepend.php Usage Example: FluentDOM::prepend()                                             
    1343                 :   * @param string|array|DOMNode|Iterator $content                                                        
    1344                 :   * @access public                                                                                       
    1345                 :   * @return FluentDOM                                                                                    
    1346                 :   */                                                                                                     
    1347                 :   public function prepend($content) {                                                                    
    1348               3 :     return $this->_insertChild($content, TRUE);                                                          
    1349                 :   }                                                                                                      
    1350                 :                                                                                                          
    1351                 :   /**                                                                                                    
    1352                 :   * Prepend all of the matched elements to another, specified, set of elements.                          
    1353                 :   * Returns all of the inserted elements.                                                                
    1354                 :   *                                                                                                      
    1355                 :   * @example prependTo.php Usage Example: FluentDOM::prependTo()                                         
    1356                 :   * @param string|array|DOMNode|DOMNodeList|FluentDOM $selector                                          
    1357                 :   * @access public                                                                                       
    1358                 :   * @return FluentDOM list of all new elements                                                           
    1359                 :   */                                                                                                     
    1360                 :   public function prependTo($selector) {                                                                 
    1361               1 :     return $this->_insertChildTo($selector, TRUE);                                                       
    1362                 :   }                                                                                                      
    1363                 :                                                                                                          
    1364                 :   /**                                                                                                    
    1365                 :   * Insert content to the inside of every matched element.                                               
    1366                 :   *                                                                                                      
    1367                 :   * @param string|array|DOMNode|Iterator $content                                                        
    1368                 :   * @param boolean $first insert at first position (or last)                                             
    1369                 :   * @access private                                                                                      
    1370                 :   * @return FluentDOM                                                                                    
    1371                 :   */                                                                                                     
    1372                 :   private function _insertChild($content, $first) {                                                      
    1373              11 :     $result = $this->_spawn();                                                                           
    1374              11 :     if (empty($this->_array) &&                                                                          
    1375               3 :         $this->_useDocumentContext &&                                                                    
    1376              11 :         !isset($this->_document->documentElement)) {                                                     
    1377               3 :       $contentNode = $this->_getContentElement($content);                                                
    1378               3 :       $result->_push(                                                                                    
    1379               3 :         $this->_document->appendChild(                                                                   
    1380                 :           $contentNode                                                                                   
    1381               3 :         )                                                                                                
    1382               3 :       );                                                                                                 
    1383               3 :     } else {                                                                                             
    1384               8 :       $contentNodes = $this->_getContentNodes($content, TRUE);                                           
    1385               8 :       foreach ($this->_array as $node) {                                                                 
    1386               8 :         foreach ($contentNodes as $contentNode) {                                                        
    1387               8 :           $result->_push(                                                                                
    1388               8 :             $node->insertBefore(                                                                         
    1389               8 :               $contentNode->cloneNode(TRUE),                                                             
    1390               8 :               ($first && $node->hasChildNodes()) ? $node->childNodes->item(0) : NULL                     
    1391               8 :             )                                                                                            
    1392               8 :           );                                                                                             
    1393               8 :         }                                                                                                
    1394               8 :       }                                                                                                  
    1395                 :     }                                                                                                    
    1396              11 :     return $result;                                                                                      
    1397                 :   }                                                                                                      
    1398                 :                                                                                                          
    1399                 :   /**                                                                                                    
    1400                 :   * Insert all of the matched elements to another, specified, set of elements.                           
    1401                 :   * Returns all of the inserted elements.                                                                
    1402                 :   *                                                                                                      
    1403                 :   * @param string|array|DOMNode|DOMNodeList|FluentDOM $selector                                          
    1404                 :   * @param boolean $first insert at first position (or last)                                             
    1405                 :   * @access public                                                                                       
    1406                 :   * @return FluentDOM                                                                                    
    1407                 :   */                                                                                                     
    1408                 :   private function _insertChildTo($selector, $first) {                                                   
    1409               2 :     $result = $this->_spawn();                                                                           
    1410               2 :     $targets = $this->_getTargetNodes($selector);                                                        
    1411               2 :     if (!empty($targets)) {                                                                              
    1412               2 :       foreach ($targets as $targetNode) {                                                                
    1413               2 :         if ($targetNode instanceof DOMElement) {                                                         
    1414               2 :           foreach ($this->_array as $node) {                                                             
    1415               2 :             $result->_push(                                                                              
    1416               2 :               $targetNode->insertBefore(                                                                 
    1417               2 :                 $node->cloneNode(TRUE),                                                                  
    1418               1 :                 ($first && $targetNode->hasChildNodes())                                                 
    1419               2 :                   ? $targetNode->childNodes->item(0) : NULL                                              
    1420               2 :               )                                                                                          
    1421               2 :             );                                                                                           
    1422               2 :           }                                                                                              
    1423               2 :         }                                                                                                
    1424               2 :         $this->_removeNodes($this->_array);                                                              
    1425               2 :       }                                                                                                  
    1426               2 :     }                                                                                                    
    1427               2 :     return $result;                                                                                      
    1428                 :   }                                                                                                      
    1429                 :                                                                                                          
    1430                 :   /*                                                                                                     
    1431                 :   * Manipulation - Inserting Outside                                                                     
    1432                 :   */                                                                                                     
    1433                 :                                                                                                          
    1434                 :   /**                                                                                                    
    1435                 :   * Insert content after each of the matched elements.                                                   
    1436                 :   *                                                                                                      
    1437                 :   * @example after.php Usage Example: FluentDOM::after()                                                 
    1438                 :   * @param string|array|DOMNode|Iterator $content                                                        
    1439                 :   * @access public                                                                                       
    1440                 :   * @return FluentDOM                                                                                    
    1441                 :   */                                                                                                     
    1442                 :   public function after($content) {                                                                      
    1443               1 :     $result = $this->_spawn();                                                                           
    1444               1 :     if ($contentNodes = $this->_getContentNodes($content, TRUE)) {                                       
    1445               1 :       foreach ($this->_array as $node) {                                                                 
    1446               1 :         $beforeNode = $node->nextSibling;                                                                
    1447               1 :         if (isset($node->parentNode)) {                                                                  
    1448               1 :           foreach ($contentNodes as $contentNode) {                                                      
    1449               1 :             $result->_push(                                                                              
    1450               1 :               $node->parentNode->insertBefore(                                                           
    1451               1 :                 $contentNode->cloneNode(TRUE),                                                           
    1452                 :                 $beforeNode                                                                              
    1453               1 :               )                                                                                          
    1454               1 :             );                                                                                           
    1455               1 :           }                                                                                              
    1456               1 :         }                                                                                                
    1457               1 :       }                                                                                                  
    1458               1 :     }                                                                                                    
    1459               1 :     return $result;                                                                                      
    1460                 :   }                                                                                                      
    1461                 :                                                                                                          
    1462                 :   /**                                                                                                    
    1463                 :   * Insert content before each of the matched elements.                                                  
    1464                 :   *                                                                                                      
    1465                 :   * @example before.php Usage Example: FluentDOM::before()                                               
    1466                 :   * @param string|array|DOMNode|Iterator $content                                                        
    1467                 :   * @access public                                                                                       
    1468                 :   * @return FluentDOM                                                                                    
    1469                 :   */                                                                                                     
    1470                 :   public function before($content) {                                                                     
    1471               1 :     $result = $this->_spawn();                                                                           
    1472               1 :     if ($contentNodes = $this->_getContentNodes($content, TRUE)) {                                       
    1473               1 :       foreach ($this->_array as $node) {                                                                 
    1474               1 :         if (isset($node->parentNode)) {                                                                  
    1475               1 :           foreach ($contentNodes as $contentNode) {                                                      
    1476               1 :             $result->_push(                                                                              
    1477               1 :               $node->parentNode->insertBefore(                                                           
    1478               1 :                 $contentNode->cloneNode(TRUE),                                                           
    1479                 :                 $node                                                                                    
    1480               1 :               )                                                                                          
    1481               1 :             );                                                                                           
    1482               1 :           }                                                                                              
    1483               1 :         }                                                                                                
    1484               1 :       }                                                                                                  
    1485               1 :     }                                                                                                    
    1486               1 :     return $result;                                                                                      
    1487                 :   }                                                                                                      
    1488                 :                                                                                                          
    1489                 :   /**                                                                                                    
    1490                 :   * Insert all of the matched elements after another, specified, set of elements.                        
    1491                 :   *                                                                                                      
    1492                 :   * @example insertAfter.php Usage Example: FluentDOM::insertAfter()                                     
    1493                 :   * @param string|array|DOMNode|DOMNodeList|FluentDOM $selector                                          
    1494                 :   * @access public                                                                                       
    1495                 :   * @return FluentDOM                                                                                    
    1496                 :   */                                                                                                     
    1497                 :   public function insertAfter($selector) {                                                               
    1498               1 :     $result = $this->_spawn();                                                                           
    1499               1 :     $targets = $this->_getTargetNodes($selector);                                                        
    1500               1 :     if (!empty($targets)) {                                                                              
    1501               1 :       foreach ($targets as $targetNode) {                                                                
    1502               1 :         if ($this->_isNode($targetNode) && isset($targetNode->parentNode)) {                             
    1503               1 :           $beforeNode = $targetNode->nextSibling;                                                        
    1504               1 :           foreach ($this->_array as $node) {                                                             
    1505               1 :             $result->_push(                                                                              
    1506               1 :               $targetNode->parentNode->insertBefore(                                                     
    1507               1 :                 $node->cloneNode(TRUE),                                                                  
    1508                 :                 $beforeNode                                                                              
    1509               1 :               )                                                                                          
    1510               1 :             );                                                                                           
    1511               1 :           }                                                                                              
    1512               1 :         }                                                                                                
    1513               1 :         $this->_removeNodes($this->_array);                                                              
    1514               1 :       }                                                                                                  
    1515               1 :     }                                                                                                    
    1516               1 :     return $result;                                                                                      
    1517                 :   }                                                                                                      
    1518                 :                                                                                                          
    1519                 :   /**                                                                                                    
    1520                 :   * Insert all of the matched elements before another, specified, set of elements.                       
    1521                 :   *                                                                                                      
    1522                 :   * @example insertBefore.php Usage Example: FluentDOM::insertBefore()                                   
    1523                 :   * @param string|array|DOMNode|DOMNodeList|FluentDOM $selector                                          
    1524                 :   * @access public                                                                                       
    1525                 :   * @return FluentDOM                                                                                    
    1526                 :   */                                                                                                     
    1527                 :   public function insertBefore($selector) {                                                              
    1528               1 :     $result = $this->_spawn();                                                                           
    1529               1 :     $targets = $this->_getTargetNodes($selector);                                                        
    1530               1 :     if (!empty($targets)) {                                                                              
    1531               1 :       foreach ($targets as $targetNode) {                                                                
    1532               1 :         if ($this->_isNode($targetNode) && isset($targetNode->parentNode)) {                             
    1533               1 :           foreach ($this->_array as $node) {                                                             
    1534               1 :             $result->_push(                                                                              
    1535               1 :               $targetNode->parentNode->insertBefore(                                                     
    1536               1 :                 $node->cloneNode(TRUE),                                                                  
    1537                 :                 $targetNode                                                                              
    1538               1 :               )                                                                                          
    1539               1 :             );                                                                                           
    1540               1 :           }                                                                                              
    1541               1 :         }                                                                                                
    1542               1 :         $this->_removeNodes($this->_array);                                                              
    1543               1 :       }                                                                                                  
    1544               1 :     }                                                                                                    
    1545               1 :     return $result;                                                                                      
    1546                 :   }                                                                                                      
    1547                 :                                                                                                          
    1548                 :   /*                                                                                                     
    1549                 :   * Manipulation - Inserting Around                                                                      
    1550                 :   */                                                                                                     
    1551                 :                                                                                                          
    1552                 :   /**                                                                                                    
    1553                 :   * Wrap $content around a set of elements                                                               
    1554                 :   *                                                                                                      
    1555                 :   * @param array $elements                                                                               
    1556                 :   * @param string|array|DOMNode|Iterator $content                                                        
    1557                 :   * @access private                                                                                      
    1558                 :   * @return FluentDOM                                                                                    
    1559                 :   */                                                                                                     
    1560                 :   private function _wrap($elements, $content) {                                                          
    1561               6 :     $wrapperTemplate = $this->_getContentElement($content);                                              
    1562               5 :     $result = array();                                                                                   
    1563               5 :     if ($wrapperTemplate instanceof DOMElement) {                                                        
    1564               5 :       $simple = FALSE;                                                                                   
    1565               5 :       foreach ($elements as $node) {                                                                     
    1566               5 :         $wrapper = $wrapperTemplate->cloneNode(TRUE);                                                    
    1567               5 :         if (!$simple) {                                                                                  
    1568               5 :           $targets = $this->_match('.//*[count(*) = 0]', $wrapper);                                      
    1569               5 :         }                                                                                                
    1570               5 :         if ($simple || $targets->length == 0) {                                                          
    1571               4 :           $target = $wrapper;                                                                            
    1572               4 :           $simple = TRUE;                                                                                
    1573               4 :         } else {                                                                                         
    1574               1 :           $target = $targets->item(0);                                                                   
    1575                 :         }                                                                                                
    1576               5 :         if (isset($node->parentNode)) {                                                                  
    1577               5 :           $node->parentNode->insertBefore($wrapper, $node);                                              
    1578               5 :         }                                                                                                
    1579               5 :         $target->appendChild($node);                                                                     
    1580               5 :         $result[] = $node;                                                                               
    1581               5 :       }                                                                                                  
    1582               5 :     }                                                                                                    
    1583               5 :     return $result;                                                                                      
    1584                 :   }                                                                                                      
    1585                 :                                                                                                          
    1586                 :   /**                                                                                                    
    1587                 :   * Wrap each matched element with the specified content.                                                
    1588                 :   *                                                                                                      
    1589                 :   * If $content contains several elements the first one is used                                          
    1590                 :   *                                                                                                      
    1591                 :   * @example wrap.php Usage Example: FluentDOM::wrap()                                                   
    1592                 :   * @param string|array|DOMNode|Iterator $content                                                        
    1593                 :   * @access public                                                                                       
    1594                 :   * @return FluentDOM                                                                                    
    1595                 :   */                                                                                                     
    1596                 :   public function wrap($content) {                                                                       
    1597               5 :     $result = $this->_spawn();                                                                           
    1598               5 :     $result->_push($this->_wrap($this->_array, $content));                                               
    1599               4 :     return $result;                                                                                      
    1600                 :   }                                                                                                      
    1601                 :                                                                                                          
    1602                 :   /**                                                                                                    
    1603                 :   * Wrap al matched elements with the specified content                                                  
    1604                 :   *                                                                                                      
    1605                 :   * If the matched elemetns are not siblings, wrap each group of siblings.                               
    1606                 :   *                                                                                                      
    1607                 :   * @example wrapAll.php Usage Example: FluentDOM::wrapAll()                                             
    1608                 :   * @param string|array|DOMNode|Iterator $content                                                        
    1609                 :   * @access public                                                                                       
    1610                 :   * @return FluentDOM                                                                                    
    1611                 :   */                                                                                                     
    1612                 :   public function wrapAll($content) {                                                                    
    1613               2 :     $result = $this->_spawn();                                                                           
    1614               2 :     $current = NULL;                                                                                     
    1615               2 :     $counter = 0;                                                                                        
    1616               2 :     $groups = array();                                                                                   
    1617                 :     //group elements by previous node - ignore whitespace text nodes                                     
    1618               2 :     foreach ($this->_array as $node) {                                                                   
    1619               2 :       $previous = $node->previousSibling;                                                                
    1620               2 :       while ($previous instanceof DOMText && $previous->isWhitespaceInElementContent()) {                
    1621               2 :         $previous = $previous->previousSibling;                                                          
    1622               2 :       }                                                                                                  
    1623               2 :       if ($previous !== $current) {                                                                      
    1624               2 :         $counter++;                                                                                      
    1625               2 :       }                                                                                                  
    1626               2 :       $groups[$counter][] = $node;                                                                       
    1627               2 :       $current = $node;                                                                                  
    1628               2 :     }                                                                                                    
    1629               2 :     if (count($groups) > 0) {                                                                            
    1630               2 :       $wrapperTemplate = $this->_getContentElement($content);                                            
    1631               2 :       $simple = FALSE;                                                                                   
    1632               2 :       foreach ($groups as $group) {                                                                      
    1633               2 :         if (isset($group[0])) {                                                                          
    1634               2 :           $node = $group[0];                                                                             
    1635               2 :           $wrapper = $wrapperTemplate->cloneNode(TRUE);                                                  
    1636               2 :           if (!$simple) {                                                                                
    1637               2 :             $targets = $this->_match('.//*[count(*) = 0]', $wrapper);                                    
    1638               2 :           }                                                                                              
    1639               2 :           if ($simple || $targets->length == 0) {                                                        
    1640               1 :             $target = $wrapper;                                                                          
    1641               1 :             $simple = TRUE;                                                                              
    1642               1 :           } else {                                                                                       
    1643               1 :             $target = $targets->item(0);                                                                 
    1644                 :           }                                                                                              
    1645               2 :           if (isset($node->parentNode)) {                                                                
    1646               2 :             $node->parentNode->insertBefore($wrapper, $node);                                            
    1647               2 :           }                                                                                              
    1648               2 :           foreach ($group as $node) {                                                                    
    1649               2 :             $target->appendChild($node);                                                                 
    1650               2 :           }                                                                                              
    1651               2 :           $result->_push($node);                                                                         
    1652               2 :         }                                                                                                
    1653               2 :       }                                                                                                  
    1654               2 :     }                                                                                                    
    1655               2 :     return $result;                                                                                      
    1656                 :   }                                                                                                      
    1657                 :                                                                                                          
    1658                 :   /**                                                                                                    
    1659                 :   * Wrap the inner child contents of each matched element                                                
    1660                 :   * (including text nodes) with an XML structure.                                                        
    1661                 :   *                                                                                                      
    1662                 :   * @example wrapInner.php Usage Example: FluentDOM::wrapInner()                                         
    1663                 :   * @param string|array|DOMNode|Iterator $content                                                        
    1664                 :   * @access public                                                                                       
    1665                 :   * @return FluentDOM                                                                                    
    1666                 :   */                                                                                                     
    1667                 :   public function wrapInner($content) {                                                                  
    1668               1 :     $result = $this->_spawn();                                                                           
    1669               1 :     $elements = array();                                                                                 
    1670               1 :     foreach ($this->_array as $node) {                                                                   
    1671               1 :       foreach ($node->childNodes as $childNode) {                                                        
    1672               1 :         if ($this->_isNode($childNode)) {                                                                
    1673               1 :           $elements[] = $childNode;                                                                      
    1674               1 :         }                                                                                                
    1675               1 :       }                                                                                                  
    1676               1 :     }                                                                                                    
    1677               1 :     $result->_push($this->_wrap($elements, $content));                                                   
    1678               1 :     return $result;                                                                                      
    1679                 :   }                                                                                                      
    1680                 :                                                                                                          
    1681                 :   /*                                                                                                     
    1682                 :   * Manipulation - Replacing                                                                             
    1683                 :   */                                                                                                     
    1684                 :                                                                                                          
    1685                 :   /**                                                                                                    
    1686                 :   * Replaces all matched elements with the specified HTML or DOM elements.                               
    1687                 :   * This returns the JQuery element that was just replaced,                                              
    1688                 :   * which has been removed from the DOM.                                                                 
    1689                 :   *                                                                                                      
    1690                 :   * @example replaceWith.php Usage Example: FluentDOM::replaceWith()                                     
    1691                 :   * @param string|array|DOMNode|Iterator $content                                                        
    1692                 :   * @access public                                                                                       
    1693                 :   * @return FluentDOM                                                                                    
    1694                 :   */                                                                                                     
    1695                 :   public function replaceWith($content) {                                                                
    1696               1 :     $contentNodes = $this->_getContentNodes($content);                                                   
    1697               1 :     foreach ($this->_array as $node) {                                                                   
    1698               1 :       if (isset($node->parentNode)) {                                                                    
    1699               1 :         foreach ($contentNodes as $contentNode) {                                                        
    1700               1 :           $node->parentNode->insertBefore(                                                               
    1701               1 :             $contentNode->cloneNode(TRUE),                                                               
    1702                 :             $node                                                                                        
    1703               1 :           );                                                                                             
    1704               1 :         }                                                                                                
    1705               1 :       }                                                                                                  
    1706               1 :     }                                                                                                    
    1707               1 :     $this->_removeNodes($this->_array);                                                                  
    1708               1 :     return $this;                                                                                        
    1709                 :   }                                                                                                      
    1710                 :                                                                                                          
    1711                 :   /**                                                                                                    
    1712                 :   * Replaces the elements matched by the specified selector with the matched elements.                   
    1713                 :   *                                                                                                      
    1714                 :   * @example replaceAll.php Usage Example: FluentDOM::replaceAll()                                       
    1715                 :   * @param string|array|DOMNode|DOMNodeList|FluentDOM $selector                                          
    1716                 :   * @access public                                                                                       
    1717                 :   * @return FluentDOM                                                                                    
    1718                 :   */                                                                                                     
    1719                 :   public function replaceAll($selector) {                                                                
    1720               8 :     $result = $this->_spawn();                                                                           
    1721               8 :     $targetNodes = $this->_getTargetNodes($selector);                                                    
    1722               7 :     foreach ($targetNodes as $targetNode) {                                                              
    1723               7 :       if (isset($targetNode->parentNode)) {                                                              
    1724               7 :         foreach ($this->_array as $node) {                                                               
    1725               7 :           $result->_push(                                                                                
    1726               7 :             $targetNode->parentNode->insertBefore(                                                       
    1727               7 :               $node->cloneNode(TRUE),                                                                    
    1728                 :               $targetNode                                                                                
    1729               7 :             )                                                                                            
    1730               7 :           );                                                                                             
    1731               7 :         }                                                                                                
    1732               7 :       }                                                                                                  
    1733               7 :     }                                                                                                    
    1734               7 :     $this->_removeNodes($targetNodes);                                                                   
    1735               7 :     $this->_removeNodes($this->_array);                                                                  
    1736               7 :     return $result;                                                                                      
    1737                 :   }                                                                                                      
    1738                 :                                                                                                          
    1739                 :   /*                                                                                                     
    1740                 :   * Manipulation - Removing                                                                              
    1741                 :   */                                                                                                     
    1742                 :                                                                                                          
    1743                 :   /**                                                                                                    
    1744                 :   * Remove all child nodes from the set of matched elements.                                             
    1745                 :   *                                                                                                      
    1746                 :   * This is the empty() method - but because empty                                                       
    1747                 :   * is a reserved word we can no declare it directly                                                     
    1748                 :   * @see __call                                                                                          
    1749                 :   *                                                                                                      
    1750                 :   * @example empty.php Usage Example: FluentDOM:empty()                                                  
    1751                 :   * @access private                                                                                      
    1752                 :   * @return FluentDOM