/** * @param $tpl template object * @return bool optimize success or not */ public static function optimizecss($tpl) { $outputpath = JPATH_ROOT . '/' . $tpl->getParam('canvas-assets', 'canvas-assets') . '/css'; $outputurl = JURI::root(true) . '/' . $tpl->getParam('canvas-assets', 'canvas-assets') . '/css'; if (!JFile::exists($outputpath)) { JFolder::create($outputpath); @chmod($outputpath, 0755); } if (!is_writeable($outputpath)) { return false; } //prepare config self::prepare($tpl); $doc = JFactory::getDocument(); //======================= Group css ================= // $mediagroup = array(); $cssgroups = array(); $stylesheets = array(); $ielimit = 4095; $selcounts = 0; $regex = '/\\{.+?\\}|,/s'; //selector counter $csspath = ''; // group css into media $mediagroup['all'] = array(); $mediagroup['screen'] = array(); foreach ($doc->_styleSheets as $url => $stylesheet) { $media = $stylesheet['media'] ? $stylesheet['media'] : 'all'; if (empty($mediagroup[$media])) { $mediagroup[$media] = array(); } $mediagroup[$media][$url] = $stylesheet; } foreach ($mediagroup as $media => $group) { $stylesheets = array(); // empty - begin a new group foreach ($group as $url => $stylesheet) { $url = self::fixUrl($url); if ($stylesheet['mime'] == 'text/css' && ($csspath = self::cssPath($url))) { $stylesheet['path'] = $csspath; $stylesheet['data'] = file_get_contents($csspath); $selcount = preg_match_all($regex, $stylesheet['data'], $matched); if (!$selcount) { $selcount = 1; //just for sure } //if we found an @import rule or reach IE limit css selector count, break into the new group if (preg_match('#@import\\s+.+#', $stylesheet['data']) || $selcounts + $selcount >= $ielimit) { if (count($stylesheets)) { $cssgroup = array(); $groupname = array(); foreach ($stylesheets as $gurl => $gsheet) { $cssgroup[$gurl] = $gsheet; $groupname[] = $gurl; } $cssgroup['groupname'] = implode('', $groupname); $cssgroup['media'] = $media; $cssgroups[] = $cssgroup; } $stylesheets = array($url => $stylesheet); // empty - begin a new group $selcounts = $selcount; } else { $stylesheets[$url] = $stylesheet; $selcounts += $selcount; } } else { // first get all the stylsheets up to this point, and get them into // the items array if (count($stylesheets)) { $cssgroup = array(); $groupname = array(); foreach ($stylesheets as $gurl => $gsheet) { $cssgroup[$gurl] = $gsheet; $groupname[] = $gurl; } $cssgroup['groupname'] = implode('', $groupname); $cssgroup['media'] = $media; $cssgroups[] = $cssgroup; } //mark ignore current stylesheet $cssgroup = array($url => $stylesheet, 'ignore' => true); $cssgroups[] = $cssgroup; $stylesheets = array(); // empty - begin a new group } } if (count($stylesheets)) { $cssgroup = array(); $groupname = array(); foreach ($stylesheets as $gurl => $gsheet) { $cssgroup[$gurl] = $gsheet; $groupname[] = $gurl; } $cssgroup['groupname'] = implode('', $groupname); $cssgroup['media'] = $media; $cssgroups[] = $cssgroup; } } //======================= Group css ================= // $output = array(); foreach ($cssgroups as $cssgroup) { if (isset($cssgroup['ignore'])) { unset($cssgroup['ignore']); unset($cssgroup['groupname']); unset($cssgroup['media']); foreach ($cssgroup as $furl => $fsheet) { $output[$furl] = $fsheet; } } else { $media = $cssgroup['media']; $groupname = 'css-' . substr(md5($cssgroup['groupname']), 0, 5) . '.css'; $groupfile = $outputpath . '/' . $groupname; $grouptime = JFile::exists($groupfile) ? @filemtime($groupfile) : -1; $rebuild = $grouptime < 0; //filemtime == -1 => rebuild unset($cssgroup['groupname']); unset($cssgroup['media']); foreach ($cssgroup as $furl => $fsheet) { if (!$rebuild && @filemtime($fsheet['path']) > $grouptime) { $rebuild = true; } } if ($rebuild) { $cssdata = array(); foreach ($cssgroup as $furl => $fsheet) { $cssdata[] = "\n\n/*==============================="; $cssdata[] = $furl; $cssdata[] = "================================================================================*/"; $cssmin = self::minifyCss($fsheet['data']); $cssmin = CANVASPath::updateUrl($cssmin, CANVASPath::relativePath($outputurl, dirname($furl))); $cssdata[] = $cssmin; } $cssdata = implode("\n", $cssdata); if (!JFile::write($groupfile, $cssdata)) { // cannot write file, ignore minify return false; } $grouptime = @filemtime($groupfile); @chmod($groupfile, 0644); } $output[$outputurl . '/' . $groupname . '?t=' . $grouptime % 1000] = array('mime' => 'text/css', 'media' => $media == 'all' ? NULL : $media, 'attribs' => array()); } } //apply the change make change $doc->_styleSheets = $output; }
/** * Parse a less file to get all its overrides before compile * @param string $path the less file */ public static function parse($path) { $rtpl_check = '@' . preg_quote(CANVAS_TEMPLATE_REL, '@') . '/@i'; $rtpl_less_check = '@' . preg_quote(CANVAS_TEMPLATE_REL, '@') . '/less/@i'; $app = JFactory::getApplication(); $theme = $app->getUserState('current_theme'); $dir = $app->getUserState('current_direction'); $is_rtl = $dir == 'rtl'; $less_rel_path = preg_replace($rtpl_less_check, '', $path); $less_rel_dir = dirname($less_rel_path); $less_rel_dir = $less_rel_dir == '.' ? '' : $less_rel_dir . '/'; // check path $realpath = realpath(JPATH_ROOT . '/' . $path); if (!is_file($realpath)) { return false; } // get file content $content = file_get_contents($realpath); //remove vars.less $content = preg_replace(self::$rimportvars, '', $content); // split into array, separated by the import $arr = preg_split(self::$rimport, $content, -1, PREG_SPLIT_DELIM_CAPTURE); $arr[] = $less_rel_path; $arr[] = ''; $list = array(); $rtl_list = array(); $list[$path] = ''; $import = false; foreach ($arr as $chunk) { if ($import) { $import = false; $import_url = CANVASPath::cleanPath(CANVAS_TEMPLATE_REL . '/less/' . $less_rel_dir . $chunk); // if $url in template, get all its overrides if (preg_match($rtpl_less_check, $import_url)) { $less_rel_url = CANVASPath::cleanPath($less_rel_dir . $chunk); $array = CANVASPath::getAllPath('less/' . $less_rel_url, true); if ($theme) { $array = array_merge($array, CANVASPath::getAllPath('less/themes/' . $theme . '/' . $less_rel_url, true)); } foreach ($array as $f) { // add file in template only if (preg_match($rtpl_check, $f)) { $list[$f] = CANVASPath::relativePath(dirname($path), $f); } } // rtl overrides if ($is_rtl) { $array = CANVASPath::getAllPath('less/rtl/' . $less_rel_url, true); if ($theme) { $array = array_merge($array, CANVASPath::getAllPath('less/rtl/themes/' . $theme . '/' . $less_rel_url, true)); } foreach ($array as $f) { // add file in template only if (preg_match($rtpl_check, $f)) { $rtl_list[$f] = CANVASPath::relativePath(dirname($path), $f); } } } } else { $list[$import_url] = $chunk; } } else { $import = true; $list[$chunk] = false; } } // remove itself unset($list[$path]); // join rtl if ($is_rtl) { $list["\n\n#" . self::$krtlsep . "{content: \"separator\";}\n\n"] = false; $list = array_merge($list, $rtl_list); } return $list; }