Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  class cssparser {
  18    private $css;
  19    private $html;
  20  
  21    public function __construct($html = true) {
  22      // Register "destructor"
  23      core_shutdown_manager::register_function(array(&$this, "finalize"));
  24      $this->html = ($html != false);
  25      $this->Clear();
  26    }
  27  
  28    /**
  29     * Old syntax of class constructor. Deprecated in PHP7.
  30     *
  31     * @deprecated since Moodle 3.1
  32     */
  33    public function cssparser($html = true) {
  34        debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
  35        self::__construct($html);
  36    }
  37  
  38    function finalize() {
  39      unset($this->css);
  40    }
  41  
  42    function Clear() {
  43      unset($this->css);
  44      $this->css = array();
  45      if($this->html) {
  46        $this->Add("ADDRESS", "");
  47        $this->Add("APPLET", "");
  48        $this->Add("AREA", "");
  49        $this->Add("A", "text-decoration : underline; color : Blue;");
  50        $this->Add("A:visited", "color : Purple;");
  51        $this->Add("BASE", "");
  52        $this->Add("BASEFONT", "");
  53        $this->Add("BIG", "");
  54        $this->Add("BLOCKQUOTE", "");
  55        $this->Add("BODY", "");
  56        $this->Add("BR", "");
  57        $this->Add("B", "font-weight: bold;");
  58        $this->Add("CAPTION", "");
  59        $this->Add("CENTER", "");
  60        $this->Add("CITE", "");
  61        $this->Add("CODE", "");
  62        $this->Add("DD", "");
  63        $this->Add("DFN", "");
  64        $this->Add("DIR", "");
  65        $this->Add("DIV", "");
  66        $this->Add("DL", "");
  67        $this->Add("DT", "");
  68        $this->Add("EM", "");
  69        $this->Add("FONT", "");
  70        $this->Add("FORM", "");
  71        $this->Add("H1", "");
  72        $this->Add("H2", "");
  73        $this->Add("H3", "");
  74        $this->Add("H4", "");
  75        $this->Add("H5", "");
  76        $this->Add("H6", "");
  77        $this->Add("HEAD", "");
  78        $this->Add("HR", "");
  79        $this->Add("HTML", "");
  80        $this->Add("IMG", "");
  81        $this->Add("INPUT", "");
  82        $this->Add("ISINDEX", "");
  83        $this->Add("I", "font-style: italic;");
  84        $this->Add("KBD", "");
  85        $this->Add("LINK", "");
  86        $this->Add("LI", "");
  87        $this->Add("MAP", "");
  88        $this->Add("MENU", "");
  89        $this->Add("META", "");
  90        $this->Add("OL", "");
  91        $this->Add("OPTION", "");
  92        $this->Add("PARAM", "");
  93        $this->Add("PRE", "");
  94        $this->Add("P", "");
  95        $this->Add("SAMP", "");
  96        $this->Add("SCRIPT", "");
  97        $this->Add("SELECT", "");
  98        $this->Add("SMALL", "");
  99        $this->Add("STRIKE", "");
 100        $this->Add("STRONG", "");
 101        $this->Add("STYLE", "");
 102        $this->Add("SUB", "");
 103        $this->Add("SUP", "");
 104        $this->Add("TABLE", "");
 105        $this->Add("TD", "");
 106        $this->Add("TEXTAREA", "");
 107        $this->Add("TH", "");
 108        $this->Add("TITLE", "");
 109        $this->Add("TR", "");
 110        $this->Add("TT", "");
 111        $this->Add("UL", "");
 112        $this->Add("U", "text-decoration : underline;");
 113        $this->Add("VAR", "");
 114      }
 115    }
 116  
 117    function SetHTML($html) {
 118      $this->html = ($html != false);
 119    }
 120  
 121    function Add($key, $codestr) {
 122      $key = strtolower($key);
 123      $codestr = strtolower($codestr);
 124      if(!isset($this->css[$key])) {
 125        $this->css[$key] = array();
 126      }
 127      $codes = explode(";",$codestr);
 128      if(count($codes) > 0) {
 129        $codekey=''; $codevalue='';
 130        foreach($codes as $code) {
 131          $code = trim($code);
 132          $this->assignValues(explode(":",$code),$codekey,$codevalue);
 133          if(strlen($codekey) > 0) {
 134            $this->css[$key][trim($codekey)] = trim($codevalue);
 135          }
 136        }
 137      }
 138    }
 139  
 140    private function assignValues($arr,&$val1,&$val2) {
 141        $n = count($arr);
 142        if ($n > 0) {
 143            $val1=$arr[0];
 144            $val2=($n > 1) ? $arr[1] : '';
 145        }
 146    }
 147    function Get($key, $property) {
 148      $key = strtolower($key);
 149      $property = strtolower($property);
 150      $tag='';$subtag='';$class='';$id='';
 151      $this->assignValues(explode(":",$key),$tag,$subtag);
 152      $this->assignValues(explode(".",$tag),$tag,$class);
 153      $this->assignValues(explode("#",$tag),$tag,$id);
 154      $result = "";
 155      $_subtag=''; $_class=''; $_id='';
 156      foreach($this->css as $_tag => $value) {
 157        $this->assignValues(explode(":",$_tag),$_tag,$_subtag);
 158        $this->assignValues(explode(".",$_tag),$_tag,$_class);
 159        $this->assignValues(explode("#",$_tag),$_tag,$_id);
 160  
 161        $tagmatch = (strcmp($tag, $_tag) == 0) | (strlen($_tag) == 0);
 162        $subtagmatch = (strcmp($subtag, $_subtag) == 0) | (strlen($_subtag) == 0);
 163        $classmatch = (strcmp($class, $_class) == 0) | (strlen($_class) == 0);
 164        $idmatch = (strcmp($id, $_id) == 0);
 165  
 166        if($tagmatch & $subtagmatch & $classmatch & $idmatch) {
 167          $temp = $_tag;
 168          if((strlen($temp) > 0) & (strlen($_class) > 0)) {
 169            $temp .= ".".$_class;
 170          } elseif(strlen($temp) == 0) {
 171            $temp = ".".$_class;
 172          }
 173          if((strlen($temp) > 0) & (strlen($_subtag) > 0)) {
 174            $temp .= ":".$_subtag;
 175          } elseif(strlen($temp) == 0) {
 176            $temp = ":".$_subtag;
 177          }
 178          if(isset($this->css[$temp][$property])) {
 179            $result = $this->css[$temp][$property];
 180          }
 181        }
 182      }
 183      return $result;
 184    }
 185  
 186    function GetSection($key) {
 187      $key = strtolower($key);
 188      $tag='';$subtag='';$class='';$id='';
 189      $_subtag=''; $_class=''; $_id='';
 190  
 191      $this->assignValues(explode(":",$key),$tag,$subtag);
 192      $this->assignValues(explode(".",$tag),$tag,$class);
 193      $this->assignValues(explode("#",$tag),$tag,$id);
 194      $result = array();
 195      foreach($this->css as $_tag => $value) {
 196        $this->assignValues(explode(":",$_tag),$_tag,$_subtag);
 197        $this->assignValues(explode(".",$_tag),$_tag,$_class);
 198        $this->assignValues(explode("#",$_tag),$_tag,$_id);
 199  
 200        $tagmatch = (strcmp($tag, $_tag) == 0) | (strlen($_tag) == 0);
 201        $subtagmatch = (strcmp($subtag, $_subtag) == 0) | (strlen($_subtag) == 0);
 202        $classmatch = (strcmp($class, $_class) == 0) | (strlen($_class) == 0);
 203        $idmatch = (strcmp($id, $_id) == 0);
 204  
 205        if($tagmatch & $subtagmatch & $classmatch & $idmatch) {
 206          $temp = $_tag;
 207          if((strlen($temp) > 0) & (strlen($_class) > 0)) {
 208            $temp .= ".".$_class;
 209          } elseif(strlen($temp) == 0) {
 210            $temp = ".".$_class;
 211          }
 212          if((strlen($temp) > 0) & (strlen($_subtag) > 0)) {
 213            $temp .= ":".$_subtag;
 214          } elseif(strlen($temp) == 0) {
 215            $temp = ":".$_subtag;
 216          }
 217          foreach($this->css[$temp] as $property => $value) {
 218            $result[$property] = $value;
 219          }
 220        }
 221      }
 222      return $result;
 223    }
 224  
 225    function ParseStr($str) {
 226      $this->Clear();
 227      // Remove comments
 228      $str = preg_replace("/\/\*(.*)?\*\//Usi", "", $str);
 229      // Parse this damn csscode
 230      $parts = explode("}",$str);
 231      if(count($parts) > 0) {
 232        foreach($parts as $part) {
 233          $keystr='';$codestr='';
 234          $this->assignValues(explode("{",$part),$keystr,$codestr);
 235          $keys = explode(",",trim($keystr));
 236          if(count($keys) > 0) {
 237            foreach($keys as $key) {
 238              if(strlen($key) > 0) {
 239                $key = str_replace("\n", "", $key);
 240                $key = str_replace("\\", "", $key);
 241                $this->Add($key, trim($codestr));
 242              }
 243            }
 244          }
 245        }
 246      }
 247      //
 248      return (count($this->css) > 0);
 249    }
 250  
 251    function Parse($filename) {
 252      $this->Clear();
 253      if(file_exists($filename)) {
 254        return $this->ParseStr(file_get_contents($filename));
 255      } else {
 256        return false;
 257      }
 258    }
 259  
 260    function GetCSS() {
 261      $result = "";
 262      foreach($this->css as $key => $values) {
 263        $result .= $key." {\n";
 264        foreach($values as $key => $value) {
 265          $result .= "  $key: $value;\n";
 266        }
 267        $result .= "}\n\n";
 268      }
 269      return $result;
 270    }
 271  }