ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
RequireJsProcess.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of Component Installer.
5  *
6  * (c) Rob Loach (http://robloach.net)
7  *
8  * For the full copyright and license information, please view the LICENSE.md
9  * file that was distributed with this source code.
10  */
11 
13 
15 use Composer\Config;
19 
24 {
28  protected $baseUrl = 'components';
29 
33  public function init()
34  {
35  $output = parent::init();
36  if ($this->config->has('component-baseurl')) {
37  $this->baseUrl = $this->config->get('component-baseurl');
38  }
39 
40  return $output;
41  }
42 
46  public function process()
47  {
48  // Construct the require.js and stick it in the destination.
49  $json = $this->requireJson($this->packages, $this->config);
50  $requireConfig = $this->requireJs($json);
51 
52  // Attempt to write the require.config.js file.
53  $destination = $this->componentDir . '/require.config.js';
54  $this->fs->ensureDirectoryExists(dirname($destination));
55  if (file_put_contents($destination, $requireConfig) === FALSE) {
56  $this->io->write('<error>Error writing require.config.js</error>');
57 
58  return false;
59  }
60 
61  // Read in require.js to prepare the final require.js.
62  if (!file_exists(dirname(__DIR__) . '/Resources/require.js')) {
63  $this->io->write('<error>Error reading in require.js</error>');
64 
65  return false;
66  }
67 
68  $assets = $this->newAssetCollection();
69  $assets->add(new FileAsset(dirname(__DIR__) . '/Resources/require.js'));
70  $assets->add(new StringAsset($requireConfig));
71 
72  // Append the config to the require.js and write it.
73  if (file_put_contents($this->componentDir . '/require.js', $assets->dump()) === FALSE) {
74  $this->io->write('<error>Error writing require.js to the components directory</error>');
75 
76  return false;
77  }
78 
79  return null;
80  }
81 
91  public function requireJson(array $packages)
92  {
93  $json = array();
94 
95  // Construct the packages configuration.
96  foreach ($packages as $package) {
97  // Retrieve information from the extra options.
98  $extra = isset($package['extra']) ? $package['extra'] : array();
99  $options = isset($extra['component']) ? $extra['component'] : array();
100 
101  // Construct the base details.
102  $name = $this->getComponentName($package['name'], $extra);
103  $component = array(
104  'name' => $name,
105  );
106 
107  // Build the "main" directive.
108  $scripts = isset($options['scripts']) ? $options['scripts'] : array();
109  if (!empty($scripts)) {
110  // Put all scripts into a build.js file.
111  $result = $this->aggregateScripts($package, $scripts, $name.DIRECTORY_SEPARATOR.$name.'-built.js');
112  if ($result) {
113  // If the aggregation was successful, add the script to the
114  // packages array.
115  $component['main'] = $name.'-built.js';
116 
117  // Add the component to the packages array.
118  $json['packages'][] = $component;
119  }
120  }
121 
122  // Add the shim definition for the package.
123  $shim = isset($options['shim']) ? $options['shim'] : array();
124  if (!empty($shim)) {
125  $json['shim'][$name] = $shim;
126  }
127 
128  // Add the config definition for the package.
129  $packageConfig = isset($options['config']) ? $options['config'] : array();
130  if (!empty($packageConfig)) {
131  $json['config'][$name] = $packageConfig;
132  }
133  }
134 
135  // Provide the baseUrl.
136  $json['baseUrl'] = $this->baseUrl;
137 
138  // Merge in configuration options from the root.
139  if ($this->config->has('component')) {
140  $config = $this->config->get('component');
141  if (isset($config) && is_array($config)) {
142  // Use a recursive, distict array merge.
143  $json = $this->arrayMergeRecursiveDistinct($json, $config);
144  }
145  }
146 
147  return $json;
148  }
149 
158  public function aggregateScripts($package, array $scripts, $file)
159  {
160  $assets = $this->newAssetCollection();
161 
162  foreach ($scripts as $script) {
163  // Collect each candidate from a glob file search.
164  $path = $this->getVendorDir($package).DIRECTORY_SEPARATOR.$script;
165  $matches = $this->fs->recursiveGlobFiles($path);
166  foreach ($matches as $match) {
167  $assets->add(new FileAsset($match));
168  }
169  }
170  $js = $assets->dump();
171 
172  // Write the file if there are any JavaScript assets.
173  if (!empty($js)) {
174  $destination = $this->componentDir.DIRECTORY_SEPARATOR.$file;
175  $this->fs->ensureDirectoryExists(dirname($destination));
176 
177  return file_put_contents($destination, $js);
178  }
179 
180  return false;
181  }
182 
192  public function requireJs(array $json = array())
193  {
194  // Encode the array to a JSON array.
195  $js = JsonFile::encode($json);
196 
197  // Construct the JavaScript output.
198  $output = <<<EOT
199 var components = $js;
200 if (typeof require !== "undefined" && require.config) {
201  require.config(components);
202 } else {
203  var require = components;
204 }
205 if (typeof exports !== "undefined" && typeof module !== "undefined") {
206  module.exports = components;
207 }
208 EOT;
209 
210  return $output;
211  }
212 
223  protected function arrayMergeRecursiveDistinct(array &$array1, array &$array2)
224  {
225  $merged = $array1;
226 
227  foreach ($array2 as $key => &$value) {
228  if(is_numeric($key)){
229  $merged[] = $value;
230  } else {
231  if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
232  $merged[$key] = $this->arrayMergeRecursiveDistinct($merged[$key], $value);
233  }
234  else {
235  $merged[$key] = $value;
236  }
237  }
238  }
239 
240  return $merged;
241  }
242 
246  protected function newAssetCollection()
247  {
248  // Aggregate all the assets into one file.
249  $assets = new AssetCollection();
250  if ($this->config->has('component-scriptFilters')) {
251  $filters = $this->config->get('component-scriptFilters');
252  if (isset($filters) && is_array($filters)) {
253  foreach ($filters as $filter => $filterParams) {
254  $reflection = new \ReflectionClass($filter);
256  $filter = $reflection->newInstanceArgs($filterParams);
257  $assets->ensureFilter($filter);
258  }
259  }
260  }
261 
262  return $assets;
263  }
264 }
requireJs(array $json=array())
Constructs the require.js file from the provided require.js JSON array.
$path
Definition: aliased.php:25
$js
$result
process()
{Called when running through the process.boolean True or false depending on whether the process was s...
$baseUrl
The base URL for the require.js configuration.
aggregateScripts($package, array $scripts, $file)
Concatenate all scripts together into one destination file.
if(!is_dir( $entity_dir)) exit("Fatal Error ([A-Za-z0-9]+)\+" &#(? foreach( $entity_files as $file) $output
A collection of assets.
Builds the require.js configuration.
if(!is_array($argv)) $options
Represents an asset loaded from a file.
Definition: FileAsset.php:22
getComponentName($prettyName, array $extra=array())
Retrieves the component name for the component.
Definition: Process.php:154
getVendorDir(array $package)
Retrieves the given package&#39;s vendor directory, where it&#39;s installed.
Definition: Process.php:199
Create styles array
The data for the language used.
arrayMergeRecursiveDistinct(array &$array1, array &$array2)
Merges two arrays without changing string array keys.
requireJson(array $packages)
Creates a require.js configuration from an array of packages.
Represents a string asset.
Definition: StringAsset.php:21
init()
{Initialize the process before its run.boolean Whether or not the process should continue after initi...
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
The base Process type.
Definition: Process.php:26