XOOPS  2.6.0
Assets.php
Go to the documentation of this file.
1 <?php
2 /*
3  You may not change or alter any portion of this comment or credits
4  of supporting developers from this source code or any supporting source code
5  which is considered copyrighted (c) material of the original comment or credit authors.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 */
11 
12 namespace Xoops\Core;
13 
16 use Assetic\Filter;
23 
36 class Assets
37 {
41  private $debug = false;
42 
46  private $default_filters = array(
47  'css' => 'cssimport,cssembed,?cssmin',
48  'js' => '?jsmin',
49  );
50 
54  private $default_output = array(
55  'css' => 'css/*.css',
56  'js' => 'js/*.js',
57  );
58 
62  private $default_asset_refs = array(
63  array(
64  'name' => 'jquery',
65  'assets' => array('media/jquery/jquery.js'),
66  'filters' => null,
67  ),
68  array(
69  'name' => 'jqueryui',
70  'assets' => array('media/jquery/ui/jquery-ui.js'),
71  'filters' => null,
72  ),
73  array(
74  'name' => 'jgrowl',
75  'assets' => array('media/jquery/plugins/jquery.jgrowl.js'),
76  'filters' => null,
77  ),
78  );
79 
83  private $assetManager = null;
84 
88  private $assetsPrefsFilename = 'var/configs/system_assets_prefs.yml';
89 
93  private $assetsPrefsCacheKey = 'system/assets/prefs';
94 
99  private $filterInterface = '\Assetic\Filter\FilterInterface';
105  public function __construct()
106  {
107  $this->assetManager = new AssetManager();
108  if (isset($_REQUEST['ASSET_DEBUG'])) {
109  $this->setDebug(true);
110  }
111  $this->readAssetsPrefs();
112  // register any asset references
113  foreach ($this->default_asset_refs as $ref) {
114  $this->registerAssetReference($ref['name'], $ref['assets'], $ref['filters']);
115  }
116  }
117 
123  protected function readAssetsPrefs()
124  {
126 
127  $assetsPrefs = array();
128 
129  try {
130  $assetsPrefs = $xoops->cache()->read($this->assetsPrefsCacheKey);
131  $file = $xoops->path($this->assetsPrefsFilename);
132  $mtime = filemtime($file);
133  if ($assetsPrefs===false || !isset($assetsPrefs['mtime']) || !$mtime
134  || (isset($assetsPrefs['mtime']) && $assetsPrefs['mtime']<$mtime)) {
135  if ($mtime) {
136  $assetsPrefs = Yaml::read($file);
137  if (!is_array($assetsPrefs)) {
138  $xoops->logger()->error("Invalid config in system_assets_prefs.yml");
139  $assetsPrefs = array();
140  } else {
141  $assetsPrefs['mtime']=$mtime;
142  $xoops->cache()->write($this->assetsPrefsCacheKey, $assetsPrefs);
143  }
144  } else {
145  // use defaults to create file
146  $assetsPrefs = array(
147  'default_filters' => $this->default_filters,
148  'default_asset_refs' => $this->default_asset_refs,
149  'mtime' => time(),
150  );
151  $this->saveAssetsPrefs($assetsPrefs);
152  }
153  }
154  if (!empty($assetsPrefs['default_filters']) && is_array($assetsPrefs['default_filters'])) {
155  $this->default_filters = $assetsPrefs['default_filters'];
156  }
157  if (!empty($assetsPrefs['default_asset_refs']) && is_array($assetsPrefs['default_asset_refs'])) {
158  $this->default_asset_refs = $assetsPrefs['default_asset_refs'];
159  }
160  } catch (\Exception $e) {
161  $xoops->events()->triggerEvent('core.exception', $e);
162  $assetsPrefs = array();
163  }
164  return $assetsPrefs;
165  }
166 
175  protected function saveAssetsPrefs($assets_prefs)
176  {
177  if (is_array($assets_prefs)) {
179  try {
180  Yaml::save($assets_prefs, $xoops->path($this->assetsPrefsFilename));
181  $xoops->cache()->write($this->assetsPrefsCacheKey, $assets_prefs);
182  } catch (\Exception $e) {
183  $xoops->events()->triggerEvent('core.exception', $e);
184  }
185  }
186  }
187 
188 
202  public function getUrlToAssets($type, $assets, $filters = 'default', $target = null)
203  {
204  if (is_scalar($assets)) {
205  $assets = array($assets); // just a single path name
206  }
207 
208  if ($filters=='default') {
209  if (isset($this->default_filters[$type])) {
210  $filters = $this->default_filters[$type];
211  } else {
212  $filters = '';
213  }
214  }
215 
216  if (!is_array($filters)) {
217  if (empty($filters)) {
218  $filters = array();
219  } else {
220  $filters = explode(',', str_replace(' ', '', $filters));
221  }
222  }
223 
224  if (isset($this->default_output[$type])) {
225  $output = $this->default_output[$type];
226  } else {
227  $output = '';
228  }
229 
231 
232  if (isset($target)) {
233  $target_path = $target;
234  } else {
235  $target_path = $xoops->path('assets');
236  }
237 
238  try {
239  $am = $this->assetManager;
240  $fm = new FilterManager();
241 
242  foreach ($filters as $filter) {
243  if (is_object($filter) && $filter instanceof $this->filterInterface) {
244  $filterArray[] = $filter;
245  } else {
246  switch (ltrim($filter, '?')) {
247  case 'cssembed':
248  $fm->set('cssembed', new Filter\PhpCssEmbedFilter());
249  break;
250  case 'cssmin':
251  $fm->set('cssmin', new Filter\CssMinFilter());
252  break;
253  case 'cssimport':
254  $fm->set('cssimport', new Filter\CssImportFilter());
255  break;
256  case 'cssrewrite':
257  $fm->set('cssrewrite', new Filter\CssRewriteFilter());
258  break;
259  case 'lessphp':
260  $fm->set('lessphp', new Filter\LessphpFilter());
261  break;
262  case 'scssphp':
263  $fm->set('scssphp', new Filter\ScssphpFilter());
264  break;
265  case 'jsmin':
266  $fm->set('jsmin', new Filter\JSMinFilter());
267  break;
268  default:
269  throw new \Exception(sprintf('%s filter not implemented.', $filter));
270  break;
271  }
272  }
273  }
274 
275  // Factory setup
276  $factory = new AssetFactory($target_path);
277  $factory->setAssetManager($am);
278  $factory->setFilterManager($fm);
279  $factory->setDefaultOutput($output);
280  $factory->setDebug($this->debug);
281  $factory->addWorker(new CacheBustingWorker());
282 
283  // Prepare the assets writer
284  $writer = new AssetWriter($target_path);
285 
286  // Translate asset paths, remove duplicates
287  $translated_assets = array();
288  foreach ($assets as $k => $v) {
289  // translate path if not a reference or absolute path
290  if (0 == preg_match("/^\\/|^\\\\|^[a-zA-Z]:|^@/", $v)) {
291  $v = $xoops->path($v);
292  }
293  if (!in_array($v, $translated_assets)) {
294  $translated_assets[] = $v;
295  }
296  }
297 
298  // Create the asset
299  $asset = $factory->createAsset(
300  $translated_assets,
301  $filters
302  );
303  $asset_path = $asset->getTargetPath();
304  if (!is_readable($target_path . $asset_path)) {
305  $xoops->events()->triggerEvent('debug.timer.start', array('writeAsset', $asset_path));
306  $oldumask = umask(0002);
307  $writer->writeAsset($asset);
308  umask($oldumask);
309  $xoops->events()->triggerEvent('debug.timer.stop', 'writeAsset');
310  }
311 
312  return $xoops->url('assets/' . $asset_path);
313 
314  } catch (\Exception $e) {
315  $xoops->events()->triggerEvent('core.exception', $e);
316  return null;
317  }
318  }
319 
320 
328  public function setDebug($debug)
329  {
330  $this->debug = (boolean) $debug;
331  }
332 
344  public function registerAssetReference($name, $assets, $filters = null)
345  {
347 
348  $assetArray = array();
349  $filterArray = array();
350 
351  try {
352  if (is_scalar($assets)) {
353  $assets = array($assets); // just a single path name
354  }
355  foreach ($assets as $a) {
356  // translate path if not a reference or absolute path
357  if ((substr_compare($a, '@', 0, 1) != 0)
358  && (substr_compare($a, '/', 0, 1) != 0)) {
359  $a = $xoops->path($a);
360  }
361  if (false===strpos($a, '*')) {
362  $assetArray[] = new FileAsset($a); // single file
363  } else {
364  $assetArray[] = new GlobAsset($a); // wild card match
365  }
366  }
367 
368  if (!is_array($filters)) {
369  if (empty($filters)) {
370  $filters = array();
371  } else {
372  $filters = explode(',', str_replace(' ', '', $filters));
373  }
374  }
375  foreach ($filters as $filter) {
376  if (is_object($filter) && $filter instanceof $this->filterInterface) {
377  $filterArray[] = $filter;
378  } else {
379  switch (ltrim($filter, '?')) {
380  case 'cssembed':
381  $filterArray[] = new Filter\PhpCssEmbedFilter();
382  break;
383  case 'cssmin':
384  $filterArray[] = new Filter\CssMinFilter();
385  break;
386  case 'cssimport':
387  $filterArray[] = new Filter\CssImportFilter();
388  break;
389  case 'cssrewrite':
390  $filterArray[] = new Filter\CssRewriteFilter();
391  break;
392  case 'lessphp':
393  $filterArray[] = new Filter\LessphpFilter();
394  break;
395  case 'scssphp':
396  $filterArray[] = new Filter\ScssphpFilter();
397  break;
398  case 'jsmin':
399  $filterArray[] = new Filter\JSMinFilter();
400  break;
401  default:
402  throw new \Exception(sprintf('%s filter not implemented.', $filter));
403  break;
404  }
405  }
406  }
407 
408  $collection = new AssetCollection($assetArray, $filterArray);
409  $this->assetManager->set($name, $collection);
410 
411  return true;
412  } catch (\Exception $e) {
413  $xoops->events()->triggerEvent('core.exception', $e);
414  return false;
415  }
416  }
417 
431  public function copyFileAssets($from_path, $pattern, $output)
432  {
434 
435  $to_path = $xoops->path('assets') . '/' . $output . '/';
436  $from = glob($from_path . '/' . $pattern);
437  $xoops->events()->triggerEvent('debug.log', $from);
438 
439  if (!is_dir($to_path)) {
440  $oldUmask = umask(0);
441  mkdir($to_path, 0775, true);
442  umask($oldUmask);
443  }
444 
445  if (!is_writable($to_path)) {
446  $xoops->logger()->warning('Asset directory is not writable. ' . $output);
447  return false;
448  } else {
449  $count = 0;
450  $oldUmask = umask(0002);
451  foreach ($from as $filepath) {
452  $filename = basename($filepath);
453  $status=copy($filepath, $to_path.$filename);
454  if (false) {
455  $xoops->logger()->warning('Failed to copy asset '.$filename);
456  } else {
457  $xoops->logger()->debug('Copied asset '.$filename);
458  ++$count;
459  }
460  }
461  umask($oldUmask);
462  return $count;
463  }
464  }
465 }
registerAssetReference($name, $assets, $filters=null)
Definition: Assets.php:344
static getInstance()
Definition: Xoops.php:160
if(!isset($xoops->paths[$path_type])) if($path_type== 'var') $file
Definition: browse.php:55
getUrlToAssets($type, $assets, $filters= 'default', $target=null)
Definition: Assets.php:202
else $filter
Definition: dialog.php:95
$xoops
Definition: admin.php:25
$oldUmask
Definition: thumbrender.php:39
$status
saveAssetsPrefs($assets_prefs)
Definition: Assets.php:175
copyFileAssets($from_path, $pattern, $output)
Definition: Assets.php:431
static save($var, $yamlFile, $inline=4, $indent=4)
Definition: Yaml.php:109
$type
Definition: misc.php:33
setDebug($debug)
Definition: Assets.php:328
static read($yamlFile)
Definition: Yaml.php:87
if($file===false||$dir===false||!strstr($file, $dir)) if(empty($file)||strpos($file, '.php')!==false) $mtime
Definition: browse.php:71
$target