@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3/**
4 * Interface to the static resource map, which is a graph of available
5 * resources, resource dependencies, and packaging information. You generally do
6 * not need to invoke it directly; instead, you call higher-level Celerity APIs
7 * and it uses the resource map to satisfy your requests.
8 */
9final class CelerityResourceMap extends Phobject {
10
11 private static $instances = array();
12
13 private $resources;
14 private $symbolMap;
15 private $requiresMap;
16 private $packageMap;
17 private $nameMap;
18 private $hashMap;
19 private $componentMap;
20
21 public function __construct(CelerityResources $resources) {
22 $this->resources = $resources;
23
24 $map = $resources->loadMap();
25 $this->symbolMap = idx($map, 'symbols', array());
26 $this->requiresMap = idx($map, 'requires', array());
27 $this->packageMap = idx($map, 'packages', array());
28 $this->nameMap = idx($map, 'names', array());
29
30 // We derive these reverse maps at runtime.
31
32 $this->hashMap = array_flip($this->nameMap);
33 $this->componentMap = array();
34 foreach ($this->packageMap as $package_name => $symbols) {
35 foreach ($symbols as $symbol) {
36 $this->componentMap[$symbol] = $package_name;
37 }
38 }
39 }
40
41 public static function getNamedInstance($name) {
42 if (empty(self::$instances[$name])) {
43 $resources_list = CelerityPhysicalResources::getAll();
44 if (empty($resources_list[$name])) {
45 throw new Exception(
46 pht(
47 'No resource source exists with name "%s"!',
48 $name));
49 }
50
51 $instance = new CelerityResourceMap($resources_list[$name]);
52 self::$instances[$name] = $instance;
53 }
54
55 return self::$instances[$name];
56 }
57
58 public function getNameMap() {
59 return $this->nameMap;
60 }
61
62 public function getSymbolMap() {
63 return $this->symbolMap;
64 }
65
66 public function getRequiresMap() {
67 return $this->requiresMap;
68 }
69
70 public function getPackageMap() {
71 return $this->packageMap;
72 }
73
74 public function getPackagedNamesForSymbols(array $symbols) {
75 $resolved = $this->resolveResources($symbols);
76 return $this->packageResources($resolved);
77 }
78
79 private function resolveResources(array $symbols) {
80 $map = array();
81 foreach ($symbols as $symbol) {
82 if (!empty($map[$symbol])) {
83 continue;
84 }
85 $this->resolveResource($map, $symbol);
86 }
87
88 return $map;
89 }
90
91 private function resolveResource(array &$map, $symbol) {
92 if (empty($this->symbolMap[$symbol])) {
93 throw new Exception(
94 pht(
95 'Attempting to resolve unknown resource, "%s".',
96 $symbol));
97 }
98
99 $hash = $this->symbolMap[$symbol];
100
101 $map[$symbol] = $hash;
102
103 if (isset($this->requiresMap[$hash])) {
104 $requires = $this->requiresMap[$hash];
105 } else {
106 $requires = array();
107 }
108
109 foreach ($requires as $required_symbol) {
110 if (!empty($map[$required_symbol])) {
111 continue;
112 }
113 $this->resolveResource($map, $required_symbol);
114 }
115 }
116
117 private function packageResources(array $resolved_map) {
118 $packaged = array();
119 $handled = array();
120 foreach ($resolved_map as $symbol => $hash) {
121 if (isset($handled[$symbol])) {
122 continue;
123 }
124
125 if (empty($this->componentMap[$symbol])) {
126 $packaged[] = $this->hashMap[$hash];
127 } else {
128 $package_name = $this->componentMap[$symbol];
129 $packaged[] = $package_name;
130
131 $package_symbols = $this->packageMap[$package_name];
132 foreach ($package_symbols as $package_symbol) {
133 $handled[$package_symbol] = true;
134 }
135 }
136 }
137
138 return $packaged;
139 }
140
141 public function getResourceDataForName($resource_name) {
142 return $this->resources->getResourceData($resource_name);
143 }
144
145 public function getResourceNamesForPackageName($package_name) {
146 $package_symbols = idx($this->packageMap, $package_name);
147 if (!$package_symbols) {
148 return null;
149 }
150
151 $resource_names = array();
152 foreach ($package_symbols as $symbol) {
153 $resource_names[] = $this->hashMap[$this->symbolMap[$symbol]];
154 }
155
156 return $resource_names;
157 }
158
159
160 /**
161 * Get the epoch timestamp of the last modification time of a symbol.
162 *
163 * @param string $name Resource symbol to lookup.
164 * @return int Epoch timestamp of last resource modification.
165 */
166 public function getModifiedTimeForName($name) {
167 if ($this->isPackageResource($name)) {
168 $names = array();
169 foreach ($this->packageMap[$name] as $symbol) {
170 $names[] = $this->getResourceNameForSymbol($symbol);
171 }
172 } else {
173 $names = array($name);
174 }
175
176 $mtime = 0;
177 foreach ($names as $name) {
178 $mtime = max($mtime, $this->resources->getResourceModifiedTime($name));
179 }
180
181 return $mtime;
182 }
183
184
185 /**
186 * Return the absolute URI for the resource associated with a symbol. This
187 * method is fairly low-level and ignores packaging.
188 *
189 * @param string $symbol Resource symbol to lookup.
190 * @return string|null Resource URI, or null if the symbol is unknown.
191 */
192 public function getURIForSymbol($symbol) {
193 $hash = idx($this->symbolMap, $symbol);
194 return $this->getURIForHash($hash);
195 }
196
197
198 /**
199 * Return the absolute URI for the resource associated with a resource name.
200 * This method is fairly low-level and ignores packaging.
201 *
202 * @param string $name Resource name to lookup.
203 * @return string|null Resource URI, or null if the name is unknown.
204 */
205 public function getURIForName($name) {
206 $hash = idx($this->nameMap, $name);
207 return $this->getURIForHash($hash);
208 }
209
210
211 public function getHashForName($name) {
212 return idx($this->nameMap, $name);
213 }
214
215
216 /**
217 * Return the absolute URI for a resource, identified by hash.
218 * This method is fairly low-level and ignores packaging.
219 *
220 * @param string $hash Resource hash to lookup.
221 * @return string|null Resource URI, or null if the hash is unknown.
222 */
223 private function getURIForHash($hash) {
224 if ($hash === null) {
225 return null;
226 }
227 return $this->resources->getResourceURI($hash, $this->hashMap[$hash]);
228 }
229
230
231 /**
232 * Return the resource symbols required by a named resource.
233 *
234 * @param string $name Resource name to lookup.
235 * @return list<string>|null List of required symbols, or null if the name
236 * is unknown.
237 */
238 public function getRequiredSymbolsForName($name) {
239 $hash = idx($this->nameMap, $name);
240 if ($hash === null) {
241 return null;
242 }
243 return idx($this->requiresMap, $hash, array());
244 }
245
246
247 /**
248 * Return the resource name for a given symbol.
249 *
250 * @param string $symbol Resource symbol to lookup.
251 * @return string|null Resource name, or null if the symbol is unknown.
252 */
253 public function getResourceNameForSymbol($symbol) {
254 $hash = idx($this->symbolMap, $symbol);
255 return idx($this->hashMap, $hash);
256 }
257
258 public function isPackageResource($name) {
259 return isset($this->packageMap[$name]);
260 }
261
262 public function getResourceTypeForName($name) {
263 return $this->resources->getResourceType($name);
264 }
265
266}