HTML_CSS Test Suite
Current file: PEAR/HTML/CSS.php
Legend: executed not executed dead code

  Coverage
  Classes Functions / Methods Lines
Total
100.00%100.00%
100.00% 1 / 1
93.75%93.75%
93.75% 45 / 48
85.68%85.68%
85.68% 1173 / 1369
 
HTML_CSS
100.00%100.00%
100.00% 1 / 1
93.75%93.75%
93.75% 45 / 48
85.68%85.68%
85.68% 1173 / 1369
 public function HTML_CSS($attributes = array ( ), $errorPrefs = array ( ))
0.00%0.00%
0.00% 0 / 1
0.00%0.00%
0.00% 0 / 2
 public function __construct($attributes = array ( ), $errorPrefs = array ( ))
100.00%100.00%
100.00% 1 / 1
89.47%89.47%
89.47% 17 / 19
 public function apiVersion()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function __set($option, $val)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 4 / 4
 public function __get($option)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 5 / 5
 public function getOptions()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function setTab($string)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 public function setLineEnd($style)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 public function setSingleLineOutput($value)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 10 / 10
 public function setOutputGroupsFirst($value)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 10 / 10
 public function parseSelectors($selectors, $outputMode = 0)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 82 / 82
 public function collapseInternalSpaces($subject)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 2 / 2
 public function sortAtRules()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 16 / 16
 public function setXhtmlCompliance($value)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 10 / 10
 public function getAtRulesList()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 public function createAtRule($atKeyword, $arguments = '', $duplicates = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 43 / 43
 public function unsetAtRule($atKeyword)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 24 / 24
 public function setAtRuleStyle($atKeyword, $arguments, $selectors, $property, $value, $duplicates = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 74 / 74
 public function getAtRuleStyle($atKeyword, $arguments, $selectors, $property)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 46 / 46
 public function createGroup($selectors, $group = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 24 / 24
 public function unsetGroup($group)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 30 / 30
 public function setGroupStyle($group, $property, $value, $duplicates = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 57 / 57
 public function getGroupStyle($group, $property)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 41 / 41
 public function addGroupSelector($group, $selectors)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 31 / 31
 public function removeGroupSelector($group, $selectors)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 39 / 39
 public function setStyle($element, $property, $value, $duplicates = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 50 / 50
 public function getStyle($element, $property)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 55 / 55
 public function grepStyle($elmPattern, $proPattern = NULL)
100.00%100.00%
100.00% 1 / 1
94.00%94.00%
94.00% 47 / 50
 public function setSameStyle($new, $old)
100.00%100.00%
100.00% 1 / 1
87.04%87.04%
87.04% 47 / 54
 public function setCache($cache = true)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 10 / 10
 public function getCache()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function setContentDisposition($enable = true, $filename = '')
100.00%100.00%
100.00% 1 / 1
86.96%86.96%
86.96% 20 / 23
 public function getContentDisposition()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function setCharset($type = 'iso-8859-1')
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 10 / 10
 public function getCharset()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 1 / 1
 public function parseString($str, $duplicates = NULL)
100.00%100.00%
100.00% 1 / 1
87.08%87.08%
87.08% 155 / 178
 public function parseFile($filename, $duplicates = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 26 / 26
 public function parseData($styles, $duplicates = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 34 / 34
 public function validate($styles, &$messages)
0.00%0.00%
0.00% 0 / 1
0.00%0.00%
0.00% 0 / 71
 public function toArray()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 9 / 9
 public function toInline($element)
100.00%100.00%
100.00% 1 / 1
64.86%64.86%
64.86% 24 / 37
 public function toFile($filename)
100.00%100.00%
100.00% 1 / 1
65.00%65.00%
65.00% 13 / 20
 public function toString()
100.00%100.00%
100.00% 1 / 1
60.00%60.00%
60.00% 51 / 85
 public function display()
100.00%100.00%
100.00% 1 / 1
23.53%23.53%
23.53% 4 / 17
 public function _initErrorStack($prefs = array ( ))
100.00%100.00%
100.00% 1 / 1
67.65%67.65%
67.65% 23 / 34
 public function _errorHandler($code, $level, $params)
100.00%100.00%
100.00% 1 / 1
75.00%75.00%
75.00% 12 / 16
 public function raiseError()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 4 / 4
 public function isError()
0.00%0.00%
0.00% 0 / 1
0.00%0.00%
0.00% 0 / 3


       1                 : <?php                                                                                
       2                 : /**                                                                                  
       3                 :  * Copyright (c) 2003-2009, Klaus Guenther <klaus@capitalfocus.org>                  
       4                 :  *                          Laurent Laville <pear@laurent-laville.org>               
       5                 :  *                                                                                   
       6                 :  * All rights reserved.                                                              
       7                 :  *                                                                                   
       8                 :  * Redistribution and use in source and binary forms, with or without                
       9                 :  * modification, are permitted provided that the following conditions                
      10                 :  * are met:                                                                          
      11                 :  *                                                                                   
      12                 :  *     * Redistributions of source code must retain the above copyright              
      13                 :  *       notice, this list of conditions and the following disclaimer.               
      14                 :  *     * Redistributions in binary form must reproduce the above copyright           
      15                 :  *       notice, this list of conditions and the following disclaimer in the         
      16                 :  *       documentation and/or other materials provided with the distribution.        
      17                 :  *     * Neither the name of the authors nor the names of its contributors           
      18                 :  *       may be used to endorse or promote products derived from this software       
      19                 :  *       without specific prior written permission.                                  
      20                 :  *                                                                                   
      21                 :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"       
      22                 :  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE         
      23                 :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE        
      24                 :  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS             
      25                 :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR            
      26                 :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF              
      27                 :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS          
      28                 :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN           
      29                 :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)           
      30                 :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE        
      31                 :  * POSSIBILITY OF SUCH DAMAGE.                                                       
      32                 :  *                                                                                   
      33                 :  * PHP versions 4 and 5                                                              
      34                 :  *                                                                                   
      35                 :  * @category  HTML                                                                   
      36                 :  * @package   HTML_CSS                                                               
      37                 :  * @author    Klaus Guenther <klaus@capitalfocus.org>                                
      38                 :  * @author    Laurent Laville <pear@laurent-laville.org>                             
      39                 :  * @copyright 2003-2009 Klaus Guenther, Laurent Laville                              
      40                 :  * @license   http://www.opensource.org/licenses/bsd-license.php  New BSD License    
      41                 :  * @version   CVS: $Id: CSS.php,v 1.89 2009/07/03 15:52:22 farell Exp $              
      42                 :  * @link      http://pear.php.net/package/HTML_CSS                                   
      43                 :  * @since     File available since Release 0.2.0                                     
      44                 :  */                                                                                  
      45                 :                                                                                      
      46                 : require_once 'HTML/Common.php';                                                      
      47                 :                                                                                      
      48                 : /**#@+                                                                               
      49                 :  * Basic error codes                                                                 
      50                 :  *                                                                                   
      51                 :  * @var        integer                                                               
      52                 :  * @since      0.3.3                                                                 
      53                 :  */                                                                                  
      54                 : define('HTML_CSS_ERROR_UNKNOWN', -1);                                                
      55                 : define('HTML_CSS_ERROR_INVALID_INPUT', -100);                                        
      56                 : define('HTML_CSS_ERROR_INVALID_GROUP', -101);                                        
      57                 : define('HTML_CSS_ERROR_NO_GROUP', -102);                                             
      58                 : define('HTML_CSS_ERROR_NO_ELEMENT', -103);                                           
      59                 : define('HTML_CSS_ERROR_NO_ELEMENT_PROPERTY', -104);                                  
      60                 : define('HTML_CSS_ERROR_NO_FILE', -105);                                              
      61                 : define('HTML_CSS_ERROR_WRITE_FILE', -106);                                           
      62                 : define('HTML_CSS_ERROR_INVALID_SOURCE', -107);                                       
      63                 : define('HTML_CSS_ERROR_INVALID_DEPS', -108);                                         
      64                 : define('HTML_CSS_ERROR_NO_ATRULE', -109);                                            
      65                 : /**#@-*/                                                                             
      66                 :                                                                                      
      67                 : /**                                                                                  
      68                 :  * Base class for CSS definitions                                                    
      69                 :  *                                                                                   
      70                 :  * This class handles the details for creating properly                              
      71                 :  * constructed CSS declarations.                                                     
      72                 :  *                                                                                   
      73                 :  * @category  HTML                                                                   
      74                 :  * @package   HTML_CSS                                                               
      75                 :  * @author    Klaus Guenther <klaus@capitalfocus.org>                                
      76                 :  * @author    Laurent Laville <pear@laurent-laville.org>                             
      77                 :  * @copyright 2003-2009 Klaus Guenther, Laurent Laville                              
      78                 :  * @license   http://www.opensource.org/licenses/bsd-license.php  BSD                
      79                 :  * @version   Release: 1.5.4                                                         
      80                 :  * @link      http://pear.php.net/package/HTML_CSS                                   
      81                 :  * @since     Class available since Release 0.2.0                                    
      82                 :  */                                                                                  
      83                 :                                                                                      
      84                 : class HTML_CSS extends HTML_Common                                                   
      85                 : {                                                                                    
      86                 :     /**                                                                              
      87                 :      * Options configuration list                                                    
      88                 :      *                                                                               
      89                 :      * - xhtml :                                                                     
      90                 :      *    Defines whether element selectors should be automatically lowercased.      
      91                 :      *    Determines how parseSelectors treats the data.                             
      92                 :      *    @see setXhtmlCompliance()                                                  
      93                 :      * - tab :                                                                       
      94                 :      *    Sets indent string.                                                        
      95                 :      *    @see setTab(), HTML_Common::setTab()                                       
      96                 :      * - filename :                                                                  
      97                 :      *    Name of file to be parsed.                                                 
      98                 :      *    @see parseFile()                                                           
      99                 :      * - cache :                                                                     
     100                 :      *    Determines whether the nocache headers are sent.                           
     101                 :      *    Controls caching of the page.                                              
     102                 :      *    @see setCache()                                                            
     103                 :      * - oneline :                                                                   
     104                 :      *    Defines whether to output all properties on one line.                      
     105                 :      *    @see setSingleLineOutput()                                                 
     106                 :      * - charset :                                                                   
     107                 :      *    Contains the character encoding string.                                    
     108                 :      *    @see setCharset()                                                          
     109                 :      * - contentDisposition :                                                        
     110                 :      *    Contains the Content-Disposition filename.                                 
     111                 :      *    @see setContentDisposition()                                               
     112                 :      * - lineEnd :                                                                   
     113                 :      *    Sets the line end style to Windows, Mac, Unix or a custom string.          
     114                 :      *    @see setLineEnd(), HTML_Common::setLineEnd()                               
     115                 :      * - groupsfirst :                                                               
     116                 :      *    Determines whether to output groups before elements.                       
     117                 :      *    @see setOutputGroupsFirst()                                                
     118                 :      * - allowduplicates :                                                           
     119                 :      *    Allow to have duplicate rules in selector. Useful for IE hack.             
     120                 :      *                                                                               
     121                 :      * @var        array                                                             
     122                 :      * @since      1.4.0                                                             
     123                 :      * @access     private                                                           
     124                 :      * @see        __set(), __get()                                                  
     125                 :      */                                                                              
     126                 :     var $options;                                                                    
     127                 :                                                                                      
     128                 :     /**                                                                              
     129                 :      * Contains the CSS definitions.                                                 
     130                 :      *                                                                               
     131                 :      * @var        array                                                             
     132                 :      * @since      0.2.0                                                             
     133                 :      * @access     private                                                           
     134                 :      */                                                                              
     135                 :     var $_css = array();                                                             
     136                 :                                                                                      
     137                 :     /**                                                                              
     138                 :      * Contains "alibis" (other elements that share a definition) of an element      
     139                 :      * defined in CSS                                                                
     140                 :      *                                                                               
     141                 :      * @var        array                                                             
     142                 :      * @since      0.2.0                                                             
     143                 :      * @access     private                                                           
     144                 :      */                                                                              
     145                 :     var $_alibis = array();                                                          
     146                 :                                                                                      
     147                 :     /**                                                                              
     148                 :      * Contains last assigned index for duplicate styles                             
     149                 :      *                                                                               
     150                 :      * @var        array                                                             
     151                 :      * @since      0.3.0                                                             
     152                 :      * @access     private                                                           
     153                 :      */                                                                              
     154                 :     var $_duplicateCounter = 0;                                                      
     155                 :                                                                                      
     156                 :     /**                                                                              
     157                 :      * Contains grouped styles                                                       
     158                 :      *                                                                               
     159                 :      * @var        array                                                             
     160                 :      * @since      0.3.0                                                             
     161                 :      * @access     private                                                           
     162                 :      */                                                                              
     163                 :     var $_groups = array();                                                          
     164                 :                                                                                      
     165                 :     /**                                                                              
     166                 :      * Number of CSS definition groups                                               
     167                 :      *                                                                               
     168                 :      * @var        int                                                               
     169                 :      * @since      0.3.0                                                             
     170                 :      * @access     private                                                           
     171                 :      */                                                                              
     172                 :     var $_groupCount = 0;                                                            
     173                 :                                                                                      
     174                 :     /**                                                                              
     175                 :      * Error message callback.                                                       
     176                 :      * This will be used to generate the error message                               
     177                 :      * from the error code.                                                          
     178                 :      *                                                                               
     179                 :      * @var        false|string|array                                                
     180                 :      * @since      1.0.0                                                             
     181                 :      * @access     private                                                           
     182                 :      * @see        _initErrorStack()                                                 
     183                 :      */                                                                              
     184                 :     var $_callback_message = false;                                                  
     185                 :                                                                                      
     186                 :     /**                                                                              
     187                 :      * Error context callback.                                                       
     188                 :      * This will be used to generate the error context for an error.                 
     189                 :      *                                                                               
     190                 :      * @var        false|string|array                                                
     191                 :      * @since      1.0.0                                                             
     192                 :      * @access     private                                                           
     193                 :      * @see        _initErrorStack()                                                 
     194                 :      */                                                                              
     195                 :     var $_callback_context = false;                                                  
     196                 :                                                                                      
     197                 :     /**                                                                              
     198                 :      * Error push callback.                                                          
     199                 :      * The return value will be used to determine whether to allow                   
     200                 :      * an error to be pushed or logged.                                              
     201                 :      *                                                                               
     202                 :      * @var        false|string|array                                                
     203                 :      * @since      1.0.0                                                             
     204                 :      * @access     private                                                           
     205                 :      * @see        _initErrorStack()                                                 
     206                 :      */                                                                              
     207                 :     var $_callback_push = false;                                                     
     208                 :                                                                                      
     209                 :     /**                                                                              
     210                 :      * Error callback.                                                               
     211                 :      * User function that decides what to do with error (display, log, ...)          
     212                 :      *                                                                               
     213                 :      * @var        false|string|array                                                
     214                 :      * @since      1.4.0                                                             
     215                 :      * @access     private                                                           
     216                 :      * @see        _initErrorStack()                                                 
     217                 :      */                                                                              
     218                 :     var $_callback_error = false;                                                    
     219                 :                                                                                      
     220                 :     /**                                                                              
     221                 :      * Error handler callback.                                                       
     222                 :      * This will handle any errors raised by this package.                           
     223                 :      *                                                                               
     224                 :      * @var        false|string|array                                                
     225                 :      * @since      1.0.0                                                             
     226                 :      * @access     private                                                           
     227                 :      * @see        _initErrorStack()                                                 
     228                 :      */                                                                              
     229                 :     var $_callback_errorhandler = false;                                             
     230                 :                                                                                      
     231                 :     /**                                                                              
     232                 :      * Associative array of key-value pairs                                          
     233                 :      * that are used to specify any handler-specific settings.                       
     234                 :      *                                                                               
     235                 :      * @var        array                                                             
     236                 :      * @since      1.0.0                                                             
     237                 :      * @access     private                                                           
     238                 :      * @see        _initErrorStack()                                                 
     239                 :      */                                                                              
     240                 :     var $_errorhandler_options = array();                                            
     241                 :                                                                                      
     242                 :     /**                                                                              
     243                 :      * Last error that might occured                                                 
     244                 :      *                                                                               
     245                 :      * @var        false|mixed                                                       
     246                 :      * @since      1.0.0RC2                                                          
     247                 :      * @access     private                                                           
     248                 :      * @see        isError(), raiseError()                                           
     249                 :      */                                                                              
     250                 :     var $_lastError = false;                                                         
     251                 :                                                                                      
     252                 :                                                                                      
     253                 :     /**                                                                              
     254                 :      * Class constructor                                                             
     255                 :      *                                                                               
     256                 :      * Class constructors :                                                          
     257                 :      * Zend Engine 1 uses HTML_CSS, while Zend Engine 2 uses __construct             
     258                 :      *                                                                               
     259                 :      * @param array $attributes (optional) Pass options to the constructor.          
     260                 :      *                          Valid options are :                                  
     261                 :      *                           - xhtml (sets xhtml compliance),                    
     262                 :      *                           - tab (sets indent string),                         
     263                 :      *                           - filename (name of file to be parsed),             
     264                 :      *                           - cache (determines whether the nocache headers     
     265                 :      *                             are sent),                                        
     266                 :      *                           - oneline (whether to output each definition        
     267                 :      *                             on one line),                                     
     268                 :      *                           - groupsfirst (determines whether to output groups  
     269                 :      *                             before elements)                                  
     270                 :      *                           - allowduplicates (allow to have duplicate rules    
     271                 :      *                             in selector)                                      
     272                 :      * @param array $errorPrefs (optional) has to configure error handler            
     273                 :      *                                                                               
     274                 :      * @since      version 0.2.0 (2003-07-31)                                        
     275                 :      * @access     public                                                            
     276                 :      */                                                                              
     277                 :     function HTML_CSS($attributes = array(), $errorPrefs = array())                  
     278                 :     {                                                                                
     279               0 :         $this->__construct($attributes, $errorPrefs);                                
     280               0 :     }                                                                                
     281                 :                                                                                      
     282                 :     /**                                                                              
     283                 :      * Class constructor                                                             
     284                 :      *                                                                               
     285                 :      * Class constructors :                                                          
     286                 :      * Zend Engine 1 uses HTML_CSS, while Zend Engine 2 uses __construct             
     287                 :      *                                                                               
     288                 :      * @param array $attributes (optional) Pass options to the constructor.          
     289                 :      *                          Valid options are :                                  
     290                 :      *                           - xhtml (sets xhtml compliance),                    
     291                 :      *                           - tab (sets indent string),                         
     292                 :      *                           - filename (name of file to be parsed),             
     293                 :      *                           - cache (determines whether the nocache headers     
     294                 :      *                             are sent),                                        
     295                 :      *                           - oneline (whether to output each definition        
     296                 :      *                             on one line),                                     
     297                 :      *                           - groupsfirst (determines whether to output groups  
     298                 :      *                             before elements)                                  
     299                 :      *                           - allowduplicates (allow to have duplicate rules    
     300                 :      *                             in selector)                                      
     301                 :      * @param array $errorPrefs (optional) has to configure error handler            
     302                 :      *                                                                               
     303                 :      * @since      version 1.4.0 (2007-12-13)                                        
     304                 :      * @access     protected                                                         
     305                 :      */                                                                              
     306                 :     function __construct($attributes = array(), $errorPrefs = array())               
     307                 :     {                                                                                
     308              56 :         $this->_initErrorStack($errorPrefs);                                         
     309                 :                                                                                      
     310              56 :         if (!is_array($attributes)) {                                                
     311               0 :             $attributes = array($attributes);                                        
     312               0 :         }                                                                            
     313              56 :         if ($attributes) {                                                           
     314              15 :             $attributes = $this->_parseAttributes($attributes);                      
     315              15 :         }                                                                            
     316                 :                                                                                      
     317              56 :         $tab = '  ';                                                                 
     318              56 :         $eol = strtolower(substr(PHP_OS, 0, 3)) == 'win' ? "\r\n" : "\n";            
     319                 :                                                                                      
     320                 :         // default options                                                           
     321              56 :         $this->options = array('xhtml' => true, 'tab' => $tab, 'cache' => true,      
     322              56 :             'oneline' => false, 'charset' => 'iso-8859-1',                           
     323              56 :             'contentDisposition' => false, 'lineEnd' => $eol,                        
     324              56 :             'groupsfirst' => true, 'allowduplicates' => false);                      
     325                 :         // and options that come directly from HTML_Common                           
     326              56 :         $this->setTab($tab);                                                         
     327              56 :         $this->setLineEnd($eol);                                                     
     328                 :                                                                                      
     329                 :         // apply user options                                                        
     330              56 :         foreach ($attributes as $opt => $val) {                                      
     331              15 :             $this->__set($opt, $val);                                                
     332              56 :         }                                                                            
     333              56 :     }                                                                                
     334                 :                                                                                      
     335                 :     /**                                                                              
     336                 :      * Return the current API version                                                
     337                 :      *                                                                               
     338                 :      * Since 1.0.0 a string is returned rather than a float (for previous versions). 
     339                 :      *                                                                               
     340                 :      * @return     string                   compatible with php.version_compare()    
     341                 :      * @since      version 0.2.0 (2003-07-31)                                        
     342                 :      * @access     public                                                            
     343                 :      */                                                                              
     344                 :     function apiVersion()                                                            
     345                 :     {                                                                                
     346               1 :         return '1.5.0';                                                              
     347                 :     }                                                                                
     348                 :                                                                                      
     349                 :     /**                                                                              
     350                 :      * Set option for the class                                                      
     351                 :      *                                                                               
     352                 :      * Set an individual option value. Option must exist.                            
     353                 :      *                                                                               
     354                 :      * @param string $option Name of option to set                                   
     355                 :      * @param string $val    Value of option to set                                  
     356                 :      *                                                                               
     357                 :      * @return void                                                                  
     358                 :      * @since  version 1.4.0 (2007-12-13)                                            
     359                 :      * @access public                                                                
     360                 :      */                                                                              
     361                 :     function __set($option, $val)                                                    
     362                 :     {                                                                                
     363              56 :         if (isset($this->options[$option])) {                                        
     364              56 :             $this->options[$option] = $val;                                          
     365              56 :         }                                                                            
     366              56 :     }                                                                                
     367                 :                                                                                      
     368                 :     /**                                                                              
     369                 :      * Get option for the class                                                      
     370                 :      *                                                                               
     371                 :      * Return current value of an individual option. If option does not exist,       
     372                 :      * returns value is NULL.                                                        
     373                 :      *                                                                               
     374                 :      * @param string $option Name of option to set                                   
     375                 :      *                                                                               
     376                 :      * @return mixed                                                                 
     377                 :      * @since  version 1.4.0 (2007-12-13)                                            
     378                 :      * @access public                                                                
     379                 :      */                                                                              
     380                 :     function __get($option)                                                          
     381                 :     {                                                                                
     382              41 :         if (isset($this->options[$option])) {                                        
     383              40 :             $r = $this->options[$option];                                            
     384              40 :         } else {                                                                     
     385               1 :             $r = null;                                                               
     386                 :         }                                                                            
     387              41 :         return $r;                                                                   
     388                 :     }                                                                                
     389                 :                                                                                      
     390                 :     /**                                                                              
     391                 :      * Return all options for the class                                              
     392                 :      *                                                                               
     393                 :      * Return all configuration options at once                                      
     394                 :      *                                                                               
     395                 :      * @return array                                                                 
     396                 :      * @since  version 1.5.0 (2008-01-15)                                            
     397                 :      * @access public                                                                
     398                 :      */                                                                              
     399                 :     function getOptions()                                                            
     400                 :     {                                                                                
     401               4 :         return $this->options;                                                       
     402                 :     }                                                                                
     403                 :                                                                                      
     404                 :     /**                                                                              
     405                 :      * Set tab value                                                                 
     406                 :      *                                                                               
     407                 :      * Sets the string used to indent HTML                                           
     408                 :      *                                                                               
     409                 :      * @param string $string String used to indent ("\11", "\t", '  ', etc.).        
     410                 :      *                                                                               
     411                 :      * @since     version 1.4.0 (2007-12-13)                                         
     412                 :      * @access    public                                                             
     413                 :      * @return    void                                                               
     414                 :      */                                                                              
     415                 :     function setTab($string)                                                         
     416                 :     {                                                                                
     417              56 :         $this->__set('tab', $string);                                                
     418              56 :         parent::setTab($string);                                                     
     419              56 :     }                                                                                
     420                 :                                                                                      
     421                 :     /**                                                                              
     422                 :      * Set lineend value                                                             
     423                 :      *                                                                               
     424                 :      * Set the line end style to Windows, Mac, Unix or a custom string               
     425                 :      *                                                                               
     426                 :      * @param string $style "win", "mac", "unix" or custom string.                   
     427                 :      *                                                                               
     428                 :      * @since   version 1.4.0 (2007-12-13)                                           
     429                 :      * @access  public                                                               
     430                 :      * @return  void                                                                 
     431                 :      */                                                                              
     432                 :     function setLineEnd($style)                                                      
     433                 :     {                                                                                
     434              56 :         $this->__set('lineEnd', $style);                                             
     435              56 :         parent::setLineEnd($style);                                                  
     436              56 :     }                                                                                
     437                 :                                                                                      
     438                 :     /**                                                                              
     439                 :      * Set oneline flag                                                              
     440                 :      *                                                                               
     441                 :      * Determine whether definitions are output on a single line or multi lines      
     442                 :      *                                                                               
     443                 :      * @param bool $value flag to true if single line, false for multi lines         
     444                 :      *                                                                               
     445                 :      * @return     void|PEAR_Error                                                   
     446                 :      * @since      version 0.3.3 (2004-05-20)                                        
     447                 :      * @access     public                                                            
     448                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT                                      
     449                 :      */                                                                              
     450                 :     function setSingleLineOutput($value)                                             
     451                 :     {                                                                                
     452               2 :         if (!is_bool($value)) {                                                      
     453               1 :             return $this->raiseError(                                                
     454               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     455               1 :                 array('var' => '$value',                                             
     456               1 :                       'was' => gettype($value),                                      
     457               1 :                       'expected' => 'boolean',                                       
     458               1 :                       'paramnum' => 1)                                               
     459               1 :             );                                                                       
     460                 :         }                                                                            
     461               1 :         $this->options['oneline'] = $value;                                          
     462               1 :     }                                                                                
     463                 :                                                                                      
     464                 :     /**                                                                              
     465                 :      * Set groupsfirst flag                                                          
     466                 :      *                                                                               
     467                 :      * Determine whether groups are output before elements or not                    
     468                 :      *                                                                               
     469                 :      * @param bool $value flag to true if groups are output before elements,         
     470                 :      *                    false otherwise                                            
     471                 :      *                                                                               
     472                 :      * @return     void|PEAR_Error                                                   
     473                 :      * @since      version 0.3.3 (2004-05-20)                                        
     474                 :      * @access     public                                                            
     475                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT                                      
     476                 :      */                                                                              
     477                 :     function setOutputGroupsFirst($value)                                            
     478                 :     {                                                                                
     479               2 :         if (!is_bool($value)) {                                                      
     480               1 :             return $this->raiseError(                                                
     481               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     482               1 :                 array('var' => '$value',                                             
     483               1 :                       'was' => gettype($value),                                      
     484               1 :                       'expected' => 'boolean',                                       
     485               1 :                       'paramnum' => 1)                                               
     486               1 :             );                                                                       
     487                 :         }                                                                            
     488               1 :         $this->options['groupsfirst'] = $value;                                      
     489               1 :     }                                                                                
     490                 :                                                                                      
     491                 :     /**                                                                              
     492                 :      * Parse a string containing selector(s)                                         
     493                 :      *                                                                               
     494                 :      * It processes it and returns an array or string containing                     
     495                 :      * modified selectors (depends on XHTML compliance setting;                      
     496                 :      * defaults to ensure lowercase element names)                                   
     497                 :      *                                                                               
     498                 :      * @param string $selectors  Selector string                                     
     499                 :      * @param int    $outputMode (optional) 0 = string; 1 = array; 2 = deep array    
     500                 :      *                                                                               
     501                 :      * @return     mixed|PEAR_Error                                                  
     502                 :      * @since      version 0.3.2 (2004-03-24)                                        
     503                 :      * @access     protected                                                         
     504                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT                                      
     505                 :      */                                                                              
     506                 :     function parseSelectors($selectors, $outputMode = 0)                             
     507                 :     {                                                                                
     508              31 :         if (!is_string($selectors)) {                                                
     509               1 :             return $this->raiseError(                                                
     510               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     511               1 :                 array('var' => '$selectors',                                         
     512               1 :                       'was' => gettype($selectors),                                  
     513               1 :                       'expected' => 'string',                                        
     514               1 :                       'paramnum' => 1)                                               
     515               1 :             );                                                                       
     516                 :                                                                                      
     517              31 :         } elseif (!is_int($outputMode)) {                                            
     518               1 :             return $this->raiseError(                                                
     519               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     520               1 :                 array('var' => '$outputMode',                                        
     521               1 :                       'was' => gettype($outputMode),                                 
     522               1 :                       'expected' => 'integer',                                       
     523               1 :                       'paramnum' => 2)                                               
     524               1 :             );                                                                       
     525                 :                                                                                      
     526              31 :         } elseif ($outputMode < 0 || $outputMode > 3) {                              
     527               1 :             return $this->raiseError(                                                
     528               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
     529               1 :                 array('var' => '$outputMode',                                        
     530               1 :                       'was' => $outputMode,                                          
     531               1 :                       'expected' => '0 | 1 | 2 | 3',                                 
     532               1 :                       'paramnum' => 2)                                               
     533               1 :             );                                                                       
     534                 :         }                                                                            
     535                 :                                                                                      
     536              31 :         $selectors_array =  explode(',', $selectors);                                
     537              31 :         $i               = 0;                                                        
     538              31 :         foreach ($selectors_array as $selector) {                                    
     539                 :             // trim to remove possible whitespace                                    
     540              31 :             $selector = trim($this->collapseInternalSpaces($selector));              
     541              31 :             if (strpos($selector, ' ')) {                                            
     542              10 :                 $sel_a = array();                                                    
     543              10 :                 foreach (explode(' ', $selector) as $sub_selector) {                 
     544              10 :                     $sel_a[] = $this->parseSelectors($sub_selector, $outputMode);    
     545              10 :                 }                                                                    
     546              10 :                 if ($outputMode === 0) {                                             
     547               6 :                         $array[$i] = implode(' ', $sel_a);                           
     548               6 :                 } else {                                                             
     549               9 :                     $sel_a2 = array();                                               
     550               9 :                     foreach ($sel_a as $sel_a_temp) {                                
     551               9 :                         $sel_a2 = array_merge($sel_a2, $sel_a_temp);                 
     552               9 :                     }                                                                
     553               9 :                     if ($outputMode == 2) {                                          
     554               1 :                         $array[$i]['inheritance'] = $sel_a2;                         
     555               1 :                     } else {                                                         
     556               8 :                         $array[$i] = implode(' ', $sel_a2);                          
     557                 :                     }                                                                
     558                 :                 }                                                                    
     559              10 :                 $i++;                                                                
     560              10 :             } else {                                                                 
     561                 :                 // initialize variables                                              
     562              31 :                 $element = '';                                                       
     563              31 :                 $id      = '';                                                       
     564              31 :                 $class   = '';                                                       
     565              31 :                 $pseudo  = '';                                                       
     566                 :                                                                                      
     567              31 :                 if (strpos($selector, ':') !== false) {                              
     568               3 :                     $pseudo   = strstr($selector, ':');                              
     569               3 :                     $selector = substr($selector, 0, strpos($selector, ':'));        
     570               3 :                 }                                                                    
     571              31 :                 if (strpos($selector, '.') !== false) {                              
     572               9 :                     $class    = strstr($selector, '.');                              
     573               9 :                     $selector = substr($selector, 0, strpos($selector, '.'));        
     574               9 :                 }                                                                    
     575              31 :                 if (strpos($selector, '#') !== false) {                              
     576               8 :                     $id       = strstr($selector, '#');                              
     577               8 :                     $selector = substr($selector, 0, strpos($selector, '#'));        
     578               8 :                 }                                                                    
     579              31 :                 if ($selector != '') {                                               
     580              29 :                     $element = $selector;                                            
     581              29 :                 }                                                                    
     582              31 :                 if ($this->options['xhtml']) {                                       
     583              27 :                     $element = strtolower($element);                                 
     584              27 :                     $pseudo  = strtolower($pseudo);                                  
     585              27 :                 }                                                                    
     586              31 :                 if ($outputMode == 2) {                                              
     587               1 :                     $array[$i]['element'] = $element;                                
     588               1 :                     $array[$i]['id']      = $id;                                     
     589               1 :                     $array[$i]['class']   = $class;                                  
     590               1 :                     $array[$i]['pseudo']  = $pseudo;                                 
     591               1 :                 } else {                                                             
     592              30 :                     $array[$i] = $element.$id.$class.$pseudo;                        
     593                 :                 }                                                                    
     594              31 :                 $i++;                                                                
     595                 :             }                                                                        
     596              31 :         }                                                                            
     597              31 :         if ($outputMode == 0) {                                                      
     598              23 :             $output = implode(', ', $array);                                         
     599              23 :             return $output;                                                          
     600                 :         } else {                                                                     
     601              27 :             return $array;                                                           
     602                 :         }                                                                            
     603                 :     }                                                                                
     604                 :                                                                                      
     605                 :     /**                                                                              
     606                 :      * Strips excess spaces in string.                                               
     607                 :      *                                                                               
     608                 :      * @param string $subject string to format                                       
     609                 :      *                                                                               
     610                 :      * @return     string                                                            
     611                 :      * @since      version 0.3.2 (2004-03-24)                                        
     612                 :      * @access     protected                                                         
     613                 :      */                                                                              
     614                 :     function collapseInternalSpaces($subject)                                        
     615                 :     {                                                                                
     616              34 :         $string = preg_replace('/\s+/', ' ', $subject);                              
     617              34 :         return $string;                                                              
     618                 :     }                                                                                
     619                 :                                                                                      
     620                 :     /**                                                                              
     621                 :      * sort and move simple declarative At-Rules to the top                          
     622                 :      *                                                                               
     623                 :      * @return     void                                                              
     624                 :      * @access     protected                                                         
     625                 :      * @since      version 1.5.0 (2008-01-15)                                        
     626                 :      */                                                                              
     627                 :     function sortAtRules()                                                           
     628                 :     {                                                                                
     629                 :         // split simple declarative At-Rules from the other                          
     630              28 :         $return = array('atrules' => array(), 'newcss' => array());                  
     631                 :                                                                                      
     632              28 :         foreach ($this->_css as $key => $value) {                                    
     633              27 :             if ((0 === strpos($key, "@")) && (1 !== strpos($key, "-"))) {            
     634              12 :                 $return["atrules"][$key] = $value;                                   
     635              12 :             } else {                                                                 
     636              20 :                 $return["newcss"][$key] = $value;                                    
     637                 :             }                                                                        
     638              28 :         }                                                                            
     639                 :                                                                                      
     640                 :         // bring sprecial rules to the top                                           
     641              28 :         foreach (array('@namespace', '@import', '@charset') as $name) {              
     642              28 :             if (isset($return['atrules'][$name])) {                                  
     643               4 :                 $rule = array($name => $return['atrules'][$name]);                   
     644               4 :                 unset($return['atrules'][$name]);                                    
     645               4 :                 $return['atrules'] = $rule + $return['atrules'];                     
     646               4 :             }                                                                        
     647              28 :         }                                                                            
     648                 :                                                                                      
     649              28 :         $this->_css = $return['atrules'] + $return['newcss'];                        
     650              28 :     }                                                                                
     651                 :                                                                                      
     652                 :     /**                                                                              
     653                 :      * Set xhtml flag                                                                
     654                 :      *                                                                               
     655                 :      * Active or not the XHTML mode compliant                                        
     656                 :      *                                                                               
     657                 :      * @param bool $value flag to true if XHTML compliance needed,                   
     658                 :      *                    false otherwise                                            
     659                 :      *                                                                               
     660                 :      * @return     void|PEAR_Error                                                   
     661                 :      * @since      version 0.3.2 (2004-03-24)                                        
     662                 :      * @access     public                                                            
     663                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT                                      
     664                 :      */                                                                              
     665                 :     function setXhtmlCompliance($value)                                              
     666                 :     {                                                                                
     667               6 :         if (!is_bool($value)) {                                                      
     668               1 :             return $this->raiseError(                                                
     669               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     670               1 :                 array('var' => '$value',                                             
     671               1 :                       'was' => gettype($value),                                      
     672               1 :                       'expected' => 'boolean',                                       
     673               1 :                       'paramnum' => 1)                                               
     674               1 :             );                                                                       
     675                 :         }                                                                            
     676               5 :         $this->options['xhtml'] = $value;                                            
     677               5 :     }                                                                                
     678                 :                                                                                      
     679                 :     /**                                                                              
     680                 :      * Return list of supported At-Rules                                             
     681                 :      *                                                                               
     682                 :      * Return the list of At-Rules supported by API 1.5.0 of HTML_CSS                
     683                 :      *                                                                               
     684                 :      * @return void                                                                  
     685                 :      * @since  version 1.5.0 (2008-01-15)                                            
     686                 :      * @access public                                                                
     687                 :      */                                                                              
     688                 :     function getAtRulesList()                                                        
     689                 :     {                                                                                
     690               5 :         $atRules = array('@charset', '@font-face',                                   
     691               5 :                          '@import', '@media', '@page', '@namespace');                
     692               5 :         return $atRules;                                                             
     693                 :     }                                                                                
     694                 :                                                                                      
     695                 :     /**                                                                              
     696                 :      * Create a new simple declarative At-Rule                                       
     697                 :      *                                                                               
     698                 :      * Create a simple at-rule without declaration style blocks.                     
     699                 :      * That include @charset, @import and @namespace                                 
     700                 :      *                                                                               
     701                 :      * @param string $atKeyword  at-rule keyword                                     
     702                 :      * @param string $arguments  argument list for @charset, @import or @namespace   
     703                 :      * @param bool   $duplicates (optional) Allow or disallow duplicates             
     704                 :      *                                                                               
     705                 :      * @return void|PEAR_Error                                                       
     706                 :      * @since  version 1.5.0 (2008-01-15)                                            
     707                 :      * @access public                                                                
     708                 :      * @throws HTML_CSS_ERROR_INVALID_INPUT                                          
     709                 :      * @see    unsetAtRule()                                                         
     710                 :      */                                                                              
     711                 :     function createAtRule($atKeyword, $arguments = '', $duplicates = null)           
     712                 :     {                                                                                
     713               5 :         $allowed_atrules = array('@charset', '@import', '@namespace');               
     714                 :                                                                                      
     715               5 :         if (!is_string($atKeyword)) {                                                
     716               1 :             return $this->raiseError(                                                
     717               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     718               1 :                 array('var' => '$atKeyword',                                         
     719               1 :                       'was' => gettype($atKeyword),                                  
     720               1 :                       'expected' => 'string',                                        
     721               1 :                       'paramnum' => 1)                                               
     722               1 :             );                                                                       
     723                 :                                                                                      
     724               5 :         } elseif (!in_array(strtolower($atKeyword), $allowed_atrules)) {             
     725               1 :             return $this->raiseError(                                                
     726               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
     727               1 :                 array('var' => '$atKeyword',                                         
     728               1 :                       'was' => $atKeyword,                                           
     729               1 :                       'expected' => implode('|', $allowed_atrules),                  
     730               1 :                       'paramnum' => 1)                                               
     731               1 :             );                                                                       
     732                 :                                                                                      
     733               5 :         } elseif (!is_string($arguments)) {                                          
     734               1 :             return $this->raiseError(                                                
     735               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     736               1 :                 array('var' => '$arguments',                                         
     737               1 :                       'was' => gettype($arguments),                                  
     738               1 :                       'expected' => 'string',                                        
     739               1 :                       'paramnum' => 2)                                               
     740               1 :             );                                                                       
     741                 :         }                                                                            
     742                 :                                                                                      
     743               5 :         if (empty($arguments)) {                                                     
     744               1 :             return $this->raiseError(                                                
     745               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
     746               1 :                 array('var' => '$arguments',                                         
     747               1 :                       'was' => $arguments,                                           
     748               1 :                       'expected' => 'not empty value',                               
     749               1 :                       'paramnum' => 2)                                               
     750               1 :             );                                                                       
     751                 :         }                                                                            
     752                 :                                                                                      
     753               4 :         if (!isset($duplicates)) {                                                   
     754               1 :             $duplicates = $this->__get('allowduplicates');                           
     755               1 :         }                                                                            
     756                 :                                                                                      
     757               4 :         if ($duplicates) {                                                           
     758               2 :             $this->_duplicateCounter++;                                              
     759               2 :             $this->_css[strtolower($atKeyword)][$this->_duplicateCounter]            
     760               2 :                 = array($arguments => '');                                           
     761               2 :         } else {                                                                     
     762               2 :             $this->_css[strtolower($atKeyword)] = array($arguments => '');           
     763                 :         }                                                                            
     764               4 :     }                                                                                
     765                 :                                                                                      
     766                 :     /**                                                                              
     767                 :      * Remove an existing At-Rule                                                    
     768                 :      *                                                                               
     769                 :      * Remove an existing and supported at-rule. See HTML_CSS::getAtRulesList()      
     770                 :      * for a full list of supported At-Rules.                                        
     771                 :      *                                                                               
     772                 :      * @param string $atKeyword at-rule keyword                                      
     773                 :      *                                                                               
     774                 :      * @return void|PEAR_Error                                                       
     775                 :      * @since  version 1.5.0 (2008-01-15)                                            
     776                 :      * @access public                                                                
     777                 :      * @throws HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_NO_ATRULE                
     778                 :      */                                                                              
     779                 :     function unsetAtRule($atKeyword)                                                 
     780                 :     {                                                                                
     781               2 :         $allowed_atrules = $this->getAtRulesList();                                  
     782                 :                                                                                      
     783               2 :         if (!is_string($atKeyword)) {                                                
     784               1 :             return $this->raiseError(                                                
     785               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     786               1 :                 array('var' => '$atKeyword',                                         
     787               1 :                       'was' => gettype($atKeyword),                                  
     788               1 :                       'expected' => 'string',                                        
     789               1 :                       'paramnum' => 1)                                               
     790               1 :             );                                                                       
     791                 :                                                                                      
     792               2 :         } elseif (!in_array(strtolower($atKeyword), $allowed_atrules)) {             
     793               1 :             return $this->raiseError(                                                
     794               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
     795               1 :                 array('var' => '$atKeyword',                                         
     796               1 :                       'was' => $atKeyword,                                           
     797               1 :                       'expected' => implode('|', $allowed_atrules),                  
     798               1 :                       'paramnum' => 1)                                               
     799               1 :             );                                                                       
     800                 :                                                                                      
     801               2 :         } elseif (!isset($this->_css[strtolower($atKeyword)])) {                     
     802               1 :             return $this->raiseError(                                                
     803               1 :                 HTML_CSS_ERROR_NO_ATRULE, 'error',                                   
     804               1 :                 array('identifier' => $atKeyword)                                    
     805               1 :             );                                                                       
     806                 :         }                                                                            
     807                 :                                                                                      
     808               1 :         unset($this->_css[strtolower($atKeyword)]);                                  
     809               1 :     }                                                                                
     810                 :                                                                                      
     811                 :     /**                                                                              
     812                 :      * Define a conditional/informative At-Rule                                      
     813                 :      *                                                                               
     814                 :      * Set arguments and declaration style block for at-rules that follow :          
     815                 :      * "@media, @page, @font-face"                                                   
     816                 :      *                                                                               
     817                 :      * @param string $atKeyword  at-rule keyword                                     
     818                 :      * @param string $arguments  argument list                                       
     819                 :      *                           (optional for @font-face)                           
     820                 :      * @param string $selectors  selectors of declaration style block                
     821                 :      *                           (optional for @media, @page, @font-face)            
     822                 :      * @param string $property   property of a single declaration style block        
     823                 :      * @param string $value      value of a single declaration style block           
     824                 :      * @param bool   $duplicates (optional) Allow or disallow duplicates             
     825                 :      *                                                                               
     826                 :      * @return void|PEAR_Error                                                       
     827                 :      * @since  version 1.5.0 (2008-01-15)                                            
     828                 :      * @access public                                                                
     829                 :      * @throws HTML_CSS_ERROR_INVALID_INPUT                                          
     830                 :      * @see    getAtRuleStyle()                                                      
     831                 :      */                                                                              
     832                 :     function setAtRuleStyle($atKeyword, $arguments, $selectors, $property, $value,   
     833                 :         $duplicates = null                                                           
     834                 :     ) {                                                                              
     835              10 :         $allowed_atrules = array('@media', '@page', '@font-face');                   
     836                 :                                                                                      
     837              10 :         if (!is_string($atKeyword)) {                                                
     838               1 :             return $this->raiseError(                                                
     839               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     840               1 :                 array('var' => '$atKeyword',                                         
     841               1 :                       'was' => gettype($atKeyword),                                  
     842               1 :                       'expected' => 'string',                                        
     843               1 :                       'paramnum' => 1)                                               
     844               1 :             );                                                                       
     845                 :                                                                                      
     846              10 :         } elseif (!in_array(strtolower($atKeyword), $allowed_atrules)) {             
     847               1 :             return $this->raiseError(                                                
     848               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
     849               1 :                 array('var' => '$atKeyword',                                         
     850               1 :                       'was' => $atKeyword,                                           
     851               1 :                       'expected' => implode('|', $allowed_atrules),                  
     852               1 :                       'paramnum' => 1)                                               
     853               1 :             );                                                                       
     854                 :                                                                                      
     855              10 :         } elseif (empty($arguments) && strtolower($atKeyword) != '@font-face') {     
     856               1 :             return $this->raiseError(                                                
     857               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
     858               1 :                 array('var' => '$arguments',                                         
     859               1 :                       'was' => $arguments,                                           
     860               1 :                       'expected' => 'not empty value for '. $atKeyword,              
     861               1 :                       'paramnum' => 2)                                               
     862               1 :             );                                                                       
     863                 :                                                                                      
     864              10 :         } elseif (!is_string($selectors)) {                                          
     865               1 :             return $this->raiseError(                                                
     866               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     867               1 :                 array('var' => '$selectors',                                         
     868               1 :                       'was' => gettype($selectors),                                  
     869               1 :                       'expected' => 'string',                                        
     870               1 :                       'paramnum' => 3)                                               
     871               1 :             );                                                                       
     872                 :                                                                                      
     873              10 :         } elseif (!is_string($property)) {                                           
     874               1 :             return $this->raiseError(                                                
     875               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     876               1 :                 array('var' => '$property',                                          
     877               1 :                       'was' => gettype($property),                                   
     878               1 :                       'expected' => 'string',                                        
     879               1 :                       'paramnum' => 4)                                               
     880               1 :             );                                                                       
     881                 :                                                                                      
     882              10 :         } elseif (!is_string($value)) {                                              
     883               1 :             return $this->raiseError(                                                
     884               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     885               1 :                 array('var' => '$value',                                             
     886               1 :                       'was' => gettype($value),                                      
     887               1 :                       'expected' => 'string',                                        
     888               1 :                       'paramnum' => 5)                                               
     889               1 :             );                                                                       
     890                 :                                                                                      
     891              10 :         } elseif (empty($property)) {                                                
     892               1 :             return $this->raiseError(                                                
     893               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
     894               1 :                 array('var' => '$property',                                          
     895               1 :                       'was' => $property,                                            
     896               1 :                       'expected' => 'no empty string',                               
     897               1 :                       'paramnum' => 4)                                               
     898               1 :             );                                                                       
     899                 :                                                                                      
     900              10 :         } elseif (empty($value)) {                                                   
     901               1 :             return $this->raiseError(                                                
     902               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
     903               1 :                 array('var' => '$value',                                             
     904               1 :                       'was' => gettype($value),                                      
     905               1 :                       'expected' => 'no empty string',                               
     906               1 :                       'paramnum' => 5)                                               
     907               1 :             );                                                                       
     908                 :         }                                                                            
     909                 :                                                                                      
     910               9 :         if (!isset($duplicates)) {                                                   
     911               2 :             $duplicates = $this->__get('allowduplicates');                           
     912               2 :         }                                                                            
     913                 :                                                                                      
     914               9 :         $atKeyword = strtolower($atKeyword);                                         
     915                 :                                                                                      
     916               9 :         if (!empty($selectors)) {                                                    
     917               7 :             $selectors = $this->parseSelectors($selectors);                          
     918               7 :         }                                                                            
     919               9 :         $this->_css[$atKeyword][$arguments][$selectors][$property] = $value;         
     920               9 :     }                                                                                
     921                 :                                                                                      
     922                 :     /**                                                                              
     923                 :      * Get style value of an existing At-Rule                                        
     924                 :      *                                                                               
     925                 :      * Retrieve arguments or style value of an existing At-Rule.                     
     926                 :      * See HTML_CSS::getAtRulesList() for a full list of supported At-Rules.         
     927                 :      *                                                                               
     928                 :      * @param string $atKeyword at-rule keyword                                      
     929                 :      * @param string $arguments argument list                                        
     930                 :      *                          (optional for @font-face)                            
     931                 :      * @param string $selectors selectors of declaration style block                 
     932                 :      *                          (optional for @media, @page, @font-face)             
     933                 :      * @param string $property  property of a single declaration style block         
     934                 :      *                                                                               
     935                 :      * @return void|PEAR_Error                                                       
     936                 :      * @since  version 1.5.0 (2008-01-15)                                            
     937                 :      * @access public                                                                
     938                 :      * @throws HTML_CSS_ERROR_INVALID_INPUT                                          
     939                 :      * @see    setAtRuleStyle()                                                      
     940                 :      */                                                                              
     941                 :     function getAtRuleStyle($atKeyword, $arguments, $selectors, $property)           
     942                 :     {                                                                                
     943               3 :         $allowed_atrules = $this->getAtRulesList();                                  
     944                 :                                                                                      
     945               3 :         if (!is_string($atKeyword)) {                                                
     946               1 :             return $this->raiseError(                                                
     947               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     948               1 :                 array('var' => '$atKeyword',                                         
     949               1 :                       'was' => gettype($atKeyword),                                  
     950               1 :                       'expected' => 'string',                                        
     951               1 :                       'paramnum' => 1)                                               
     952               1 :             );                                                                       
     953                 :                                                                                      
     954               3 :         } elseif (!in_array(strtolower($atKeyword), $allowed_atrules)) {             
     955               1 :             return $this->raiseError(                                                
     956               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
     957               1 :                 array('var' => '$atKeyword',                                         
     958               1 :                       'was' => $atKeyword,                                           
     959               1 :                       'expected' => implode('|', $allowed_atrules),                  
     960               1 :                       'paramnum' => 1)                                               
     961               1 :             );                                                                       
     962                 :                                                                                      
     963               3 :         } elseif (!is_string($arguments)) {                                          
     964               1 :             return $this->raiseError(                                                
     965               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     966               1 :                 array('var' => '$arguments',                                         
     967               1 :                       'was' => gettype($arguments),                                  
     968               1 :                       'expected' => 'string',                                        
     969               1 :                       'paramnum' => 2)                                               
     970               1 :             );                                                                       
     971                 :                                                                                      
     972               3 :         } elseif (!is_string($selectors)) {                                          
     973               1 :             return $this->raiseError(                                                
     974               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     975               1 :                 array('var' => '$selectors',                                         
     976               1 :                       'was' => gettype($selectors),                                  
     977               1 :                       'expected' => 'string',                                        
     978               1 :                       'paramnum' => 3)                                               
     979               1 :             );                                                                       
     980                 :                                                                                      
     981               3 :         } elseif (!is_string($property)) {                                           
     982               1 :             return $this->raiseError(                                                
     983               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
     984               1 :                 array('var' => '$property',                                          
     985               1 :                       'was' => gettype($property),                                   
     986               1 :                       'expected' => 'string',                                        
     987               1 :                       'paramnum' => 4)                                               
     988               1 :             );                                                                       
     989                 :         }                                                                            
     990                 :                                                                                      
     991               2 :         if (isset($this->_css[$atKeyword][$arguments][$selectors][$property])) {     
     992               1 :             $val = $this->_css[$atKeyword][$arguments][$selectors][$property];       
     993               1 :         } else {                                                                     
     994               1 :             $val = null;                                                             
     995                 :         }                                                                            
     996               2 :         return $val;                                                                 
     997                 :     }                                                                                
     998                 :                                                                                      
     999                 :     /**                                                                              
    1000                 :      * Create a new CSS definition group                                             
    1001                 :      *                                                                               
    1002                 :      * Create a new CSS definition group. Return an integer identifying the group.   
    1003                 :      *                                                                               
    1004                 :      * @param string $selectors Selector(s) to be defined, comma delimited.          
    1005                 :      * @param mixed  $group     (optional) Group identifier. If not passed,          
    1006                 :      *                          will return an automatically assigned integer.       
    1007                 :      *                                                                               
    1008                 :      * @return     mixed|PEAR_Error                                                  
    1009                 :      * @since      version 0.3.0 (2003-11-03)                                        
    1010                 :      * @access     public                                                            
    1011                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_INVALID_GROUP        
    1012                 :      * @see        unsetGroup()                                                      
    1013                 :      */                                                                              
    1014                 :     function createGroup($selectors, $group = null)                                  
    1015                 :     {                                                                                
    1016              14 :         if (!is_string($selectors)) {                                                
    1017               1 :             return $this->raiseError(                                                
    1018               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1019               1 :                 array('var' => '$selectors',                                         
    1020               1 :                       'was' => gettype($selectors),                                  
    1021               1 :                       'expected' => 'string',                                        
    1022               1 :                       'paramnum' => 1)                                               
    1023               1 :             );                                                                       
    1024                 :         }                                                                            
    1025                 :                                                                                      
    1026              14 :         if (!isset($group)) {                                                        
    1027              12 :             $this->_groupCount++;                                                    
    1028              12 :             $group = $this->_groupCount;                                             
    1029              12 :         } else {                                                                     
    1030               3 :             if (isset($this->_groups['@-'.$group])) {                                
    1031               1 :                 return $this->raiseError(                                            
    1032               1 :                     HTML_CSS_ERROR_INVALID_GROUP, 'error',                           
    1033               1 :                     array('identifier' => $group)                                    
    1034               1 :                 );                                                                   
    1035                 :             }                                                                        
    1036                 :         }                                                                            
    1037                 :                                                                                      
    1038              14 :         $groupIdent = '@-'.$group;                                                   
    1039                 :                                                                                      
    1040              14 :         $selectors = $this->parseSelectors($selectors, 1);                           
    1041              14 :         foreach ($selectors as $selector) {                                          
    1042              14 :             $this->_alibis[$selector][] = $groupIdent;                               
    1043              14 :         }                                                                            
    1044                 :                                                                                      
    1045              14 :         $this->_groups[$groupIdent] = $selectors;                                    
    1046                 :                                                                                      
    1047              14 :         return $group;                                                               
    1048                 :     }                                                                                
    1049                 :                                                                                      
    1050                 :     /**                                                                              
    1051                 :      * Remove a CSS definition group                                                 
    1052                 :      *                                                                               
    1053                 :      * Remove a CSS definition group. Use the same identifier as for group creation. 
    1054                 :      *                                                                               
    1055                 :      * @param mixed $group CSS definition group identifier                           
    1056                 :      *                                                                               
    1057                 :      * @return     void|PEAR_Error                                                   
    1058                 :      * @since      version 0.3.0 (2003-11-03)                                        
    1059                 :      * @access     public                                                            
    1060                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_NO_GROUP             
    1061                 :      * @see        createGroup()                                                     
    1062                 :      */                                                                              
    1063                 :     function unsetGroup($group)                                                      
    1064                 :     {                                                                                
    1065               2 :         if (!is_int($group) && !is_string($group)) {                                 
    1066               1 :             return $this->raiseError(                                                
    1067               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1068               1 :                 array('var' => '$group',                                             
    1069               1 :                       'was' => gettype($group),                                      
    1070               1 :                       'expected' => 'integer | string',                              
    1071               1 :                       'paramnum' => 1)                                               
    1072               1 :             );                                                                       
    1073                 :         }                                                                            
    1074               2 :         $groupIdent = '@-'.$group;                                                   
    1075               2 :         if ($group < 0 || $group > $this->_groupCount                                
    1076               2 :             || !isset($this->_groups[$groupIdent])                                   
    1077               2 :         ) {                                                                          
    1078               1 :             return $this->raiseError(                                                
    1079               1 :                 HTML_CSS_ERROR_NO_GROUP, 'error',                                    
    1080               1 :                 array('identifier' => $group)                                        
    1081               1 :             );                                                                       
    1082                 :         }                                                                            
    1083                 :                                                                                      
    1084               1 :         $alibis = $this->_alibis;                                                    
    1085               1 :         foreach ($alibis as $selector => $data) {                                    
    1086               1 :             foreach ($data as $key => $value) {                                      
    1087               1 :                 if ($value == $groupIdent) {                                         
    1088               1 :                     unset($this->_alibis[$selector][$key]);                          
    1089               1 :                     break;                                                           
    1090                 :                 }                                                                    
    1091               1 :             }                                                                        
    1092               1 :             if (count($this->_alibis[$selector]) == 0) {                             
    1093               1 :                 unset($this->_alibis[$selector]);                                    
    1094               1 :             }                                                                        
    1095               1 :         }                                                                            
    1096               1 :         unset($this->_groups[$groupIdent]);                                          
    1097               1 :         unset($this->_css[$groupIdent]);                                             
    1098               1 :     }                                                                                
    1099                 :                                                                                      
    1100                 :     /**                                                                              
    1101                 :      * Set or add a CSS definition for a CSS group                                   
    1102                 :      *                                                                               
    1103                 :      * Define the new value of a property for a CSS group. The group should exist.   
    1104                 :      * If not, use HTML_CSS::createGroup first                                       
    1105                 :      *                                                                               
    1106                 :      * @param mixed  $group      CSS definition group identifier                     
    1107                 :      * @param string $property   Property defined                                    
    1108                 :      * @param string $value      Value assigned                                      
    1109                 :      * @param bool   $duplicates (optional) Allow or disallow duplicates.            
    1110                 :      *                                                                               
    1111                 :      * @return     void|int|PEAR_Error     Returns an integer if duplicates          
    1112                 :      *                                     are allowed.                              
    1113                 :      * @since      version 0.3.0 (2003-11-03)                                        
    1114                 :      * @access     public                                                            
    1115                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_NO_GROUP             
    1116                 :      * @see        getGroupStyle()                                                   
    1117                 :      */                                                                              
    1118                 :     function setGroupStyle($group, $property, $value, $duplicates = null)            
    1119                 :     {                                                                                
    1120              13 :         if (!is_int($group) && !is_string($group)) {                                 
    1121               1 :             return $this->raiseError(                                                
    1122               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1123               1 :                 array('var' => '$group',                                             
    1124               1 :                       'was' => gettype($group),                                      
    1125               1 :                       'expected' => 'integer | string',                              
    1126               1 :                       'paramnum' => 1)                                               
    1127               1 :             );                                                                       
    1128                 :                                                                                      
    1129              13 :         } elseif (!is_string($property)) {                                           
    1130               1 :             return $this->raiseError(                                                
    1131               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1132               1 :                 array('var' => '$property',                                          
    1133               1 :                       'was' => gettype($property),                                   
    1134               1 :                       'expected' => 'string',                                        
    1135               1 :                       'paramnum' => 2)                                               
    1136               1 :             );                                                                       
    1137                 :                                                                                      
    1138              13 :         } elseif (empty($property)) {                                                
    1139               1 :             return $this->raiseError(                                                
    1140               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
    1141               1 :                 array('var' => '$property',                                          
    1142               1 :                       'was' => gettype($property),                                   
    1143               1 :                       'expected' => 'no empty string',                               
    1144               1 :                       'paramnum' => 2)                                               
    1145               1 :             );                                                                       
    1146                 :                                                                                      
    1147              13 :         } elseif (!is_string($value)) {                                              
    1148               1 :             return $this->raiseError(                                                
    1149               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1150               1 :                 array('var' => '$value',                                             
    1151               1 :                       'was' => gettype($value),                                      
    1152               1 :                       'expected' => 'string',                                        
    1153               1 :                       'paramnum' => 3)                                               
    1154               1 :             );                                                                       
    1155                 :                                                                                      
    1156              13 :         } elseif (isset($duplicates) && !is_bool($duplicates)) {                     
    1157               1 :             return $this->raiseError(                                                
    1158               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1159               1 :                 array('var' => '$duplicates',                                        
    1160               1 :                       'was' => gettype($duplicates),                                 
    1161               1 :                       'expected' => 'bool',                                          
    1162               1 :                       'paramnum' => 4)                                               
    1163               1 :             );                                                                       
    1164                 :         }                                                                            
    1165                 :                                                                                      
    1166              13 :         if (!isset($duplicates)) {                                                   
    1167               6 :             $duplicates = $this->__get('allowduplicates');                           
    1168               6 :         }                                                                            
    1169                 :                                                                                      
    1170              13 :         $groupIdent = '@-'.$group;                                                   
    1171              13 :         if ($group < 0 || $group > $this->_groupCount                                
    1172              13 :             || !isset($this->_groups[$groupIdent])                                   
    1173              13 :         ) {                                                                          
    1174               1 :             return $this->raiseError(                                                
    1175               1 :                 HTML_CSS_ERROR_NO_GROUP, 'error',                                    
    1176               1 :                 array('identifier' => $group)                                        
    1177               1 :             );                                                                       
    1178                 :         }                                                                            
    1179                 :                                                                                      
    1180              12 :         if ($duplicates === true) {                                                  
    1181               1 :             $this->_duplicateCounter++;                                              
    1182               1 :             $this->_css[$groupIdent][$this->_duplicateCounter][$property] = $value;  
    1183               1 :             return $this->_duplicateCounter;                                         
    1184                 :         } else {                                                                     
    1185              11 :             $this->_css[$groupIdent][$property] = $value;                            
    1186                 :         }                                                                            
    1187              11 :     }                                                                                
    1188                 :                                                                                      
    1189                 :     /**                                                                              
    1190                 :      * Return CSS definition for a CSS group                                         
    1191                 :      *                                                                               
    1192                 :      * Get the CSS definition for group created by setGroupStyle()                   
    1193                 :      *                                                                               
    1194                 :      * @param mixed  $group    CSS definition group identifier                       
    1195                 :      * @param string $property Property defined                                      
    1196                 :      *                                                                               
    1197                 :      * @return     mixed|PEAR_Error                                                  
    1198                 :      * @since      version 0.3.0 (2003-11-03)                                        
    1199                 :      * @access     public                                                            
    1200                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_NO_GROUP,            
    1201                 :      *             HTML_CSS_ERROR_NO_ELEMENT                                         
    1202                 :      * @see        setGroupStyle()                                                   
    1203                 :      */                                                                              
    1204                 :     function getGroupStyle($group, $property)                                        
    1205                 :     {                                                                                
    1206               3 :         if (!is_int($group) && !is_string($group)) {                                 
    1207               1 :             return $this->raiseError(                                                
    1208               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1209               1 :                 array('var' => '$group',                                             
    1210               1 :                       'was' => gettype($group),                                      
    1211               1 :                       'expected' => 'integer | string',                              
    1212               1 :                       'paramnum' => 1)                                               
    1213               1 :             );                                                                       
    1214                 :                                                                                      
    1215               3 :         } elseif (!is_string($property)) {                                           
    1216               1 :             return $this->raiseError(                                                
    1217               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1218               1 :                 array('var' => '$property',                                          
    1219               1 :                       'was' => gettype($property),                                   
    1220               1 :                       'expected' => 'string',                                        
    1221               1 :                       'paramnum' => 2)                                               
    1222               1 :             );                                                                       
    1223                 :         }                                                                            
    1224               3 :         $groupIdent = '@-'.$group;                                                   
    1225               3 :         if ($group < 0 || $group > $this->_groupCount                                
    1226               3 :             || !isset($this->_groups[$groupIdent])                                   
    1227               3 :         ) {                                                                          
    1228               1 :             return $this->raiseError(                                                
    1229               1 :                 HTML_CSS_ERROR_NO_GROUP, 'error',                                    
    1230               1 :                 array('identifier' => $group)                                        
    1231               1 :             );                                                                       
    1232                 :         }                                                                            
    1233                 :                                                                                      
    1234               3 :         $styles = array();                                                           
    1235                 :                                                                                      
    1236               3 :         if (!isset($this->_css[$groupIdent])) {                                      
    1237               1 :             return $styles;                                                          
    1238                 :         }                                                                            
    1239                 :                                                                                      
    1240               2 :         foreach ($this->_css[$groupIdent] as $rank => $prop) {                       
    1241                 :             // if the style is not duplicate                                         
    1242               2 :             if (!is_numeric($rank)) {                                                
    1243               2 :                 $prop = array($rank => $prop);                                       
    1244               2 :             }                                                                        
    1245               2 :             foreach ($prop as $key => $value) {                                      
    1246               2 :                 if ($key == $property) {                                             
    1247               2 :                     $styles[] = $value;                                              
    1248               2 :                 }                                                                    
    1249               2 :             }                                                                        
    1250               2 :         }                                                                            
    1251                 :                                                                                      
    1252               2 :         if (count($styles) < 2) {                                                    
    1253               2 :             $styles = array_shift($styles);                                          
    1254               2 :         }                                                                            
    1255               2 :         return $styles;                                                              
    1256                 :     }                                                                                
    1257                 :                                                                                      
    1258                 :     /**                                                                              
    1259                 :      * Add a selector to a CSS definition group.                                     
    1260                 :      *                                                                               
    1261                 :      * Add a selector to a CSS definition group                                      
    1262                 :      *                                                                               
    1263                 :      * @param mixed  $group     CSS definition group identifier                      
    1264                 :      * @param string $selectors Selector(s) to be defined, comma delimited.          
    1265                 :      *                                                                               
    1266                 :      * @return   void|PEAR_Error                                                     
    1267                 :      * @since    version 0.3.0 (2003-11-03)                                          
    1268                 :      * @access   public                                                              
    1269                 :      * @throws   HTML_CSS_ERROR_NO_GROUP, HTML_CSS_ERROR_INVALID_INPUT               
    1270                 :      */                                                                              
    1271                 :     function addGroupSelector($group, $selectors)                                    
    1272                 :     {                                                                                
    1273               2 :         if (!is_int($group) && !is_string($group)) {                                 
    1274               1 :             return $this->raiseError(                                                
    1275               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1276               1 :                 array('var' => '$group',                                             
    1277               1 :                       'was' => gettype($group),                                      
    1278               1 :                       'expected' => 'integer | string',                              
    1279               1 :                       'paramnum' => 1)                                               
    1280               1 :             );                                                                       
    1281                 :         }                                                                            
    1282               2 :         $groupIdent = '@-'.$group;                                                   
    1283               2 :         if ($group < 0 || $group > $this->_groupCount                                
    1284               2 :             || !isset($this->_groups[$groupIdent])                                   
    1285               2 :         ) {                                                                          
    1286               1 :             return $this->raiseError(                                                
    1287               1 :                 HTML_CSS_ERROR_NO_GROUP, 'error',                                    
    1288               1 :                 array('identifier' => $group)                                        
    1289               1 :             );                                                                       
    1290                 :                                                                                      
    1291               2 :         } elseif (!is_string($selectors)) {                                          
    1292               1 :             return $this->raiseError(                                                
    1293               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1294               1 :                 array('var' => '$selectors',                                         
    1295               1 :                       'was' => gettype($selectors),                                  
    1296               1 :                       'expected' => 'string',                                        
    1297               1 :                       'paramnum' => 2)                                               
    1298               1 :             );                                                                       
    1299                 :         }                                                                            
    1300                 :                                                                                      
    1301               1 :         $newSelectors = $this->parseSelectors($selectors, 1);                        
    1302               1 :         foreach ($newSelectors as $selector) {                                       
    1303               1 :             $this->_alibis[$selector][] = $groupIdent;                               
    1304               1 :         }                                                                            
    1305               1 :         $oldSelectors = $this->_groups[$groupIdent];                                 
    1306                 :                                                                                      
    1307               1 :         $this->_groups[$groupIdent] = array_merge($oldSelectors, $newSelectors);     
    1308               1 :     }                                                                                
    1309                 :                                                                                      
    1310                 :     /**                                                                              
    1311                 :      * Remove a selector from a group                                                
    1312                 :      *                                                                               
    1313                 :      * Definitively remove a selector from a CSS group                               
    1314                 :      *                                                                               
    1315                 :      * @param mixed  $group     CSS definition group identifier                      
    1316                 :      * @param string $selectors Selector(s) to be removed, comma delimited.          
    1317                 :      *                                                                               
    1318                 :      * @return   void|PEAR_Error                                                     
    1319                 :      * @since    version 0.3.0 (2003-11-03)                                          
    1320                 :      * @access   public                                                              
    1321                 :      * @throws   HTML_CSS_ERROR_NO_GROUP, HTML_CSS_ERROR_INVALID_INPUT               
    1322                 :      */                                                                              
    1323                 :     function removeGroupSelector($group, $selectors)                                 
    1324                 :     {                                                                                
    1325               2 :         if (!is_int($group) && !is_string($group)) {                                 
    1326               1 :             return $this->raiseError(                                                
    1327               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1328               1 :                 array('var' => '$group',                                             
    1329               1 :                       'was' => gettype($group),                                      
    1330               1 :                       'expected' => 'integer | string',                              
    1331               1 :                       'paramnum' => 1)                                               
    1332               1 :             );                                                                       
    1333                 :         }                                                                            
    1334               2 :         $groupIdent = '@-'.$group;                                                   
    1335               2 :         if ($group < 0 || $group > $this->_groupCount                                
    1336               2 :             || !isset($this->_groups[$groupIdent])                                   
    1337               2 :         ) {                                                                          
    1338               1 :             return $this->raiseError(                                                
    1339               1 :                 HTML_CSS_ERROR_NO_GROUP, 'error',                                    
    1340               1 :                 array('identifier' => $group)                                        
    1341               1 :             );                                                                       
    1342                 :                                                                                      
    1343               2 :         } elseif (!is_string($selectors)) {                                          
    1344               1 :             return $this->raiseError(                                                
    1345               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1346               1 :                 array('var' => '$selectors',                                         
    1347               1 :                       'was' => gettype($selectors),                                  
    1348               1 :                       'expected' => 'string',                                        
    1349               1 :                       'paramnum' => 2)                                               
    1350               1 :             );                                                                       
    1351                 :         }                                                                            
    1352                 :                                                                                      
    1353               1 :         $oldSelectors = $this->_groups[$groupIdent];                                 
    1354               1 :         $selectors    = $this->parseSelectors($selectors, 1);                        
    1355               1 :         foreach ($selectors as $selector) {                                          
    1356               1 :             foreach ($oldSelectors as $key => $value) {                              
    1357               1 :                 if ($value == $selector) {                                           
    1358               1 :                     unset($this->_groups[$groupIdent][$key]);                        
    1359               1 :                 }                                                                    
    1360               1 :             }                                                                        
    1361               1 :             foreach ($this->_alibis[$selector] as $key => $value) {                  
    1362               1 :                 if ($value == $groupIdent) {                                         
    1363               1 :                     unset($this->_alibis[$selector][$key]);                          
    1364               1 :                 }                                                                    
    1365               1 :             }                                                                        
    1366               1 :         }                                                                            
    1367               1 :     }                                                                                
    1368                 :                                                                                      
    1369                 :     /**                                                                              
    1370                 :      * Set or add a CSS definition                                                   
    1371                 :      *                                                                               
    1372                 :      * Add or change a single value for an element property                          
    1373                 :      *                                                                               
    1374                 :      * @param string $element    Element (or class) to be defined                    
    1375                 :      * @param string $property   Property defined                                    
    1376                 :      * @param string $value      Value assigned                                      
    1377                 :      * @param bool   $duplicates (optional) Allow or disallow duplicates.            
    1378                 :      *                                                                               
    1379                 :      * @return     void|PEAR_Error                                                   
    1380                 :      * @since      version 0.2.0 (2003-07-31)                                        
    1381                 :      * @access     public                                                            
    1382                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT                                      
    1383                 :      * @see        getStyle()                                                        
    1384                 :      */                                                                              
    1385                 :     function setStyle($element, $property, $value, $duplicates = null)               
    1386                 :     {                                                                                
    1387              18 :         if (!is_string($element)) {                                                  
    1388               1 :             return $this->raiseError(                                                
    1389               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1390               1 :                 array('var' => '$element',                                           
    1391               1 :                       'was' => gettype($element),                                    
    1392               1 :                       'expected' => 'string',                                        
    1393               1 :                       'paramnum' => 1)                                               
    1394               1 :             );                                                                       
    1395                 :                                                                                      
    1396              18 :         } elseif (!is_string($property)) {                                           
    1397               1 :             return $this->raiseError(                                                
    1398               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1399               1 :                 array('var' => '$property',                                          
    1400               1 :                       'was' => gettype($property),                                   
    1401               1 :                       'expected' => 'string',                                        
    1402               1 :                       'paramnum' => 2)                                               
    1403               1 :             );                                                                       
    1404                 :                                                                                      
    1405              18 :         } elseif (!is_string($value)) {                                              
    1406               1 :             return $this->raiseError(                                                
    1407               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1408               1 :                 array('var' => '$value',                                             
    1409               1 :                       'was' => gettype($value),                                      
    1410               1 :                       'expected' => 'string',                                        
    1411               1 :                       'paramnum' => 3)                                               
    1412               1 :             );                                                                       
    1413                 :                                                                                      
    1414              18 :         } elseif (strpos($element, ',')) {                                           
    1415                 :             // Check if there are any groups.                                        
    1416               1 :             return $this->raiseError(                                                
    1417               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
    1418               1 :                 array('var' => '$element',                                           
    1419               1 :                       'was' => $element,                                             
    1420               1 :                       'expected' => 'string without comma',                          
    1421               1 :                       'paramnum' => 1)                                               
    1422               1 :             );                                                                       
    1423                 :                                                                                      
    1424              18 :         } elseif (isset($duplicates) && !is_bool($duplicates)) {                     
    1425               1 :             return $this->raiseError(                                                
    1426               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1427               1 :                 array('var' => '$duplicates',                                        
    1428               1 :                       'was' => gettype($duplicates),                                 
    1429               1 :                       'expected' => 'bool',                                          
    1430               1 :                       'paramnum' => 4)                                               
    1431               1 :             );                                                                       
    1432                 :         }                                                                            
    1433                 :                                                                                      
    1434              18 :         if (!isset($duplicates)) {                                                   
    1435               8 :              $duplicates = $this->__get('allowduplicates');                          
    1436               8 :         }                                                                            
    1437                 :                                                                                      
    1438              18 :         $element = $this->parseSelectors($element);                                  
    1439                 :                                                                                      
    1440              18 :         if ($duplicates === true) {                                                  
    1441               2 :             $this->_duplicateCounter++;                                              
    1442               2 :             $this->_css[$element][$this->_duplicateCounter][$property] = $value;     
    1443               2 :             return $this->_duplicateCounter;                                         
    1444                 :         } else {                                                                     
    1445              17 :             $this->_css[$element][$property] = $value;                               
    1446                 :         }                                                                            
    1447              17 :     }                                                                                
    1448                 :                                                                                      
    1449                 :     /**                                                                              
    1450                 :      * Return the value of a CSS property                                            
    1451                 :      *                                                                               
    1452                 :      * Get the value of a property to an identifed simple CSS element                
    1453                 :      *                                                                               
    1454                 :      * @param string $element  Element (or class) to be defined                      
    1455                 :      * @param string $property Property defined                                      
    1456                 :      *                                                                               
    1457                 :      * @return     mixed|PEAR_Error                                                  
    1458                 :      * @since      version 0.3.0 (2003-11-03)                                        
    1459                 :      * @access     public                                                            
    1460                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT,                                     
    1461                 :      *             HTML_CSS_ERROR_NO_ELEMENT, HTML_CSS_ERROR_NO_ELEMENT_PROPERTY     
    1462                 :      * @see        setStyle()                                                        
    1463                 :      */                                                                              
    1464                 :     function getStyle($element, $property)                                           
    1465                 :     {                                                                                
    1466               3 :         if (!is_string($element)) {                                                  
    1467               1 :             return $this->raiseError(                                                
    1468               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1469               1 :                 array('var' => '$element',                                           
    1470               1 :                       'was' => gettype($element),                                    
    1471               1 :                       'expected' => 'string',                                        
    1472               1 :                       'paramnum' => 1)                                               
    1473               1 :             );                                                                       
    1474                 :                                                                                      
    1475               3 :         } elseif (!is_string($property)) {                                           
    1476               1 :             return $this->raiseError(                                                
    1477               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1478               1 :                 array('var' => '$property',                                          
    1479               1 :                       'was' => gettype($property),                                   
    1480               1 :                       'expected' => 'string',                                        
    1481               1 :                       'paramnum' => 2)                                               
    1482               1 :             );                                                                       
    1483                 :         }                                                                            
    1484               3 :         if (!isset($this->_css[$element]) && !isset($this->_alibis[$element])) {     
    1485               1 :             return $this->raiseError(                                                
    1486               1 :                 HTML_CSS_ERROR_NO_ELEMENT, 'error',                                  
    1487               1 :                 array('identifier' => $element)                                      
    1488               1 :             );                                                                       
    1489                 :         }                                                                            
    1490                 :                                                                                      
    1491               3 :         if (isset($this->_css[$element]) && isset($this->_alibis[$element])) {       
    1492               2 :             $lastImplementation = array_keys($this->_alibis[$element]);              
    1493               2 :             $lastImplementation = array_pop($lastImplementation);                    
    1494                 :                                                                                      
    1495               2 :             $group = substr($this->_alibis[$element][$lastImplementation], 2);       
    1496                 :                                                                                      
    1497               2 :             $property_value = $this->getGroupStyle($group, $property);               
    1498               2 :             if (count($property_value) == 0) {                                       
    1499               1 :                 unset($property_value);                                              
    1500               1 :             }                                                                        
    1501               2 :         }                                                                            
    1502               3 :         if (isset($this->_css[$element]) && !isset($property_value)) {               
    1503               2 :             $property_value = array();                                               
    1504               2 :             foreach ($this->_css[$element] as $rank => $prop) {                      
    1505               2 :                 if (!is_numeric($rank)) {                                            
    1506               2 :                     $prop = array($rank => $prop);                                   
    1507               2 :                 }                                                                    
    1508               2 :                 foreach ($prop as $key => $value) {                                  
    1509               2 :                     if ($key == $property) {                                         
    1510               1 :                         $property_value[] = $value;                                  
    1511               1 :                     }                                                                
    1512               2 :                 }                                                                    
    1513               2 :             }                                                                        
    1514               2 :             if (count($property_value) == 1) {                                       
    1515               1 :                 $property_value = $property_value[0];                                
    1516               2 :             } elseif (count($property_value) == 0) {                                 
    1517               1 :                 unset($property_value);                                              
    1518               1 :             }                                                                        
    1519               2 :         }                                                                            
    1520                 :                                                                                      
    1521               3 :         if (!isset($property_value)) {                                               
    1522               1 :             return $this->raiseError(                                                
    1523               1 :                 HTML_CSS_ERROR_NO_ELEMENT_PROPERTY, 'error',                         
    1524               1 :                 array('identifier' => $element,                                      
    1525               1 :                       'property'   => $property)                                     
    1526               1 :             );                                                                       
    1527                 :         }                                                                            
    1528               2 :         return $property_value;                                                      
    1529                 :     }                                                                                
    1530                 :                                                                                      
    1531                 :     /**                                                                              
    1532                 :      * Retrieve styles corresponding to an element filter                            
    1533                 :      *                                                                               
    1534                 :      * Return array entries of styles that match patterns (Perl compatible)          
    1535                 :      *                                                                               
    1536                 :      * @param string $elmPattern Element or class pattern to retrieve                
    1537                 :      * @param string $proPattern (optional) Property pattern to retrieve             
    1538                 :      *                                                                               
    1539                 :      * @return     array|PEAR_Error                                                  
    1540                 :      * @since      version 1.1.0 (2007-01-01)                                        
    1541                 :      * @access     public                                                            
    1542                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT                                      
    1543                 :      * @link       http://www.php.net/en/ref.pcre.php                                
    1544                 :      *             Regular Expression Functions (Perl-Compatible)                    
    1545                 :      */                                                                              
    1546                 :     function grepStyle($elmPattern, $proPattern = null)                              
    1547                 :     {                                                                                
    1548               2 :         if (!is_string($elmPattern)) {                                               
    1549               1 :             return $this->raiseError(                                                
    1550               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1551               1 :                 array('var' => '$elmPattern',                                        
    1552               1 :                       'was' => gettype($elmPattern),                                 
    1553               1 :                       'expected' => 'string',                                        
    1554               1 :                       'paramnum' => 1)                                               
    1555               1 :             );                                                                       
    1556                 :                                                                                      
    1557               2 :         } elseif (isset($proPattern) && !is_string($proPattern)) {                   
    1558               1 :             return $this->raiseError(                                                
    1559               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1560               1 :                 array('var' => '$proPattern',                                        
    1561               1 :                       'was' => gettype($proPattern),                                 
    1562               1 :                       'expected' => 'string',                                        
    1563               1 :                       'paramnum' => 2)                                               
    1564               1 :             );                                                                       
    1565                 :         }                                                                            
    1566                 :                                                                                      
    1567               1 :         $styles = array();                                                           
    1568                 :                                                                                      
    1569                 :         // first, search inside alibis                                               
    1570               1 :         $alibis = array_keys($this->_alibis);                                        
    1571               1 :         $alibis = preg_grep($elmPattern, $alibis);                                   
    1572               1 :         foreach ($alibis as $a) {                                                    
    1573               1 :             foreach ($this->_alibis[$a] as $g) {                                     
    1574               1 :                 if (isset($proPattern)) {                                            
    1575               1 :                     $properties = array_keys($this->_css[$g]);                       
    1576               1 :                     $properties = preg_grep($proPattern, $properties);               
    1577               1 :                     if (count($properties) == 0) {                                   
    1578                 :                         // this group does not have a such property pattern          
    1579               1 :                         continue;                                                    
    1580                 :                     }                                                                
    1581               0 :                 }                                                                    
    1582               1 :                 if (isset($styles[$a])) {                                            
    1583               0 :                     $styles[$a] = array_merge($styles[$a], $this->_css[$g]);         
    1584               0 :                 } else {                                                             
    1585               1 :                     $styles[$a] = $this->_css[$g];                                   
    1586                 :                 }                                                                    
    1587               1 :             }                                                                        
    1588               1 :         }                                                                            
    1589                 :                                                                                      
    1590                 :         // second, search inside elements                                            
    1591               1 :         $elements = array_keys($this->_css);                                         
    1592               1 :         $elements = preg_grep($elmPattern, $elements);                               
    1593               1 :         foreach ($elements as $e) {                                                  
    1594               1 :             if (substr($e, 0, 1) == '@' ) {                                          
    1595                 :                 // excludes groups (already found with alibis)                       
    1596               1 :                 continue;                                                            
    1597                 :             }                                                                        
    1598               1 :             if (isset($proPattern)) {                                                
    1599               1 :                 $properties = array_keys($this->_css[$e]);                           
    1600               1 :                 $properties = preg_grep($proPattern, $properties);                   
    1601               1 :                 if (count($properties) == 0) {                                       
    1602                 :                     // this element does not have a such property pattern            
    1603               1 :                     continue;                                                        
    1604                 :                 }                                                                    
    1605               1 :             }                                                                        
    1606               1 :             if (isset($styles[$e])) {                                                
    1607               1 :                 $styles[$e] = array_merge($styles[$e], $this->_css[$e]);             
    1608               1 :             } else {                                                                 
    1609               1 :                 $styles[$e] = $this->_css[$e];                                       
    1610                 :             }                                                                        
    1611               1 :         }                                                                            
    1612               1 :         return $styles;                                                              
    1613                 :     }                                                                                
    1614                 :                                                                                      
    1615                 :     /**                                                                              
    1616                 :      * Apply same styles on two selectors                                            
    1617                 :      *                                                                               
    1618                 :      * Set or change the properties of new selectors                                 
    1619                 :      * to the values of an existing selector                                         
    1620                 :      *                                                                               
    1621                 :      * @param string $new New selector(s) that should share the same                 
    1622                 :      *                    definitions, separated by commas                           
    1623                 :      * @param string $old Selector that is already defined                           
    1624                 :      *                                                                               
    1625                 :      * @return     void|PEAR_Error                                                   
    1626                 :      * @since      version 0.2.0 (2003-07-31)                                        
    1627                 :      * @access     public                                                            
    1628                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_NO_ELEMENT           
    1629                 :      */                                                                              
    1630                 :     function setSameStyle($new, $old)                                                
    1631                 :     {                                                                                
    1632               4 :         if (!is_string($new)) {                                                      
    1633               1 :             return $this->raiseError(                                                
    1634               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1635               1 :                 array('var' => '$new',                                               
    1636               1 :                       'was' => gettype($new),                                        
    1637               1 :                       'expected' => 'string',                                        
    1638               1 :                       'paramnum' => 1)                                               
    1639               1 :             );                                                                       
    1640                 :                                                                                      
    1641               4 :         } elseif (!is_string($old)) {                                                
    1642               1 :             return $this->raiseError(                                                
    1643               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1644               1 :                 array('var' => '$old',                                               
    1645               1 :                       'was' => gettype($old),                                        
    1646               1 :                       'expected' => 'string',                                        
    1647               1 :                       'paramnum' => 2)                                               
    1648               1 :             );                                                                       
    1649                 :                                                                                      
    1650               4 :         } elseif (strpos($new, ',')) {                                               
    1651                 :             // Check if there are any groups.                                        
    1652               1 :             return $this->raiseError(                                                
    1653               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
    1654               1 :                 array('var' => '$new',                                               
    1655               1 :                       'was' => $new,                                                 
    1656               1 :                       'expected' => 'string without comma',                          
    1657               1 :                       'paramnum' => 1)                                               
    1658               1 :             );                                                                       
    1659                 :                                                                                      
    1660               3 :         } elseif (strpos($old, ',')) {                                               
    1661                 :             // Check if there are any groups.                                        
    1662               0 :             return $this->raiseError(                                                
    1663               0 :                 HTML_CSS_ERROR_INVALID_INPUT, 'error',                               
    1664               0 :                 array('var' => '$old',                                               
    1665               0 :                       'was' => $old,                                                 
    1666               0 :                       'expected' => 'string without comma',                          
    1667               0 :                       'paramnum' => 2)                                               
    1668               0 :             );                                                                       
    1669                 :         }                                                                            
    1670                 :                                                                                      
    1671               3 :         $old = $this->parseSelectors($old);                                          
    1672               3 :         if (!isset($this->_css[$old])) {                                             
    1673               1 :             return $this->raiseError(                                                
    1674               1 :                 HTML_CSS_ERROR_NO_ELEMENT, 'error',                                  
    1675               1 :                 array('identifier' => $old)                                          
    1676               1 :             );                                                                       
    1677                 :         }                                                                            
    1678                 :                                                                                      
    1679               2 :         $selector = implode(', ', array($old, $new));                                
    1680               2 :         $grp      = $this->createGroup($selector, 'samestyleas_'.$old);              
    1681                 :                                                                                      
    1682               2 :         $others = $this->parseSelectors($new, 1);                                    
    1683               2 :         foreach ($others as $other) {                                                
    1684               2 :             $other = trim($other);                                                   
    1685               2 :             foreach ($this->_css[$old] as $rank => $property) {                      
    1686               2 :                 if (!is_numeric($rank)) {                                            
    1687               2 :                     $property = array($rank => $property);                           
    1688               2 :                 }                                                                    
    1689               2 :                 foreach ($property as $key => $value) {                              
    1690               2 :                     $this->setGroupStyle($grp, $key, $value);                        
    1691               2 :                 }                                                                    
    1692               2 :             }                                                                        
    1693               2 :             unset($this->_css[$old]);                                                
    1694               2 :         }                                                                            
    1695               2 :     }                                                                                
    1696                 :                                                                                      
    1697                 :     /**                                                                              
    1698                 :      * Set cache flag                                                                
    1699                 :      *                                                                               
    1700                 :      * Define if the document should be cached by the browser. Default to false.     
    1701                 :      *                                                                               
    1702                 :      * @param bool $cache (optional) flag to true to cache result, false otherwise   
    1703                 :      *                                                                               
    1704                 :      * @return     void|PEAR_Error                                                   
    1705                 :      * @since      version 0.2.0 (2003-07-31)                                        
    1706                 :      * @access     public                                                            
    1707                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT                                      
    1708                 :      */                                                                              
    1709                 :     function setCache($cache = true)                                                 
    1710                 :     {                                                                                
    1711               2 :         if (!is_bool($cache)) {                                                      
    1712               1 :             return $this->raiseError(                                                
    1713               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1714               1 :                 array('var' => '$cache',                                             
    1715               1 :                       'was' => gettype($cache),                                      
    1716               1 :                       'expected' => 'boolean',                                       
    1717               1 :                       'paramnum' => 1)                                               
    1718               1 :             );                                                                       
    1719                 :         }                                                                            
    1720               1 :         $this->options['cache'] = $cache;                                            
    1721               1 :     }                                                                                
    1722                 :                                                                                      
    1723                 :     /**                                                                              
    1724                 :      * Returns the cache option value                                                
    1725                 :      *                                                                               
    1726                 :      * @return     boolean                                                           
    1727                 :      * @since      version 1.4.0 (2007-12-13)                                        
    1728                 :      * @access     public                                                            
    1729                 :      * @see        setCache()                                                        
    1730                 :      */                                                                              
    1731                 :     function getCache()                                                              
    1732                 :     {                                                                                
    1733               1 :         return $this->__get('cache');                                                
    1734                 :     }                                                                                
    1735                 :                                                                                      
    1736                 :     /**                                                                              
    1737                 :      * Set Content-Disposition header                                                
    1738                 :      *                                                                               
    1739                 :      * Define the Content-Disposition header to supply a recommended filename        
    1740                 :      * and force the browser to display the save dialog.                             
    1741                 :      * Default to basename($_SERVER['PHP_SELF']).'.css'                              
    1742                 :      *                                                                               
    1743                 :      * @param bool   $enable   (optional)                                            
    1744                 :      * @param string $filename (optional)                                            
    1745                 :      *                                                                               
    1746                 :      * @return     void|PEAR_Error                                                   
    1747                 :      * @since      version 1.3.0 (2007-10-22)                                        
    1748                 :      * @access     public                                                            
    1749                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT                                      
    1750                 :      * @see        getContentDisposition()                                           
    1751                 :      * @link       http://pear.php.net/bugs/bug.php?id=12195                         
    1752                 :      *             Patch by Carsten Wiedmann                                         
    1753                 :      */                                                                              
    1754                 :     function setContentDisposition($enable = true, $filename = '')                   
    1755                 :     {                                                                                
    1756               2 :         if (!is_bool($enable)) {                                                     
    1757               1 :             return $this->raiseError(                                                
    1758               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1759               1 :                 array('var' => '$enable',                                            
    1760               1 :                       'was' => gettype($enable),                                     
    1761               1 :                       'expected' => 'bool',                                          
    1762               1 :                       'paramnum' => 1)                                               
    1763               1 :             );                                                                       
    1764               2 :         } elseif (!is_string($filename)) {                                           
    1765               1 :             return $this->raiseError(                                                
    1766               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1767               1 :                 array('var' => '$filename',                                          
    1768               1 :                       'was' => gettype($filename),                                   
    1769               1 :                       'expected' => 'string',                                        
    1770               1 :                       'paramnum' => 2)                                               
    1771               1 :             );                                                                       
    1772                 :         }                                                                            
    1773                 :                                                                                      
    1774               1 :         if ($enable == false) {                                                      
    1775               0 :             $filename = false;                                                       
    1776               1 :         } elseif ($filename == '') {                                                 
    1777               0 :             $filename = basename($_SERVER['PHP_SELF']) . '.css';                     
    1778               0 :         }                                                                            
    1779                 :                                                                                      
    1780               1 :         $this->options['contentDisposition'] = $filename;                            
    1781               1 :     }                                                                                
    1782                 :                                                                                      
    1783                 :     /**                                                                              
    1784                 :      * Return the Content-Disposition header                                         
    1785                 :      *                                                                               
    1786                 :      * Get value of Content-Disposition header (inline filename) used                
    1787                 :      * to display results                                                            
    1788                 :      *                                                                               
    1789                 :      * @return     mixed     boolean FALSE if no content disposition, otherwise      
    1790                 :      *                       string for inline filename                              
    1791                 :      * @since      version 1.3.0 (2007-10-22)                                        
    1792                 :      * @access     public                                                            
    1793                 :      * @see        setContentDisposition()                                           
    1794                 :      * @link       http://pear.php.net/bugs/bug.php?id=12195                         
    1795                 :      *             Patch by Carsten Wiedmann                                         
    1796                 :      */                                                                              
    1797                 :     function getContentDisposition()                                                 
    1798                 :     {                                                                                
    1799               1 :         return $this->__get('contentDisposition');                                   
    1800                 :     }                                                                                
    1801                 :                                                                                      
    1802                 :     /**                                                                              
    1803                 :      * Set charset value                                                             
    1804                 :      *                                                                               
    1805                 :      * Define the charset for the file. Default to ISO-8859-1 because of CSS1        
    1806                 :      * compatability issue for older browsers.                                       
    1807                 :      *                                                                               
    1808                 :      * @param string $type (optional) Charset encoding; defaults to ISO-8859-1.      
    1809                 :      *                                                                               
    1810                 :      * @return     void|PEAR_Error                                                   
    1811                 :      * @since      version 0.2.0 (2003-07-31)                                        
    1812                 :      * @access     public                                                            
    1813                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT                                      
    1814                 :      * @see        getCharset()                                                      
    1815                 :      */                                                                              
    1816                 :     function setCharset($type = 'iso-8859-1')                                        
    1817                 :     {                                                                                
    1818               2 :         if (!is_string($type)) {                                                     
    1819               1 :             return $this->raiseError(                                                
    1820               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1821               1 :                 array('var' => '$type',                                              
    1822               1 :                       'was' => gettype($type),                                       
    1823               1 :                       'expected' => 'string',                                        
    1824               1 :                       'paramnum' => 1)                                               
    1825               1 :             );                                                                       
    1826                 :         }                                                                            
    1827               1 :         $this->options['charset'] = $type;                                           
    1828               1 :     }                                                                                
    1829                 :                                                                                      
    1830                 :     /**                                                                              
    1831                 :      * Return the charset encoding string                                            
    1832                 :      *                                                                               
    1833                 :      * By default, HTML_CSS uses iso-8859-1 encoding.                                
    1834                 :      *                                                                               
    1835                 :      * @return     string                                                            
    1836                 :      * @since      version 0.2.0 (2003-07-31)                                        
    1837                 :      * @access     public                                                            
    1838                 :      * @see        setCharset()                                                      
    1839                 :      */                                                                              
    1840                 :     function getCharset()                                                            
    1841                 :     {                                                                                
    1842               1 :         return $this->__get('charset');                                              
    1843                 :     }                                                                                
    1844                 :                                                                                      
    1845                 :     /**                                                                              
    1846                 :      * Parse a string                                                                
    1847                 :      *                                                                               
    1848                 :      * Parse a string that contains CSS information                                  
    1849                 :      *                                                                               
    1850                 :      * @param string $str        text string to parse                                
    1851                 :      * @param bool   $duplicates (optional) Allows or disallows                      
    1852                 :      *                           duplicate style definitions                         
    1853                 :      *                                                                               
    1854                 :      * @return     void|PEAR_Error                                                   
    1855                 :      * @since      version 0.3.0 (2003-11-03)                                        
    1856                 :      * @access     public                                                            
    1857                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT                                      
    1858                 :      * @see        createGroup(), setGroupStyle(), setStyle()                        
    1859                 :      */                                                                              
    1860                 :     function parseString($str, $duplicates = null)                                   
    1861                 :     {                                                                                
    1862              23 :         if (!is_string($str)) {                                                      
    1863               1 :             return $this->raiseError(                                                
    1864               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1865               1 :                 array('var' => '$str',                                               
    1866               1 :                       'was' => gettype($str),                                        
    1867               1 :                       'expected' => 'string',                                        
    1868               1 :                       'paramnum' => 1)                                               
    1869               1 :             );                                                                       
    1870                 :                                                                                      
    1871              23 :         } elseif (isset($duplicates) && !is_bool($duplicates)) {                     
    1872               1 :             return $this->raiseError(                                                
    1873               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    1874               1 :                 array('var' => '$duplicates',                                        
    1875               1 :                       'was' => gettype($duplicates),                                 
    1876               1 :                       'expected' => 'bool',                                          
    1877               1 :                       'paramnum' => 2)                                               
    1878               1 :             );                                                                       
    1879                 :         }                                                                            
    1880                 :                                                                                      
    1881              23 :         if (!isset($duplicates)) {                                                   
    1882              14 :             $duplicates = $this->__get('allowduplicates');                           
    1883              14 :         }                                                                            
    1884                 :                                                                                      
    1885                 :         // Remove comments                                                           
    1886              23 :         $str = preg_replace("/\/\*(.*)?\*\//Usi", '', $str);                         
    1887                 :                                                                                      
    1888                 :         // Protect parser vs IE hack                                                 
    1889              23 :         $str = str_replace('"\"}\""', '#34#125#34', $str);                           
    1890                 :                                                                                      
    1891                 :         // Parse simple declarative At-Rules                                         
    1892              23 :         $atRules    = array();                                                       
    1893              23 :         $elements   = array();                                                       
    1894              23 :         $properties = array();                                                       
    1895                 :                                                                                      
    1896                 :         // core of major 1.5.4 parser                                                
    1897              23 :         preg_match_all(                                                              
    1898              23 :             '/(?ims)([a-z0-9\s\.\:#_\-@,]+)\{([^\{|^\}]*)\}/',                       
    1899              23 :             $str, $rules, PREG_SET_ORDER                                             
    1900              23 :         );                                                                           
    1901                 :                                                                                      
    1902                 :         // structure simplified                                                      
    1903              23 :         $structure = preg_replace(                                                   
    1904              23 :             '/(?ims)([a-zA-Z0-9\s\.\:#_\-@,]+)\{([^\{|^\}]*)\}/',                    
    1905              23 :             '\1{}', $str                                                             
    1906              23 :         );                                                                           
    1907                 :         // structure map                                                             
    1908              23 :         $structure = preg_split(                                                     
    1909              23 :             '/([a-zA-Z0-9\s\.\:#_\-@,]+)\{(.*)\}/', $structure, -1,                  
    1910              23 :             PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY                           
    1911              23 :         );                                                                           
    1912                 :                                                                                      
    1913              23 :         $atRulesMap = array();                                                       
    1914              23 :         $atRule = '';                                                                
    1915              23 :         foreach ($structure as $struct) {                                            
    1916              23 :             $struct = trim($struct);                                                 
    1917              23 :             if (empty($struct)) {                                                    
    1918               9 :                 continue;                                                            
    1919                 :             }                                                                        
    1920              23 :             if ($struct{0} == '}') {                                                 
    1921               6 :                 $atRule = '';                                                        
    1922               6 :                 $struct = substr($struct, 1);                                        
    1923               6 :                 $struct = ltrim($struct);                                            
    1924               6 :             }                                                                        
    1925                 :                                                                                      
    1926              23 :             if ($this->options['xhtml']) {                                           
    1927              19 :                 $struct = strtolower($struct);                                       
    1928              19 :             }                                                                        
    1929                 :                                                                                      
    1930                 :                                                                                      
    1931              23 :             $has_AtRules = preg_match_all(                                           
    1932              23 :                 '/^(@[a-zA-Z\-]+)\s+(.+);\s*$/m', $struct, $atRules,                 
    1933                 :                 PREG_SET_ORDER                                                       
    1934              23 :             );                                                                       
    1935              23 :             if ($has_AtRules) {                                                      
    1936               2 :                 foreach ($atRules as $value) {                                       
    1937               2 :                     $this->createAtRule(                                             
    1938               2 :                         trim($value[1]), trim($value[2]), $duplicates                
    1939               2 :                     );                                                               
    1940               2 :                 }                                                                    
    1941               2 :                 continue;                                                            
    1942                 :             }                                                                        
    1943              22 :             $struct = $this->collapseInternalSpaces($struct);                        
    1944                 :                                                                                      
    1945              22 :             $pos = strpos($struct, '{');                                             
    1946                 :             if ($pos                                                                 
    1947              22 :                 || (strpos($struct, ':') && !empty($atRule))                         
    1948              22 :             ) {                                                                      
    1949               9 :                 $cc = count_chars($struct, 1);                                       
    1950               9 :                 if ((isset($cc[64]) && $cc[64] > 1)                                  
    1951               8 :                     || (isset($cc[58]) && $cc[58] == 1)                              
    1952               9 :                 ) {                                                                  
    1953               3 :                     $context  = debug_backtrace();                                   
    1954               3 :                     $context  = @array_pop($context);                                
    1955               3 :                     $function = strtolower($context['function']);                    
    1956               3 :                     if ($function === 'parsestring') {                               
    1957               0 :                         $var = 'str';                                                
    1958               3 :                     } elseif ($function === 'parsefile') {                           
    1959               0 :                         $var = 'filename';                                           
    1960               0 :                     } else {                                                         
    1961               3 :                         $var = 'styles';                                             
    1962                 :                     }                                                                
    1963                 :                                                                                      
    1964               3 :                     return $this->raiseError(                                        
    1965               3 :                         HTML_CSS_ERROR_INVALID_INPUT, 'error',                       
    1966               3 :                         array('var' => '$'.$var,                                     
    1967               3 :                               'was' => 'invalid data source',                        
    1968               3 :                               'expected' => 'valid CSS structure',                   
    1969               3 :                               'paramnum' => 1)                                       
    1970               3 :                     );                                                               
    1971                 :                 }                                                                    
    1972               8 :                 $atRule = rtrim(substr($struct, 0, $pos));                           
    1973                 :                                                                                      
    1974               8 :             } else {                                                                 
    1975              20 :                 $atRulesMap[$struct][] = $atRule;                                    
    1976                 :             }                                                                        
    1977              22 :         }                                                                            
    1978                 :                                                                                      
    1979              20 :         foreach ($rules as $rule) {                                                  
    1980                 :                                                                                      
    1981                 :             // prevent invalid css data structure                                    
    1982              19 :             $pos = strpos($rule[0], '{');                                            
    1983              19 :             $sel = trim($rule[1]);                                                   
    1984              19 :             if ((strpos($rule[0], '{', $pos+1) !== false)                            
    1985              19 :                 || (substr($sel, -1, 1) == ':')                                      
    1986              19 :             ) {                                                                      
    1987               0 :                 $context  = debug_backtrace();                                       
    1988               0 :                 $context  = @array_pop($context);                                    
    1989               0 :                 $function = strtolower($context['function']);                        
    1990               0 :                 if ($function === 'parsestring') {                                   
    1991               0 :                     $var = 'str';                                                    
    1992               0 :                 } elseif ($function === 'parsefile') {                               
    1993               0 :                     $var = 'filename';                                               
    1994               0 :                 } else {                                                             
    1995               0 :                     $var = 'styles';                                                 
    1996                 :                 }                                                                    
    1997                 :                                                                                      
    1998               0 :                 return $this->raiseError(                                            
    1999               0 :                     HTML_CSS_ERROR_INVALID_INPUT, 'error',                           
    2000               0 :                     array('var' => '$'.$var,                                         
    2001               0 :                           'was' => 'invalid data source',                            
    2002               0 :                           'expected' => 'valid CSS structure',                       
    2003               0 :                           'paramnum' => 1)                                           
    2004               0 :                 );                                                                   
    2005                 :             }                                                                        
    2006                 :                                                                                      
    2007              19 :             if ($this->options['xhtml']) {                                           
    2008              15 :                 $rule[1] = strtolower($rule[1]);                                     
    2009              15 :             }                                                                        
    2010                 :                                                                                      
    2011              19 :             $elements[]   = trim($rule[1]);                                          
    2012              19 :             $properties[] = trim($rule[2]);                                          
    2013              20 :         }                                                                            
    2014                 :                                                                                      
    2015              20 :         foreach ($elements as $i => $keystr) {                                       
    2016                 :                                                                                      
    2017              19 :             $key_a   = $this->parseSelectors($keystr, 1);                            
    2018              19 :             $keystr  = implode(', ', $key_a);                                        
    2019              19 :             $codestr = $properties[$i];                                              
    2020                 :                                                                                      
    2021              19 :             $key = trim($keystr);                                                    
    2022              19 :             $parentAtRule = isset($atRulesMap[$key][$i])                             
    2023              19 :                 ? $atRulesMap[$key][$i] : $atRulesMap[$key][0];                      
    2024                 :                                                                                      
    2025                 :             // Check if there are any groups; in standard selectors exclude at-rules 
    2026              19 :             if (strpos($keystr, ',') && (empty($parentAtRule))) {                    
    2027               6 :                 $group = $this->createGroup($keystr);                                
    2028                 :                                                                                      
    2029                 :                 // Parse each property of an element                                 
    2030               6 :                 $codes = explode(";", trim($codestr));                               
    2031               6 :                 foreach ($codes as $code) {                                          
    2032               6 :                     if (strlen(trim($code)) > 0) {                                   
    2033                 :                         // find the property and the value                           
    2034                 :                         $property                                                    
    2035               6 :                             = trim(substr($code, 0, strpos($code, ':', 0)));         
    2036                 :                         $value                                                       
    2037               6 :                             = trim(substr($code, strpos($code, ':', 0) + 1));        
    2038                 :                         // IE hack only                                              
    2039               6 :                         if (strcasecmp($property, 'voice-family') == 0) {            
    2040                 :                             $value                                                   
    2041               0 :                                 = str_replace('#34#125#34', '"\"}\""', $value);      
    2042               0 :                         }                                                            
    2043               6 :                         $this->setGroupStyle(                                        
    2044               6 :                             $group, $property, $value, $duplicates                   
    2045               6 :                         );                                                           
    2046               6 :                     }                                                                
    2047               6 :                 }                                                                    
    2048               6 :             } else {                                                                 
    2049                 :                 // Parse each property of an element                                 
    2050              17 :                 $codes = explode(";", trim($codestr));                               
    2051              17 :                 foreach ($codes as $code) {                                          
    2052              17 :                     if (strlen(trim($code)) == 0) {                                  
    2053              13 :                         continue;                                                    
    2054                 :                     }                                                                
    2055              17 :                     $code = ltrim($code, "\r\n}");                                   
    2056                 :                                                                                      
    2057              17 :                     $p = trim(substr($code, 0, strpos($code, ':')));                 
    2058              17 :                     $v = trim(substr($code, strpos($code, ':') + 1));                
    2059                 :                     // IE hack only                                                  
    2060              17 :                     if (strcasecmp($p, 'voice-family') == 0) {                       
    2061               1 :                         $v = str_replace('#34#125#34', '"\"}\""', $v);               
    2062               1 :                     }                                                                
    2063                 :                                                                                      
    2064              17 :                     if (!empty($parentAtRule)) {                                     
    2065                 :                         // at-rules                                                  
    2066               6 :                         $atkw_args = preg_split(                                     
    2067               6 :                             '/(@[a-zA-Z\-]+)\s+(.+)/', $parentAtRule, -1,            
    2068               6 :                             PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY           
    2069               6 :                         );                                                           
    2070               6 :                         if (count($atkw_args) == 1) {                                
    2071                 :                             // special case of @font-face (without argument)         
    2072               0 :                             $atkw_args[] = '';                                       
    2073               0 :                         }                                                            
    2074               6 :                         list($atKeyword, $arguments) = $atkw_args;                   
    2075               6 :                         $this->setAtRuleStyle(                                       
    2076               6 :                             $atKeyword, $arguments, $keystr, $p, $v, $duplicates     
    2077               6 :                         );                                                           
    2078                 :                                                                                      
    2079              17 :                     } elseif ($key{0} == '@') {                                      
    2080               2 :                         $atkw_args = preg_split(                                     
    2081               2 :                             '/(@[a-zA-Z\-]+)\s+(.+)/', $key, -1,                     
    2082               2 :                             PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY           
    2083               2 :                         );                                                           
    2084               2 :                         if (count($atkw_args) == 1) {                                
    2085               1 :                             $atkw_args[] = '';                                       
    2086               1 :                         }                                                            
    2087               2 :                         list($atKeyword, $arguments) = $atkw_args;                   
    2088               2 :                         $this->setAtRuleStyle(                                       
    2089               2 :                             $atKeyword, $arguments, '', $p, $v, $duplicates          
    2090               2 :                         );                                                           
    2091               2 :                     } else {                                                         
    2092                 :                         // simple declarative style                                  
    2093              12 :                         $this->setStyle($key, $p, $v, $duplicates);                  
    2094                 :                     }                                                                
    2095              17 :                 }                                                                    
    2096                 :             }                                                                        
    2097              20 :         }                                                                            
    2098              20 :     }                                                                                
    2099                 :                                                                                      
    2100                 :     /**                                                                              
    2101                 :      * Parse file content                                                            
    2102                 :      *                                                                               
    2103                 :      * Parse a file that contains CSS information                                    
    2104                 :      *                                                                               
    2105                 :      * @param string $filename   file to parse                                       
    2106                 :      * @param bool   $duplicates (optional) Allow or disallow duplicates.            
    2107                 :      *                                                                               
    2108                 :      * @return     void|PEAR_Error                                                   
    2109                 :      * @since      version 0.3.0 (2003-11-03)                                        
    2110                 :      * @access     public                                                            
    2111                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_NO_FILE              
    2112                 :      * @see        parseString()                                                     
    2113                 :      */                                                                              
    2114                 :     function parseFile($filename, $duplicates = null)                                
    2115                 :     {                                                                                
    2116               3 :         if (!is_string($filename)) {                                                 
    2117               1 :             return $this->raiseError(                                                
    2118               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    2119               1 :                 array('var' => '$filename',                                          
    2120               1 :                       'was' => gettype($filename),                                   
    2121               1 :                       'expected' => 'string',                                        
    2122               1 :                       'paramnum' => 1)                                               
    2123               1 :             );                                                                       
    2124                 :                                                                                      
    2125               3 :         } elseif (!file_exists($filename)) {                                         
    2126               1 :             return $this->raiseError(                                                
    2127               1 :                 HTML_CSS_ERROR_NO_FILE, 'error',                                     
    2128               1 :                 array('identifier' => $filename)                                     
    2129               1 :             );                                                                       
    2130                 :                                                                                      
    2131               3 :         } elseif (isset($duplicates) && !is_bool($duplicates)) {                     
    2132               1 :             return $this->raiseError(                                                
    2133               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    2134               1 :                 array('var' => '$duplicates',                                        
    2135               1 :                       'was' => gettype($duplicates),                                 
    2136               1 :                       'expected' => 'bool',                                          
    2137               1 :                       'paramnum' => 2)                                               
    2138               1 :             );                                                                       
    2139                 :         }                                                                            
    2140                 :                                                                                      
    2141               2 :         if (!isset($duplicates)) {                                                   
    2142               1 :             $duplicates = $this->__get('allowduplicates');                           
    2143               1 :         }                                                                            
    2144                 :                                                                                      
    2145               2 :         $ret = $this->parseString(file_get_contents($filename), $duplicates);        
    2146               2 :         return $ret;                                                                 
    2147                 :     }                                                                                
    2148                 :                                                                                      
    2149                 :     /**                                                                              
    2150                 :      * Parse multiple data sources                                                   
    2151                 :      *                                                                               
    2152                 :      * Parse data sources, file(s) or string(s), that contains CSS information       
    2153                 :      *                                                                               
    2154                 :      * @param array $styles     data sources to parse                                
    2155                 :      * @param bool  $duplicates (optional) Allow or disallow duplicates.             
    2156                 :      *                                                                               
    2157                 :      * @return     void|PEAR_Error                                                   
    2158                 :      * @since      version 1.0.0RC2 (2005-12-15)                                     
    2159                 :      * @access     public                                                            
    2160                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT                                      
    2161                 :      * @see        parseString(), parseFile()                                        
    2162                 :      */                                                                              
    2163                 :     function parseData($styles, $duplicates = null)                                  
    2164                 :     {                                                                                
    2165               2 :         if (!is_array($styles)) {                                                    
    2166               1 :             return $this->raiseError(                                                
    2167               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    2168               1 :                 array('var' => '$styles',                                            
    2169               1 :                       'was' => gettype($styles),                                     
    2170               1 :                       'expected' => 'array',                                         
    2171               1 :                       'paramnum' => 1)                                               
    2172               1 :             );                                                                       
    2173                 :                                                                                      
    2174               2 :         } elseif (isset($duplicates) && !is_bool($duplicates)) {                     
    2175               1 :             return $this->raiseError(                                                
    2176               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    2177               1 :                 array('var' => '$duplicates',                                        
    2178               1 :                       'was' => gettype($duplicates),                                 
    2179               1 :                       'expected' => 'bool',                                          
    2180               1 :                       'paramnum' => 2)                                               
    2181               1 :             );                                                                       
    2182                 :         }                                                                            
    2183                 :                                                                                      
    2184               2 :         if (!isset($duplicates)) {                                                   
    2185               2 :             $duplicates = $this->__get('allowduplicates');                           
    2186               2 :         }                                                                            
    2187                 :                                                                                      
    2188               2 :         foreach ($styles as $i => $style) {                                          
    2189               2 :             if (!is_string($style)) {                                                
    2190               1 :                 return $this->raiseError(                                            
    2191               1 :                     HTML_CSS_ERROR_INVALID_INPUT, 'exception',                       
    2192               1 :                     array('var' => '$styles[' . $i . ']',                            
    2193               1 :                           'was' => gettype($styles[$i]),                             
    2194               1 :                           'expected' => 'string',                                    
    2195               1 :                           'paramnum' => 1)                                           
    2196               1 :                 );                                                                   
    2197                 :             }                                                                        
    2198               2 :             if (strcasecmp(substr($style, -4, 4), '.css') == 0) {                    
    2199               1 :                 $this->parseFile($style, $duplicates);                               
    2200               1 :             } else {                                                                 
    2201               2 :                 $this->parseString($style, $duplicates);                             
    2202                 :             }                                                                        
    2203               2 :         }                                                                            
    2204               1 :     }                                                                                
    2205                 :                                                                                      
    2206                 :     /**                                                                              
    2207                 :      * Validate a CSS data source                                                    
    2208                 :      *                                                                               
    2209                 :      * Execute the W3C CSS validator service on each data source (filename           
    2210                 :      * or string) given by parameter $styles.                                        
    2211                 :      *                                                                               
    2212                 :      * @param array $styles    Data sources to check validity                        
    2213                 :      * @param array &$messages Error and Warning messages                            
    2214                 :      *                         issue from W3C CSS validator service                  
    2215                 :      *                                                                               
    2216                 :      * @return     boolean|PEAR_Error                                                
    2217                 :      * @since      version 1.5.0 (2008-01-15)                                        
    2218                 :      * @access     public                                                            
    2219                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT,                                     
    2220                 :      *             HTML_CSS_ERROR_INVALID_DEPS, HTML_CSS_ERROR_INVALID_SOURCE        
    2221                 :      */                                                                              
    2222                 :     function validate($styles, &$messages)                                           
    2223                 :     {                                                                                
    2224               0 :         $php = phpversion();                                                         
    2225               0 :         if (version_compare($php, '5.0.0', '<')) {                                   
    2226               0 :             return $this->raiseError(                                                
    2227               0 :                 HTML_CSS_ERROR_INVALID_DEPS, 'exception',                            
    2228               0 :                 array('funcname' => __FUNCTION__,                                    
    2229               0 :                       'dependency' => 'PHP 5',                                       
    2230               0 :                       'currentdep' => "PHP $php")                                    
    2231               0 :             );                                                                       
    2232                 :         }                                                                            
    2233               0 :         @include_once 'Services/W3C/CSSValidator.php';                               
    2234               0 :         if (class_exists('Services_W3C_CSSValidator', false) === false) {            
    2235               0 :             return $this->raiseError(                                                
    2236               0 :                 HTML_CSS_ERROR_INVALID_DEPS, 'exception',                            
    2237               0 :                 array('funcname' => __FUNCTION__,                                    
    2238               0 :                       'dependency' => 'PEAR::Services_W3C_CSSValidator',             
    2239               0 :                       'currentdep' => 'nothing')                                     
    2240               0 :             );                                                                       
    2241                 :         }                                                                            
    2242               0 :         if (!is_array($styles)) {                                                    
    2243               0 :             return $this->raiseError(                                                
    2244               0 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    2245               0 :                 array('var' => '$styles',                                            
    2246               0 :                       'was' => gettype($styles),                                     
    2247               0 :                       'expected' => 'array',                                         
    2248               0 :                       'paramnum' => 1)                                               
    2249               0 :             );                                                                       
    2250                 :                                                                                      
    2251               0 :         } elseif (!is_array($messages)) {                                            
    2252               0 :             return $this->raiseError(                                                
    2253               0 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    2254               0 :                 array('var' => '$messages',                                          
    2255               0 :                       'was' => gettype($messages),                                   
    2256               0 :                       'expected' => 'array',                                         
    2257               0 :                       'paramnum' => 2)                                               
    2258               0 :             );                                                                       
    2259                 :         }                                                                            
    2260                 :                                                                                      
    2261                 :         // prepare to call the W3C CSS validator service                             
    2262               0 :         $v        = new Services_W3C_CSSValidator();                                 
    2263               0 :         $validity = true;                                                            
    2264               0 :         $messages = array('errors' => array(), 'warnings' => array());               
    2265                 :                                                                                      
    2266               0 :         foreach ($styles as $i => $source) {                                         
    2267               0 :             if (!is_string($source)) {                                               
    2268               0 :                 return $this->raiseError(                                            
    2269               0 :                     HTML_CSS_ERROR_INVALID_INPUT, 'exception',                       
    2270               0 :                     array('var' => '$styles[' . $i . ']',                            
    2271               0 :                           'was' => gettype($styles[$i]),                             
    2272               0 :                           'expected' => 'string',                                    
    2273               0 :                           'paramnum' => 1)                                           
    2274               0 :                 );                                                                   
    2275                 :             }                                                                        
    2276               0 :             if (strcasecmp(substr($source, -4, 4), '.css') == 0) {                   
    2277                 :                 // validate a file as CSS content                                    
    2278               0 :                 $r = $v->validateFile($source);                                      
    2279               0 :             } else {                                                                 
    2280                 :                 // validate a string as CSS content                                  
    2281               0 :                 $r = $v->validateFragment($source);                                  
    2282                 :             }                                                                        
    2283               0 :             if ($r === false) {                                                      
    2284               0 :                 $validity = false;                                                   
    2285               0 :             }                                                                        
    2286               0 :             if ($r->isValid() === false) {                                           
    2287               0 :                 $validity = false;                                                   
    2288               0 :                 foreach ($r->errors as $error) {                                     
    2289               0 :                     $properties           = get_object_vars($error);                 
    2290               0 :                     $messages['errors'][] = $properties;                             
    2291               0 :                 }                                                                    
    2292               0 :                 foreach ($r->warnings as $warning) {                                 
    2293               0 :                     $properties             = get_object_vars($warning);             
    2294               0 :                     $messages['warnings'][] = $properties;                           
    2295               0 :                 }                                                                    
    2296               0 :                 $this->raiseError(                                                   
    2297               0 :                     HTML_CSS_ERROR_INVALID_SOURCE,                                   
    2298               0 :                     ((count($r->errors) == 0) ? 'warning' : 'error'),                
    2299               0 :                     array('sourcenum' => $i,                                         
    2300               0 :                           'errcount' => count($r->errors),                           
    2301               0 :                           'warncount' => count($r->warnings))                        
    2302               0 :                 );                                                                   
    2303               0 :             }                                                                        
    2304               0 :         }                                                                            
    2305               0 :         return $validity;                                                            
    2306                 :     }                                                                                
    2307                 :                                                                                      
    2308                 :     /**                                                                              
    2309                 :      * Return the CSS contents in an array                                           
    2310                 :      *                                                                               
    2311                 :      * Return the full contents of CSS data sources (parsed) in an array             
    2312                 :      *                                                                               
    2313                 :      * @return     array                                                             
    2314                 :      * @since      version 0.2.0 (2003-07-31)                                        
    2315                 :      * @access     public                                                            
    2316                 :      */                                                                              
    2317                 :     function toArray()                                                               
    2318                 :     {                                                                                
    2319              27 :         $css = array();                                                              
    2320                 :                                                                                      
    2321                 :         // bring AtRules in correct order                                            
    2322              27 :         $this->sortAtRules();                                                        
    2323                 :                                                                                      
    2324              27 :         foreach ($this->_css as $key => $value) {                                    
    2325              26 :             if (strpos($key, '@-') === 0) {                                          
    2326              10 :                 $key = implode(', ', $this->_groups[$key]);                          
    2327              10 :             }                                                                        
    2328              26 :             $css[$key] = $value;                                                     
    2329              27 :         }                                                                            
    2330              27 :         return $css;                                                                 
    2331                 :     }                                                                                
    2332                 :                                                                                      
    2333                 :     /**                                                                              
    2334                 :      * Return a string-properties for style attribute of an HTML element             
    2335                 :      *                                                                               
    2336                 :      * Generate and return the CSS properties of an element or class                 
    2337                 :      * as a string for inline use.                                                   
    2338                 :      *                                                                               
    2339                 :      * @param string $element Element or class                                       
    2340                 :      *                        for which inline CSS should be generated               
    2341                 :      *                                                                               
    2342                 :      * @return     string|PEAR_Error                                                 
    2343                 :      * @since      version 0.2.0 (2003-07-31)                                        
    2344                 :      * @access     public                                                            
    2345                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT                                      
    2346                 :      */                                                                              
    2347                 :     function toInline($element)                                                      
    2348                 :     {                                                                                
    2349               2 :         if (!is_string($element)) {                                                  
    2350               1 :             return $this->raiseError(                                                
    2351               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    2352               1 :                 array('var' => '$element',                                           
    2353               1 :                       'was' => gettype($element),                                    
    2354               1 :                       'expected' => 'string',                                        
    2355               1 :                       'paramnum' => 1)                                               
    2356               1 :             );                                                                       
    2357                 :         }                                                                            
    2358                 :                                                                                      
    2359               1 :         $strCss      = '';                                                           
    2360               1 :         $newCssArray = array();                                                      
    2361                 :                                                                                      
    2362                 :         // This allows for grouped elements definitions to work                      
    2363               1 :         if (isset($this->_alibis[$element])) {                                       
    2364               1 :             $alibis = $this->_alibis[$element];                                      
    2365                 :                                                                                      
    2366                 :             // All the groups must be run through to be able to                      
    2367                 :             // properly assign the value to the inline.                              
    2368               1 :             foreach ($alibis as $alibi) {                                            
    2369               1 :                 foreach ($this->_css[$alibi] as $key => $value) {                    
    2370               1 :                     $newCssArray[$key] = $value;                                     
    2371               1 :                 }                                                                    
    2372               1 :             }                                                                        
    2373               1 :         }                                                                            
    2374                 :                                                                                      
    2375                 :         // This allows for single elements definitions to work                       
    2376               1 :         if (isset($this->_css[$element])) {                                          
    2377               0 :             foreach ($this->_css[$element] as $rank => $property) {                  
    2378               0 :                 if (!is_numeric($rank)) {                                            
    2379               0 :                     $property = array($rank => $property);                           
    2380               0 :                 }                                                                    
    2381               0 :                 foreach ($property as $key => $value) {                              
    2382               0 :                     if ($key != 'other-elements') {                                  
    2383               0 :                         $newCssArray[$key] = $value;                                 
    2384               0 :                     }                                                                
    2385               0 :                 }                                                                    
    2386               0 :             }                                                                        
    2387               0 :         }                                                                            
    2388                 :                                                                                      
    2389               1 :         foreach ($newCssArray as $key => $value) {                                   
    2390               1 :             if ((0 === strpos($element, '@')) && ('' == $value)) {                   
    2391                 :                 // simple declarative At-Rule definition                             
    2392               0 :                 $strCss .= $key . ';';                                               
    2393               0 :             } else {                                                                 
    2394                 :                 // other CSS definition                                              
    2395               1 :                 $strCss .= $key . ':' . $value . ";";                                
    2396                 :             }                                                                        
    2397               1 :         }                                                                            
    2398                 :                                                                                      
    2399               1 :         return $strCss;                                                              
    2400                 :     }                                                                                
    2401                 :                                                                                      
    2402                 :     /**                                                                              
    2403                 :      * Generate CSS and stores it in a file                                          
    2404                 :      *                                                                               
    2405                 :      * Generate current parsed CSS data sources and write result in a user file      
    2406                 :      *                                                                               
    2407                 :      * @param string $filename Name of file that content the stylesheet              
    2408                 :      *                                                                               
    2409                 :      * @return     void|PEAR_Error                                                   
    2410                 :      * @since      version 0.3.0 (2003-11-03)                                        
    2411                 :      * @access     public                                                            
    2412                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_WRITE_FILE           
    2413                 :      * @see        toString()                                                        
    2414                 :      */                                                                              
    2415                 :     function toFile($filename)                                                       
    2416                 :     {                                                                                
    2417               2 :         if (!is_string($filename)) {                                                 
    2418               1 :             return $this->raiseError(                                                
    2419               1 :                 HTML_CSS_ERROR_INVALID_INPUT, 'exception',                           
    2420               1 :                 array('var' => '$filename',                                          
    2421               1 :                       'was' => gettype($filename),                                   
    2422               1 :                       'expected' => 'string',                                        
    2423               1 :                       'paramnum' => 1)                                               
    2424               1 :             );                                                                       
    2425                 :         }                                                                            
    2426                 :                                                                                      
    2427               1 :         if (function_exists('file_put_contents')) {                                  
    2428               1 :             file_put_contents($filename, $this->toString());                         
    2429               1 :         } else {                                                                     
    2430               0 :             $file = fopen($filename, 'wb');                                          
    2431               0 :             fwrite($file, $this->toString());                                        
    2432               0 :             fclose($file);                                                           
    2433                 :         }                                                                            
    2434               1 :         if (!file_exists($filename)) {                                               
    2435               0 :             return $this->raiseError(                                                
    2436               0 :                 HTML_CSS_ERROR_WRITE_FILE, 'error',                                  
    2437               0 :                 array('filename' => $filename)                                       
    2438               0 :             );                                                                       
    2439                 :         }                                                                            
    2440               1 :     }                                                                                
    2441                 :                                                                                      
    2442                 :     /**                                                                              
    2443                 :      * Return current CSS parsed data as a string                                    
    2444                 :      *                                                                               
    2445                 :      * Generate current parsed CSS data sources and return result as a string        
    2446                 :      *                                                                               
    2447                 :      * @return     string                                                            
    2448                 :      * @since      version 0.2.0 (2003-07-31)                                        
    2449                 :      * @access     public                                                            
    2450                 :      */                                                                              
    2451                 :     function toString()                                                              
    2452                 :     {                                                                                
    2453                 :         // get line endings                                                          
    2454               2 :         $lnEnd = $this->_getLineEnd();                                               
    2455               2 :         $tabs  = $this->_getTabs();                                                  
    2456               2 :         $tab   = $this->_getTab();                                                   
    2457                 :                                                                                      
    2458                 :         // initialize $alibis                                                        
    2459               2 :         $alibis = array();                                                           
    2460                 :                                                                                      
    2461               2 :         $strCss     = '';                                                            
    2462               2 :         $strAtRules = '';                                                            
    2463                 :                                                                                      
    2464                 :         // Allow a CSS comment                                                       
    2465               2 :         if ($this->_comment) {                                                       
    2466               0 :             $strCss = $tabs . '/* ' . $this->getComment() . ' */' . $lnEnd;          
    2467               0 :         }                                                                            
    2468                 :                                                                                      
    2469                 :         // If groups are to be output first, initialize a special variable           
    2470               2 :         if ($this->__get('groupsfirst')) {                                           
    2471               2 :             $strCssElements = '';                                                    
    2472               2 :         }                                                                            
    2473                 :                                                                                      
    2474                 :         // bring AtRules in correct order                                            
    2475               2 :         $this->sortAtRules();                                                        
    2476                 :                                                                                      
    2477                 :         // Iterate through the array and process each element                        
    2478               2 :         foreach ($this->_css as $identifier => $rank) {                              
    2479                 :                                                                                      
    2480                 :             // Groups are handled separately                                         
    2481               2 :             if (strpos($identifier, '@-') !== false) {                               
    2482                 :                 // its a group                                                       
    2483               2 :                 $element = implode(', ', $this->_groups[$identifier]);               
    2484               2 :             } else {                                                                 
    2485               1 :                 $element = $identifier;                                              
    2486                 :             }                                                                        
    2487                 :                                                                                      
    2488               2 :             if ((0 === strpos($element, '@')) && (1 !== strpos($element, '-'))) {    
    2489                 :                 // simple declarative At-Rule definition                             
    2490               0 :                 foreach ($rank as $arg => $decla) {                                  
    2491                 :                     // check to see if it is a duplicate                             
    2492               0 :                     if (is_numeric($arg)) {                                          
    2493               0 :                         $arg   = array_keys($decla);                                 
    2494               0 :                         $arg   = array_shift($arg);                                  
    2495               0 :                         $decla = array_values($decla);                               
    2496               0 :                         $decla = array_shift($decla);                                
    2497               0 :                     }                                                                
    2498               0 :                     if (is_array($decla)) {                                          
    2499               0 :                         $strAtRules .= $element . ' ' . $arg;                        
    2500               0 :                         foreach ($decla as $s => $d) {                               
    2501               0 :                             $t = $tabs . $tab;                                       
    2502               0 :                             if (empty($s)) {                                         
    2503               0 :                                 $strAtRules .= ' {' . $lnEnd;                        
    2504               0 :                             } else {                                                 
    2505               0 :                                 $t          .= $tab;                                 
    2506               0 :                                 $strAtRules .= ' {' . $lnEnd .                       
    2507               0 :                                     $tab . $s . ' {' . $lnEnd;                       
    2508                 :                             }                                                        
    2509               0 :                             foreach ($d as $p => $v) {                               
    2510               0 :                                 $strAtRules .= $t . $p . ': ' . $v . ';' . $lnEnd;   
    2511               0 :                             }                                                        
    2512               0 :                             if (empty($s)) {                                         
    2513               0 :                                 $strAtRules .= $tabs . '}';                          
    2514               0 :                             } else {                                                 
    2515               0 :                                 $strAtRules .=  $tabs . $tab . '}' . $lnEnd . '}';   
    2516                 :                             }                                                        
    2517               0 :                         }                                                            
    2518               0 :                         $strAtRules .=  $lnEnd . $lnEnd;;                            
    2519               0 :                     } else {                                                         
    2520               0 :                         $strAtRules .= $element . ' ' . $arg . ';' . $lnEnd . $lnEnd;
    2521                 :                     }                                                                
    2522               0 :                 }                                                                    
    2523               0 :             } else {                                                                 
    2524                 :                 // Start CSS element definition                                      
    2525               2 :                 $definition = $element . ' {' . $lnEnd;                              
    2526                 :                                                                                      
    2527                 :                 // Iterate through the array of properties                           
    2528               2 :                 foreach ($rank as $pos => $property) {                               
    2529                 :                     // check to see if it is a duplicate                             
    2530               2 :                     if (!is_numeric($pos)) {                                         
    2531               2 :                         $property = array($pos => $property);                        
    2532               2 :                         unset($pos);                                                 
    2533               2 :                     }                                                                
    2534               2 :                     foreach ($property as $key => $value) {                          
    2535                 :                         $definition .= $tabs . $tab                                  
    2536               2 :                                     . $key . ': ' . $value . ';' . $lnEnd;           
    2537               2 :                     }                                                                
    2538               2 :                 }                                                                    
    2539                 :                                                                                      
    2540                 :                 // end CSS element definition                                        
    2541               2 :                 $definition .= $tabs . '}';                                          
    2542                 :             }                                                                        
    2543                 :                                                                                      
    2544                 :             // if this is to be on a single line, collapse                           
    2545               2 :             if ($this->options['oneline']) {                                         
    2546               1 :                 $definition = $this->collapseInternalSpaces($definition);            
    2547               1 :                 $strAtRules = $this->collapseInternalSpaces($strAtRules);            
    2548               1 :             }                                                                        
    2549                 :                                                                                      
    2550                 :             // if groups are to be output first, elements must be placed in a        
    2551                 :             // different string which will be appended in the end                    
    2552               2 :             if (isset($definition)) {                                                
    2553               2 :                 if ($this->__get('groupsfirst') === true                             
    2554               2 :                     && strpos($identifier, '@-') === false                           
    2555               2 :                 ) {                                                                  
    2556                 :                     // add to elements                                               
    2557               1 :                     $strCssElements .= $lnEnd . $tabs . $definition . $lnEnd;        
    2558               1 :                 } else {                                                             
    2559                 :                     // add to strCss                                                 
    2560               2 :                     $strCss .= $lnEnd . $tabs . $definition . $lnEnd;                
    2561                 :                 }                                                                    
    2562               2 :             }                                                                        
    2563               2 :         }                                                                            
    2564                 :                                                                                      
    2565               2 :         if ($this->__get('groupsfirst')) {                                           
    2566               2 :             $strCss .= $strCssElements;                                              
    2567               2 :         }                                                                            
    2568                 :                                                                                      
    2569               2 :         $strAtRules = rtrim($strAtRules);                                            
    2570               2 :         if (!empty($strAtRules)) {                                                   
    2571               0 :             $strAtRules .= $lnEnd;                                                   
    2572               0 :         }                                                                            
    2573               2 :         $strCss = $strAtRules . $strCss;                                             
    2574                 :                                                                                      
    2575               2 :         if ($this->options['oneline']) {                                             
    2576               1 :             $strCss = preg_replace('/(\n|\r\n|\r)/', '', $strCss);                   
    2577               1 :         }                                                                            
    2578                 :                                                                                      
    2579               2 :         return $strCss;                                                              
    2580                 :     }                                                                                
    2581                 :                                                                                      
    2582                 :     /**                                                                              
    2583                 :      * Output CSS Code.                                                              
    2584                 :      *                                                                               
    2585                 :      * Send the stylesheet content to standard output, handling cacheControl         
    2586                 :      * and contentDisposition headers                                                
    2587                 :      *                                                                               
    2588                 :      * @return     void                                                              
    2589                 :      * @since      version 0.2.0 (2003-07-31)                                        
    2590                 :      * @access     public                                                            
    2591                 :      * @see        toString()                                                        
    2592                 :      */                                                                              
    2593                 :     function display()                                                               
    2594                 :     {                                                                                
    2595               1 :         if (!headers_sent()) {                                                       
    2596               0 :             if ($this->__get('cache') !== true) {                                    
    2597               0 :                 header("Expires: Tue, 1 Jan 1980 12:00:00 GMT");                     
    2598               0 :                 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");       
    2599               0 :                 header("Cache-Control: no-cache");                                   
    2600               0 :                 header("Pragma: no-cache");                                          
    2601               0 :             }                                                                        
    2602                 :                                                                                      
    2603                 :             // set character encoding                                                
    2604               0 :             header("Content-Type: text/css; charset=" . $this->__get('charset'));    
    2605                 :                                                                                      
    2606                 :             // set Content-Disposition                                               
    2607               0 :             if ($this->__get('contentDisposition') !== false) {                      
    2608               0 :                 header(                                                              
    2609                 :                     'Content-Disposition: inline; filename="' .                      
    2610               0 :                     $this->__get('contentDisposition') . '"'                         
    2611               0 :                 );                                                                   
    2612               0 :             }                                                                        
    2613               0 :         }                                                                            
    2614                 :                                                                                      
    2615               1 :         $strCss = $this->toString();                                                 
    2616               1 :         print $strCss;                                                               
    2617               1 :     }                                                                                
    2618                 :                                                                                      
    2619                 :     /**                                                                              
    2620                 :      * Initialize Error engine preferences                                           
    2621                 :      *                                                                               
    2622                 :      * @param array $prefs (optional) hash of params to customize error generation   
    2623                 :      *                                                                               
    2624                 :      * @return     void                                                              
    2625                 :      * @since      version 0.3.3 (2004-05-20)                                        
    2626                 :      * @access     private                                                           
    2627                 :      */                                                                              
    2628                 :     function _initErrorStack($prefs = array())                                       
    2629                 :     {                                                                                
    2630                 :         // error message mapping callback                                            
    2631              56 :         if (isset($prefs['message_callback'])                                        
    2632               0 :             && is_callable($prefs['message_callback'])                               
    2633              56 :         ) {                                                                          
    2634               0 :             $this->_callback_message = $prefs['message_callback'];                   
    2635               0 :         } else {                                                                     
    2636              56 :             $this->_callback_message = array('HTML_CSS_Error', '_msgCallback');      
    2637                 :         }                                                                            
    2638                 :                                                                                      
    2639                 :         // error context mapping callback                                            
    2640              56 :         if (isset($prefs['context_callback'])                                        
    2641               0 :             && is_callable($prefs['context_callback'])                               
    2642              56 :         ) {                                                                          
    2643               0 :             $this->_callback_context = $prefs['context_callback'];                   
    2644               0 :         } else {                                                                     
    2645              56 :             $this->_callback_context = array('HTML_CSS_Error', 'getBacktrace');      
    2646                 :         }                                                                            
    2647                 :                                                                                      
    2648                 :         // determine whether to allow an error to be pushed or logged                
    2649              56 :         if (isset($prefs['push_callback'])                                           
    2650              56 :             && is_callable($prefs['push_callback'])                                  
    2651              56 :         ) {                                                                          
    2652              56 :             $this->_callback_push = $prefs['push_callback'];                         
    2653              56 :         } else {                                                                     
    2654               2 :             $this->_callback_push = array('HTML_CSS_Error', '_handleError');         
    2655                 :         }                                                                            
    2656                 :                                                                                      
    2657                 :         // determine whether to display or log an error by a free user function      
    2658              56 :         if (isset($prefs['error_callback'])                                          
    2659              56 :             && is_callable($prefs['error_callback'])                                 
    2660              56 :         ) {                                                                          
    2661              56 :             $this->_callback_error = $prefs['error_callback'];                       
    2662              56 :         } else {                                                                     
    2663               2 :             $this->_callback_error = null;                                           
    2664                 :         }                                                                            
    2665                 :                                                                                      
    2666                 :         // default error handler will use PEAR_Error                                 
    2667              56 :         if (isset($prefs['error_handler'])                                           
    2668               0 :             && is_callable($prefs['error_handler'])                                  
    2669              56 :         ) {                                                                          
    2670               0 :             $this->_callback_errorhandler = $prefs['error_handler'];                 
    2671               0 :         } else {                                                                     
    2672              56 :             $this->_callback_errorhandler = array(&$this, '_errorHandler');          
    2673                 :         }                                                                            
    2674                 :                                                                                      
    2675                 :         // any handler-specific settings                                             
    2676              56 :         if (isset($prefs['handler'])) {                                              
    2677               0 :             $this->_errorhandler_options = $prefs['handler'];                        
    2678               0 :         }                                                                            
    2679              56 :     }                                                                                
    2680                 :                                                                                      
    2681                 :     /**                                                                              
    2682                 :      * Standard error handler that will use PEAR_Error object                        
    2683                 :      *                                                                               
    2684                 :      * To improve performances, the PEAR.php file is included dynamically.           
    2685                 :      * The file is so included only when an error is triggered. So, in most          
    2686                 :      * cases, the file isn't included and perfs are much better.                     
    2687                 :      *                                                                               
    2688                 :      * @param integer $code   Error code.                                            
    2689                 :      * @param string  $level  The error level of the message.                        
    2690                 :      * @param array   $params Associative array of error parameters                  
    2691                 :      *                                                                               
    2692                 :      * @return     PEAR_Error                                                        
    2693                 :      * @since      version 1.0.0 (2006-06-24)                                        
    2694                 :      * @access     private                                                           
    2695                 :      */                                                                              
    2696                 :     function _errorHandler($code, $level, $params)                                   
    2697                 :     {                                                                                
    2698               5 :         include_once 'HTML/CSS/Error.php';                                           
    2699                 :                                                                                      
    2700               5 :         $mode    = call_user_func($this->_callback_push, $code, $level);             
    2701               5 :         $message = call_user_func($this->_callback_message, $code, $params);         
    2702               5 :         $options = $this->_callback_error;                                           
    2703                 :                                                                                      
    2704               5 :         $userinfo['level'] = $level;                                                 
    2705                 :                                                                                      
    2706               5 :         if (isset($this->_errorhandler_options['display'])) {                        
    2707               0 :             $userinfo['display'] = $this->_errorhandler_options['display'];          
    2708               0 :         } else {                                                                     
    2709               5 :             $userinfo['display'] = array();                                          
    2710                 :         }                                                                            
    2711               5 :         if (isset($this->_errorhandler_options['log'])) {                            
    2712               0 :             $userinfo['log'] = $this->_errorhandler_options['log'];                  
    2713               0 :         } else {                                                                     
    2714               5 :             $userinfo['log'] = array();                                              
    2715                 :         }                                                                            
    2716                 :                                                                                      
    2717               5 :         return PEAR::raiseError(                                                     
    2718               5 :             $message, $code, $mode, $options, $userinfo, 'HTML_CSS_Error'            
    2719               5 :         );                                                                           
    2720                 :     }                                                                                
    2721                 :                                                                                      
    2722                 :     /**                                                                              
    2723                 :      * A basic wrapper around the default PEAR_Error object                          
    2724                 :      *                                                                               
    2725                 :      * This method is a wrapper that returns an instance of the configured           
    2726                 :      * error class with this object's default error handling applied.                
    2727                 :      *                                                                               
    2728                 :      * @return     object    PEAR_Error when default error handler is used           
    2729                 :      * @since      version 0.3.3 (2004-05-20)                                        
    2730                 :      * @access     public                                                            
    2731                 :      * @see        _errorHandler()                                                   
    2732                 :      */                                                                              
    2733                 :     function raiseError()                                                            
    2734                 :     {                                                                                
    2735               5 :         $args = func_get_args();                                                     
    2736               5 :         $this->_lastError                                                            
    2737               5 :             = call_user_func_array($this->_callback_errorhandler, $args);            
    2738               5 :         return $this->_lastError;                                                    
    2739                 :     }                                                                                
    2740                 :                                                                                      
    2741                 :     /**                                                                              
    2742                 :      * Determine whether there is an error                                           
    2743                 :      *                                                                               
    2744                 :      * Determine whether last action raised an error or not                          
    2745                 :      *                                                                               
    2746                 :      * @return     boolean               TRUE if error raised, FALSE otherwise       
    2747                 :      * @since      version 1.0.0RC2 (2005-12-15)                                     
    2748                 :      * @access     public                                                            
    2749                 :      */                                                                              
    2750                 :     function isError()                                                               
    2751                 :     {                                                                                
    2752               0 :          $res              = (!is_bool($this->_lastError));                          
    2753               0 :          $this->_lastError = false;                                                  
    2754               0 :          return $res;                                                                
    2755                 :     }                                                                                
    2756                 : }                                                                                    

Generated by PHPUnit 3.3.17 and Xdebug 2.0.5 at Sat Jul 4 10:34:12 CEST 2009.