1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13: class Assets
14: {
15: private $js = array();
16:
17:
18: private $js_hash = '';
19:
20:
21: private $css = array();
22:
23:
24: private $css_hash = '';
25:
26:
27: private $base_uri;
28:
29:
30: public function __construct($app)
31: {
32: $this->app = $app;
33:
34: $this->base_uri = $app->request->base_uri;
35: if (empty($app->settings['system']['multi_domain']) === FALSE) {
36: $this->base_uri = $app->request->base_domain_uri;
37: }
38:
39: return $this;
40: }
41:
42:
43: public function linked($type = 'all')
44: {
45: $out = Html::element();
46:
47: if (($type === 'all'
48: OR $type === 'css')
49: AND empty($this->css) === FALSE) {
50:
51: $hash = $this->create_cache('css');
52:
53: $data = array(
54: 'type' => 'css',
55: 'name' => $hash
56: );
57:
58: $uri = $this->app->create_uri('assets', $data);
59:
60:
61: $out->create('link')
62: ->rel('stylesheet')
63: ->type('text/css')
64: ->href($uri)
65: ->charset('UTF-8')
66: ->media('screen');
67: }
68:
69: if (($type === 'all'
70: OR $type === 'js')
71: AND empty($this->js) === FALSE) {
72:
73: $hash = $this->create_cache('js');
74:
75: $data = array(
76: 'type' => 'js',
77: 'name' => $hash
78: );
79:
80: $uri = $this->app->create_uri('assets', $data);
81:
82: $out->create('script')
83: ->type('text/javascript')
84: ->src($uri)
85: ->charset('UTF-8');
86: }
87:
88: return $out;
89: }
90:
91:
92: public function included($type = 'all')
93: {
94: $out = Html::element();
95:
96: if (($type === 'all'
97: OR $type === 'css')
98: AND empty($this->css) === FALSE) {
99:
100: $css_code = $this->create_cache('css', TRUE);
101:
102: $out->create('style')
103: ->type('text/css')
104: ->set_text($css_code);
105: }
106:
107: if (($type === 'all'
108: OR $type === 'js')
109: AND empty($this->js) === FALSE) {
110:
111: $js_code = '<!--' . chr(10);
112: $js_code .= $this->create_cache('js', TRUE);
113: $js_code .= chr(10) . '-->';
114:
115: $out->create('script')
116: ->type('text/javascript')
117: ->set_text($js_code, TRUE);
118: }
119:
120: return $out;
121: }
122:
123:
124: public function js($file, $code = FALSE, $minifiy = TRUE)
125: {
126: $this->asset('js', $file, $code, $minifiy);
127: }
128:
129:
130: public function css($file, $code = FALSE, $minifiy = TRUE)
131: {
132: $this->asset('css', $file, $code, $minifiy);
133: }
134:
135:
136: public function asset($type, $file, $code = FALSE, $minify = TRUE)
137: {
138: if ($code === FALSE
139: AND strpos($file, '.min.') == TRUE) {
140:
141: $minify = FALSE;
142: }
143:
144: $asset = array(
145: 'file' => $file,
146: 'minify' => $minify,
147: 'code' => $code
148: );
149:
150: $this->$type = array_merge($this->$type, array($asset));
151:
152: $type_hash = $type . '_hash';
153:
154: if ($code === FALSE) {
155: $this->$type_hash .= filemtime($file);
156:
157: } else {
158: $this->$type_hash .= md5($file);
159: }
160: }
161:
162:
163: private function create_cache($type, $return_content = FALSE)
164: {
165: $hash_name = $type . '_hash';
166:
167: $hash = md5($this->$hash_name);
168:
169: $cache_file = CACHE_DIR . '/' . $type . '/' . $hash;
170:
171: if (file_exists($cache_file) === FALSE) {
172: $assets = $this->compositing_assets($type);
173:
174: $assets = str_replace('\'./', '\'' . $this->base_uri . '/', $assets);
175: $assets = str_replace('"./', '"' . $this->base_uri . '/', $assets);
176: $assets = str_replace('(./', '(' . $this->base_uri . '/', $assets);
177:
178: file_put_contents($cache_file, $assets);
179:
180: if ($return_content === TRUE) {
181: return $assets;
182: }
183:
184: } else {
185: if ($return_content === TRUE) {
186: return file_get_contents($cache_file);
187: }
188: }
189:
190: return $hash;
191: }
192:
193:
194: private function compositing_assets($type)
195: {
196: $composite_assets = '';
197:
198: $minify_function = $type . '_minify';
199:
200: foreach ($this->$type as $asset) {
201: if ($asset['code'] === TRUE) {
202: $asset_code = $asset['file'];
203:
204: } else {
205: $asset_code = file_get_contents($asset['file']);
206: }
207:
208: if ($asset['minify'] === TRUE
209: AND DEBUG === FALSE) {
210:
211: $asset_code = call_user_func(array('Assets', $minify_function), $asset_code);
212: }
213:
214: $composite_assets .= chr(10) . chr(10) . $asset_code;
215: }
216:
217: return $composite_assets;
218: }
219:
220:
221: public function js_minify($js)
222: {
223: return JSMin::minify($js);
224: }
225:
226:
227: public function css_minify($style)
228: {
229: $style = preg_replace('|/\*[^*]*\*+([^/][^*]*\*+)*/|', '', $style);
230: $style = str_replace(array("\r", "\n", "\t"), '', $style);
231: $style = preg_replace('|\ +|', ' ', $style);
232: $style = str_replace('; ', ';', $style);
233: $style = str_replace(array('{ ', ' {'), '{', $style);
234: $style = str_replace(array(' }', ';}'), '}', $style);
235: $style = str_replace(': ', ':', $style);
236: $style = str_replace(', ', ',', $style);
237:
238: return trim($style);
239: }
240:
241:
242: public function reset($type = 'all')
243: {
244: if ($type === 'all'
245: OR $type === 'css') {
246:
247: $this->css = array();
248: }
249:
250: if ($type === 'all'
251: OR $type === 'js') {
252:
253: $this->js = array();
254: }
255: }
256: }
257:
258:
259:
260:
261: 262: 263: 264: 265: 266: 267: 268: 269:
270:
271: class AssetsController extends Controller
272: {
273: 274: 275: 276: 277: 278: 279:
280: public function send($type, $name)
281: {
282: $types = array(
283: 'js' => 'text/javascript',
284: 'css' => 'text/css'
285: );
286:
287: $cache_file = CACHE_DIR . '/' . $type . '/' . $name;
288:
289: if (file_exists($cache_file) === FALSE) {
290: $this->app->response->status_code = 404;
291: $this->app->response->set_body('Not found!');
292: $this->app->response->send();
293: }
294:
295: $this->app->response->cache_lifetime = 31536000;
296: $this->app->response->set_header('Content-Type', $types[$type]);
297: $this->app->response->status_code = 200;
298: $this->app->response->set_body(file_get_contents($cache_file));
299: $this->app->response->send();
300: }
301: }
302: