@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
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add packaging to Celerity.

+241 -39
+61 -3
scripts/celerity_mapper.php
··· 1 1 #!/usr/bin/env php 2 2 <?php 3 3 4 + $package_spec = array( 5 + 'core.pkg.css' => array( 6 + 'phabricator-core-css', 7 + 'phabricator-core-buttons-css', 8 + 'phabricator-standard-page-view', 9 + 'aphront-dialog-view-css', 10 + 'aphront-form-view-css', 11 + 'aphront-panel-view-css', 12 + 'aphront-side-nav-view-css', 13 + 'aphront-table-view-css', 14 + 'aphront-tokenizer-control-css', 15 + 'aphront-typeahead-control-css', 16 + 17 + 'phabricator-directory-css', 18 + ), 19 + 'differential.pkg.css' => array( 20 + 'differential-core-view-css', 21 + 'differential-changeset-view-css', 22 + 'differential-revision-detail-css', 23 + 'differential-revision-history-css', 24 + 'differential-table-of-contents-css', 25 + ), 26 + ); 27 + 28 + 4 29 require_once dirname(__FILE__).'/__init_script__.php'; 5 30 6 31 if ($argc != 2) { ··· 39 64 40 65 $runtime_map = array(); 41 66 67 + $hash_map = array(); 68 + 42 69 $parser = new PhutilDocblockParser(); 43 70 foreach ($file_map as $path => $info) { 44 71 $data = Filesystem::readFile($info['disk']); ··· 69 96 $type = 'css'; 70 97 } 71 98 72 - $path = '/res/'.substr($info['hash'], 0, 8).$path; 99 + $uri = '/res/'.substr($info['hash'], 0, 8).$path; 100 + 101 + $hash_map[$provides] = $info['hash']; 73 102 74 103 $runtime_map[$provides] = array( 75 - 'path' => $path, 104 + 'uri' => $uri, 76 105 'type' => $type, 77 106 'requires' => $requires, 107 + 'disk' => $path, 78 108 ); 79 109 } 80 110 111 + $package_map = array(); 112 + foreach ($package_spec as $name => $package) { 113 + $hashes = array(); 114 + foreach ($package as $symbol) { 115 + if (empty($hash_map[$symbol])) { 116 + throw new Exception( 117 + "Package specification for '{$name}' includes '{$symbol}', but that ". 118 + "symbol is not defined anywhere."); 119 + } 120 + $hashes[] = $symbol.':'.$hash_map[$symbol]; 121 + } 122 + $key = substr(md5(implode("\n", $hashes)), 0, 8); 123 + $package_map['packages'][$key] = array( 124 + 'name' => $name, 125 + 'symbols' => $package, 126 + 'uri' => '/res/pkg/'.$key.'/'.$name, 127 + 'type' => 'css', // TODO LOL 128 + ); 129 + foreach ($package as $symbol) { 130 + $package_map['reverse'][$symbol] = $key; 131 + } 132 + } 133 + 134 + 81 135 $runtime_map = var_export($runtime_map, true); 82 136 $runtime_map = preg_replace('/\s+$/m', '', $runtime_map); 83 137 $runtime_map = preg_replace('/array \(/', 'array(', $runtime_map); 138 + 139 + $package_map = var_export($package_map, true); 140 + $pacakge_map = preg_replace('/\s+$/m', '', $package_map); 141 + $package_map = preg_replace('/array \(/', 'array(', $package_map); 84 142 85 143 $resource_map = <<<EOFILE 86 144 <?php ··· 91 149 * @generated 92 150 */ 93 151 94 - celerity_register_resource_map({$runtime_map}); 152 + celerity_register_resource_map({$runtime_map}, {$pacakge_map}); 95 153 96 154 EOFILE; 97 155
+107 -25
src/__celerity_resource_map__.php
··· 9 9 celerity_register_resource_map(array( 10 10 'aphront-dialog-view-css' => 11 11 array( 12 - 'path' => '/res/771b987d/rsrc/css/aphront/dialog-view.css', 12 + 'uri' => '/res/771b987d/rsrc/css/aphront/dialog-view.css', 13 13 'type' => 'css', 14 14 'requires' => 15 15 array( 16 16 ), 17 + 'disk' => '/rsrc/css/aphront/dialog-view.css', 17 18 ), 18 19 'aphront-form-view-css' => 19 20 array( 20 - 'path' => '/res/785ac1c6/rsrc/css/aphront/form-view.css', 21 + 'uri' => '/res/785ac1c6/rsrc/css/aphront/form-view.css', 21 22 'type' => 'css', 22 23 'requires' => 23 24 array( 24 25 ), 26 + 'disk' => '/rsrc/css/aphront/form-view.css', 25 27 ), 26 28 'aphront-panel-view-css' => 27 29 array( 28 - 'path' => '/res/fe62e634/rsrc/css/aphront/panel-view.css', 30 + 'uri' => '/res/fe62e634/rsrc/css/aphront/panel-view.css', 29 31 'type' => 'css', 30 32 'requires' => 31 33 array( 32 34 ), 35 + 'disk' => '/rsrc/css/aphront/panel-view.css', 33 36 ), 34 37 'aphront-side-nav-view-css' => 35 38 array( 36 - 'path' => '/res/0fc0545c/rsrc/css/aphront/side-nav-view.css', 39 + 'uri' => '/res/0fc0545c/rsrc/css/aphront/side-nav-view.css', 37 40 'type' => 'css', 38 41 'requires' => 39 42 array( 40 43 ), 44 + 'disk' => '/rsrc/css/aphront/side-nav-view.css', 41 45 ), 42 46 'aphront-table-view-css' => 43 47 array( 44 - 'path' => '/res/52b0191f/rsrc/css/aphront/table-view.css', 48 + 'uri' => '/res/52b0191f/rsrc/css/aphront/table-view.css', 45 49 'type' => 'css', 46 50 'requires' => 47 51 array( 48 52 ), 53 + 'disk' => '/rsrc/css/aphront/table-view.css', 49 54 ), 50 55 'aphront-tokenizer-control-css' => 51 56 array( 52 - 'path' => '/res/a3d23074/rsrc/css/aphront/tokenizer.css', 57 + 'uri' => '/res/a3d23074/rsrc/css/aphront/tokenizer.css', 53 58 'type' => 'css', 54 59 'requires' => 55 60 array( 56 61 0 => 'aphront-typeahead-control-css', 57 62 ), 63 + 'disk' => '/rsrc/css/aphront/tokenizer.css', 58 64 ), 59 65 'aphront-typeahead-control-css' => 60 66 array( 61 - 'path' => '/res/928df9f0/rsrc/css/aphront/typeahead.css', 67 + 'uri' => '/res/928df9f0/rsrc/css/aphront/typeahead.css', 62 68 'type' => 'css', 63 69 'requires' => 64 70 array( 65 71 ), 72 + 'disk' => '/rsrc/css/aphront/typeahead.css', 66 73 ), 67 74 'phabricator-standard-page-view' => 68 75 array( 69 - 'path' => '/res/1f93ada7/rsrc/css/application/base/standard-page-view.css', 76 + 'uri' => '/res/1f93ada7/rsrc/css/application/base/standard-page-view.css', 70 77 'type' => 'css', 71 78 'requires' => 72 79 array( 73 80 ), 81 + 'disk' => '/rsrc/css/application/base/standard-page-view.css', 74 82 ), 75 83 'differential-changeset-view-css' => 76 84 array( 77 - 'path' => '/res/658d181a/rsrc/css/application/differential/changeset-view.css', 85 + 'uri' => '/res/658d181a/rsrc/css/application/differential/changeset-view.css', 78 86 'type' => 'css', 79 87 'requires' => 80 88 array( 81 89 ), 90 + 'disk' => '/rsrc/css/application/differential/changeset-view.css', 82 91 ), 83 92 'differential-core-view-css' => 84 93 array( 85 - 'path' => '/res/525d1a12/rsrc/css/application/differential/core.css', 94 + 'uri' => '/res/525d1a12/rsrc/css/application/differential/core.css', 86 95 'type' => 'css', 87 96 'requires' => 88 97 array( 89 98 ), 99 + 'disk' => '/rsrc/css/application/differential/core.css', 90 100 ), 91 101 'differential-revision-detail-css' => 92 102 array( 93 - 'path' => '/res/11a36dad/rsrc/css/application/differential/revision-detail.css', 103 + 'uri' => '/res/230a67c6/rsrc/css/application/differential/revision-detail.css', 94 104 'type' => 'css', 95 105 'requires' => 96 106 array( 97 107 ), 108 + 'disk' => '/rsrc/css/application/differential/revision-detail.css', 98 109 ), 99 110 'differential-revision-history-css' => 100 111 array( 101 - 'path' => '/res/755f3da3/rsrc/css/application/differential/revision-history.css', 112 + 'uri' => '/res/755f3da3/rsrc/css/application/differential/revision-history.css', 102 113 'type' => 'css', 103 114 'requires' => 104 115 array( 105 116 ), 117 + 'disk' => '/rsrc/css/application/differential/revision-history.css', 106 118 ), 107 119 'differential-table-of-contents-css' => 108 120 array( 109 - 'path' => '/res/a4a7b2b5/rsrc/css/application/differential/table-of-contents.css', 121 + 'uri' => '/res/a4a7b2b5/rsrc/css/application/differential/table-of-contents.css', 110 122 'type' => 'css', 111 123 'requires' => 112 124 array( 113 125 ), 126 + 'disk' => '/rsrc/css/application/differential/table-of-contents.css', 114 127 ), 115 128 'phabricator-directory-css' => 116 129 array( 117 - 'path' => '/res/6a000601/rsrc/css/application/directory/phabricator-directory.css', 130 + 'uri' => '/res/6a000601/rsrc/css/application/directory/phabricator-directory.css', 118 131 'type' => 'css', 119 132 'requires' => 120 133 array( 121 134 ), 135 + 'disk' => '/rsrc/css/application/directory/phabricator-directory.css', 122 136 ), 123 137 'phabricator-core-buttons-css' => 124 138 array( 125 - 'path' => '/res/6e348ba4/rsrc/css/core/buttons.css', 139 + 'uri' => '/res/6e348ba4/rsrc/css/core/buttons.css', 126 140 'type' => 'css', 127 141 'requires' => 128 142 array( 129 143 ), 144 + 'disk' => '/rsrc/css/core/buttons.css', 130 145 ), 131 146 'phabricator-core-css' => 132 147 array( 133 - 'path' => '/res/39ce37c2/rsrc/css/core/core.css', 148 + 'uri' => '/res/39ce37c2/rsrc/css/core/core.css', 134 149 'type' => 'css', 135 150 'requires' => 136 151 array( 137 152 ), 153 + 'disk' => '/rsrc/css/core/core.css', 138 154 ), 139 155 'syntax-highlighting-css' => 140 156 array( 141 - 'path' => '/res/fb673ece/rsrc/css/core/syntax.css', 157 + 'uri' => '/res/fb673ece/rsrc/css/core/syntax.css', 142 158 'type' => 'css', 143 159 'requires' => 144 160 array( 145 161 ), 162 + 'disk' => '/rsrc/css/core/syntax.css', 146 163 ), 147 164 'javelin-behavior-aphront-basic-tokenizer' => 148 165 array( 149 - 'path' => '/res/8317d761/rsrc/js/application/core/behavior-tokenizer.js', 166 + 'uri' => '/res/8317d761/rsrc/js/application/core/behavior-tokenizer.js', 150 167 'type' => 'js', 151 168 'requires' => 152 169 array( 153 170 0 => 'javelin-lib-dev', 154 171 ), 172 + 'disk' => '/rsrc/js/application/core/behavior-tokenizer.js', 155 173 ), 156 174 'javelin-behavior-differential-populate' => 157 175 array( 158 - 'path' => '/res/9982573c/rsrc/js/application/differential/behavior-populate.js', 176 + 'uri' => '/res/9982573c/rsrc/js/application/differential/behavior-populate.js', 159 177 'type' => 'js', 160 178 'requires' => 161 179 array( 162 180 0 => 'javelin-lib-dev', 163 181 ), 182 + 'disk' => '/rsrc/js/application/differential/behavior-populate.js', 164 183 ), 165 184 'javelin-init-dev' => 166 185 array( 167 - 'path' => '/res/c57a9e89/rsrc/js/javelin/init.dev.js', 186 + 'uri' => '/res/c57a9e89/rsrc/js/javelin/init.dev.js', 168 187 'type' => 'js', 169 188 'requires' => 170 189 array( 171 190 ), 191 + 'disk' => '/rsrc/js/javelin/init.dev.js', 172 192 ), 173 193 'javelin-init-prod' => 174 194 array( 175 - 'path' => '/res/f0172c54/rsrc/js/javelin/init.min.js', 195 + 'uri' => '/res/f0172c54/rsrc/js/javelin/init.min.js', 176 196 'type' => 'js', 177 197 'requires' => 178 198 array( 179 199 ), 200 + 'disk' => '/rsrc/js/javelin/init.min.js', 180 201 ), 181 202 'javelin-lib-dev' => 182 203 array( 183 - 'path' => '/res/3e747182/rsrc/js/javelin/javelin.dev.js', 204 + 'uri' => '/res/3e747182/rsrc/js/javelin/javelin.dev.js', 184 205 'type' => 'js', 185 206 'requires' => 186 207 array( 187 208 ), 209 + 'disk' => '/rsrc/js/javelin/javelin.dev.js', 188 210 ), 189 211 'javelin-lib-prod' => 190 212 array( 191 - 'path' => '/res/9438670e/rsrc/js/javelin/javelin.min.js', 213 + 'uri' => '/res/9438670e/rsrc/js/javelin/javelin.min.js', 192 214 'type' => 'js', 193 215 'requires' => 194 216 array( 195 217 ), 218 + 'disk' => '/rsrc/js/javelin/javelin.min.js', 196 219 ), 197 220 'javelin-typeahead-dev' => 198 221 array( 199 - 'path' => '/res/c81c0f01/rsrc/js/javelin/typeahead.dev.js', 222 + 'uri' => '/res/c81c0f01/rsrc/js/javelin/typeahead.dev.js', 200 223 'type' => 'js', 201 224 'requires' => 202 225 array( 203 226 ), 227 + 'disk' => '/rsrc/js/javelin/typeahead.dev.js', 204 228 ), 205 229 'javelin-typeahead-prod' => 206 230 array( 207 - 'path' => '/res/1da2d984/rsrc/js/javelin/typeahead.min.js', 231 + 'uri' => '/res/1da2d984/rsrc/js/javelin/typeahead.min.js', 208 232 'type' => 'js', 209 233 'requires' => 210 234 array( 211 235 ), 236 + 'disk' => '/rsrc/js/javelin/typeahead.min.js', 237 + ), 238 + ), array ( 239 + 'packages' => 240 + array ( 241 + '4efe7b58' => 242 + array ( 243 + 'name' => 'core.pkg.css', 244 + 'symbols' => 245 + array ( 246 + 0 => 'phabricator-core-css', 247 + 1 => 'phabricator-core-buttons-css', 248 + 2 => 'phabricator-standard-page-view', 249 + 3 => 'aphront-dialog-view-css', 250 + 4 => 'aphront-form-view-css', 251 + 5 => 'aphront-panel-view-css', 252 + 6 => 'aphront-side-nav-view-css', 253 + 7 => 'aphront-table-view-css', 254 + 8 => 'aphront-tokenizer-control-css', 255 + 9 => 'aphront-typeahead-control-css', 256 + 10 => 'phabricator-directory-css', 257 + ), 258 + 'uri' => '/res/pkg/4efe7b58/core.pkg.css', 259 + 'type' => 'css', 260 + ), 261 + '69b11588' => 262 + array ( 263 + 'name' => 'differential.pkg.css', 264 + 'symbols' => 265 + array ( 266 + 0 => 'differential-core-view-css', 267 + 1 => 'differential-changeset-view-css', 268 + 2 => 'differential-revision-detail-css', 269 + 3 => 'differential-revision-history-css', 270 + 4 => 'differential-table-of-contents-css', 271 + ), 272 + 'uri' => '/res/pkg/69b11588/differential.pkg.css', 273 + 'type' => 'css', 274 + ), 275 + ), 276 + 'reverse' => 277 + array ( 278 + 'phabricator-core-css' => '4efe7b58', 279 + 'phabricator-core-buttons-css' => '4efe7b58', 280 + 'phabricator-standard-page-view' => '4efe7b58', 281 + 'aphront-dialog-view-css' => '4efe7b58', 282 + 'aphront-form-view-css' => '4efe7b58', 283 + 'aphront-panel-view-css' => '4efe7b58', 284 + 'aphront-side-nav-view-css' => '4efe7b58', 285 + 'aphront-table-view-css' => '4efe7b58', 286 + 'aphront-tokenizer-control-css' => '4efe7b58', 287 + 'aphront-typeahead-control-css' => '4efe7b58', 288 + 'phabricator-directory-css' => '4efe7b58', 289 + 'differential-core-view-css' => '69b11588', 290 + 'differential-changeset-view-css' => '69b11588', 291 + 'differential-revision-detail-css' => '69b11588', 292 + 'differential-revision-history-css' => '69b11588', 293 + 'differential-table-of-contents-css' => '69b11588', 212 294 ), 213 295 ));
+1 -1
src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
··· 89 89 ), 90 90 91 91 '/res/' => array( 92 - '(?<hash>[a-f0-9]{8})/(?<path>.+\.(?:css|js))$' 92 + '(?<package>pkg/)?(?<hash>[a-f0-9]{8})/(?<path>.+\.(?:css|js))$' 93 93 => 'CelerityResourceController', 94 94 ), 95 95
+25 -6
src/infratructure/celerity/controller/CelerityResourceController.php
··· 20 20 21 21 private $path; 22 22 private $hash; 23 + private $package; 23 24 24 25 public function willProcessRequest(array $data) { 25 26 $this->path = $data['path']; 26 27 $this->hash = $data['hash']; 28 + $this->package = !empty($data['package']); 27 29 } 28 30 29 31 public function processRequest() { ··· 35 37 if (!preg_match('/\.(css|js)$/', $path, $matches)) { 36 38 throw new Exception("Only CSS and JS resources may be served."); 37 39 } 38 - 40 + 39 41 $type = $matches[1]; 40 42 41 - 42 43 $root = dirname(phutil_get_library_root('phabricator')); 43 44 44 - try { 45 - $data = Filesystem::readFile($root.'/webroot/'.$path); 46 - } catch (Exception $ex) { 47 - return new Aphront404Response(); 45 + if ($this->package) { 46 + $map = CelerityResourceMap::getInstance(); 47 + $paths = $map->resolvePackage($this->hash); 48 + if (!$paths) { 49 + return new Aphront404Response(); 50 + } 51 + 52 + try { 53 + $data = array(); 54 + foreach ($paths as $path) { 55 + $data[] = Filesystem::readFile($root.'/webroot/'.$path); 56 + } 57 + $data = implode("\n\n", $data); 58 + } catch (Exception $ex) { 59 + return new Aphront404Response(); 60 + } 61 + } else { 62 + try { 63 + $data = Filesystem::readFile($root.'/webroot/'.$path); 64 + } catch (Exception $ex) { 65 + return new Aphront404Response(); 66 + } 48 67 } 49 68 50 69 $response = new AphrontFileResponse();
+42 -1
src/infratructure/celerity/map/CelerityResourceMap.php
··· 20 20 21 21 private static $instance; 22 22 private $resourceMap; 23 + private $packageMap; 23 24 24 25 public static function getInstance() { 25 26 if (empty(self::$instance)) { ··· 66 67 67 68 $map[$symbol] = $info; 68 69 } 70 + 71 + public function setPackageMap($package_map) { 72 + $this->packageMap = $package_map; 73 + } 74 + 75 + public function packageResources(array $resolved_map) { 76 + $packaged = array(); 77 + $handled = array(); 78 + foreach ($resolved_map as $symbol => $info) { 79 + if (isset($handled[$symbol])) { 80 + continue; 81 + } 82 + if (empty($this->packageMap['reverse'][$symbol])) { 83 + $packaged[$symbol] = $info; 84 + } else { 85 + $package = $this->packageMap['reverse'][$symbol]; 86 + $package_info = $this->packageMap['packages'][$package]; 87 + $packaged[$package_info['name']] = $package_info; 88 + foreach ($package_info['symbols'] as $symbol) { 89 + $handled[$symbol] = true; 90 + } 91 + } 92 + } 93 + return $packaged; 94 + } 95 + 96 + public function resolvePackage($package_hash) { 97 + $package = idx($this->packageMap['packages'], $package_hash); 98 + if (!$package) { 99 + return null; 100 + } 101 + 102 + $paths = array(); 103 + foreach ($package['symbols'] as $symbol) { 104 + $paths[] = $this->resourceMap[$symbol]['disk']; 105 + } 106 + 107 + return $paths; 108 + } 69 109 70 110 } 71 111 72 - function celerity_register_resource_map(array $map) { 112 + function celerity_register_resource_map(array $map, array $package_map) { 73 113 $instance = CelerityResourceMap::getInstance(); 74 114 $instance->setResourceMap($map); 115 + $instance->setPackageMap($package_map); 75 116 }
+5 -3
src/infratructure/celerity/response/CelerityStaticResourceResponse.php
··· 21 21 private $symbols = array(); 22 22 private $needsResolve = true; 23 23 private $resolved; 24 + private $packaged; 24 25 private $metadata = array(); 25 26 private $metadataBlock = 0; 26 27 private $behaviors = array(); ··· 57 58 if ($this->needsResolve) { 58 59 $map = CelerityResourceMap::getInstance(); 59 60 $this->resolved = $map->resolveResources(array_keys($this->symbols)); 61 + $this->packaged = $map->packageResources($this->resolved); 60 62 $this->needsResolve = false; 61 63 } 62 64 return $this; ··· 65 67 public function renderResourcesOfType($type) { 66 68 $this->resolveResources(); 67 69 $output = array(); 68 - foreach ($this->resolved as $resource) { 70 + foreach ($this->packaged as $resource) { 69 71 if ($resource['type'] == $type) { 70 72 $output[] = $this->renderResource($resource); 71 73 } ··· 76 78 private function renderResource(array $resource) { 77 79 switch ($resource['type']) { 78 80 case 'css': 79 - $path = phutil_escape_html($resource['path']); 81 + $path = phutil_escape_html($resource['uri']); 80 82 return '<link rel="stylesheet" type="text/css" href="'.$path.'" />'; 81 83 case 'js': 82 - $path = phutil_escape_html($resource['path']); 84 + $path = phutil_escape_html($resource['uri']); 83 85 return '<script type="text/javascript" src="'.$path.'">'. 84 86 '</script>'; 85 87 }