Stump Assets
  • Namespace
  • Class
  • Tree
  • Todo
  • Download

Namespaces

  • Skimia
    • Assets
      • Console
        • Commands
      • Events
      • Providers
      • Scanner

Classes

  • Skimia\Assets\AssetsServiceProvider
  • Skimia\Assets\Console\Commands\DumpCollectionsCommand
  • Skimia\Assets\Console\Commands\FlushPipelineCommand
  • Skimia\Assets\Events\BeforeMergeCollectionFiles
  • Skimia\Assets\Manager
  • Skimia\Assets\Providers\StolzAssetsServiceProvider
  • Skimia\Assets\Scanner\Scanner
  • Skimia\Assets\Scanner\ScannerServiceProvider
  1 <?php
  2 /**
  3  * Created by PhpStorm.
  4  * User: kessler
  5  * Date: 02/02/16
  6  * Time: 15:20.
  7  */
  8 namespace Skimia\Assets\Scanner;
  9 
 10 use Illuminate\Contracts\Foundation\Application;
 11 use Skimia\Assets\Events\BeforeMergeCollectionFiles;
 12 use Symfony\Component\Finder\Finder;
 13 use File;
 14 use Cache;
 15 
 16 class Scanner
 17 {
 18     /**
 19      * @var Application
 20      */
 21     protected $app;
 22 
 23     /**
 24      * @var array
 25      */
 26     protected $directories;
 27 
 28     /**
 29      * @var array
 30      */
 31     protected $builded_collections = [];
 32 
 33     /**
 34      * @var array
 35      */
 36     protected $last_builded_collections = [];
 37 
 38     /**
 39      * @var array
 40      */
 41     protected $directories_options;
 42 
 43     /**
 44      * @param Application $app
 45      */
 46     public function __construct(Application $app)
 47     {
 48         $this->app = $app;
 49     }
 50 
 51     /**
 52      * {@inheritdoc}
 53      */
 54     public function getScannedPath()
 55     {
 56         return $this->app['path.storage'].'/framework/assets.generation.scanned.php';
 57     }
 58 
 59     public function isScanned()
 60     {
 61         return $this->app['files']->exists($this->getScannedPath());
 62     }
 63 
 64     public function loadScanned()
 65     {
 66         if ($this->isScanned()) {
 67             require $this->getScannedPath();
 68 
 69             return true;
 70         }
 71 
 72         return false;
 73     }
 74 
 75     public function setDirectoriesToScan($directories)
 76     {
 77         $dirsToScan = [];
 78         foreach ($directories as $path => $directory) {
 79             if (is_string($path) && File::exists($path)) {
 80                 $dirsToScan[] = $path;
 81                 $this->directories_options[$path] = $directory;
 82             } elseif (is_string($directory) && File::exists($directory)) {
 83                 $dirsToScan[] = $directory;
 84             }
 85         }
 86         $this->directories = $dirsToScan;
 87     }
 88 
 89     public function scan()
 90     {
 91         file_put_contents(
 92             $this->getScannedPath(), '<?php '.$this->getDefinitions()
 93         );
 94     }
 95 
 96     protected function getOrderedFileDefinitions()
 97     {
 98         $files_defs = [];
 99         foreach ($this->directories as $path) {
100             if (! \File::exists($path)) {
101                 continue; // @codeCoverageIgnore
102             }
103 
104             $finder = Finder::create()->files()->ignoreDotFiles(false)->in($path);
105 
106             $max_depth = $this->app['config']->get('assets.max_depth', 3);
107             if (isset($this->directories_options[$path]['max_depth'])) {
108                 $max_depth = $this->directories_options[$path]['max_depth'];
109             }
110 
111             $files = $finder->depth('<= '.$max_depth)->name('.assets.json');
112 
113             foreach ($files as $file) {
114                 $content = $this->filterFile(json_decode($file->getContents(), true));
115                 $content['__dir'] = dirname($file->getRealpath());
116                 $files_defs[isset($content['alias']) ? $content['alias'] : $content['name']] = $content;
117             }
118         }
119 
120         return $this->orderBydeps($files_defs);
121     }
122 
123     protected function filterFile($file)
124     {
125         $file = array_merge(
126             [
127                 'name' => 'must_be_defined',
128                 'alias' => 'directory',
129             ],
130             $file
131         );
132 
133         return $file;
134     }
135 
136     public function getDefinitions()
137     {
138         $output = '$makeCollections = function($container){'.PHP_EOL;
139 
140         $files = $this->getOrderedFileDefinitions();
141 
142         $event = new BeforeMergeCollectionFiles($files);
143         event($event);
144         //$describe($files_defs['js-stac']);
145         $collections = $this->mergeFiles($files);
146 
147         foreach ($collections as $name => $assets) {
148             $output .= $this->buildCollection($name, $assets);
149         }
150 
151         $this->saveBuildedCollections();
152 
153         $output .= '};'.PHP_EOL;
154 
155         $output .= $this->makeGroups();
156 
157         return trim($output);
158     }
159 
160     protected function getAssetsGroups()
161     {
162         $groups = [];
163         $config = $this->app['config']->get('assets.groups', []);
164 
165         if (! isset($config['default'])) {
166             return['default'];
167         }
168 
169         foreach ($config as $groupName => $groupConfig) {
170             $groups[] = $groupName;
171         }
172 
173         return $groups;
174     }
175 
176     protected function makeGroups()
177     {
178         $output = '';
179 
180         $groups = $this->getAssetsGroups();
181 
182         foreach ($groups as $groupName) {
183             $output .= '$makeCollections(\''.$groupName.'\');'.PHP_EOL;
184         }
185 
186         return $output;
187     }
188 
189     protected function mergeFiles($files)
190     {
191         $collections = [];
192 
193         foreach ($files as $file) {
194             $file = $this->updateFile($file);
195             $file_collections = $file['collections'];
196             $collections = array_merge($collections, $file_collections);
197         }
198 
199         return $collections;
200     }
201 
202     protected function updateFile($file)
203     {
204         $collections = $file['collections'];
205         $file['__collections'] = $collections;
206         foreach ($collections as $name => &$files) {
207             foreach ($files as &$f) {
208 
209                 //do not prefix si c'est une collection
210                 if (\File::exists($file['__dir'].'/'.$f)) {
211                     $f = $file['alias'].'#'.$f;
212                 }
213             }
214         }
215 
216         $file['collections'] = $collections;
217 
218         $this->copyCollections($file);
219 
220         return $file;
221     }
222 
223     protected function copyCollections($file)
224     {
225         $mode = $this->app['config']->get('assets.copy_mode', 'copy');
226         $collections_dir = $this->app['config']->get('assets.collections_dir', 'collections');
227         $collections_dir = public_path($collections_dir);
228 
229         if (isset($file['copy'])) {
230             foreach ($file['copy'] as $directory) {
231                 $input = $file['__dir'].'/'.$directory;
232 
233                 $output = $collections_dir.'/'.$file['alias'].'/'.$directory;
234 
235                 if ($mode == 'copy') {
236                     $this->copyAssets($input, $output);
237                 } else {
238                     $this->symlinkAssets($input, $output);
239                 }
240             }
241         }
242     }
243 
244     protected function copyAssets($in, $out)
245     {
246         $out_dir = dirname($out);
247         \File::makeDirectory($out_dir, 0777, true, true);
248         \File::copyDirectory($in, $out);
249 
250         return true;
251     }
252 
253     protected function symlinkAssets($in, $out)
254     {
255         $out_dir = dirname($out);
256         \File::makeDirectory($out_dir, 0777, true, true);
257         symlink($in, $out);
258 
259         return true;
260     }
261 
262     protected function orderBydeps($list)
263     {
264         $resolved = [];
265         $seen = [];
266         $element = [
267             'name' => false,
268             'resolve_this' => false,
269             'require' => array_keys($list),
270         ];
271         $this->dep_resolve($list, $element, $resolved, $seen);
272 
273         return $resolved;
274     }
275 
276     protected function dep_resolve($list, $node, &$resolved, &$unresolved)
277     {
278         //echo $node['name']."<br/>";
279         $unresolved[] = $node;
280         if (isset($node['require'])) {
281             foreach ($node['require'] as $required) {
282                 if (! isset($list[$required])) {
283                     throw new \Exception('Unknown or not accessible dep: '.$required.' for '.$node['name'].(isset($node['alias']) ? '('.$node['alias'].')' : ''));
284                 }
285                 if (! in_array($list[$required], $resolved)) {
286                     if (in_array($list[$required], $unresolved)) {
287                         throw new \Exception('Circular reference detected: '.$node['name'].' -> '.$list[$required]['name'].(isset($list[$required]['alias']) ? '('.$list[$required]['alias'].')' : ''));
288                     }
289                     $this->dep_resolve($list, $list[$required], $resolved, $unresolved);
290                 }
291             }
292         }
293         if (! isset($node['resolve_this']) || $node['resolve_this'] === true) {
294             $resolved[] = $node;
295         }
296         unset($unresolved[array_search($node, $unresolved)]);
297     }
298 
299     protected function buildCollection($name, $files)
300     {
301         $this->builded_collections[] = $name;
302 
303         return sprintf('    Assets::group($container)->registerCollection(\'%s\', %s);'.PHP_EOL,
304             $name,
305             var_export($files, true));
306     }
307 
308     /**
309      * @codeCoverageIgnore
310      */
311     protected function saveBuildedCollections()
312     {
313         $this->last_builded_collections = Cache::get('skimia.assets.collections.builded', []);
314         Cache::forever('skimia.assets.collections.builded', $this->builded_collections);
315     }
316 
317     /**
318      * @codeCoverageIgnore
319      */
320     public function getNewlyBuildedCollections()
321     {
322         return array_diff($this->builded_collections, $this->last_builded_collections);
323     }
324 
325     /**
326      * @codeCoverageIgnore
327      */
328     public function getRemovedBuildedCollections()
329     {
330         return array_diff($this->last_builded_collections, $this->builded_collections);
331     }
332 }
333 
Stump Assets API documentation generated by ApiGen