1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16: class Horde_Themes_Css
17: {
18: 19: 20: 21: 22:
23: protected $_cacheid;
24:
25: 26: 27: 28: 29:
30: protected $_cssFiles = array();
31:
32: 33: 34: 35: 36:
37: protected $_cssThemeFiles = array();
38:
39: 40: 41: 42: 43: 44:
45: public function addStylesheet($file, $url)
46: {
47: $this->_cssFiles[$file] = $url;
48: }
49:
50: 51: 52: 53: 54:
55: public function addThemeStylesheet($file)
56: {
57: $this->_cssThemeFiles[$file] = true;
58: }
59:
60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80:
81: public function getStylesheetUrls(array $opts = array())
82: {
83: global $conf, $injector, $prefs, $registry;
84:
85: $themesfs = $registry->get('themesfs');
86: $themesuri = $registry->get('themesuri');
87:
88: $theme = isset($opts['theme'])
89: ? $opts['theme']
90: : $prefs->getValue('theme');
91: $css = $this->getStylesheets($theme, $opts);
92: if (!count($css)) {
93: return array();
94: }
95:
96: $cache_type = !empty($opts['nocache']) || empty($conf['cachecss'])
97: ? 'none'
98: : $conf['cachecssparams']['driver'];
99:
100: if ($cache_type == 'none') {
101: $css_out = array();
102: foreach ($css as $file) {
103: $css_out[] = Horde::url($file['uri'], true, array('append_session' => -1));
104: }
105: return $css_out;
106: }
107:
108: $out = '';
109: $sig = hash('md5', serialize($css) . $this->_cacheid);
110:
111: switch ($cache_type) {
112: case 'filesystem':
113: $css_filename = '/static/' . $sig . '.css';
114: $css_path = $registry->get('fileroot', 'horde') . $css_filename;
115: $css_url = Horde::url($registry->get('webroot', 'horde') . $css_filename, true, array('append_session' => -1));
116: $exists = file_exists($css_path);
117: break;
118:
119: case 'horde_cache':
120: $cache = $injector->getInstance('Horde_Cache');
121:
122:
123: $exists = $cache->exists($sig, empty($conf['cachecssparams']['lifetime']) ? 0 : $conf['cachecssparams']['lifetime']);
124: $css_url = Horde::getCacheUrl('css', array('cid' => $sig));
125: break;
126: }
127:
128: if (!$exists) {
129: $out = $this->loadCssFiles($css);
130:
131:
132: if ($conf['cachecssparams']['compress'] == 'php') {
133: try {
134: $out = $injector->getInstance('Horde_Core_Factory_TextFilter')->filter($out, 'csstidy');
135: } catch (Horde_Exception $e) {}
136: }
137:
138: switch ($cache_type) {
139: case 'filesystem':
140: if (!file_put_contents($css_path, $out)) {
141: throw new Horde_Exception('Could not write cached CSS file to disk.');
142: }
143: break;
144:
145: case 'horde_cache':
146: $cache->set($sig, $out);
147: break;
148: }
149: }
150:
151: return array($css_url);
152: }
153:
154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177:
178: public function getStylesheets($theme = '', array $opts = array())
179: {
180: if (($theme === '') && isset($GLOBALS['prefs'])) {
181: $theme = $GLOBALS['prefs']->getValue('theme');
182: }
183:
184: $add_css = $css_out = array();
185: $css_list = empty($opts['nobase'])
186: ? $this->getBaseStylesheetList()
187: : array();
188:
189: $css_list = array_unique(array_merge($css_list, array_keys($this->_cssThemeFiles)));
190:
191: $curr_app = empty($opts['app'])
192: ? $GLOBALS['registry']->getApp()
193: : $opts['app'];
194: $mask = empty($opts['nohorde'])
195: ? 0
196: : Horde_Themes_Cache::APP_DEFAULT | Horde_Themes_Cache::APP_THEME;
197: $sub = empty($opts['sub'])
198: ? null
199: : $opts['sub'];
200:
201: $cache = $GLOBALS['injector']->getInstance('Horde_Core_Factory_ThemesCache')->create($curr_app, $theme);
202: $this->_cacheid = $cache->getCacheId();
203:
204: foreach ($css_list as $css_name) {
205: if (empty($opts['subonly'])) {
206: $css_out = array_merge($css_out, array_reverse($cache->getAll($css_name, $mask)));
207: }
208:
209: if ($sub) {
210: $css_out = array_merge($css_out, array_reverse($cache->getAll($sub . '/' . $css_name, $mask)));
211: }
212: }
213:
214:
215: foreach ($this->_cssFiles as $f => $u) {
216: if (file_exists($f)) {
217: $add_css[$f] = $u;
218: }
219: }
220:
221:
222: try {
223: $add_css = array_merge($add_css, Horde::callHook('cssfiles', array($theme), 'horde'));
224: } catch (Horde_Exception_HookNotSet $e) {
225: }
226:
227: if ($curr_app != 'horde') {
228: try {
229: $add_css = array_merge($add_css, Horde::callHook('cssfiles', array($theme), $curr_app));
230: } catch (Horde_Exception_HookNotSet $e) {
231: }
232: }
233:
234: foreach ($add_css as $f => $u) {
235: $css_out[] = array(
236: 'fs' => $f,
237: 'uri' => $u
238: );
239: }
240:
241: return $css_out;
242: }
243:
244: 245: 246: 247: 248: 249:
250: public function getBaseStylesheetList()
251: {
252: $css_list = array('screen.css');
253:
254: if ($GLOBALS['registry']->nlsconfig->curr_rtl) {
255: $css_list[] = 'rtl.css';
256: }
257:
258:
259: switch ($GLOBALS['browser']->getBrowser()) {
260: case 'msie':
261: $ie_major = $GLOBALS['browser']->getMajor();
262: if ($ie_major == 8) {
263: $css_list[] = 'ie8.css';
264: } elseif ($ie_major == 7) {
265: $css_list[] = 'ie7.css';
266: } elseif ($ie_major < 7) {
267: $css_list[] = 'ie6_or_less.css';
268: }
269: break;
270:
271: case 'opera':
272: $css_list[] = 'opera.css';
273: break;
274:
275: case 'mozilla':
276: $css_list[] = 'mozilla.css';
277: break;
278:
279: case 'webkit':
280: $css_list[] = 'webkit.css';
281: }
282:
283: return $css_list;
284: }
285:
286: 287: 288: 289: 290: 291: 292: 293:
294: public function loadCssFiles($files)
295: {
296: $dataurl = $GLOBALS['browser']->hasFeature('dataurl');
297: $out = '';
298:
299: foreach ($files as $file) {
300: $path = substr($file['uri'], 0, strrpos($file['uri'], '/') + 1);
301:
302:
303:
304:
305: $tmp = preg_replace(array('/(url\(["\']?)([^\/])/i', '/\s+/', '/\/\*.*?\*\//'), array('$1' . $path . '$2', ' ', ''), implode('', file($file['fs'], FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)));
306: if ($dataurl) {
307: $tmp = preg_replace_callback('/(background(?:-image)?:[^;}]*(?:url\(["\']?))(.*?)((?:["\']?\)))/i', array($this, '_base64Callback'), $tmp);
308: }
309:
310:
311: $tmp = preg_replace_callback('/@import\s+url\(["\']?(.*?)["\']?\)(?:\s*;\s*)*/i', array($this, '_importCallback'), $tmp);
312:
313: $out .= $tmp;
314: }
315:
316: return $out;
317: }
318:
319: 320: 321: 322: 323: 324: 325: 326:
327: protected function _base64Callback($matches)
328: {
329:
330: return $matches[1] . Horde::base64ImgData($matches[2], 16384) . $matches[3];
331: }
332:
333: 334: 335: 336: 337: 338: 339:
340: protected function _importCallback($matches)
341: {
342: $ob = Horde_Themes_Element::fromUri($matches[1]);
343:
344: return $this->loadCssFiles(array(array(
345: 'fs' => $ob->fs,
346: 'uri' => $ob->uri
347: )));
348: }
349:
350: }
351: