Autodoc
  • Namespace
  • Class
  • Tree

Namespaces

  • BlueTihi
    • Context
  • Brickrouge
    • Element
      • Nodes
    • Renderer
    • Widget
  • ICanBoogie
    • ActiveRecord
    • AutoConfig
    • CLDR
    • Composer
    • Core
    • Event
    • Exception
    • HTTP
      • Dispatcher
      • Request
    • I18n
      • Translator
    • Mailer
    • Modules
      • Taxonomy
        • Support
      • Thumbnailer
        • Versions
    • Object
    • Operation
      • Dispatcher
    • Prototype
    • Routes
    • Routing
      • Dispatcher
    • Session
  • Icybee
    • ActiveRecord
      • Model
    • ConfigOperation
    • Document
    • EditBlock
    • Element
      • ActionbarContextual
      • ActionbarSearch
      • ActionbarToolbar
    • FormBlock
    • Installer
    • ManageBlock
    • Modules
      • Articles
      • Cache
        • Collection
        • ManageBlock
      • Comments
        • ManageBlock
      • Contents
        • ManageBlock
      • Dashboard
      • Editor
        • Collection
      • Files
        • File
        • ManageBlock
      • Forms
        • Form
        • ManageBlock
      • I18n
      • Images
        • ManageBlock
      • Members
      • Modules
        • ManageBlock
      • Nodes
        • ManageBlock
        • Module
      • Pages
        • BreadcrumbElement
        • LanguagesElement
        • ManageBlock
        • NavigationBranchElement
        • NavigationElement
        • Page
        • PageController
      • Registry
      • Search
      • Seo
      • Sites
        • ManageBlock
      • Taxonomy
        • Terms
          • ManageBlock
        • Vocabulary
          • ManageBlock
      • Users
        • ManageBlock
        • NonceLogin
        • Roles
      • Views
        • ActiveRecordProvider
        • Collection
        • View
    • Operation
      • ActiveRecord
      • Constructor
      • Module
      • Widget
    • Rendering
  • None
  • Patron
  • PHP

Classes

  • A
  • Actions
  • Alert
  • AlterCSSClassNamesEvent
  • AssetsCollector
  • Button
  • CSSCollector
  • Dataset
  • Date
  • DateRange
  • DateTime
  • Decorator
  • Document
  • DropdownMenu
  • Element
  • File
  • Form
  • Group
  • Helpers
  • HTMLString
  • Iterator
  • JSCollector
  • ListView
  • ListViewColumn
  • Modal
  • Pager
  • Popover
  • PopoverWidget
  • Ranger
  • RecursiveIterator
  • Salutation
  • Searchbox
  • Section
  • SplitButton
  • Text
  • Widget

Interfaces

  • CSSClassNames
  • DecoratorInterface
  • HTMLStringInterface
  • Validator

Traits

  • CSSClassNamesProperty

Exceptions

  • ElementIsEmpty

