NFC - Short array syntax - auto-convert Civi dir
[civicrm-core.git] / Civi / Angular / Page / Modules.php
CommitLineData
e5afbdad
TO
1<?php
2
3namespace Civi\Angular\Page;
4
5/**
27a90ef6
TO
6 * This page aggregates data from Angular modules.
7 *
8 * Example: Aggregate metadata about all modules in JSON format.
9 * civicrm/ajax/angular-modules?format=json
10 *
11 * Example: Aggregate metadata for crmUi and crmUtil modules.
12 * civicrm/ajax/angular-modules?format=json&modules=crmUi,crmUtil
13 *
14 * Example: Aggregate *.js files for all modules.
15 * civicrm/ajax/angular-modules?format=js
16 *
17 * Example: Aggregate *.css files for all modules.
18 * civicrm/ajax/angular-modules?format=css
e5afbdad
TO
19 */
20class Modules extends \CRM_Core_Page {
21
22 /**
466e4b29
TO
23 * Generate asset content (when accessed via older, custom
24 * "civicrm/ajax/anulgar-modules" route).
25 *
26 * @deprecated
e5afbdad
TO
27 */
28 public function run() {
e5afbdad
TO
29 /**
30 * @var \Civi\Angular\Manager $angular
31 */
048222df 32 $angular = \Civi::service('angular');
27a90ef6
TO
33 $moduleNames = $this->parseModuleNames(\CRM_Utils_Request::retrieve('modules', 'String'), $angular);
34
35 switch (\CRM_Utils_Request::retrieve('format', 'String')) {
36 case 'json':
37 case '':
38 $this->send(
39 'application/javascript',
40 json_encode($this->getMetadata($moduleNames, $angular))
41 );
42 break;
43
44 case 'js':
45 $this->send(
46 'application/javascript',
ad295ca9 47 $this->digestJs($angular->getResources($moduleNames, 'js', 'path'))
27a90ef6
TO
48 );
49 break;
50
51 case 'css':
52 $this->send(
53 'text/css',
54 \CRM_Utils_File::concat($angular->getResources($moduleNames, 'css', 'path'), "\n")
55 );
56 break;
57
58 default:
59 \CRM_Core_Error::fatal("Unrecognized format");
60 }
61
62 \CRM_Utils_System::civiExit();
63 }
e5afbdad 64
466e4b29
TO
65 /**
66 * Generate asset content (when accessed via AssetBuilder).
67 *
68 * @param \Civi\Core\Event\GenericHookEvent $event
69 * @see CRM_Utils_hook::buildAsset()
70 * @see \Civi\Core\AssetBuilder
71 */
72 public static function buildAngularModules($event) {
73 $page = new Modules();
74 $angular = \Civi::service('angular');
75
76 switch ($event->asset) {
77 case 'angular-modules.json':
78 $moduleNames = $page->parseModuleNames(\CRM_Utils_Array::value('modules', $event->params), $angular);
79 $event->mimeType = 'application/json';
80 $event->content = json_encode($page->getMetadata($moduleNames, $angular));
81 break;
82
83 case 'angular-modules.js':
84 $moduleNames = $page->parseModuleNames(\CRM_Utils_Array::value('modules', $event->params), $angular);
85 $event->mimeType = 'application/javascript';
86 $event->content = $page->digestJs($angular->getResources($moduleNames, 'js', 'path'));
87 break;
88
89 case 'angular-modules.css':
90 $moduleNames = $page->parseModuleNames(\CRM_Utils_Array::value('modules', $event->params), $angular);
91 $event->mimeType = 'text/css';
92 $event->content = \CRM_Utils_File::concat($angular->getResources($moduleNames, 'css', 'path'), "\n");
93
94 default:
95 // Not our problem.
96 }
97 }
98
ad295ca9
TO
99 /**
100 * @param array $files
101 * File paths.
102 * @return string
103 */
104 public function digestJs($files) {
c64f69d9 105 $scripts = [];
ad295ca9
TO
106 foreach ($files as $file) {
107 $scripts[] = file_get_contents($file);
108 }
109 $scripts = \CRM_Utils_JS::dedupeClosures(
110 $scripts,
c64f69d9
CW
111 ['angular', '$', '_'],
112 ['angular', 'CRM.$', 'CRM._']
ad295ca9 113 );
b047e061
TO
114 // This impl of stripComments currently adds 10-20ms and cuts ~7%
115 return \CRM_Utils_JS::stripComments(implode("\n", $scripts));
ad295ca9
TO
116 }
117
27a90ef6
TO
118 /**
119 * @param string $modulesExpr
120 * Comma-separated list of module names.
121 * @param \Civi\Angular\Manager $angular
122 * @return array
123 * Any well-formed module names. All if moduleExpr is blank.
124 */
125 public function parseModuleNames($modulesExpr, $angular) {
e5afbdad
TO
126 if ($modulesExpr) {
127 $moduleNames = preg_grep(
128 '/^[a-zA-Z0-9\-_\.]+$/',
129 explode(',', $modulesExpr)
130 );
27a90ef6 131 return $moduleNames;
e5afbdad
TO
132 }
133 else {
27a90ef6
TO
134 $moduleNames = array_keys($angular->getModules());
135 return $moduleNames;
e5afbdad 136 }
27a90ef6 137 }
e5afbdad 138
27a90ef6
TO
139 /**
140 * @param array $moduleNames
141 * List of module names.
142 * @param \Civi\Angular\Manager $angular
143 * @return array
144 */
145 public function getMetadata($moduleNames, $angular) {
146 $modules = $angular->getModules();
c64f69d9 147 $result = [];
e5afbdad
TO
148 foreach ($moduleNames as $moduleName) {
149 if (isset($modules[$moduleName])) {
c64f69d9 150 $result[$moduleName] = [];
e3d90d6c 151 $result[$moduleName]['domain'] = $modules[$moduleName]['ext'];
27a90ef6
TO
152 $result[$moduleName]['js'] = $angular->getResources($moduleName, 'js', 'rawUrl');
153 $result[$moduleName]['css'] = $angular->getResources($moduleName, 'css', 'rawUrl');
e5afbdad
TO
154 $result[$moduleName]['partials'] = $angular->getPartials($moduleName);
155 $result[$moduleName]['strings'] = $angular->getTranslatedStrings($moduleName);
156 }
157 }
27a90ef6
TO
158 return $result;
159 }
e5afbdad 160
27a90ef6
TO
161 /**
162 * Send a response.
163 *
164 * @param string $type
165 * Content type.
166 * @param string $data
167 * Content.
168 */
169 public function send($type, $data) {
170 // Encourage browsers to cache for a long time - 1 year
171 $ttl = 60 * 60 * 24 * 364;
956d2f84
CW
172 \CRM_Utils_System::setHttpHeader('Expires', gmdate('D, d M Y H:i:s \G\M\T', time() + $ttl));
173 \CRM_Utils_System::setHttpHeader("Content-Type", $type);
174 \CRM_Utils_System::setHttpHeader("Cache-Control", "max-age=$ttl, public");
27a90ef6 175 echo $data;
e5afbdad
TO
176 }
177
178}