1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16: class Horde_Themes_Cache implements Serializable
17: {
18:
19: const HORDE_DEFAULT = 1;
20: const APP_DEFAULT = 2;
21: const HORDE_THEME = 4;
22: const APP_THEME = 8;
23:
24: 25: 26: 27: 28:
29: public $changed = false;
30:
31: 32: 33: 34: 35:
36: protected $_app;
37:
38: 39: 40: 41: 42:
43: protected $_cacheid;
44:
45: 46: 47: 48: 49:
50: protected $_complete = false;
51:
52: 53: 54: 55: 56:
57: protected $_data = array();
58:
59: 60: 61: 62: 63:
64: protected $_theme;
65:
66: 67: 68: 69: 70: 71:
72: public function __construct($app, $theme)
73: {
74: $this->_app = $app;
75: $this->_theme = $theme;
76: }
77:
78: 79: 80: 81: 82:
83: public function build()
84: {
85: if (!$this->_complete) {
86: $this->_data = array();
87:
88: $this->_build('horde', 'default', self::HORDE_DEFAULT);
89: $this->_build('horde', $this->_theme, self::HORDE_THEME);
90: if ($this->_app != 'horde') {
91: $this->_build($this->_app, 'default', self::APP_DEFAULT);
92: $this->_build($this->_app, $this->_theme, self::APP_THEME);
93: }
94:
95: $this->changed = $this->_complete = true;
96: }
97:
98: return array_keys($this->_data);
99: }
100:
101: 102: 103: 104: 105: 106: 107:
108: protected function _build($app, $theme, $mask)
109: {
110: $path = $GLOBALS['registry']->get('themesfs', $app) . '/'. $theme;
111:
112: try {
113: $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
114: } catch (UnexpectedValueException $e) {
115: return;
116: }
117:
118: foreach ($it as $val) {
119: if (!$val->isDir()) {
120: $sub = $it->getSubPathname();
121:
122: if (isset($this->_data[$sub])) {
123: $this->_data[$sub] |= $mask;
124: } else {
125: $this->_data[$sub] = $mask;
126: }
127: }
128: }
129: }
130:
131: 132:
133: public function get($item, $mask = 0)
134: {
135: if (!($entry = $this->_get($item))) {
136: return null;
137: }
138:
139: if ($mask) {
140: $entry &= $mask;
141: }
142:
143: if ($entry & self::APP_THEME) {
144: $app = $this->_app;
145: $theme = $this->_theme;
146: } elseif ($entry & self::HORDE_THEME) {
147: $app = 'horde';
148: $theme = $this->_theme;
149: } elseif ($entry & self::APP_DEFAULT) {
150: $app = $this->_app;
151: $theme = 'default';
152: } elseif ($entry & self::HORDE_DEFAULT) {
153: $app = 'horde';
154: $theme = 'default';
155: } else {
156: return null;
157: }
158:
159: return $this->_getOutput($app, $theme, $item);
160: }
161:
162: 163:
164: protected function _get($item)
165: {
166: if (!isset($this->_data[$item])) {
167: $entry = 0;
168:
169: $path = $GLOBALS['registry']->get('themesfs', 'horde');
170: if (file_exists($path . '/default/' . $item)) {
171: $entry |= self::HORDE_DEFAULT;
172: }
173: if (file_exists($path . '/' . $this->_theme . '/' . $item)) {
174: $entry |= self::HORDE_THEME;
175: }
176:
177: if ($this->_app != 'horde') {
178: $path = $GLOBALS['registry']->get('themesfs', $this->_app);
179: if (file_exists($path . '/default/' . $item)) {
180: $entry |= self::APP_DEFAULT;
181: }
182: if (file_exists($path . '/' . $this->_theme . '/' . $item)) {
183: $entry |= self::APP_THEME;
184: }
185: }
186:
187: $this->_data[$item] = $entry;
188: $this->changed = true;
189: }
190:
191: return $this->_data[$item];
192: }
193:
194: 195:
196: protected function _getOutput($app, $theme, $item)
197: {
198: return array(
199: 'fs' => $GLOBALS['registry']->get('themesfs', $app) . '/' . $theme . '/' . $item,
200: 'uri' => $GLOBALS['registry']->get('themesuri', $app) . '/' . $theme . '/' . $item
201: );
202: }
203:
204: 205:
206: public function getAll($item, $mask = 0)
207: {
208: if (!($entry = $this->_get($item))) {
209: return array();
210: }
211:
212: if ($mask) {
213: $entry &= $mask;
214: }
215: $out = array();
216:
217: if ($entry & self::APP_THEME) {
218: $out[] = $this->_getOutput($this->_app, $this->_theme, $item);
219: }
220: if ($entry & self::HORDE_THEME) {
221: $out[] = $this->_getOutput('horde', $this->_theme, $item);
222: }
223: if ($entry & self::APP_DEFAULT) {
224: $out[] = $this->_getOutput($this->_app, 'default', $item);
225: }
226: if ($entry & self::HORDE_DEFAULT) {
227: $out[] = $this->_getOutput('horde', 'default', $item);
228: }
229:
230: return $out;
231: }
232:
233: 234:
235: public function getCacheId()
236: {
237: if (!isset($this->_cacheid)) {
238: $check = isset($GLOBALS['conf']['cachethemesparams']['check']) ? $GLOBALS['conf']['cachethemesparams']['check'] : null;
239: switch ($check) {
240: case 'appversion':
241: default:
242: $id = array($GLOBALS['registry']->getVersion($this->_app));
243: if ($this->_app != 'horde') {
244: $id[] = $GLOBALS['registry']->getVersion('horde');
245: }
246: $this->_cacheid = 'v:' . implode('|', $id);
247: break;
248:
249: case 'none':
250: $this->_cacheid = '';
251: break;
252: }
253: }
254:
255: return $this->_cacheid;
256: }
257:
258:
259:
260: 261:
262: public function serialize()
263: {
264: return serialize(array(
265: 'a' => $this->_app,
266: 'c' => $this->_complete,
267: 'd' => $this->_data,
268: 'id' => $this->getCacheId(),
269: 't' => $this->_theme
270: ));
271: }
272:
273: 274:
275: public function unserialize($data)
276: {
277: $out = @unserialize($data);
278:
279: if (isset($out['id']) && ($out['id'] != $this->getCacheId())) {
280: throw new Exception('Cache invalidated');
281: }
282:
283: $this->_app = $out['a'];
284: $this->_complete = $out['c'];
285: $this->_data = $out['d'];
286: $this->_theme = $out['t'];
287: }
288:
289: }
290: