block.assetic.php
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2020 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of the MIT License.
7  *
8  * See the LICENSE file distributed with this work for
9  * additional information.
10  */
16 
17 use Assetic\Asset\AssetCache;
18 use Assetic\Asset\AssetCollection;
19 use Assetic\Asset\FileAsset;
20 use Assetic\Asset\StringAsset;
21 use Assetic\AssetWriter;
22 use Assetic\Cache\FilesystemCache;
23 use Assetic\Filter\CssRewriteFilter;
24 use Minifier\MinFilter;
25 
26 if (!class_exists('Assetic\Asset\AssetCollection')) {
27  throw new ConfigurationException(
28  'smarty_block_assetic requires '.
29  'Assetic. If you are using composer, add kriswallsmith/assetic '.
30  'as dependency to your project');
31 }
32 
33 /**
34  * Deliver assets using assetic library. Files will be combined and minified.
35  * JS and CSS will be recognized by the file extension.
36  * In order to not minify minified files again, the must use .min. in the filename.
37  * The result will be cached in the frontend cache (_FrontendCache_ configuration section).
38  *
39  * Example:
40  * @code
41  * {assetic name='header' debug=false}
42  * <link rel="stylesheet" href="css/normalize.min.css">
43  * <link rel="stylesheet" href="css/main.css">
44  *
45  * <script src="js/vendor/modernizr-2.8.3.min.js"></script>
46  * <script src="js/main.js"></script>
47  * {/assetic}
48  * @endcode
49  *
50  * @note Works only for local files.
51  *
52  * @param $params Array with keys:
53  * - name: The name of the created file (will be appended by .min.js|.min.css)
54  * - debug: Boolean, if true the content will be returned as is
55  * @param $content
56  * @param $template Smarty_Internal_Template
57  * @param $repeat
58  * @return String
59  */
60 function smarty_block_assetic($params, $content, Smarty_Internal_Template $template, &$repeat) {
61  if(!$repeat) {
62  if (isset($content)) {
63  if ($params['debug'] == true) {
64  return $content;
65  }
66  else {
67  $result = '';
68 
69  // parse urls and group resources by extension and minified state
70  $resources = [];
71  $urls = StringUtil::getUrls($content);
72  foreach ($urls as $url) {
73  $parts = pathinfo($url);
74  $extension = strtolower($parts['extension']);
75  $min = preg_match('/\.min$/', $parts['filename']);
76  if (!isset($resources[$extension])) {
77  $resources[$extension] = ['min' => [], 'src' => []];
78  }
79  $resources[$extension][$min ? 'min' : 'src'][] = $url;
80  }
81 
82  // setup assetic
83  $config = ObjectFactory::getInstance('configuration');
84  $basePath = dirname(FileUtil::realpath($_SERVER['SCRIPT_FILENAME'])).'/';
85  $cacheRootAbs = $config->getDirectoryValue('cacheDir', 'FrontendCache');
86  $cacheRootRel = URIUtil::makeRelative($cacheRootAbs, $basePath);
87  $hmacKey = $config->getValue('secret', 'application');
88 
89  // process resources
90  foreach ($resources as $type => $files) {
91  $filesystem = new FilesystemCache($cacheRootAbs);
92  $writer = new AssetWriter($cacheRootAbs);
93 
94  // hash content for cache busting
95  $hash = hash_init('sha1', HASH_HMAC, $hmacKey);
96  foreach (array_merge($files['min'], $files['src']) as $file) {
97  $content = file_exists($file) ? file_get_contents($file) : '';
98  hash_update($hash, $content);
99  }
100  $hash = substr(hash_final($hash), 0, 7);
101 
102  $cacheFile = (isset($params['name']) ? $params['name'] : '').'-'.$hash.'.min.'.$type;
103  $cachePathRel = $cacheRootRel.$cacheFile;
104 
105  // create filters
106  $filters = [];
107  if ($type == 'css') {
108  $filters[] = new CssRewriteFilter();
109  }
110  $minFilters = array_merge($filters, [new MinFilter($type)]);
111 
112  // create string assets from files (sourcePath and targetPath must be
113  // set correctly in order to make CssRewriteFilter work)
114  $minAssets = [];
115  foreach ($files['min'] as $file) {
116  $asset = new FileAsset($file, $filters, '', $file);
117  $asset->setTargetPath($cachePathRel);
118  $minAssets[] = new StringAsset($asset->dump());
119  }
120  foreach ($files['src'] as $file) {
121  $asset = new FileAsset($file, $minFilters, '', $file);
122  $asset->setTargetPath($cachePathRel);
123  $minAssets[] = new StringAsset($asset->dump());
124  }
125 
126  // write collected assets into cached file
127  $minCollection = new AssetCollection($minAssets);
128  $cache = new AssetCache($minCollection, $filesystem);
129  $cache->setTargetPath($cacheFile);
130  $writer->writeAsset($cache);
131 
132  // create html tag
133  switch ($type) {
134  case 'js':
135  $tag = '<script src="'.$cachePathRel.'"></script>';
136  break;
137  case 'css':
138  $tag = '<link rel="stylesheet" href="'.$cachePathRel.'">';
139  break;
140  }
141  $result .= $tag;
142  }
143  return $result;
144  }
145  }
146  }
147 }
148 ?>
StringUtil provides support for string manipulation.
Definition: StringUtil.php:18
ConfigurationException signals an exception in the configuration.
URIUtil provides support for uri manipulation.
Definition: URIUtil.php:18
FileUtil provides basic support for file functionality like HTTP file upload.
Definition: FileUtil.php:22
ObjectFactory implements the service locator pattern by wrapping a Factory instance and providing sta...