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
95.83%95.83%
95.83% 46 / 48
87.62%87.62%
87.62% 991 / 1131
 
HTML_CSS
100.00%100.00%
100.00% 1 / 1
95.83%95.83%
95.83% 46 / 48
87.62%87.62%
87.62% 991 / 1131
 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% 8 / 8
 public function setOutputGroupsFirst($value)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 8 / 8
 public function parseSelectors($selectors, $outputMode = 0)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 76 / 76
 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% 8 / 8
 public function getAtRulesList()
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 3 / 3
 public function createAtRule($atKeyword, $arguments = '')
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 27 / 27
 public function unsetAtRule($atKeyword)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 18 / 18
 public function setAtRuleStyle($atKeyword, $arguments, $selectors, $property, $value, $duplicates = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 61 / 61
 public function getAtRuleStyle($atKeyword, $arguments, $selectors, $property)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 36 / 36
 public function createGroup($selectors, $group = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 20 / 20
 public function unsetGroup($group)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 25 / 25
 public function setGroupStyle($group, $property, $value, $duplicates = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 44 / 44
 public function getGroupStyle($group, $property)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 34 / 34
 public function addGroupSelector($group, $selectors)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 24 / 24
 public function removeGroupSelector($group, $selectors)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 32 / 32
 public function setStyle($element, $property, $value, $duplicates = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 40 / 40
 public function getStyle($element, $property)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 47 / 47
 public function grepStyle($elmPattern, $proPattern = NULL)
100.00%100.00%
100.00% 1 / 1
93.48%93.48%
93.48% 43 / 46
 public function setSameStyle($new, $old)
100.00%100.00%
100.00% 1 / 1
88.64%88.64%
88.64% 39 / 44
 public function setCache($cache = true)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 8 / 8
 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
84.21%84.21%
84.21% 16 / 19
 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% 8 / 8
 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
92.74%92.74%
92.74% 115 / 124
 public function parseFile($filename, $duplicates = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 20 / 20
 public function parseData($styles, $duplicates = NULL)
100.00%100.00%
100.00% 1 / 1
100.00%100.00%
100.00% 28 / 28
 public function validate($styles, &$messages)
100.00%100.00%
100.00% 1 / 1
27.12%27.12%
27.12% 16 / 59
 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
62.86%62.86%
62.86% 22 / 35
 public function toFile($filename)
100.00%100.00%
100.00% 1 / 1
68.75%68.75%
68.75% 11 / 16
 public function toString()
100.00%100.00%
100.00% 1 / 1
64.10%64.10%
64.10% 50 / 78
 public function display()
100.00%100.00%
100.00% 1 / 1
25.00%25.00%
25.00% 4 / 16
 public function _initErrorStack($prefs = array ( ))
100.00%100.00%
100.00% 1 / 1
72.41%72.41%
72.41% 21 / 29
 public function _errorHandler($code, $level, $params)
100.00%100.00%
100.00% 1 / 1
73.33%73.33%
73.33% 11 / 15
 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.85 2009/01/21 10:47:37 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.3
      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              48 :         $this->_initErrorStack($errorPrefs);                                         
     309                 :
     310              48 :         if (!is_array($attributes)) {                                                
     311               0 :             $attributes = array($attributes);                                        
     312               0 :         }                                                                            
     313              48 :         if ($attributes) {                                                           
     314               9 :             $attributes = $this->_parseAttributes($attributes);                      
     315               9 :         }                                                                            
     316                 :
     317              48 :         $tab = '  ';                                                                 
     318              48 :         $eol = strtolower(substr(PHP_OS, 0, 3)) == 'win' ? "\r\n" : "\n";            
     319                 :
     320                 :         // default options
     321              48 :         $this->options = array('xhtml' => true, 'tab' => $tab, 'cache' => true,      
     322              48 :             'oneline' => false, 'charset' => 'iso-8859-1',                           
     323              48 :             'contentDisposition' => false, 'lineEnd' => $eol,                        
     324              48 :             'groupsfirst' => true, 'allowduplicates' => false);                      
     325                 :         // and options that come directly from HTML_Common
     326              48 :         $this->setTab($tab);                                                         
     327              48 :         $this->setLineEnd($eol);                                                     
     328                 :
     329                 :         // apply user options
     330              48 :         foreach ($attributes as $opt => $val) {                                      
     331               9 :             $this->__set($opt, $val);                                                
     332              48 :         }                                                                            
     333              48 :     }                                                                                
     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              48 :         if (isset($this->options[$option])) {                                        
     364              48 :             $this->options[$option] = $val;                                          
     365              48 :         }                                                                            
     366              48 :     }                                                                                
     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              39 :         if (isset($this->options[$option])) {                                        
     383              38 :             $r = $this->options[$option];                                            
     384              38 :         } else {                                                                     
     385               1 :             $r = null;                                                               
     386                 :         }
     387              39 :         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              48 :         $this->__set('tab', $string);                                                
     418              48 :         parent::setTab($string);                                                     
     419              48 :     }                                                                                
     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              48 :         $this->__set('lineEnd', $style);                                             
     435              48 :         parent::setLineEnd($style);                                                  
     436              48 :     }                                                                                
     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(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     454               1 :                 array('var' => '$value',                                             
     455               1 :                       'was' => gettype($value),                                      
     456               1 :                       'expected' => 'boolean',                                       
     457               1 :                       'paramnum' => 1));                                             
     458                 :         }                                                                            
     459               1 :         $this->options['oneline'] = $value;                                          
     460               1 :     }                                                                                
     461                 :
     462                 :     /**
     463                 :      * Set groupsfirst flag
     464                 :      *
     465                 :      * Determine whether groups are output before elements or not
     466                 :      *
     467                 :      * @param bool $value flag to true if groups are output before elements,
     468                 :      *                    false otherwise
     469                 :      *
     470                 :      * @return     void|PEAR_Error
     471                 :      * @since      version 0.3.3 (2004-05-20)
     472                 :      * @access     public
     473                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT
     474                 :      */
     475                 :     function setOutputGroupsFirst($value)
     476                 :     {
     477               2 :         if (!is_bool($value)) {                                                      
     478               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     479               1 :                 array('var' => '$value',                                             
     480               1 :                       'was' => gettype($value),                                      
     481               1 :                       'expected' => 'boolean',                                       
     482               1 :                       'paramnum' => 1));                                             
     483                 :         }                                                                            
     484               1 :         $this->options['groupsfirst'] = $value;                                      
     485               1 :     }                                                                                
     486                 :
     487                 :     /**
     488                 :      * Parse a string containing selector(s)
     489                 :      *
     490                 :      * It processes it and returns an array or string containing
     491                 :      * modified selectors (depends on XHTML compliance setting;
     492                 :      * defaults to ensure lowercase element names)
     493                 :      *
     494                 :      * @param string $selectors  Selector string
     495                 :      * @param int    $outputMode (optional) 0 = string; 1 = array; 2 = deep array
     496                 :      *
     497                 :      * @return     mixed|PEAR_Error
     498                 :      * @since      version 0.3.2 (2004-03-24)
     499                 :      * @access     protected
     500                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT
     501                 :      */
     502                 :     function parseSelectors($selectors, $outputMode = 0)
     503                 :     {
     504              26 :         if (!is_string($selectors)) {                                                
     505               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     506               1 :                 array('var' => '$selectors',                                         
     507               1 :                       'was' => gettype($selectors),                                  
     508               1 :                       'expected' => 'string',                                        
     509               1 :                       'paramnum' => 1));                                             
     510                 :
     511              26 :         } elseif (!is_int($outputMode)) {                                            
     512               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     513               1 :                 array('var' => '$outputMode',                                        
     514               1 :                       'was' => gettype($outputMode),                                 
     515               1 :                       'expected' => 'integer',                                       
     516               1 :                       'paramnum' => 2));                                             
     517                 :
     518              26 :         } elseif ($outputMode < 0 || $outputMode > 3) {                              
     519               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
     520               1 :                 array('var' => '$outputMode',                                        
     521               1 :                       'was' => $outputMode,                                          
     522               1 :                       'expected' => '0 | 1 | 2 | 3',                                 
     523               1 :                       'paramnum' => 2));                                             
     524                 :         }                                                                            
     525                 :
     526              26 :         $selectors_array =  explode(',', $selectors);                                
     527              26 :         $i               = 0;                                                        
     528              26 :         foreach ($selectors_array as $selector) {                                    
     529                 :             // trim to remove possible whitespace
     530              26 :             $selector = trim($this->collapseInternalSpaces($selector));              
     531              26 :             if (strpos($selector, ' ')) {                                            
     532              10 :                 $sel_a = array();                                                    
     533              10 :                 foreach (explode(' ', $selector) as $sub_selector) {                 
     534              10 :                     $sel_a[] = $this->parseSelectors($sub_selector, $outputMode);    
     535              10 :                 }                                                                    
     536              10 :                 if ($outputMode === 0) {                                             
     537               6 :                         $array[$i] = implode(' ', $sel_a);                           
     538               6 :                 } else {                                                             
     539               9 :                     $sel_a2 = array();                                               
     540               9 :                     foreach ($sel_a as $sel_a_temp) {                                
     541               9 :                         $sel_a2 = array_merge($sel_a2, $sel_a_temp);                 
     542               9 :                     }                                                                
     543               9 :                     if ($outputMode == 2) {                                          
     544               1 :                         $array[$i]['inheritance'] = $sel_a2;                         
     545               1 :                     } else {                                                         
     546               8 :                         $array[$i] = implode(' ', $sel_a2);                          
     547                 :                     }
     548                 :                 }
     549              10 :                 $i++;                                                                
     550              10 :             } else {                                                                 
     551                 :                 // initialize variables
     552              26 :                 $element = '';                                                       
     553              26 :                 $id      = '';                                                       
     554              26 :                 $class   = '';                                                       
     555              26 :                 $pseudo  = '';                                                       
     556                 :
     557              26 :                 if (strpos($selector, ':') !== false) {                              
     558               3 :                     $pseudo   = strstr($selector, ':');                              
     559               3 :                     $selector = substr($selector, 0, strpos($selector, ':'));        
     560               3 :                 }                                                                    
     561              26 :                 if (strpos($selector, '.') !== false) {                              
     562               9 :                     $class    = strstr($selector, '.');                              
     563               9 :                     $selector = substr($selector, 0, strpos($selector, '.'));        
     564               9 :                 }                                                                    
     565              26 :                 if (strpos($selector, '#') !== false) {                              
     566               7 :                     $id       = strstr($selector, '#');                              
     567               7 :                     $selector = substr($selector, 0, strpos($selector, '#'));        
     568               7 :                 }                                                                    
     569              26 :                 if ($selector != '') {                                               
     570              24 :                     $element = $selector;                                            
     571              24 :                 }                                                                    
     572              26 :                 if ($this->options['xhtml']) {                                       
     573              26 :                     $element = strtolower($element);                                 
     574              26 :                     $pseudo  = strtolower($pseudo);                                  
     575              26 :                 }                                                                    
     576              26 :                 if ($outputMode == 2) {                                              
     577               1 :                     $array[$i]['element'] = $element;                                
     578               1 :                     $array[$i]['id']      = $id;                                     
     579               1 :                     $array[$i]['class']   = $class;                                  
     580               1 :                     $array[$i]['pseudo']  = $pseudo;                                 
     581               1 :                 } else {                                                             
     582              25 :                     $array[$i] = $element.$id.$class.$pseudo;                        
     583                 :                 }
     584              26 :                 $i++;                                                                
     585                 :             }
     586              26 :         }                                                                            
     587              26 :         if ($outputMode == 0) {                                                      
     588              18 :             $output = implode(', ', $array);                                         
     589              18 :             return $output;                                                          
     590                 :         } else {                                                                     
     591              23 :             return $array;                                                           
     592                 :         }
     593                 :     }                                                                                
     594                 :
     595                 :     /**
     596                 :      * Strips excess spaces in string.
     597                 :      *
     598                 :      * @param string $subject string to format
     599                 :      *
     600                 :      * @return     string
     601                 :      * @since      version 0.3.2 (2004-03-24)
     602                 :      * @access     protected
     603                 :      */
     604                 :     function collapseInternalSpaces($subject)
     605                 :     {
     606              26 :         $string = preg_replace('/\s+/', ' ', $subject);                              
     607              26 :         return $string;                                                              
     608                 :     }                                                                                
     609                 :
     610                 :     /**
     611                 :      * sort and move simple declarative At-Rules to the top
     612                 :      *
     613                 :      * @return     void
     614                 :      * @access     protected
     615                 :      * @since      version 1.5.0 (2008-01-15)
     616                 :      */
     617                 :     function sortAtRules()
     618                 :     {
     619                 :         // split simple declarative At-Rules from the other
     620              20 :         $return = array('atrules' => array(), 'newcss' => array());                  
     621                 :
     622              20 :         foreach ($this->_css as $key => $value) {                                    
     623              20 :             if ((0 === strpos($key, "@")) && (1 !== strpos($key, "-"))) {            
     624               5 :                 $return["atrules"][$key] = $value;                                   
     625               5 :             } else {                                                                 
     626              19 :                 $return["newcss"][$key] = $value;                                    
     627                 :             }
     628              20 :         }                                                                            
     629                 :
     630                 :         // bring sprecial rules to the top
     631              20 :         foreach (array('@namespace', '@import', '@charset') as $name) {              
     632              20 :             if (isset($return['atrules'][$name])) {                                  
     633               2 :                 $rule = array($name => $return['atrules'][$name]);                   
     634               2 :                 unset($return['atrules'][$name]);                                    
     635               2 :                 $return['atrules'] = $rule + $return['atrules'];                     
     636               2 :             }                                                                        
     637              20 :         }                                                                            
     638                 :
     639              20 :         $this->_css = $return['atrules'] + $return['newcss'];                        
     640              20 :     }                                                                                
     641                 :
     642                 :     /**
     643                 :      * Set xhtml flag
     644                 :      *
     645                 :      * Active or not the XHTML mode compliant
     646                 :      *
     647                 :      * @param bool $value flag to true if XHTML compliance needed,
     648                 :      *                    false otherwise
     649                 :      *
     650                 :      * @return     void|PEAR_Error
     651                 :      * @since      version 0.3.2 (2004-03-24)
     652                 :      * @access     public
     653                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT
     654                 :      */
     655                 :     function setXhtmlCompliance($value)
     656                 :     {
     657               2 :         if (!is_bool($value)) {                                                      
     658               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     659               1 :                 array('var' => '$value',                                             
     660               1 :                       'was' => gettype($value),                                      
     661               1 :                       'expected' => 'boolean',                                       
     662               1 :                       'paramnum' => 1));                                             
     663                 :         }                                                                            
     664               1 :         $this->options['xhtml'] = $value;                                            
     665               1 :     }                                                                                
     666                 :
     667                 :     /**
     668                 :      * Return list of supported At-Rules
     669                 :      *
     670                 :      * Return the list of At-Rules supported by API 1.5.0 of HTML_CSS
     671                 :      *
     672                 :      * @return void
     673                 :      * @since  version 1.5.0 (2008-01-15)
     674                 :      * @access public
     675                 :      */
     676                 :     function getAtRulesList()
     677                 :     {
     678               5 :         $atRules = array('@charset', '@font-face',                                   
     679               5 :                          '@import', '@media', '@page', '@namespace');                
     680               5 :         return $atRules;                                                             
     681                 :     }                                                                                
     682                 :
     683                 :     /**
     684                 :      * Create a new simple declarative At-Rule
     685                 :      *
     686                 :      * Create a simple at-rule without declaration style blocks.
     687                 :      * That include @charset, @import and @namespace
     688                 :      *
     689                 :      * @param string $atKeyword at-rule keyword
     690                 :      * @param string $arguments argument list for @charset, @import or @namespace
     691                 :      *
     692                 :      * @return void|PEAR_Error
     693                 :      * @since  version 1.5.0 (2008-01-15)
     694                 :      * @access public
     695                 :      * @throws HTML_CSS_ERROR_INVALID_INPUT
     696                 :      * @see    unsetAtRule()
     697                 :      */
     698                 :     function createAtRule($atKeyword, $arguments = '')
     699                 :     {
     700               3 :         $allowed_atrules = array('@charset', '@import', '@namespace');               
     701                 :
     702               3 :         if (!is_string($atKeyword)) {                                                
     703               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     704               1 :                 array('var' => '$atKeyword',                                         
     705               1 :                       'was' => gettype($atKeyword),                                  
     706               1 :                       'expected' => 'string',                                        
     707               1 :                       'paramnum' => 1));                                             
     708                 :
     709               3 :         } elseif (!in_array(strtolower($atKeyword), $allowed_atrules)) {             
     710               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
     711               1 :                 array('var' => '$atKeyword',                                         
     712               1 :                       'was' => $atKeyword,                                           
     713               1 :                       'expected' => implode('|', $allowed_atrules),                  
     714               1 :                       'paramnum' => 1));                                             
     715                 :
     716               3 :         } elseif (!is_string($arguments)) {                                          
     717               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     718               1 :                 array('var' => '$arguments',                                         
     719               1 :                       'was' => gettype($arguments),                                  
     720               1 :                       'expected' => 'string',                                        
     721               1 :                       'paramnum' => 2));                                             
     722                 :         }                                                                            
     723                 :
     724               3 :         if (empty($arguments)) {                                                     
     725               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
     726               1 :                 array('var' => '$arguments',                                         
     727               1 :                       'was' => $arguments,                                           
     728               1 :                       'expected' => 'not empty value',                               
     729               1 :                       'paramnum' => 2));                                             
     730                 :         } else {                                                                     
     731               2 :             $this->_css[strtolower($atKeyword)] = array($arguments => '');           
     732                 :         }
     733               2 :     }                                                                                
     734                 :
     735                 :     /**
     736                 :      * Remove an existing At-Rule
     737                 :      *
     738                 :      * Remove an existing and supported at-rule. See HTML_CSS::getAtRulesList()
     739                 :      * for a full list of supported At-Rules.
     740                 :      *
     741                 :      * @param string $atKeyword at-rule keyword
     742                 :      *
     743                 :      * @return void|PEAR_Error
     744                 :      * @since  version 1.5.0 (2008-01-15)
     745                 :      * @access public
     746                 :      * @throws HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_NO_ATRULE
     747                 :      */
     748                 :     function unsetAtRule($atKeyword)
     749                 :     {
     750               2 :         $allowed_atrules = $this->getAtRulesList();                                  
     751                 :
     752               2 :         if (!is_string($atKeyword)) {                                                
     753               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     754               1 :                 array('var' => '$atKeyword',                                         
     755               1 :                       'was' => gettype($atKeyword),                                  
     756               1 :                       'expected' => 'string',                                        
     757               1 :                       'paramnum' => 1));                                             
     758                 :
     759               2 :         } elseif (!in_array(strtolower($atKeyword), $allowed_atrules)) {             
     760               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
     761               1 :                 array('var' => '$atKeyword',                                         
     762               1 :                       'was' => $atKeyword,                                           
     763               1 :                       'expected' => implode('|', $allowed_atrules),                  
     764               1 :                       'paramnum' => 1));                                             
     765                 :
     766               2 :         } elseif (!isset($this->_css[strtolower($atKeyword)])) {                     
     767               1 :             return $this->raiseError(HTML_CSS_ERROR_NO_ATRULE, 'error',              
     768               1 :                 array('identifier' => $atKeyword));                                  
     769                 :         }                                                                            
     770                 :
     771               1 :         unset($this->_css[strtolower($atKeyword)]);                                  
     772               1 :     }                                                                                
     773                 :
     774                 :     /**
     775                 :      * Define a conditional/informative At-Rule
     776                 :      *
     777                 :      * Set arguments and declaration style block for at-rules that follow :
     778                 :      * "@media, @page, @font-face"
     779                 :      *
     780                 :      * @param string $atKeyword  at-rule keyword
     781                 :      * @param string $arguments  argument list
     782                 :      *                           (optional for @font-face)
     783                 :      * @param string $selectors  selectors of declaration style block
     784                 :      *                           (optional for @media, @page, @font-face)
     785                 :      * @param string $property   property of a single declaration style block
     786                 :      * @param string $value      value of a single declaration style block
     787                 :      * @param bool   $duplicates (optional) Allow or disallow duplicates
     788                 :      *
     789                 :      * @return void|PEAR_Error
     790                 :      * @since  version 1.5.0 (2008-01-15)
     791                 :      * @access public
     792                 :      * @throws HTML_CSS_ERROR_INVALID_INPUT
     793                 :      * @see    getAtRuleStyle()
     794                 :      */
     795                 :     function setAtRuleStyle($atKeyword, $arguments, $selectors, $property, $value,
     796                 :         $duplicates = null)
     797                 :     {
     798               5 :         $allowed_atrules = array('@media', '@page', '@font-face');                   
     799                 :
     800               5 :         if (!is_string($atKeyword)) {                                                
     801               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     802               1 :                 array('var' => '$atKeyword',                                         
     803               1 :                       'was' => gettype($atKeyword),                                  
     804               1 :                       'expected' => 'string',                                        
     805               1 :                       'paramnum' => 1));                                             
     806                 :
     807               5 :         } elseif (!in_array(strtolower($atKeyword), $allowed_atrules)) {             
     808               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
     809               1 :                 array('var' => '$atKeyword',                                         
     810               1 :                       'was' => $atKeyword,                                           
     811               1 :                       'expected' => implode('|', $allowed_atrules),                  
     812               1 :                       'paramnum' => 1));                                             
     813                 :
     814               5 :         } elseif (empty($arguments) && strtolower($atKeyword) != '@font-face') {     
     815               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
     816               1 :                 array('var' => '$arguments',                                         
     817               1 :                       'was' => $arguments,                                           
     818               1 :                       'expected' => 'not empty value for '. $atKeyword,              
     819               1 :                       'paramnum' => 2));                                             
     820                 :
     821               5 :         } elseif (!is_string($selectors)) {                                          
     822               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     823               1 :                 array('var' => '$selectors',                                         
     824               1 :                       'was' => gettype($selectors),                                  
     825               1 :                       'expected' => 'string',                                        
     826               1 :                       'paramnum' => 3));                                             
     827                 :
     828               5 :         } elseif (!is_string($property)) {                                           
     829               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     830               1 :                 array('var' => '$property',                                          
     831               1 :                       'was' => gettype($property),                                   
     832               1 :                       'expected' => 'string',                                        
     833               1 :                       'paramnum' => 4));                                             
     834                 :
     835               5 :         } elseif (!is_string($value)) {                                              
     836               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     837               1 :                 array('var' => '$value',                                             
     838               1 :                       'was' => gettype($value),                                      
     839               1 :                       'expected' => 'string',                                        
     840               1 :                       'paramnum' => 5));                                             
     841                 :
     842               5 :         } elseif (empty($property)) {                                                
     843               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
     844               1 :                 array('var' => '$property',                                          
     845               1 :                       'was' => $property,                                            
     846               1 :                       'expected' => 'no empty string',                               
     847               1 :                       'paramnum' => 4));                                             
     848                 :
     849               5 :         } elseif (empty($value)) {                                                   
     850               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
     851               1 :                 array('var' => '$value',                                             
     852               1 :                       'was' => gettype($value),                                      
     853               1 :                       'expected' => 'no empty string',                               
     854               1 :                       'paramnum' => 5));                                             
     855                 :         }                                                                            
     856                 :
     857               4 :         if (!isset($duplicates)) {                                                   
     858               2 :             $duplicates = $this->__get('allowduplicates');                           
     859               2 :         }                                                                            
     860                 :
     861               4 :         $atKeyword = strtolower($atKeyword);                                         
     862                 :
     863               4 :         if ($selectors == '') {                                                      
     864               4 :             $this->_css[$atKeyword][$arguments][$selectors][$property] = $value;     
     865               4 :         } else {                                                                     
     866               2 :             $selectors = $this->parseSelectors($selectors, 1);                       
     867               2 :             foreach ($selectors as $selector) {                                      
     868               2 :                 $this->_css[$atKeyword][$arguments][$selector][$property] = $value;  
     869               2 :             }                                                                        
     870                 :         }
     871               4 :     }                                                                                
     872                 :
     873                 :     /**
     874                 :      * Get style value of an existing At-Rule
     875                 :      *
     876                 :      * Retrieve arguments or style value of an existing At-Rule.
     877                 :      * See HTML_CSS::getAtRulesList() for a full list of supported At-Rules.
     878                 :      *
     879                 :      * @param string $atKeyword at-rule keyword
     880                 :      * @param string $arguments argument list
     881                 :      *                          (optional for @font-face)
     882                 :      * @param string $selectors selectors of declaration style block
     883                 :      *                          (optional for @media, @page, @font-face)
     884                 :      * @param string $property  property of a single declaration style block
     885                 :      *
     886                 :      * @return void|PEAR_Error
     887                 :      * @since  version 1.5.0 (2008-01-15)
     888                 :      * @access public
     889                 :      * @throws HTML_CSS_ERROR_INVALID_INPUT
     890                 :      * @see    setAtRuleStyle()
     891                 :      */
     892                 :     function getAtRuleStyle($atKeyword, $arguments, $selectors, $property)
     893                 :     {
     894               3 :         $allowed_atrules = $this->getAtRulesList();                                  
     895                 :
     896               3 :         if (!is_string($atKeyword)) {                                                
     897               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     898               1 :                 array('var' => '$atKeyword',                                         
     899               1 :                       'was' => gettype($atKeyword),                                  
     900               1 :                       'expected' => 'string',                                        
     901               1 :                       'paramnum' => 1));                                             
     902                 :
     903               3 :         } elseif (!in_array(strtolower($atKeyword), $allowed_atrules)) {             
     904               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
     905               1 :                 array('var' => '$atKeyword',                                         
     906               1 :                       'was' => $atKeyword,                                           
     907               1 :                       'expected' => implode('|', $allowed_atrules),                  
     908               1 :                       'paramnum' => 1));                                             
     909                 :
     910               3 :         } elseif (!is_string($arguments)) {                                          
     911               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     912               1 :                 array('var' => '$arguments',                                         
     913               1 :                       'was' => gettype($arguments),                                  
     914               1 :                       'expected' => 'string',                                        
     915               1 :                       'paramnum' => 2));                                             
     916                 :
     917               3 :         } elseif (!is_string($selectors)) {                                          
     918               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     919               1 :                 array('var' => '$selectors',                                         
     920               1 :                       'was' => gettype($selectors),                                  
     921               1 :                       'expected' => 'string',                                        
     922               1 :                       'paramnum' => 3));                                             
     923                 :
     924               3 :         } elseif (!is_string($property)) {                                           
     925               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     926               1 :                 array('var' => '$property',                                          
     927               1 :                       'was' => gettype($property),                                   
     928               1 :                       'expected' => 'string',                                        
     929               1 :                       'paramnum' => 4));                                             
     930                 :         }                                                                            
     931                 :
     932               2 :         if (isset($this->_css[$atKeyword][$arguments][$selectors][$property])) {     
     933               1 :             $val = $this->_css[$atKeyword][$arguments][$selectors][$property];       
     934               1 :         } else {                                                                     
     935               1 :             $val = null;                                                             
     936                 :         }
     937               2 :         return $val;                                                                 
     938                 :     }                                                                                
     939                 :
     940                 :     /**
     941                 :      * Create a new CSS definition group
     942                 :      *
     943                 :      * Create a new CSS definition group. Return an integer identifying the group.
     944                 :      *
     945                 :      * @param string $selectors Selector(s) to be defined, comma delimited.
     946                 :      * @param mixed  $group     (optional) Group identifier. If not passed,
     947                 :      *                          will return an automatically assigned integer.
     948                 :      *
     949                 :      * @return     mixed|PEAR_Error
     950                 :      * @since      version 0.3.0 (2003-11-03)
     951                 :      * @access     public
     952                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_INVALID_GROUP
     953                 :      * @see        unsetGroup()
     954                 :      */
     955                 :     function createGroup($selectors, $group = null)
     956                 :     {
     957              14 :         if (!is_string($selectors)) {                                                
     958               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
     959               1 :                 array('var' => '$selectors',                                         
     960               1 :                       'was' => gettype($selectors),                                  
     961               1 :                       'expected' => 'string',                                        
     962               1 :                       'paramnum' => 1));                                             
     963                 :         }                                                                            
     964                 :
     965              14 :         if (!isset($group)) {                                                        
     966              12 :             $this->_groupCount++;                                                    
     967              12 :             $group = $this->_groupCount;                                             
     968              12 :         } else {                                                                     
     969               3 :             if (isset($this->_groups['@-'.$group])) {                                
     970               1 :                 return $this->raiseError(HTML_CSS_ERROR_INVALID_GROUP, 'error',      
     971               1 :                     array('identifier' => $group));                                  
     972                 :             }                                                                        
     973                 :         }
     974                 :
     975              14 :         $groupIdent = '@-'.$group;                                                   
     976                 :
     977              14 :         $selectors = $this->parseSelectors($selectors, 1);                           
     978              14 :         foreach ($selectors as $selector) {                                          
     979              14 :             $this->_alibis[$selector][] = $groupIdent;                               
     980              14 :         }                                                                            
     981                 :
     982              14 :         $this->_groups[$groupIdent] = $selectors;                                    
     983                 :
     984              14 :         return $group;                                                               
     985                 :     }                                                                                
     986                 :
     987                 :     /**
     988                 :      * Remove a CSS definition group
     989                 :      *
     990                 :      * Remove a CSS definition group. Use the same identifier as for group creation.
     991                 :      *
     992                 :      * @param mixed $group CSS definition group identifier
     993                 :      *
     994                 :      * @return     void|PEAR_Error
     995                 :      * @since      version 0.3.0 (2003-11-03)
     996                 :      * @access     public
     997                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_NO_GROUP
     998                 :      * @see        createGroup()
     999                 :      */
    1000                 :     function unsetGroup($group)
    1001                 :     {
    1002               2 :         if (!is_int($group) && !is_string($group)) {                                 
    1003               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1004               1 :                 array('var' => '$group',                                             
    1005               1 :                       'was' => gettype($group),                                      
    1006               1 :                       'expected' => 'integer | string',                              
    1007               1 :                       'paramnum' => 1));                                             
    1008                 :         }                                                                            
    1009               2 :         $groupIdent = '@-'.$group;                                                   
    1010               2 :         if ($group < 0 || $group > $this->_groupCount ||                             
    1011               2 :             !isset($this->_groups[$groupIdent])) {                                   
    1012               1 :             return $this->raiseError(HTML_CSS_ERROR_NO_GROUP, 'error',               
    1013               1 :                 array('identifier' => $group));                                      
    1014                 :         }                                                                            
    1015                 :
    1016               1 :         $alibis = $this->_alibis;                                                    
    1017               1 :         foreach ($alibis as $selector => $data) {                                    
    1018               1 :             foreach ($data as $key => $value) {                                      
    1019               1 :                 if ($value == $groupIdent) {                                         
    1020               1 :                     unset($this->_alibis[$selector][$key]);                          
    1021               1 :                     break;                                                           
    1022                 :                 }                                                                    
    1023               1 :             }                                                                        
    1024               1 :             if (count($this->_alibis[$selector]) == 0) {                             
    1025               1 :                 unset($this->_alibis[$selector]);                                    
    1026               1 :             }                                                                        
    1027               1 :         }                                                                            
    1028               1 :         unset($this->_groups[$groupIdent]);                                          
    1029               1 :         unset($this->_css[$groupIdent]);                                             
    1030               1 :     }                                                                                
    1031                 :
    1032                 :     /**
    1033                 :      * Set or add a CSS definition for a CSS group
    1034                 :      *
    1035                 :      * Define the new value of a property for a CSS group. The group should exist.
    1036                 :      * If not, use HTML_CSS::createGroup first
    1037                 :      *
    1038                 :      * @param mixed  $group      CSS definition group identifier
    1039                 :      * @param string $property   Property defined
    1040                 :      * @param string $value      Value assigned
    1041                 :      * @param bool   $duplicates (optional) Allow or disallow duplicates.
    1042                 :      *
    1043                 :      * @return     void|int|PEAR_Error     Returns an integer if duplicates
    1044                 :      *                                     are allowed.
    1045                 :      * @since      version 0.3.0 (2003-11-03)
    1046                 :      * @access     public
    1047                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_NO_GROUP
    1048                 :      * @see        getGroupStyle()
    1049                 :      */
    1050                 :     function setGroupStyle($group, $property, $value, $duplicates = null)
    1051                 :     {
    1052              13 :         if (!is_int($group) && !is_string($group)) {                                 
    1053               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1054               1 :                 array('var' => '$group',                                             
    1055               1 :                       'was' => gettype($group),                                      
    1056               1 :                       'expected' => 'integer | string',                              
    1057               1 :                       'paramnum' => 1));                                             
    1058                 :
    1059              13 :         } elseif (!is_string($property)) {                                           
    1060               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1061               1 :                 array('var' => '$property',                                          
    1062               1 :                       'was' => gettype($property),                                   
    1063               1 :                       'expected' => 'string',                                        
    1064               1 :                       'paramnum' => 2));                                             
    1065                 :
    1066              13 :         } elseif (empty($property)) {                                                
    1067               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
    1068               1 :                 array('var' => '$property',                                          
    1069               1 :                       'was' => gettype($property),                                   
    1070               1 :                       'expected' => 'no empty string',                               
    1071               1 :                       'paramnum' => 2));                                             
    1072                 :
    1073              13 :         } elseif (!is_string($value)) {                                              
    1074               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1075               1 :                 array('var' => '$value',                                             
    1076               1 :                       'was' => gettype($value),                                      
    1077               1 :                       'expected' => 'string',                                        
    1078               1 :                       'paramnum' => 3));                                             
    1079                 :
    1080              13 :         } elseif (isset($duplicates) && !is_bool($duplicates)) {                     
    1081               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1082               1 :                 array('var' => '$duplicates',                                        
    1083               1 :                       'was' => gettype($duplicates),                                 
    1084               1 :                       'expected' => 'bool',                                          
    1085               1 :                       'paramnum' => 4));                                             
    1086                 :         }                                                                            
    1087                 :
    1088              13 :         if (!isset($duplicates)) {                                                   
    1089               6 :             $duplicates = $this->__get('allowduplicates');                           
    1090               6 :         }                                                                            
    1091                 :
    1092              13 :         $groupIdent = '@-'.$group;                                                   
    1093              13 :         if ($group < 0 || $group > $this->_groupCount ||                             
    1094              13 :             !isset($this->_groups[$groupIdent])) {                                   
    1095               1 :             return $this->raiseError(HTML_CSS_ERROR_NO_GROUP, 'error',               
    1096               1 :                 array('identifier' => $group));                                      
    1097                 :         }                                                                            
    1098                 :
    1099              12 :         if ($duplicates === true) {                                                  
    1100               1 :             $this->_duplicateCounter++;                                              
    1101               1 :             $this->_css[$groupIdent][$this->_duplicateCounter][$property] = $value;  
    1102               1 :             return $this->_duplicateCounter;                                         
    1103                 :         } else {                                                                     
    1104              11 :             $this->_css[$groupIdent][$property] = $value;                            
    1105                 :         }
    1106              11 :     }                                                                                
    1107                 :
    1108                 :     /**
    1109                 :      * Return CSS definition for a CSS group
    1110                 :      *
    1111                 :      * Get the CSS definition for group created by setGroupStyle()
    1112                 :      *
    1113                 :      * @param mixed  $group    CSS definition group identifier
    1114                 :      * @param string $property Property defined
    1115                 :      *
    1116                 :      * @return     mixed|PEAR_Error
    1117                 :      * @since      version 0.3.0 (2003-11-03)
    1118                 :      * @access     public
    1119                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_NO_GROUP,
    1120                 :      *             HTML_CSS_ERROR_NO_ELEMENT
    1121                 :      * @see        setGroupStyle()
    1122                 :      */
    1123                 :     function getGroupStyle($group, $property)
    1124                 :     {
    1125               3 :         if (!is_int($group) && !is_string($group)) {                                 
    1126               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1127               1 :                 array('var' => '$group',                                             
    1128               1 :                       'was' => gettype($group),                                      
    1129               1 :                       'expected' => 'integer | string',                              
    1130               1 :                       'paramnum' => 1));                                             
    1131                 :
    1132               3 :         } elseif (!is_string($property)) {                                           
    1133               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1134               1 :                 array('var' => '$property',                                          
    1135               1 :                       'was' => gettype($property),                                   
    1136               1 :                       'expected' => 'string',                                        
    1137               1 :                       'paramnum' => 2));                                             
    1138                 :         }                                                                            
    1139               3 :         $groupIdent = '@-'.$group;                                                   
    1140               3 :         if ($group < 0 || $group > $this->_groupCount ||                             
    1141               3 :             !isset($this->_groups[$groupIdent])) {                                   
    1142               1 :             return $this->raiseError(HTML_CSS_ERROR_NO_GROUP, 'error',               
    1143               1 :                 array('identifier' => $group));                                      
    1144                 :         }                                                                            
    1145                 :
    1146               3 :         $styles = array();                                                           
    1147                 :
    1148               3 :         if (!isset($this->_css[$groupIdent])) {                                      
    1149               1 :             return $styles;                                                          
    1150                 :         }                                                                            
    1151                 :
    1152               2 :         foreach ($this->_css[$groupIdent] as $rank => $prop) {                       
    1153                 :             // if the style is not duplicate
    1154               2 :             if (!is_numeric($rank)) {                                                
    1155               2 :                 $prop = array($rank => $prop);                                       
    1156               2 :             }                                                                        
    1157               2 :             foreach ($prop as $key => $value) {                                      
    1158               2 :                 if ($key == $property) {                                             
    1159               2 :                     $styles[] = $value;                                              
    1160               2 :                 }                                                                    
    1161               2 :             }                                                                        
    1162               2 :         }                                                                            
    1163                 :
    1164               2 :         if (count($styles) < 2) {                                                    
    1165               2 :             $styles = array_shift($styles);                                          
    1166               2 :         }                                                                            
    1167               2 :         return $styles;                                                              
    1168                 :     }                                                                                
    1169                 :
    1170                 :     /**
    1171                 :      * Add a selector to a CSS definition group.
    1172                 :      *
    1173                 :      * Add a selector to a CSS definition group
    1174                 :      *
    1175                 :      * @param mixed  $group     CSS definition group identifier
    1176                 :      * @param string $selectors Selector(s) to be defined, comma delimited.
    1177                 :      *
    1178                 :      * @return   void|PEAR_Error
    1179                 :      * @since    version 0.3.0 (2003-11-03)
    1180                 :      * @access   public
    1181                 :      * @throws   HTML_CSS_ERROR_NO_GROUP, HTML_CSS_ERROR_INVALID_INPUT
    1182                 :      */
    1183                 :     function addGroupSelector($group, $selectors)
    1184                 :     {
    1185               2 :         if (!is_int($group) && !is_string($group)) {                                 
    1186               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1187               1 :                 array('var' => '$group',                                             
    1188               1 :                       'was' => gettype($group),                                      
    1189               1 :                       'expected' => 'integer | string',                              
    1190               1 :                       'paramnum' => 1));                                             
    1191                 :         }                                                                            
    1192               2 :         $groupIdent = '@-'.$group;                                                   
    1193               2 :         if ($group < 0 || $group > $this->_groupCount ||                             
    1194               2 :             !isset($this->_groups[$groupIdent])) {                                   
    1195               1 :             return $this->raiseError(HTML_CSS_ERROR_NO_GROUP, 'error',               
    1196               1 :                 array('identifier' => $group));                                      
    1197                 :
    1198               2 :         } elseif (!is_string($selectors)) {                                          
    1199               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1200               1 :                 array('var' => '$selectors',                                         
    1201               1 :                       'was' => gettype($selectors),                                  
    1202               1 :                       'expected' => 'string',                                        
    1203               1 :                       'paramnum' => 2));                                             
    1204                 :         }                                                                            
    1205                 :
    1206               1 :         $newSelectors = $this->parseSelectors($selectors, 1);                        
    1207               1 :         foreach ($newSelectors as $selector) {                                       
    1208               1 :             $this->_alibis[$selector][] = $groupIdent;                               
    1209               1 :         }                                                                            
    1210               1 :         $oldSelectors = $this->_groups[$groupIdent];                                 
    1211                 :
    1212               1 :         $this->_groups[$groupIdent] = array_merge($oldSelectors, $newSelectors);     
    1213               1 :     }                                                                                
    1214                 :
    1215                 :     /**
    1216                 :      * Remove a selector from a group
    1217                 :      *
    1218                 :      * Definitively remove a selector from a CSS group
    1219                 :      *
    1220                 :      * @param mixed  $group     CSS definition group identifier
    1221                 :      * @param string $selectors Selector(s) to be removed, comma delimited.
    1222                 :      *
    1223                 :      * @return   void|PEAR_Error
    1224                 :      * @since    version 0.3.0 (2003-11-03)
    1225                 :      * @access   public
    1226                 :      * @throws   HTML_CSS_ERROR_NO_GROUP, HTML_CSS_ERROR_INVALID_INPUT
    1227                 :      */
    1228                 :     function removeGroupSelector($group, $selectors)
    1229                 :     {
    1230               2 :         if (!is_int($group) && !is_string($group)) {                                 
    1231               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1232               1 :                 array('var' => '$group',                                             
    1233               1 :                       'was' => gettype($group),                                      
    1234               1 :                       'expected' => 'integer | string',                              
    1235               1 :                       'paramnum' => 1));                                             
    1236                 :         }                                                                            
    1237               2 :         $groupIdent = '@-'.$group;                                                   
    1238               2 :         if ($group < 0 || $group > $this->_groupCount ||                             
    1239               2 :             !isset($this->_groups[$groupIdent])) {                                   
    1240               1 :             return $this->raiseError(HTML_CSS_ERROR_NO_GROUP, 'error',               
    1241               1 :                 array('identifier' => $group));                                      
    1242                 :
    1243               2 :         } elseif (!is_string($selectors)) {                                          
    1244               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1245               1 :                 array('var' => '$selectors',                                         
    1246               1 :                       'was' => gettype($selectors),                                  
    1247               1 :                       'expected' => 'string',                                        
    1248               1 :                       'paramnum' => 2));                                             
    1249                 :         }                                                                            
    1250                 :
    1251               1 :         $oldSelectors = $this->_groups[$groupIdent];                                 
    1252               1 :         $selectors    = $this->parseSelectors($selectors, 1);                        
    1253               1 :         foreach ($selectors as $selector) {                                          
    1254               1 :             foreach ($oldSelectors as $key => $value) {                              
    1255               1 :                 if ($value == $selector) {                                           
    1256               1 :                     unset($this->_groups[$groupIdent][$key]);                        
    1257               1 :                 }                                                                    
    1258               1 :             }                                                                        
    1259               1 :             foreach ($this->_alibis[$selector] as $key => $value) {                  
    1260               1 :                 if ($value == $groupIdent) {                                         
    1261               1 :                     unset($this->_alibis[$selector][$key]);                          
    1262               1 :                 }                                                                    
    1263               1 :             }                                                                        
    1264               1 :         }                                                                            
    1265               1 :     }                                                                                
    1266                 :
    1267                 :     /**
    1268                 :      * Set or add a CSS definition
    1269                 :      *
    1270                 :      * Add or change a single value for an element property
    1271                 :      *
    1272                 :      * @param string $element    Element (or class) to be defined
    1273                 :      * @param string $property   Property defined
    1274                 :      * @param string $value      Value assigned
    1275                 :      * @param bool   $duplicates (optional) Allow or disallow duplicates.
    1276                 :      *
    1277                 :      * @return     void|PEAR_Error
    1278                 :      * @since      version 0.2.0 (2003-07-31)
    1279                 :      * @access     public
    1280                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT
    1281                 :      * @see        getStyle()
    1282                 :      */
    1283                 :     function setStyle($element, $property, $value, $duplicates = null)
    1284                 :     {
    1285              17 :         if (!is_string($element)) {                                                  
    1286               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1287               1 :                 array('var' => '$element',                                           
    1288               1 :                       'was' => gettype($element),                                    
    1289               1 :                       'expected' => 'string',                                        
    1290               1 :                       'paramnum' => 1));                                             
    1291                 :
    1292              17 :         } elseif (!is_string($property)) {                                           
    1293               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1294               1 :                 array('var' => '$property',                                          
    1295               1 :                       'was' => gettype($property),                                   
    1296               1 :                       'expected' => 'string',                                        
    1297               1 :                       'paramnum' => 2));                                             
    1298                 :
    1299              17 :         } elseif (!is_string($value)) {                                              
    1300               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1301               1 :                 array('var' => '$value',                                             
    1302               1 :                       'was' => gettype($value),                                      
    1303               1 :                       'expected' => 'string',                                        
    1304               1 :                       'paramnum' => 3));                                             
    1305                 :
    1306              17 :         } elseif (strpos($element, ',')) {                                           
    1307                 :             // Check if there are any groups.
    1308               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
    1309               1 :                 array('var' => '$element',                                           
    1310               1 :                       'was' => $element,                                             
    1311               1 :                       'expected' => 'string without comma',                          
    1312               1 :                       'paramnum' => 1));                                             
    1313                 :
    1314              17 :         } elseif (isset($duplicates) && !is_bool($duplicates)) {                     
    1315               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1316               1 :                 array('var' => '$duplicates',                                        
    1317               1 :                       'was' => gettype($duplicates),                                 
    1318               1 :                       'expected' => 'bool',                                          
    1319               1 :                       'paramnum' => 4));                                             
    1320                 :         }                                                                            
    1321                 :
    1322              17 :         if (!isset($duplicates)) {                                                   
    1323               8 :              $duplicates = $this->__get('allowduplicates');                          
    1324               8 :         }                                                                            
    1325                 :
    1326              17 :         $element = $this->parseSelectors($element);                                  
    1327                 :
    1328              17 :         if ($duplicates === true) {                                                  
    1329               2 :             $this->_duplicateCounter++;                                              
    1330               2 :             $this->_css[$element][$this->_duplicateCounter][$property] = $value;     
    1331               2 :             return $this->_duplicateCounter;                                         
    1332                 :         } else {                                                                     
    1333              16 :             $this->_css[$element][$property] = $value;                               
    1334                 :         }
    1335              16 :     }                                                                                
    1336                 :
    1337                 :     /**
    1338                 :      * Return the value of a CSS property
    1339                 :      *
    1340                 :      * Get the value of a property to an identifed simple CSS element
    1341                 :      *
    1342                 :      * @param string $element  Element (or class) to be defined
    1343                 :      * @param string $property Property defined
    1344                 :      *
    1345                 :      * @return     mixed|PEAR_Error
    1346                 :      * @since      version 0.3.0 (2003-11-03)
    1347                 :      * @access     public
    1348                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT,
    1349                 :      *             HTML_CSS_ERROR_NO_ELEMENT, HTML_CSS_ERROR_NO_ELEMENT_PROPERTY
    1350                 :      * @see        setStyle()
    1351                 :      */
    1352                 :     function getStyle($element, $property)
    1353                 :     {
    1354               3 :         if (!is_string($element)) {                                                  
    1355               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1356               1 :                 array('var' => '$element',                                           
    1357               1 :                       'was' => gettype($element),                                    
    1358               1 :                       'expected' => 'string',                                        
    1359               1 :                       'paramnum' => 1));                                             
    1360                 :
    1361               3 :         } elseif (!is_string($property)) {                                           
    1362               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1363               1 :                 array('var' => '$property',                                          
    1364               1 :                       'was' => gettype($property),                                   
    1365               1 :                       'expected' => 'string',                                        
    1366               1 :                       'paramnum' => 2));                                             
    1367                 :         }                                                                            
    1368               3 :         if (!isset($this->_css[$element]) && !isset($this->_alibis[$element])) {     
    1369               1 :             return $this->raiseError(HTML_CSS_ERROR_NO_ELEMENT, 'error',             
    1370               1 :                 array('identifier' => $element));                                    
    1371                 :         }                                                                            
    1372                 :
    1373               3 :         if (isset($this->_css[$element]) && isset($this->_alibis[$element])) {       
    1374               2 :             $lastImplementation = array_keys($this->_alibis[$element]);              
    1375               2 :             $lastImplementation = array_pop($lastImplementation);                    
    1376                 :
    1377               2 :             $group = substr($this->_alibis[$element][$lastImplementation], 2);       
    1378                 :
    1379               2 :             $property_value = $this->getGroupStyle($group, $property);               
    1380               2 :             if (count($property_value) == 0) {                                       
    1381               1 :                 unset($property_value);                                              
    1382               1 :             }                                                                        
    1383               2 :         }                                                                            
    1384               3 :         if (isset($this->_css[$element]) && !isset($property_value)) {               
    1385               2 :             $property_value = array();                                               
    1386               2 :             foreach ($this->_css[$element] as $rank => $prop) {                      
    1387               2 :                 if (!is_numeric($rank)) {                                            
    1388               2 :                     $prop = array($rank => $prop);                                   
    1389               2 :                 }                                                                    
    1390               2 :                 foreach ($prop as $key => $value) {                                  
    1391               2 :                     if ($key == $property) {                                         
    1392               1 :                         $property_value[] = $value;                                  
    1393               1 :                     }                                                                
    1394               2 :                 }                                                                    
    1395               2 :             }                                                                        
    1396               2 :             if (count($property_value) == 1) {                                       
    1397               1 :                 $property_value = $property_value[0];                                
    1398               2 :             } elseif (count($property_value) == 0) {                                 
    1399               1 :                 unset($property_value);                                              
    1400               1 :             }                                                                        
    1401               2 :         }                                                                            
    1402                 :
    1403               3 :         if (!isset($property_value)) {                                               
    1404               1 :             return $this->raiseError(HTML_CSS_ERROR_NO_ELEMENT_PROPERTY, 'error',    
    1405               1 :                 array('identifier' => $element,                                      
    1406               1 :                       'property'   => $property));                                   
    1407                 :         }                                                                            
    1408               2 :         return $property_value;                                                      
    1409                 :     }                                                                                
    1410                 :
    1411                 :     /**
    1412                 :      * Retrieve styles corresponding to an element filter
    1413                 :      *
    1414                 :      * Return array entries of styles that match patterns (Perl compatible)
    1415                 :      *
    1416                 :      * @param string $elmPattern Element or class pattern to retrieve
    1417                 :      * @param string $proPattern (optional) Property pattern to retrieve
    1418                 :      *
    1419                 :      * @return     array|PEAR_Error
    1420                 :      * @since      version 1.1.0 (2007-01-01)
    1421                 :      * @access     public
    1422                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT
    1423                 :      * @link       http://www.php.net/en/ref.pcre.php
    1424                 :      *             Regular Expression Functions (Perl-Compatible)
    1425                 :      */
    1426                 :     function grepStyle($elmPattern, $proPattern = null)
    1427                 :     {
    1428               2 :         if (!is_string($elmPattern)) {                                               
    1429               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1430               1 :                 array('var' => '$elmPattern',                                        
    1431               1 :                       'was' => gettype($elmPattern),                                 
    1432               1 :                       'expected' => 'string',                                        
    1433               1 :                       'paramnum' => 1));                                             
    1434                 :
    1435               2 :         } elseif (isset($proPattern) && !is_string($proPattern)) {                   
    1436               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1437               1 :                 array('var' => '$proPattern',                                        
    1438               1 :                       'was' => gettype($proPattern),                                 
    1439               1 :                       'expected' => 'string',                                        
    1440               1 :                       'paramnum' => 2));                                             
    1441                 :         }                                                                            
    1442                 :
    1443               1 :         $styles = array();                                                           
    1444                 :
    1445                 :         // first, search inside alibis
    1446               1 :         $alibis = array_keys($this->_alibis);                                        
    1447               1 :         $alibis = preg_grep($elmPattern, $alibis);                                   
    1448               1 :         foreach ($alibis as $a) {                                                    
    1449               1 :             foreach ($this->_alibis[$a] as $g) {                                     
    1450               1 :                 if (isset($proPattern)) {                                            
    1451               1 :                     $properties = array_keys($this->_css[$g]);                       
    1452               1 :                     $properties = preg_grep($proPattern, $properties);               
    1453               1 :                     if (count($properties) == 0) {                                   
    1454                 :                         // this group does not have a such property pattern
    1455               1 :                         continue;                                                    
    1456                 :                     }                                                                
    1457               0 :                 }                                                                    
    1458               1 :                 if (isset($styles[$a])) {                                            
    1459               0 :                     $styles[$a] = array_merge($styles[$a], $this->_css[$g]);         
    1460               0 :                 } else {                                                             
    1461               1 :                     $styles[$a] = $this->_css[$g];                                   
    1462                 :                 }
    1463               1 :             }                                                                        
    1464               1 :         }                                                                            
    1465                 :
    1466                 :         // second, search inside elements
    1467               1 :         $elements = array_keys($this->_css);                                         
    1468               1 :         $elements = preg_grep($elmPattern, $elements);                               
    1469               1 :         foreach ($elements as $e) {                                                  
    1470               1 :             if (substr($e, 0, 1) == '@' ) {                                          
    1471                 :                 // excludes groups (already found with alibis)
    1472               1 :                 continue;                                                            
    1473                 :             }                                                                        
    1474               1 :             if (isset($proPattern)) {                                                
    1475               1 :                 $properties = array_keys($this->_css[$e]);                           
    1476               1 :                 $properties = preg_grep($proPattern, $properties);                   
    1477               1 :                 if (count($properties) == 0) {                                       
    1478                 :                     // this element does not have a such property pattern
    1479               1 :                     continue;                                                        
    1480                 :                 }                                                                    
    1481               1 :             }                                                                        
    1482               1 :             if (isset($styles[$e])) {                                                
    1483               1 :                 $styles[$e] = array_merge($styles[$e], $this->_css[$e]);             
    1484               1 :             } else {                                                                 
    1485               1 :                 $styles[$e] = $this->_css[$e];                                       
    1486                 :             }
    1487               1 :         }                                                                            
    1488               1 :         return $styles;                                                              
    1489                 :     }                                                                                
    1490                 :
    1491                 :     /**
    1492                 :      * Apply same styles on two selectors
    1493                 :      *
    1494                 :      * Set or change the properties of new selectors
    1495                 :      * to the values of an existing selector
    1496                 :      *
    1497                 :      * @param string $new New selector(s) that should share the same
    1498                 :      *                    definitions, separated by commas
    1499                 :      * @param string $old Selector that is already defined
    1500                 :      *
    1501                 :      * @return     void|PEAR_Error
    1502                 :      * @since      version 0.2.0 (2003-07-31)
    1503                 :      * @access     public
    1504                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_NO_ELEMENT
    1505                 :      */
    1506                 :     function setSameStyle($new, $old)
    1507                 :     {
    1508               4 :         if (!is_string($new)) {                                                      
    1509               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1510               1 :                 array('var' => '$new',                                               
    1511               1 :                       'was' => gettype($new),                                        
    1512               1 :                       'expected' => 'string',                                        
    1513               1 :                       'paramnum' => 1));                                             
    1514                 :
    1515               4 :         } elseif (!is_string($old)) {                                                
    1516               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1517               1 :                 array('var' => '$old',                                               
    1518               1 :                       'was' => gettype($old),                                        
    1519               1 :                       'expected' => 'string',                                        
    1520               1 :                       'paramnum' => 2));                                             
    1521                 :
    1522               4 :         } elseif (strpos($new, ',')) {                                               
    1523                 :             // Check if there are any groups.
    1524               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
    1525               1 :                 array('var' => '$new',                                               
    1526               1 :                       'was' => $new,                                                 
    1527               1 :                       'expected' => 'string without comma',                          
    1528               1 :                       'paramnum' => 1));                                             
    1529                 :
    1530               3 :         } elseif (strpos($old, ',')) {                                               
    1531                 :             // Check if there are any groups.
    1532               0 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',          
    1533               0 :                 array('var' => '$old',                                               
    1534               0 :                       'was' => $old,                                                 
    1535               0 :                       'expected' => 'string without comma',                          
    1536               0 :                       'paramnum' => 2));                                             
    1537                 :         }                                                                            
    1538                 :
    1539               3 :         $old = $this->parseSelectors($old);                                          
    1540               3 :         if (!isset($this->_css[$old])) {                                             
    1541               1 :             return $this->raiseError(HTML_CSS_ERROR_NO_ELEMENT, 'error',             
    1542               1 :                 array('identifier' => $old));                                        
    1543                 :         }                                                                            
    1544                 :
    1545               2 :         $selector = implode(', ', array($old, $new));                                
    1546               2 :         $grp      = $this->createGroup($selector, 'samestyleas_'.$old);              
    1547                 :
    1548               2 :         $others = $this->parseSelectors($new, 1);                                    
    1549               2 :         foreach ($others as $other) {                                                
    1550               2 :             $other = trim($other);                                                   
    1551               2 :             foreach ($this->_css[$old] as $rank => $property) {                      
    1552               2 :                 if (!is_numeric($rank)) {                                            
    1553               2 :                     $property = array($rank => $property);                           
    1554               2 :                 }                                                                    
    1555               2 :                 foreach ($property as $key => $value) {                              
    1556               2 :                     $this->setGroupStyle($grp, $key, $value);                        
    1557               2 :                 }                                                                    
    1558               2 :             }                                                                        
    1559               2 :             unset($this->_css[$old]);                                                
    1560               2 :         }                                                                            
    1561               2 :     }                                                                                
    1562                 :
    1563                 :     /**
    1564                 :      * Set cache flag
    1565                 :      *
    1566                 :      * Define if the document should be cached by the browser. Default to false.
    1567                 :      *
    1568                 :      * @param bool $cache (optional) flag to true to cache result, false otherwise
    1569                 :      *
    1570                 :      * @return     void|PEAR_Error
    1571                 :      * @since      version 0.2.0 (2003-07-31)
    1572                 :      * @access     public
    1573                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT
    1574                 :      */
    1575                 :     function setCache($cache = true)
    1576                 :     {
    1577               2 :         if (!is_bool($cache)) {                                                      
    1578               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1579               1 :                 array('var' => '$cache',                                             
    1580               1 :                       'was' => gettype($cache),                                      
    1581               1 :                       'expected' => 'boolean',                                       
    1582               1 :                       'paramnum' => 1));                                             
    1583                 :         }                                                                            
    1584               1 :         $this->options['cache'] = $cache;                                            
    1585               1 :     }                                                                                
    1586                 :
    1587                 :     /**
    1588                 :      * Returns the cache option value
    1589                 :      *
    1590                 :      * @return     boolean
    1591                 :      * @since      version 1.4.0 (2007-12-13)
    1592                 :      * @access     public
    1593                 :      * @see        setCache()
    1594                 :      */
    1595                 :     function getCache()
    1596                 :     {
    1597               1 :         return $this->__get('cache');                                                
    1598                 :     }                                                                                
    1599                 :
    1600                 :     /**
    1601                 :      * Set Content-Disposition header
    1602                 :      *
    1603                 :      * Define the Content-Disposition header to supply a recommended filename
    1604                 :      * and force the browser to display the save dialog.
    1605                 :      * Default to basename($_SERVER['PHP_SELF']).'.css'
    1606                 :      *
    1607                 :      * @param bool   $enable   (optional)
    1608                 :      * @param string $filename (optional)
    1609                 :      *
    1610                 :      * @return     void|PEAR_Error
    1611                 :      * @since      version 1.3.0 (2007-10-22)
    1612                 :      * @access     public
    1613                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT
    1614                 :      * @see        getContentDisposition()
    1615                 :      * @link       http://pear.php.net/bugs/bug.php?id=12195
    1616                 :      *             Patch by Carsten Wiedmann
    1617                 :      */
    1618                 :     function setContentDisposition($enable = true, $filename = '')
    1619                 :     {
    1620               2 :         if (!is_bool($enable)) {                                                     
    1621               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1622               1 :                 array('var' => '$enable',                                            
    1623               1 :                       'was' => gettype($enable),                                     
    1624               1 :                       'expected' => 'bool',                                          
    1625               1 :                       'paramnum' => 1));                                             
    1626               2 :         } elseif (!is_string($filename)) {                                           
    1627               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1628               1 :                 array('var' => '$filename',                                          
    1629               1 :                       'was' => gettype($filename),                                   
    1630               1 :                       'expected' => 'string',                                        
    1631               1 :                       'paramnum' => 2));                                             
    1632                 :         }                                                                            
    1633                 :
    1634               1 :         if ($enable == false) {                                                      
    1635               0 :             $filename = false;                                                       
    1636               1 :         } elseif ($filename == '') {                                                 
    1637               0 :             $filename = basename($_SERVER['PHP_SELF']) . '.css';                     
    1638               0 :         }                                                                            
    1639                 :
    1640               1 :         $this->options['contentDisposition'] = $filename;                            
    1641               1 :     }                                                                                
    1642                 :
    1643                 :     /**
    1644                 :      * Return the Content-Disposition header
    1645                 :      *
    1646                 :      * Get value of Content-Disposition header (inline filename) used
    1647                 :      * to display results
    1648                 :      *
    1649                 :      * @return     mixed     boolean FALSE if no content disposition, otherwise
    1650                 :      *                       string for inline filename
    1651                 :      * @since      version 1.3.0 (2007-10-22)
    1652                 :      * @access     public
    1653                 :      * @see        setContentDisposition()
    1654                 :      * @link       http://pear.php.net/bugs/bug.php?id=12195
    1655                 :      *             Patch by Carsten Wiedmann
    1656                 :      */
    1657                 :     function getContentDisposition()
    1658                 :     {
    1659               1 :         return $this->__get('contentDisposition');                                   
    1660                 :     }                                                                                
    1661                 :
    1662                 :     /**
    1663                 :      * Set charset value
    1664                 :      *
    1665                 :      * Define the charset for the file. Default to ISO-8859-1 because of CSS1
    1666                 :      * compatability issue for older browsers.
    1667                 :      *
    1668                 :      * @param string $type (optional) Charset encoding; defaults to ISO-8859-1.
    1669                 :      *
    1670                 :      * @return     void|PEAR_Error
    1671                 :      * @since      version 0.2.0 (2003-07-31)
    1672                 :      * @access     public
    1673                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT
    1674                 :      * @see        getCharset()
    1675                 :      */
    1676                 :     function setCharset($type = 'iso-8859-1')
    1677                 :     {
    1678               2 :         if (!is_string($type)) {                                                     
    1679               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1680               1 :                 array('var' => '$type',                                              
    1681               1 :                       'was' => gettype($type),                                       
    1682               1 :                       'expected' => 'string',                                        
    1683               1 :                       'paramnum' => 1));                                             
    1684                 :         }                                                                            
    1685               1 :         $this->options['charset'] = $type;                                           
    1686               1 :     }                                                                                
    1687                 :
    1688                 :     /**
    1689                 :      * Return the charset encoding string
    1690                 :      *
    1691                 :      * By default, HTML_CSS uses iso-8859-1 encoding.
    1692                 :      *
    1693                 :      * @return     string
    1694                 :      * @since      version 0.2.0 (2003-07-31)
    1695                 :      * @access     public
    1696                 :      * @see        setCharset()
    1697                 :      */
    1698                 :     function getCharset()
    1699                 :     {
    1700               1 :         return $this->__get('charset');                                              
    1701                 :     }                                                                                
    1702                 :
    1703                 :     /**
    1704                 :      * Parse a string
    1705                 :      *
    1706                 :      * Parse a string that contains CSS information
    1707                 :      *
    1708                 :      * @param string $str        text string to parse
    1709                 :      * @param bool   $duplicates (optional) Allows or disallows
    1710                 :      *                           duplicate style definitions
    1711                 :      *
    1712                 :      * @return     void|PEAR_Error
    1713                 :      * @since      version 0.3.0 (2003-11-03)
    1714                 :      * @access     public
    1715                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT
    1716                 :      * @see        createGroup(), setGroupStyle(), setStyle()
    1717                 :      */
    1718                 :     function parseString($str, $duplicates = null)
    1719                 :     {
    1720              16 :         if (!is_string($str)) {                                                      
    1721               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1722               1 :                 array('var' => '$str',                                               
    1723               1 :                       'was' => gettype($str),                                        
    1724               1 :                       'expected' => 'string',                                        
    1725               1 :                       'paramnum' => 1));                                             
    1726                 :
    1727              16 :         } elseif (isset($duplicates) && !is_bool($duplicates)) {                     
    1728               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1729               1 :                 array('var' => '$duplicates',                                        
    1730               1 :                       'was' => gettype($duplicates),                                 
    1731               1 :                       'expected' => 'bool',                                          
    1732               1 :                       'paramnum' => 2));                                             
    1733                 :         }                                                                            
    1734                 :
    1735              16 :         if (!isset($duplicates)) {                                                   
    1736              12 :             $duplicates = $this->__get('allowduplicates');                           
    1737              12 :         }                                                                            
    1738                 :
    1739                 :         // Remove comments
    1740              16 :         $str = preg_replace("/\/\*(.*)?\*\//Usi", '', $str);                         
    1741                 :
    1742                 :         // Protect parser vs IE hack
    1743              16 :         $str = str_replace('"\"}\""', '#34#125#34', $str);                           
    1744                 :
    1745                 :         // Parse simple declarative At-Rules
    1746              16 :         $atRules = array();                                                          
    1747              16 :         if (preg_match_all('/^\s*(@[a-z\-]+)\s+(.+);\s*$/m', $str, $atRules,         
    1748              16 :             PREG_SET_ORDER)) {                                                       
    1749               1 :             foreach ($atRules as $value) {                                           
    1750               1 :                 $this->createAtRule(trim($value[1]), trim($value[2]));               
    1751               1 :             }                                                                        
    1752               1 :             $str = preg_replace('/^\s*@[a-z\-]+\s+.+;\s*$/m', '', $str);             
    1753               1 :         }                                                                            
    1754                 :
    1755              16 :         $elements   = array();                                                       
    1756              16 :         $properties = array();                                                       
    1757                 :
    1758                 :         // Parse each element of csscode
    1759              16 :         $parts = explode("}", $str);                                                 
    1760              16 :         foreach ($parts as $part) {                                                  
    1761              16 :             $part = trim($part);                                                     
    1762              16 :             if (strlen($part) == 0) {                                                
    1763              14 :                 continue;                                                            
    1764                 :             }                                                                        
    1765                 :             // prevent invalide css data structure
    1766              16 :             $pos = strpos($part, '{');                                               
    1767              16 :             if (strpos($part, '{', $pos+1) !== false && $part{0} !== '@') {          
    1768                 :
    1769               2 :                 $context  = debug_backtrace();                                       
    1770               2 :                 $context  = @array_pop($context);                                    
    1771               2 :                 $function = strtolower($context['function']);                        
    1772               2 :                 if ($function === 'parsestring') {                                   
    1773               0 :                     $var = 'str';                                                    
    1774               2 :                 } elseif ($function === 'parsefile') {                               
    1775               0 :                     $var = 'filename';                                               
    1776               0 :                 } else {                                                             
    1777               2 :                     $var = 'styles';                                                 
    1778                 :                 }
    1779                 :
    1780               2 :                 return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'error',      
    1781               2 :                     array('var' => '$'.$var,                                         
    1782               2 :                           'was' => 'invalid data source',                            
    1783               2 :                           'expected' => 'valid CSS structure',                       
    1784               2 :                           'paramnum' => 1));                                         
    1785                 :             }                                                                        
    1786              15 :             $parse = preg_split('/\{(.*)\}/', "$part }", -1,                         
    1787              15 :                          PREG_SPLIT_DELIM_CAPTURE);                                  
    1788                 :
    1789              15 :             if (count($parse) == 1) {                                                
    1790              10 :                 list($keystr, $codestr) = explode("{", $part);                       
    1791              10 :                 $elements[]             = trim($keystr);                             
    1792              10 :                 $properties[]           = trim($codestr);                            
    1793              10 :             } else {                                                                 
    1794               7 :                 for ($i = 0; $i < 2; $i++) {                                         
    1795               7 :                     if ($i == 0) {                                                   
    1796               7 :                         $part = ltrim($parse[$i], "\r\n}");                          
    1797               7 :                         $pos  = strpos($part, '{');                                  
    1798               7 :                         if ($pos === false) {                                        
    1799               7 :                             $elements[] = trim($part);                               
    1800               7 :                         } else {                                                     
    1801                 :                             // Remove eol
    1802               1 :                             $part = preg_replace("/\r?\n?/", '', $part);             
    1803                 :
    1804               1 :                             if (strpos($part, '}', $pos+1) === false) {              
    1805                 :                                 // complex declaration block style (nested)
    1806               1 :                                 list($keystr, $codestr) = explode("{", $part);       
    1807               1 :                                 $elements[]             = trim($part);               
    1808               1 :                             } else {                                                 
    1809                 :                                 // simple declaration block style
    1810               0 :                                 $parse        = preg_split('/\{(.*)\}/', "$part }",  
    1811               0 :                                                     -1, PREG_SPLIT_DELIM_CAPTURE);   
    1812               0 :                                 $elements[]   = trim($parse[0]);                     
    1813               0 :                                 $properties[] = trim($parse[1]);                     
    1814                 :                             }
    1815                 :                         }
    1816               7 :                     } else {                                                         
    1817               7 :                         $properties[] = trim($parse[$i]);                            
    1818                 :                     }
    1819               7 :                 }                                                                    
    1820                 :             }
    1821              15 :         }                                                                            
    1822                 :
    1823              14 :         foreach ($elements as $i => $keystr) {                                       
    1824              14 :             if (strpos($keystr, '{') === false) {                                    
    1825              14 :                 $nested_bloc = false;                                                
    1826              14 :             } else {                                                                 
    1827               1 :                 $nested_bloc = true;                                                 
    1828                 :
    1829               1 :                 list($keystr, $nestedsel) = explode("{", $keystr);                   
    1830                 :             }
    1831                 :
    1832              14 :             $key_a   = $this->parseSelectors($keystr, 1);                            
    1833              14 :             $keystr  = implode(', ', $key_a);                                        
    1834              14 :             $codestr = $properties[$i];                                              
    1835                 :             // Check if there are any groups; in standard selectors exclude at-rules
    1836              14 :             if (strpos($keystr, ',') && $keystr{0} !== '@') {                        
    1837               6 :                 $group = $this->createGroup($keystr);                                
    1838                 :
    1839                 :                 // Parse each property of an element
    1840               6 :                 $codes = explode(";", trim($codestr));                               
    1841               6 :                 foreach ($codes as $code) {                                          
    1842               6 :                     if (strlen(trim($code)) > 0) {                                   
    1843                 :                         // find the property and the value
    1844                 :                         $property
    1845               6 :                             = trim(substr($code, 0, strpos($code, ':', 0)));         
    1846                 :                         $value
    1847               6 :                             = trim(substr($code, strpos($code, ':', 0) + 1));        
    1848                 :                         // IE hack only
    1849               6 :                         if (strcasecmp($property, 'voice-family') == 0) {            
    1850                 :                             $value
    1851               0 :                                 = str_replace('#34#125#34', '"\"}\""', $value);      
    1852               0 :                         }                                                            
    1853               6 :                         $this->setGroupStyle($group, $property, $value,              
    1854               6 :                             $duplicates);                                            
    1855               6 :                     }                                                                
    1856               6 :                 }                                                                    
    1857               6 :             } else {                                                                 
    1858                 :                 // let's get on with regular definitions
    1859              12 :                 $key = trim($keystr);                                                
    1860                 :
    1861                 :                 // Parse each property of an element
    1862              12 :                 $codes = explode(";", trim($codestr));                               
    1863              12 :                 foreach ($codes as $code) {                                          
    1864              12 :                     if (strlen(trim($code)) == 0) {                                  
    1865              12 :                         continue;                                                    
    1866                 :                     }                                                                
    1867              12 :                     $code = ltrim($code, "\r\n}");                                   
    1868                 :
    1869              12 :                     $p = trim(substr($code, 0, strpos($code, ':')));                 
    1870              12 :                     $v = trim(substr($code, strpos($code, ':') + 1));                
    1871                 :                     // IE hack only
    1872              12 :                     if (strcasecmp($p, 'voice-family') == 0) {                       
    1873               1 :                         $v = str_replace('#34#125#34', '"\"}\""',                    
    1874               1 :                                      $v);                                            
    1875               1 :                     }                                                                
    1876                 :
    1877              12 :                     if ($key{0} == '@') {                                            
    1878                 :                         // at-rules
    1879               2 :                         list($atKeyword, $arguments) = explode(' ', "$key ");        
    1880               2 :                         if ($nested_bloc) {                                          
    1881               1 :                             $this->setAtRuleStyle($atKeyword, $arguments, $nestedsel,
    1882               1 :                                 $p, $v, $duplicates);                                
    1883               1 :                         } else {                                                     
    1884               2 :                             $this->setAtRuleStyle($atKeyword, $arguments, '',        
    1885               2 :                                 $p, $v, $duplicates);                                
    1886                 :                         }
    1887                 :
    1888               2 :                     } else {                                                         
    1889                 :                         // simple declarative style
    1890              11 :                         $this->setStyle($key, $p, $v, $duplicates);                  
    1891                 :                     }
    1892              12 :                 }                                                                    
    1893                 :             }
    1894              14 :         }                                                                            
    1895              14 :     }                                                                                
    1896                 :
    1897                 :     /**
    1898                 :      * Parse file content
    1899                 :      *
    1900                 :      * Parse a file that contains CSS information
    1901                 :      *
    1902                 :      * @param string $filename   file to parse
    1903                 :      * @param bool   $duplicates (optional) Allow or disallow duplicates.
    1904                 :      *
    1905                 :      * @return     void|PEAR_Error
    1906                 :      * @since      version 0.3.0 (2003-11-03)
    1907                 :      * @access     public
    1908                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_NO_FILE
    1909                 :      * @see        parseString()
    1910                 :      */
    1911                 :     function parseFile($filename, $duplicates = null)
    1912                 :     {
    1913               3 :         if (!is_string($filename)) {                                                 
    1914               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1915               1 :                 array('var' => '$filename',                                          
    1916               1 :                       'was' => gettype($filename),                                   
    1917               1 :                       'expected' => 'string',                                        
    1918               1 :                       'paramnum' => 1));                                             
    1919                 :
    1920               3 :         } elseif (!file_exists($filename)) {                                         
    1921               1 :             return $this->raiseError(HTML_CSS_ERROR_NO_FILE, 'error',                
    1922               1 :                     array('identifier' => $filename));                               
    1923                 :
    1924               3 :         } elseif (isset($duplicates) && !is_bool($duplicates)) {                     
    1925               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1926               1 :                 array('var' => '$duplicates',                                        
    1927               1 :                       'was' => gettype($duplicates),                                 
    1928               1 :                       'expected' => 'bool',                                          
    1929               1 :                       'paramnum' => 2));                                             
    1930                 :         }                                                                            
    1931                 :
    1932               2 :         if (!isset($duplicates)) {                                                   
    1933               1 :             $duplicates = $this->__get('allowduplicates');                           
    1934               1 :         }                                                                            
    1935                 :
    1936               2 :         $ret = $this->parseString(file_get_contents($filename), $duplicates);        
    1937               2 :         return $ret;                                                                 
    1938                 :     }                                                                                
    1939                 :
    1940                 :     /**
    1941                 :      * Parse multiple data sources
    1942                 :      *
    1943                 :      * Parse data sources, file(s) or string(s), that contains CSS information
    1944                 :      *
    1945                 :      * @param array $styles     data sources to parse
    1946                 :      * @param bool  $duplicates (optional) Allow or disallow duplicates.
    1947                 :      *
    1948                 :      * @return     void|PEAR_Error
    1949                 :      * @since      version 1.0.0RC2 (2005-12-15)
    1950                 :      * @access     public
    1951                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT
    1952                 :      * @see        parseString(), parseFile()
    1953                 :      */
    1954                 :     function parseData($styles, $duplicates = null)
    1955                 :     {
    1956               2 :         if (!is_array($styles)) {                                                    
    1957               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1958               1 :                 array('var' => '$styles',                                            
    1959               1 :                       'was' => gettype($styles),                                     
    1960               1 :                       'expected' => 'array',                                         
    1961               1 :                       'paramnum' => 1));                                             
    1962                 :
    1963               2 :         } elseif (isset($duplicates) && !is_bool($duplicates)) {                     
    1964               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    1965               1 :                 array('var' => '$duplicates',                                        
    1966               1 :                       'was' => gettype($duplicates),                                 
    1967               1 :                       'expected' => 'bool',                                          
    1968               1 :                       'paramnum' => 2));                                             
    1969                 :         }                                                                            
    1970                 :
    1971               2 :         if (!isset($duplicates)) {                                                   
    1972               2 :             $duplicates = $this->__get('allowduplicates');                           
    1973               2 :         }                                                                            
    1974                 :
    1975               2 :         foreach ($styles as $i => $style) {                                          
    1976               2 :             if (!is_string($style)) {                                                
    1977               1 :                 return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',  
    1978               1 :                     array('var' => '$styles[' . $i . ']',                            
    1979               1 :                           'was' => gettype($styles[$i]),                             
    1980               1 :                           'expected' => 'string',                                    
    1981               1 :                           'paramnum' => 1));                                         
    1982                 :             }                                                                        
    1983               2 :             if (strcasecmp(substr($style, -4, 4), '.css') == 0) {                    
    1984               1 :                 $this->parseFile($style, $duplicates);                               
    1985               1 :             } else {                                                                 
    1986               2 :                 $this->parseString($style, $duplicates);                             
    1987                 :             }
    1988               2 :         }                                                                            
    1989               1 :     }                                                                                
    1990                 :
    1991                 :     /**
    1992                 :      * Validate a CSS data source
    1993                 :      *
    1994                 :      * Execute the W3C CSS validator service on each data source (filename
    1995                 :      * or string) given by parameter $styles.
    1996                 :      *
    1997                 :      * @param array $styles    Data sources to check validity
    1998                 :      * @param array &$messages Error and Warning messages
    1999                 :      *                         issue from W3C CSS validator service
    2000                 :      *
    2001                 :      * @return     boolean|PEAR_Error
    2002                 :      * @since      version 1.5.0 (2008-01-15)
    2003                 :      * @access     public
    2004                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT,
    2005                 :      *             HTML_CSS_ERROR_INVALID_DEPS, HTML_CSS_ERROR_INVALID_SOURCE
    2006                 :      */
    2007                 :     function validate($styles, &$messages)
    2008                 :     {
    2009               1 :         $php = phpversion();                                                         
    2010               1 :         if (version_compare($php, '5.0.0', '<')) {                                   
    2011               0 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_DEPS, 'exception',       
    2012               0 :                 array('funcname' => __FUNCTION__,                                    
    2013               0 :                       'dependency' => 'PHP 5',                                       
    2014               0 :                       'currentdep' => "PHP $php"));                                  
    2015                 :         }                                                                            
    2016               1 :         @include_once 'Services/W3C/CSSValidator.php';                               
    2017               1 :         if (class_exists('Services_W3C_CSSValidator', false) === false) {            
    2018               0 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_DEPS, 'exception',       
    2019               0 :                 array('funcname' => __FUNCTION__,                                    
    2020               0 :                       'dependency' => 'PEAR::Services_W3C_CSSValidator',             
    2021               0 :                       'currentdep' => 'nothing'));                                   
    2022                 :         }                                                                            
    2023               1 :         if (!is_array($styles)) {                                                    
    2024               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    2025               1 :                 array('var' => '$styles',                                            
    2026               1 :                       'was' => gettype($styles),                                     
    2027               1 :                       'expected' => 'array',                                         
    2028               1 :                       'paramnum' => 1));                                             
    2029                 :
    2030               1 :         } elseif (!is_array($messages)) {                                            
    2031               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    2032               1 :                 array('var' => '$messages',                                          
    2033               1 :                       'was' => gettype($messages),                                   
    2034               1 :                       'expected' => 'array',                                         
    2035               1 :                       'paramnum' => 2));                                             
    2036                 :         }                                                                            
    2037                 :
    2038                 :         // prepare to call the W3C CSS validator service
    2039               0 :         $v        = new Services_W3C_CSSValidator();                                 
    2040               0 :         $validity = true;                                                            
    2041               0 :         $messages = array('errors' => array(), 'warnings' => array());               
    2042                 :
    2043               0 :         foreach ($styles as $i => $source) {                                         
    2044               0 :             if (!is_string($source)) {                                               
    2045               0 :                 return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',  
    2046               0 :                     array('var' => '$styles[' . $i . ']',                            
    2047               0 :                           'was' => gettype($styles[$i]),                             
    2048               0 :                           'expected' => 'string',                                    
    2049               0 :                           'paramnum' => 1));                                         
    2050                 :             }                                                                        
    2051               0 :             if (strcasecmp(substr($source, -4, 4), '.css') == 0) {                   
    2052                 :                 // validate a file as CSS content
    2053               0 :                 $r = $v->validateFile($source);                                      
    2054               0 :             } else {                                                                 
    2055                 :                 // validate a string as CSS content
    2056               0 :                 $r = $v->validateFragment($source);                                  
    2057                 :             }
    2058               0 :             if ($r === false) {                                                      
    2059               0 :                 $validity = false;                                                   
    2060               0 :             }                                                                        
    2061               0 :             if ($r->isValid() === false) {                                           
    2062               0 :                 $validity = false;                                                   
    2063               0 :                 foreach ($r->errors as $error) {                                     
    2064               0 :                     $properties           = get_object_vars($error);                 
    2065               0 :                     $messages['errors'][] = $properties;                             
    2066               0 :                 }                                                                    
    2067               0 :                 foreach ($r->warnings as $warning) {                                 
    2068               0 :                     $properties             = get_object_vars($warning);             
    2069               0 :                     $messages['warnings'][] = $properties;                           
    2070               0 :                 }                                                                    
    2071               0 :                 $this->raiseError(HTML_CSS_ERROR_INVALID_SOURCE,                     
    2072               0 :                     ((count($r->errors) == 0) ? 'warning' : 'error'),                
    2073               0 :                     array('sourcenum' => $i,                                         
    2074               0 :                           'errcount' => count($r->errors),                           
    2075               0 :                           'warncount' => count($r->warnings)));                      
    2076               0 :             }                                                                        
    2077               0 :         }                                                                            
    2078               0 :         return $validity;                                                            
    2079                 :     }                                                                                
    2080                 :
    2081                 :     /**
    2082                 :      * Return the CSS contents in an array
    2083                 :      *
    2084                 :      * Return the full contents of CSS data sources (parsed) in an array
    2085                 :      *
    2086                 :      * @return     array
    2087                 :      * @since      version 0.2.0 (2003-07-31)
    2088                 :      * @access     public
    2089                 :      */
    2090                 :     function toArray()
    2091                 :     {
    2092              19 :         $css = array();                                                              
    2093                 :
    2094                 :         // bring AtRules in correct order
    2095              19 :         $this->sortAtRules();                                                        
    2096                 :
    2097              19 :         foreach ($this->_css as $key => $value) {                                    
    2098              19 :             if (strpos($key, '@-') === 0) {                                          
    2099              10 :                 $key = implode(', ', $this->_groups[$key]);                          
    2100              10 :             }                                                                        
    2101              19 :             $css[$key] = $value;                                                     
    2102              19 :         }                                                                            
    2103              19 :         return $css;                                                                 
    2104                 :     }                                                                                
    2105                 :
    2106                 :     /**
    2107                 :      * Return a string-properties for style attribute of an HTML element
    2108                 :      *
    2109                 :      * Generate and return the CSS properties of an element or class
    2110                 :      * as a string for inline use.
    2111                 :      *
    2112                 :      * @param string $element Element or class
    2113                 :      *                        for which inline CSS should be generated
    2114                 :      *
    2115                 :      * @return     string|PEAR_Error
    2116                 :      * @since      version 0.2.0 (2003-07-31)
    2117                 :      * @access     public
    2118                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT
    2119                 :      */
    2120                 :     function toInline($element)
    2121                 :     {
    2122               2 :         if (!is_string($element)) {                                                  
    2123               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    2124               1 :                 array('var' => '$element',                                           
    2125               1 :                       'was' => gettype($element),                                    
    2126               1 :                       'expected' => 'string',                                        
    2127               1 :                       'paramnum' => 1));                                             
    2128                 :         }                                                                            
    2129                 :
    2130               1 :         $strCss      = '';                                                           
    2131               1 :         $newCssArray = array();                                                      
    2132                 :
    2133                 :         // This allows for grouped elements definitions to work
    2134               1 :         if (isset($this->_alibis[$element])) {                                       
    2135               1 :             $alibis = $this->_alibis[$element];                                      
    2136                 :
    2137                 :             // All the groups must be run through to be able to
    2138                 :             // properly assign the value to the inline.
    2139               1 :             foreach ($alibis as $alibi) {                                            
    2140               1 :                 foreach ($this->_css[$alibi] as $key => $value) {                    
    2141               1 :                     $newCssArray[$key] = $value;                                     
    2142               1 :                 }                                                                    
    2143               1 :             }                                                                        
    2144               1 :         }                                                                            
    2145                 :
    2146                 :         // This allows for single elements definitions to work
    2147               1 :         if (isset($this->_css[$element])) {                                          
    2148               0 :             foreach ($this->_css[$element] as $rank => $property) {                  
    2149               0 :                 if (!is_numeric($rank)) {                                            
    2150               0 :                     $property = array($rank => $property);                           
    2151               0 :                 }                                                                    
    2152               0 :                 foreach ($property as $key => $value) {                              
    2153               0 :                     if ($key != 'other-elements') {                                  
    2154               0 :                         $newCssArray[$key] = $value;                                 
    2155               0 :                     }                                                                
    2156               0 :                 }                                                                    
    2157               0 :             }                                                                        
    2158               0 :         }                                                                            
    2159                 :
    2160               1 :         foreach ($newCssArray as $key => $value) {                                   
    2161               1 :             if ((0 === strpos($element, '@')) && ('' == $value)) {                   
    2162                 :                 // simple declarative At-Rule definition
    2163               0 :                 $strCss .= $key . ';';                                               
    2164               0 :             } else {                                                                 
    2165                 :                 // other CSS definition
    2166               1 :                 $strCss .= $key . ':' . $value . ";";                                
    2167                 :             }
    2168               1 :         }                                                                            
    2169                 :
    2170               1 :         return $strCss;                                                              
    2171                 :     }                                                                                
    2172                 :
    2173                 :     /**
    2174                 :      * Generate CSS and stores it in a file
    2175                 :      *
    2176                 :      * Generate current parsed CSS data sources and write result in a user file
    2177                 :      *
    2178                 :      * @param string $filename Name of file that content the stylesheet
    2179                 :      *
    2180                 :      * @return     void|PEAR_Error
    2181                 :      * @since      version 0.3.0 (2003-11-03)
    2182                 :      * @access     public
    2183                 :      * @throws     HTML_CSS_ERROR_INVALID_INPUT, HTML_CSS_ERROR_WRITE_FILE
    2184                 :      * @see        toString()
    2185                 :      */
    2186                 :     function toFile($filename)
    2187                 :     {
    2188               2 :         if (!is_string($filename)) {                                                 
    2189               1 :             return $this->raiseError(HTML_CSS_ERROR_INVALID_INPUT, 'exception',      
    2190               1 :                 array('var' => '$filename',                                          
    2191               1 :                       'was' => gettype($filename),                                   
    2192               1 :                       'expected' => 'string',                                        
    2193               1 :                       'paramnum' => 1));                                             
    2194                 :         }                                                                            
    2195                 :
    2196               1 :         if (function_exists('file_put_contents')) {                                  
    2197               1 :             file_put_contents($filename, $this->toString());                         
    2198               1 :         } else {                                                                     
    2199               0 :             $file = fopen($filename, 'wb');                                          
    2200               0 :             fwrite($file, $this->toString());                                        
    2201               0 :             fclose($file);                                                           
    2202                 :         }
    2203               1 :         if (!file_exists($filename)) {                                               
    2204               0 :             return $this->raiseError(HTML_CSS_ERROR_WRITE_FILE, 'error',             
    2205               0 :                     array('filename' => $filename));                                 
    2206                 :         }                                                                            
    2207               1 :     }                                                                                
    2208                 :
    2209                 :     /**
    2210                 :      * Return current CSS parsed data as a string
    2211                 :      *
    2212                 :      * Generate current parsed CSS data sources and return result as a string
    2213                 :      *
    2214                 :      * @return     string
    2215                 :      * @since      version 0.2.0 (2003-07-31)
    2216                 :      * @access     public
    2217                 :      */
    2218                 :     function toString()
    2219                 :     {
    2220                 :         // get line endings
    2221               2 :         $lnEnd = $this->_getLineEnd();                                               
    2222               2 :         $tabs  = $this->_getTabs();                                                  
    2223               2 :         $tab   = $this->_getTab();                                                   
    2224                 :
    2225                 :         // initialize $alibis
    2226               2 :         $alibis = array();                                                           
    2227                 :
    2228               2 :         $strCss     = '';                                                            
    2229               2 :         $strAtRules = '';                                                            
    2230                 :
    2231                 :         // Allow a CSS comment
    2232               2 :         if ($this->_comment) {                                                       
    2233               0 :             $strCss = $tabs . '/* ' . $this->getComment() . ' */' . $lnEnd;          
    2234               0 :         }                                                                            
    2235                 :
    2236                 :         // If groups are to be output first, initialize a special variable
    2237               2 :         if ($this->__get('groupsfirst')) {                                           
    2238               2 :             $strCssElements = '';                                                    
    2239               2 :         }                                                                            
    2240                 :
    2241                 :         // bring AtRules in correct order
    2242               2 :         $this->sortAtRules();                                                        
    2243                 :
    2244                 :         // Iterate through the array and process each element
    2245               2 :         foreach ($this->_css as $identifier => $rank) {                              
    2246                 :
    2247                 :             // Groups are handled separately
    2248               2 :             if (strpos($identifier, '@-') !== false) {                               
    2249                 :                 // its a group
    2250               2 :                 $element = implode(', ', $this->_groups[$identifier]);               
    2251               2 :             } else {                                                                 
    2252               1 :                 $element = $identifier;                                              
    2253                 :             }
    2254                 :
    2255               2 :             if ((0 === strpos($element, '@')) && (1 !== strpos($element, '-'))) {    
    2256                 :                 // simple declarative At-Rule definition
    2257               0 :                 foreach ($rank as $arg => $decla) {                                  
    2258               0 :                     if (is_array($decla)) {                                          
    2259               0 :                         $strAtRules .= $element . ' ' . $arg;                        
    2260               0 :                         foreach ($decla as $s => $d) {                               
    2261               0 :                             $t = $tabs . $tab;                                       
    2262               0 :                             if (empty($s)) {                                         
    2263               0 :                                 $strAtRules .= ' {' . $lnEnd;                        
    2264               0 :                             } else {                                                 
    2265               0 :                                 $t          .= $tab;                                 
    2266               0 :                                 $strAtRules .= ' {' . $lnEnd .                       
    2267               0 :                                     $tab . $s . ' {' . $lnEnd;                       
    2268                 :                             }
    2269               0 :                             foreach ($d as $p => $v) {                               
    2270               0 :                                 $strAtRules .= $t . $p . ': ' . $v . ';' . $lnEnd;   
    2271               0 :                             }                                                        
    2272               0 :                             if (empty($s)) {                                         
    2273               0 :                                 $strAtRules .= $tabs . '}';                          
    2274               0 :                             } else {                                                 
    2275               0 :                                 $strAtRules .=  $tabs . $tab . '}' . $lnEnd . '}';   
    2276                 :                             }
    2277               0 :                         }                                                            
    2278               0 :                         $strAtRules .=  $lnEnd . $lnEnd;;                            
    2279               0 :                     } else {                                                         
    2280               0 :                         $strAtRules .= $element . ' ' . $arg . ';' . $lnEnd . $lnEnd;
    2281                 :                     }
    2282               0 :                 }                                                                    
    2283               0 :             } else {                                                                 
    2284                 :                 // Start CSS element definition
    2285               2 :                 $definition = $element . ' {' . $lnEnd;                              
    2286                 :
    2287                 :                 // Iterate through the array of properties
    2288               2 :                 foreach ($rank as $pos => $property) {                               
    2289                 :                     // check to see if it is a duplicate
    2290               2 :                     if (!is_numeric($pos)) {                                         
    2291               2 :                         $property = array($pos => $property);                        
    2292               2 :                         unset($pos);                                                 
    2293               2 :                     }                                                                
    2294               2 :                     foreach ($property as $key => $value) {                          
    2295                 :                         $definition .= $tabs . $tab
    2296               2 :                                     . $key . ': ' . $value . ';' . $lnEnd;           
    2297               2 :                     }                                                                
    2298               2 :                 }                                                                    
    2299                 :
    2300                 :                 // end CSS element definition
    2301               2 :                 $definition .= $tabs . '}';                                          
    2302                 :             }
    2303                 :
    2304                 :             // if this is to be on a single line, collapse
    2305               2 :             if ($this->options['oneline']) {                                         
    2306               1 :                 $definition = $this->collapseInternalSpaces($definition);            
    2307               1 :                 $strAtRules = $this->collapseInternalSpaces($strAtRules);            
    2308               1 :             }                                                                        
    2309                 :
    2310                 :             // if groups are to be output first, elements must be placed in a
    2311                 :             // different string which will be appended in the end
    2312               2 :             if (isset($definition)) {                                                
    2313               2 :                 if ($this->__get('groupsfirst') === true                             
    2314               2 :                     && strpos($identifier, '@-') === false) {                        
    2315                 :                     // add to elements
    2316               1 :                     $strCssElements .= $lnEnd . $tabs . $definition . $lnEnd;        
    2317               1 :                 } else {                                                             
    2318                 :                     // add to strCss
    2319               2 :                     $strCss .= $lnEnd . $tabs . $definition . $lnEnd;                
    2320                 :                 }
    2321               2 :             }                                                                        
    2322               2 :         }                                                                            
    2323                 :
    2324               2 :         if ($this->__get('groupsfirst')) {                                           
    2325               2 :             $strCss .= $strCssElements;                                              
    2326               2 :         }                                                                            
    2327                 :
    2328               2 :         $strAtRules = rtrim($strAtRules);                                            
    2329               2 :         if (!empty($strAtRules)) {                                                   
    2330               0 :             $strAtRules .= $lnEnd;                                                   
    2331               0 :         }                                                                            
    2332               2 :         $strCss = $strAtRules . $strCss;                                             
    2333                 :
    2334               2 :         if ($this->options['oneline']) {                                             
    2335               1 :             $strCss = preg_replace('/(\n|\r\n|\r)/', '', $strCss);                   
    2336               1 :         }                                                                            
    2337                 :
    2338               2 :         return $strCss;                                                              
    2339                 :     }                                                                                
    2340                 :
    2341                 :     /**
    2342                 :      * Output CSS Code.
    2343                 :      *
    2344                 :      * Send the stylesheet content to standard output, handling cacheControl
    2345                 :      * and contentDisposition headers
    2346                 :      *
    2347                 :      * @return     void
    2348                 :      * @since      version 0.2.0 (2003-07-31)
    2349                 :      * @access     public
    2350                 :      * @see        toString()
    2351                 :      */
    2352                 :     function display()
    2353                 :     {
    2354               1 :         if (!headers_sent()) {                                                       
    2355               0 :             if ($this->__get('cache') !== true) {                                    
    2356               0 :                 header("Expires: Tue, 1 Jan 1980 12:00:00 GMT");                     
    2357               0 :                 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");       
    2358               0 :                 header("Cache-Control: no-cache");                                   
    2359               0 :                 header("Pragma: no-cache");                                          
    2360               0 :             }                                                                        
    2361                 :
    2362                 :             // set character encoding
    2363               0 :             header("Content-Type: text/css; charset=" . $this->__get('charset'));    
    2364                 :
    2365                 :             // set Content-Disposition
    2366               0 :             if ($this->__get('contentDisposition') !== false) {                      
    2367               0 :                 header('Content-Disposition: inline; filename="' .                   
    2368               0 :                     $this->__get('contentDisposition') . '"');                       
    2369               0 :             }                                                                        
    2370               0 :         }                                                                            
    2371                 :
    2372               1 :         $strCss = $this->toString();                                                 
    2373               1 :         print $strCss;                                                               
    2374               1 :     }                                                                                
    2375                 :
    2376                 :     /**
    2377                 :      * Initialize Error engine preferences
    2378                 :      *
    2379                 :      * @param array $prefs (optional) hash of params to customize error generation
    2380                 :      *
    2381                 :      * @return     void
    2382                 :      * @since      version 0.3.3 (2004-05-20)
    2383                 :      * @access     private
    2384                 :      */
    2385                 :     function _initErrorStack($prefs = array())
    2386                 :     {
    2387                 :         // error message mapping callback
    2388              48 :         if (isset($prefs['message_callback'])                                        
    2389              48 :             && is_callable($prefs['message_callback'])) {                            
    2390               0 :             $this->_callback_message = $prefs['message_callback'];                   
    2391               0 :         } else {                                                                     
    2392              48 :             $this->_callback_message = array('HTML_CSS_Error', '_msgCallback');      
    2393                 :         }
    2394                 :
    2395                 :         // error context mapping callback
    2396              48 :         if (isset($prefs['context_callback'])                                        
    2397              48 :             && is_callable($prefs['context_callback'])) {                            
    2398               0 :             $this->_callback_context = $prefs['context_callback'];                   
    2399               0 :         } else {                                                                     
    2400              48 :             $this->_callback_context = array('HTML_CSS_Error', 'getBacktrace');      
    2401                 :         }
    2402                 :
    2403                 :         // determine whether to allow an error to be pushed or logged
    2404              48 :         if (isset($prefs['push_callback'])                                           
    2405              48 :             && is_callable($prefs['push_callback'])) {                               
    2406              48 :             $this->_callback_push = $prefs['push_callback'];                         
    2407              48 :         } else {                                                                     
    2408               2 :             $this->_callback_push = array('HTML_CSS_Error', '_handleError');         
    2409                 :         }
    2410                 :
    2411                 :         // determine whether to display or log an error by a free user function
    2412              48 :         if (isset($prefs['error_callback'])                                          
    2413              48 :             && is_callable($prefs['error_callback'])) {                              
    2414              48 :             $this->_callback_error = $prefs['error_callback'];                       
    2415              48 :         } else {                                                                     
    2416               2 :             $this->_callback_error = null;                                           
    2417                 :         }
    2418                 :
    2419                 :         // default error handler will use PEAR_Error
    2420              48 :         if (isset($prefs['error_handler'])                                           
    2421              48 :             && is_callable($prefs['error_handler'])) {                               
    2422               0 :             $this->_callback_errorhandler = $prefs['error_handler'];                 
    2423               0 :         } else {                                                                     
    2424              48 :             $this->_callback_errorhandler = array(&$this, '_errorHandler');          
    2425                 :         }
    2426                 :
    2427                 :         // any handler-specific settings
    2428              48 :         if (isset($prefs['handler'])) {                                              
    2429               0 :             $this->_errorhandler_options = $prefs['handler'];                        
    2430               0 :         }                                                                            
    2431              48 :     }                                                                                
    2432                 :
    2433                 :     /**
    2434                 :      * Standard error handler that will use PEAR_Error object
    2435                 :      *
    2436                 :      * To improve performances, the PEAR.php file is included dynamically.
    2437                 :      * The file is so included only when an error is triggered. So, in most
    2438                 :      * cases, the file isn't included and perfs are much better.
    2439                 :      *
    2440                 :      * @param integer $code   Error code.
    2441                 :      * @param string  $level  The error level of the message.
    2442                 :      * @param array   $params Associative array of error parameters
    2443                 :      *
    2444                 :      * @return     PEAR_Error
    2445                 :      * @since      version 1.0.0 (2006-06-24)
    2446                 :      * @access     private
    2447                 :      */
    2448                 :     function _errorHandler($code, $level, $params)
    2449                 :     {
    2450               4 :         include_once 'HTML/CSS/Error.php';                                           
    2451                 :
    2452               4 :         $mode    = call_user_func($this->_callback_push, $code, $level);             
    2453               4 :         $message = call_user_func($this->_callback_message, $code, $params);         
    2454               4 :         $options = $this->_callback_error;                                           
    2455                 :
    2456               4 :         $userinfo['level'] = $level;                                                 
    2457                 :
    2458               4 :         if (isset($this->_errorhandler_options['display'])) {                        
    2459               0 :             $userinfo['display'] = $this->_errorhandler_options['display'];          
    2460               0 :         } else {                                                                     
    2461               4 :             $userinfo['display'] = array();                                          
    2462                 :         }
    2463               4 :         if (isset($this->_errorhandler_options['log'])) {                            
    2464               0 :             $userinfo['log'] = $this->_errorhandler_options['log'];                  
    2465               0 :         } else {                                                                     
    2466               4 :             $userinfo['log'] = array();                                              
    2467                 :         }
    2468                 :
    2469               4 :         return PEAR::raiseError($message, $code, $mode, $options, $userinfo,         
    2470               4 :                    'HTML_CSS_Error');                                                
    2471                 :     }                                                                                
    2472                 :
    2473                 :     /**
    2474                 :      * A basic wrapper around the default PEAR_Error object
    2475                 :      *
    2476                 :      * This method is a wrapper that returns an instance of the configured
    2477                 :      * error class with this object's default error handling applied.
    2478                 :      *
    2479                 :      * @return     object    PEAR_Error when default error handler is used
    2480                 :      * @since      version 0.3.3 (2004-05-20)
    2481                 :      * @access     public
    2482                 :      * @see        _errorHandler()
    2483                 :      */
    2484                 :     function raiseError()
    2485                 :     {
    2486               4 :         $args = func_get_args();                                                     
    2487               4 :         $this->_lastError                                                            
    2488               4 :             = call_user_func_array($this->_callback_errorhandler, $args);            
    2489               4 :         return $this->_lastError;                                                    
    2490                 :     }                                                                                
    2491                 :
    2492                 :     /**
    2493                 :      * Determine whether there is an error
    2494                 :      *
    2495                 :      * Determine whether last action raised an error or not
    2496                 :      *
    2497                 :      * @return     boolean               TRUE if error raised, FALSE otherwise
    2498                 :      * @since      version 1.0.0RC2 (2005-12-15)
    2499                 :      * @access     public
    2500                 :      */
    2501                 :     function isError()
    2502                 :     {
    2503               0 :          $res              = (!is_bool($this->_lastError));                          
    2504               0 :          $this->_lastError = false;                                                  
    2505               0 :          return $res;                                                                
    2506                 :     }                                                                                
    2507                 : }

Generated by PHPUnit 3.3.14 and Xdebug 2.0.4 at Wed Feb 11 17:47:26 CET 2009.