Functions

  • _array_flatten_callback
  • array_flatten
  • array_insert
  • check_session
  • dump
  • escape
  • escape_all
  • format
  • format_size
  • get_accessible_file
  • get_document
  • normalize
  • render_css_class
  • render_exception
  • retrieve_form
  • retrieve_form_errors
  • shorten
  • stable_sort
  • store_form
  • store_form_errors
  • strip
  • t
  1 <?php
  2 
  3 /*
  4  * This file is part of the Brickrouge package.
  5  *
  6  * (c) Olivier Laviale <olivier.laviale@gmail.com>
  7  *
  8  * For the full copyright and license information, please view the LICENSE
  9  * file that was distributed with this source code.
 10  */
 11 
 12 namespace Brickrouge;
 13 
 14 use ICanBoogie\FileCache;
 15 
 16 /**
 17  * An HTML document.
 18  *
 19  * @property $assets array The Javascript and CSS assets used by the document.
 20  */
 21 class Document extends \ICanBoogie\Object
 22 {
 23     public $body;
 24 
 25     /**
 26      * @var JSCollector Collector for Javascript assets.
 27      */
 28     public $js;
 29 
 30     /**
 31      * @var CSSCollector Collector for CSS assets.
 32      */
 33     public $css;
 34 
 35     /**
 36      * Constructor.
 37      *
 38      * Creates the Javascript and CSS collectors.
 39      */
 40     public function __construct()
 41     {
 42         global $core;
 43 
 44         $use_cache = !empty($core->config['cache assets']);
 45 
 46         $this->body = new Element('body');
 47         $this->js = new JSCollector($use_cache);
 48         $this->css = new CSSCollector($use_cache);
 49     }
 50 
 51     /**
 52      * Returns the Javascript and CSS assets used by the document as an array or URLs.
 53      *
 54      * @return array The assets used by the document.
 55      */
 56     protected function get_assets()
 57     {
 58         return array
 59         (
 60             'css' => $this->css->get(),
 61             'js' => $this->js->get()
 62         );
 63     }
 64 
 65     /**
 66      * Sets the assets of the document.
 67      *
 68      * @param array $assets An array where CSS and JS assets are stored under the 'css' and 'js'
 69      * keys respectively. Each asset is defined as a key/value pair where the key if the path to
 70      * the asset and the key is its priority.
 71      *
 72      * @example
 73      *
 74      * $document->assets = array
 75      * (
 76      *     'css' => array('brickrouge.css' => 0),
 77      *     'js' => array('brickrouge.js' => 0)
 78      * );
 79      */
 80     protected function set_assets(array $assets)
 81     {
 82         unset($this->assets);
 83         $this->add_assets($assets);
 84     }
 85 
 86     /**
 87      * Clears JS and CSS assets.
 88      *
 89      * @example
 90      *
 91      * $document->js->add('brickrouge.js');
 92      * $document->css->add('brickrouge.css');
 93      *
 94      * var_dump($document->assets);
 95      * // ['css' => ['brickrouge.css'], 'js' => ['brickrouge.js']]
 96      *
 97      * unset($document->assets);
 98      *
 99      * var_dump($document->assets);
100      * // ['css' => [], 'js' => []]
101      */
102     protected function __unset_assets()
103     {
104         $this->js->clear();
105         $this->css->clear();
106     }
107 
108     /**
109      * Adds a number of assets to the document.
110      *
111      * @param array $assets An array where CSS and JS assets are stored under the 'css' and 'js'
112      * keys respectively. Each asset is defined as a key/value pair where the key if the path to
113      * the asset and the key is its priority.
114      *
115      * @example
116      *
117      * $document->add_assets
118      * (
119      *     array
120      *     (
121      *         'css' => array('brickrouge.css' => 0),
122      *         'js' => array('brickrouge.js' => 0)
123      *     )
124      * );
125      */
126     public function add_assets(array $assets)
127     {
128         if (!empty($assets['css']))
129         {
130             foreach ($assets['css'] as $path => $priority)
131             {
132                 $this->css->add($path, $priority);
133             }
134         }
135 
136         if (!empty($assets['js']))
137         {
138             foreach ($assets['js'] as $path => $priority)
139             {
140                 $this->js->add($path, $priority);
141             }
142         }
143     }
144 
145     /**
146      * Tries to locate the file where the assets was added by searching for the first file which
147      * is not the file where our class is defined.
148      *
149      * @return string|null The path to the directory of the file or null if no file could be found.
150      */
151     static private function resolve_root()
152     {
153         $stack = debug_backtrace();
154 
155         foreach ($stack as $trace)
156         {
157             if (empty($trace['file']) || $trace['file'] == __FILE__)
158             {
159                 continue;
160             }
161 
162             return dirname($trace['file']);
163         }
164     }
165 
166     /**
167      * Resolves a server path into a URL accessible from the `DOCUMENT_ROOT`.
168      *
169      * Unless the path uses a scheme (http://, https:// or phar://) it is always considered
170      * relative to the path specified by the $relative parameter or to the `DOCUMENT_ROOT`.
171      *
172      * @param string $path
173      * @param string $relative Relative path that can be used to resolve the path. If the
174      * parameter is null the method tries to _guess_ the relative path using the
175      * {@link resolve_root()} private method.
176      *
177      * @return string The URL resolved from the path.
178      */
179     static public function resolve_url($path, $relative=null)
180     {
181         if (strpos($path, 'http://') === 0 || strpos($path, 'https://') === 0)
182         {
183             return $path;
184         }
185         else if (strpos($path, 'phar://') === 0)
186         {
187             if (file_exists($path))
188             {
189                 $path = get_accessible_file($path, 'phar');
190             }
191             else
192             {
193                 trigger_error(format('Phar file %path does not exists.', array('%path' => $path)));
194 
195                 return;
196             }
197         }
198 
199         $root = DOCUMENT_ROOT;
200 
201         # trying from directory
202 
203         $tried = array($path);
204         $realpath = realpath($path);
205 
206         # trying from relative
207 
208         if (!$realpath)
209         {
210             if (!$relative)
211             {
212                 $relative = self::resolve_root() . DIRECTORY_SEPARATOR;
213             }
214 
215             $tried[] = $relative . $path;
216             $realpath = realpath($relative . $path);
217         }
218 
219         # trying from document root
220 
221         if (!$realpath)
222         {
223             $tries[] = $root . $path;
224             $realpath = realpath($root . $path);
225         }
226 
227         #
228         # We can't find a matching file :-(
229         #
230 
231         if (!$realpath)
232         {
233             trigger_error(format('Unable to resolve path %path to an URL, tried: !tried', array('path' => $path, 'tried' => implode(', ', $tried))));
234 
235             return;
236         }
237 
238         #
239         # If the file is not accessible from the document root, we create an accessible version.
240         #
241 
242         if (strpos($realpath, $root) === false)
243         {
244             $realpath = get_accessible_file($realpath);
245         }
246 
247         #
248         # let's turn this pathname into a lovely URL
249         #
250 
251         $url = substr($realpath, strlen($root));
252 
253         if (DIRECTORY_SEPARATOR == '\\')
254         {
255             $url = strtr($url, '\\', '/');
256         }
257 
258         if ($url{0} != '/')
259         {
260             $url = '/' . $url;
261         }
262 
263         return $url;
264     }
265 }
266 
267 /**
268  * Root class for documents assets collectors.
269  */
270 abstract class AssetsCollector
271 {
272     /**
273      * Collected assets
274      *
275      * @var array
276      */
277     protected $collected = array();
278 
279     /**
280      * Whether the collected assets should be cached.
281      *
282      * @var bool
283      */
284     public $use_cache = false;
285 
286     /**
287      * Sets the cache policy according to the configuration.
288      */
289     public function __construct($use_cache=false)
290     {
291         $this->use_cache = $use_cache;
292     }
293 
294     /**
295      * Adds an asset to the collection.
296      *
297      * @param string $path Path, or relative path to the asset.
298      * @param int $weight Weight of the asset in the collection.
299      * @param string|null $root Root used to resolve the asset path into a URL.
300      *
301      * @return AssetsCollector Return the object itself for chainable calls.
302      */
303     public function add($path, $weight=0, $root=null)
304     {
305         $url = Document::resolve_url($path, $root);
306 
307         $this->collected[$url] = $weight;
308 
309         return $this;
310     }
311 
312     /**
313      * Returns the collected assets as an array of URL.
314      *
315      * @return array
316      */
317     public function get()
318     {
319         $by_priority = array();
320 
321         foreach ($this->collected as $url => $priority)
322         {
323             $by_priority[$priority][] = $url;
324         }
325 
326         ksort($by_priority);
327 
328         $sorted = array();
329 
330         foreach ($by_priority as $urls)
331         {
332             $sorted = array_merge($sorted, $urls);
333         }
334 
335         return $sorted;
336     }
337 
338     /**
339      * Clears the collected assets.
340      */
341     public function clear()
342     {
343         $this->collected = array();
344     }
345 
346     abstract public function cache_construct(FileCache $cache, $key, array $userdata);
347 }
348 
349 /**
350  * Collector for CSS assets.
351  */
352 class CSSCollector extends AssetsCollector
353 {
354     public function __toString()
355     {
356         global $core;
357 
358         $collected = $this->get();
359 
360         try
361         {
362             if ($this->use_cache)
363             {
364                 $recent = 0;
365                 $root = DOCUMENT_ROOT;
366 
367                 foreach ($collected as $file)
368                 {
369                     $recent = max($recent, filemtime($root . $file));
370                 }
371 
372                 $cache = new FileCache
373                 (
374                     array
375                     (
376                         FileCache::T_REPOSITORY => $core->config['repository.files'] . '/assets',
377                         FileCache::T_MODIFIED_TIME => $recent
378                     )
379                 );
380 
381                 $key = sha1(implode(',', $collected)) . '.css';
382 
383                 $rc = $cache->get($key, array($this, 'cache_construct'), array($collected));
384 
385                 if ($rc)
386                 {
387                     $list = json_encode($collected);
388 
389                     return <<<EOT
390 
391 <link type="text/css" href="{$cache->repository}/{$key}" rel="stylesheet" />
392 
393 <script type="text/javascript">
394 
395 var brickrouge_cached_css_assets = $list;
396 
397 </script>
398 
399 EOT;
400 
401                 }
402             }
403         }
404         catch (\Exception $e) { echo render_exception($e); }
405 
406         #
407         # default ouput
408         #
409 
410         $rc = '';
411 
412         foreach ($collected as $url)
413         {
414             $rc .= '<link type="text/css" href="' . escape($url) . '" rel="stylesheet" />' . PHP_EOL;
415         }
416 
417         return $rc;
418     }
419 
420     public function cache_construct(FileCache $cache, $key, array $userdata)
421     {
422         list($collected) = $userdata;
423 
424         $rc = '/* Compiled CSS file generated by ' . __CLASS__ . ' */' . PHP_EOL . PHP_EOL;
425 
426         foreach ($collected as $url)
427         {
428             $contents = file_get_contents(DOCUMENT_ROOT . $url);
429             $contents = preg_replace('/url\(([^\)]+)/', 'url(' . dirname($url) . '/$1', $contents);
430 
431             $rc .= $contents . PHP_EOL;
432         }
433 
434         file_put_contents(getcwd() . '/' . $key, $rc);
435 
436         return $key;
437     }
438 }
439 
440 /**
441  * Collector for Javascript assets.
442  */
443 class JSCollector extends AssetsCollector
444 {
445     public function __toString()
446     {
447         global $core;
448 
449         $collected = $this->get();
450 
451         #
452         # exchange with minified versions
453         #
454 
455         if (0)
456         {
457             $root = DOCUMENT_ROOT;
458             $repository = $core->config['repository.files'] . '/assets/minified/';
459 
460             foreach ($collected as $file)
461             {
462                 $minified_key = md5($file);
463 
464                 if (!file_exists($root . $repository . $minified_key))
465                 {
466                     echo "<code>create minified ($minified_key) for $file</code><br />";
467 
468                     $cmd = "java -jar /users/serveurweb/Sites/yuicompressor-2.4.6.jar {$root}{$file} -o {$root}{$repository}{$minified_key}.js --charset utf-8";
469 
470                     echo "<code><strong>cmd:</strong> $cmd</code>";
471 
472                     $output = null;
473                     $return_var = null;
474 
475                     exec($cmd, $output, $return_var);
476 
477                     var_dump($output, $return_var);
478                 }
479             }
480         }
481 
482         #
483         # cached ouput
484         #
485 
486         try
487         {
488             if ($this->use_cache)
489             {
490                 $recent = 0;
491                 $root = DOCUMENT_ROOT;
492 
493                 foreach ($collected as $file)
494                 {
495                     $recent = max($recent, filemtime($root . $file));
496                 }
497 
498                 $cache = new FileCache
499                 (
500                     array
501                     (
502                         FileCache::T_REPOSITORY => $core->config['repository.files'] . '/assets',
503                         FileCache::T_MODIFIED_TIME => $recent
504                     )
505                 );
506 
507                 $key = sha1(implode(',', $collected)) . '.js';
508 
509                 $rc = $cache->get($key, array($this, 'cache_construct'), array($collected));
510 
511                 if ($rc)
512                 {
513                     return PHP_EOL . PHP_EOL . '<script type="text/javascript" src="' . $cache->repository . '/' . $key . '"></script>' . PHP_EOL . PHP_EOL;
514                 }
515             }
516         }
517         catch (\Exception $e) { echo render_exception($e); }
518 
519         #
520         # default output
521         #
522 
523         $rc = '';
524 
525         foreach ($collected as $url)
526         {
527             $rc .= '<script type="text/javascript" src="' . escape($url) . '"></script>' . PHP_EOL;
528         }
529 
530         return $rc;
531     }
532 
533     public function cache_construct(FileCache $cache, $key, array $userdata)
534     {
535         list($collected) = $userdata;
536 
537         $class = __CLASS__;
538         $date = date('Y-m-d');
539         $list = json_encode($collected);
540 
541         $content = <<<EOT
542 /*
543  * Compiled Javascript file generated by $class ($date)
544  */
545 
546 var brickrouge_cached_js_assets = $list;
547 
548 EOT;
549 
550         foreach ($collected as $url)
551         {
552             $content .= file_get_contents(DOCUMENT_ROOT . $url) . PHP_EOL;
553         }
554 
555         file_put_contents(getcwd() . '/' . $key, $content);
556 
557         return $key;
558     }
559 }
Autodoc API documentation generated by ApiGen 2.8.0