1<?php 2/** 3 * EGroupware API - CSS Includes 4 * 5 * @link http://www.egroupware.org 6 * @author Ralf Becker <RalfBecker-AT-outdoor-training.de> rewrite in 12/2006 7 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License 8 * @package api 9 * @subpackage framework 10 * @access public 11 * @version $Id$ 12 */ 13 14namespace EGroupware\Api\Framework; 15 16/** 17 * CSS includes 18 */ 19class CssIncludes 20{ 21 /** 22 * Content from add calls 23 * 24 * @var array 25 */ 26 protected static $files = array(); 27 28 /** 29 * Include a css file, either speicified by it's path (relative to EGW_SERVER_ROOT) or appname and css file name 30 * 31 * @param string $app path (relative to EGW_SERVER_ROOT) or appname (if !is_null($name)) 32 * @param string $name =null name of css file in $app/templates/{default|$this->template}/$name.css 33 * @param boolean $append =true true append file, false prepend (add as first) file used eg. for template itself 34 * @param boolean $clear_includes =false true: clear all previous includes 35 * @return boolean false: css file not found, true: file found 36 */ 37 public static function add($app, $name=null, $append=true, $clear_includes=false) 38 { 39 if ($clear_includes) 40 { 41 self::$files = array(); 42 } 43 44 if (!is_null($name)) 45 { 46 foreach($GLOBALS['egw']->framework->template_dirs as $dir) 47 { 48 if (file_exists(EGW_SERVER_ROOT.($path = '/'.$app.'/templates/'.$dir.'/'.$name.'.css'))) 49 { 50 break; 51 } 52 } 53 } 54 else 55 { 56 $path = $app; 57 } 58 if (!file_exists(EGW_SERVER_ROOT.$path) && !file_exists(EGW_SERVER_ROOT . parse_url($path,PHP_URL_PATH))) 59 { 60 //error_log(__METHOD__."($app,$name) $path NOT found!"); 61 return false; 62 } 63 if (!in_array($path,self::$files)) 64 { 65 if ($append) 66 { 67 self::$files[] = $path; 68 } 69 else 70 { 71 self::$files = array_merge(array($path), self::$files); 72 } 73 } 74 return true; 75 } 76 77 /** 78 * Get all css files included with add 79 * 80 * @return string 81 */ 82 public static function get($resolve=false) 83 { 84 if (!$resolve) 85 { 86 return self::$files; 87 } 88 $files = array(); 89 foreach(self::$files as $path) 90 { 91 foreach(self::resolve_css_includes($path) as $path) 92 { 93 $files[] = $path; 94 } 95 } 96 return $files; 97 } 98 99 /** 100 * Return link tags for all included css files incl. minifying 101 * 102 * @return string 103 */ 104 public static function tags() 105 { 106 // add all css files from self::includeCSS 107 $max_modified = 0; 108 //no more dynamic minifying: $debug_minify = $GLOBALS['egw_info']['server']['debug_minify'] === 'True'; 109 $base_path = $GLOBALS['egw_info']['server']['webserver_url']; 110 if ($base_path[0] != '/') $base_path = parse_url($base_path, PHP_URL_PATH); 111 $css_files = ''; 112 foreach(self::$files as $path) 113 { 114 foreach(self::resolve_css_includes($path) as $path) 115 { 116 list($file,$query) = explode('?',$path,2); 117 if (($mod = filemtime(EGW_SERVER_ROOT.$file)) > $max_modified) $max_modified = $mod; 118 119 // do NOT include app.css or categories.php, as it changes from app to app 120 //no more dynamic minifying: if ($debug_minify || substr($path, -8) == '/app.css' || substr($file,-14) == 'categories.php') 121 { 122 $css_files .= '<link href="'.$GLOBALS['egw_info']['server']['webserver_url'].$path.($query ? '&' : '?').$mod.'" type="text/css" rel="StyleSheet" />'."\n"; 123 } 124 /* no more dynamic minifying 125 else 126 { 127 $css_file .= ($css_file ? ',' : '').substr($path, 1); 128 }*/ 129 } 130 } 131 /* no more dynamic minifying 132 if (!$debug_minify) 133 { 134 $css = $GLOBALS['egw_info']['server']['webserver_url'].'/phpgwapi/inc/min/?'; 135 if ($base_path && $base_path != '/') $css .= 'b='.substr($base_path, 1).'&'; 136 $css .= 'f='.$css_file . 137 ($GLOBALS['egw_info']['server']['debug_minify'] === 'debug' ? '&debug' : ''). 138 '&'.$max_modified; 139 $css_files = '<link href="'.$css.'" type="text/css" rel="StyleSheet" />'."\n".$css_files; 140 }*/ 141 return $css_files; 142 } 143 144 /** 145 * Parse beginning of given CSS file for /*@import url("...") statements 146 * 147 * @param string $path EGroupware relative path eg. /phpgwapi/templates/default/some.css 148 * @return array parsed pathes (EGroupware relative) including $path itself 149 */ 150 protected static function resolve_css_includes($path, &$pathes=array()) 151 { 152 $matches = null; 153 154 list($file) = explode('?',$path,2); 155 if (($to_check = file_get_contents (EGW_SERVER_ROOT.$file, false, null, 0, 1024)) && 156 stripos($to_check, '/*@import') !== false && preg_match_all('|/\*@import url\("([^"]+)"|i', $to_check, $matches)) 157 { 158 foreach($matches[1] as $import_path) 159 { 160 if ($import_path[0] != '/') 161 { 162 $dir = dirname($path); 163 while(substr($import_path,0,3) == '../') 164 { 165 $dir = dirname($dir); 166 $import_path = substr($import_path, 3); 167 } 168 $import_path = ($dir != '/' ? $dir : '').'/'.$import_path; 169 } 170 self::resolve_css_includes($import_path, $pathes); 171 } 172 } 173 $pathes[] = $path; 174 175 return $pathes; 176 } 177} 178