Page MenuHomestyx hydra

No OneTemporary

diff --git a/scripts/celerity_mapper.php b/scripts/celerity_mapper.php
index a7a388c087..d281da41ce 100755
--- a/scripts/celerity_mapper.php
+++ b/scripts/celerity_mapper.php
@@ -1,102 +1,160 @@
#!/usr/bin/env php
<?php
+$package_spec = array(
+ 'core.pkg.css' => array(
+ 'phabricator-core-css',
+ 'phabricator-core-buttons-css',
+ 'phabricator-standard-page-view',
+ 'aphront-dialog-view-css',
+ 'aphront-form-view-css',
+ 'aphront-panel-view-css',
+ 'aphront-side-nav-view-css',
+ 'aphront-table-view-css',
+ 'aphront-tokenizer-control-css',
+ 'aphront-typeahead-control-css',
+
+ 'phabricator-directory-css',
+ ),
+ 'differential.pkg.css' => array(
+ 'differential-core-view-css',
+ 'differential-changeset-view-css',
+ 'differential-revision-detail-css',
+ 'differential-revision-history-css',
+ 'differential-table-of-contents-css',
+ ),
+);
+
+
require_once dirname(__FILE__).'/__init_script__.php';
if ($argc != 2) {
$self = basename($argv[0]);
echo "usage: {$self} <webroot>\n";
exit(1);
}
phutil_require_module('phutil', 'filesystem');
phutil_require_module('phutil', 'filesystem/filefinder');
phutil_require_module('phutil', 'future/exec');
phutil_require_module('phutil', 'parser/docblock');
$root = Filesystem::resolvePath($argv[1]);
echo "Finding static resources...\n";
$files = id(new FileFinder($root))
->withType('f')
->withSuffix('js')
->withSuffix('css')
->setGenerateChecksums(true)
->find();
echo "Processing ".count($files)." files";
$file_map = array();
foreach ($files as $path => $hash) {
echo ".";
$name = '/'.Filesystem::readablePath($path, $root);
$file_map[$name] = array(
'hash' => $hash,
'disk' => $path,
);
}
echo "\n";
$runtime_map = array();
+$hash_map = array();
+
$parser = new PhutilDocblockParser();
foreach ($file_map as $path => $info) {
$data = Filesystem::readFile($info['disk']);
$matches = array();
$ok = preg_match('@/[*][*].*?[*]/@s', $data, $matches);
if (!$ok) {
throw new Exception(
"File {$path} does not have a header doc comment. Encode dependency ".
"data in a header docblock.");
}
list($description, $metadata) = $parser->parse($matches[0]);
$provides = preg_split('/\s+/', trim(idx($metadata, 'provides')));
$requires = preg_split('/\s+/', trim(idx($metadata, 'requires')));
$provides = array_filter($provides);
$requires = array_filter($requires);
if (count($provides) !== 1) {
throw new Exception(
"File {$path} must @provide exactly one Celerity target.");
}
$provides = reset($provides);
$type = 'js';
if (preg_match('/\.css$/', $path)) {
$type = 'css';
}
- $path = '/res/'.substr($info['hash'], 0, 8).$path;
+ $uri = '/res/'.substr($info['hash'], 0, 8).$path;
+
+ $hash_map[$provides] = $info['hash'];
$runtime_map[$provides] = array(
- 'path' => $path,
+ 'uri' => $uri,
'type' => $type,
'requires' => $requires,
+ 'disk' => $path,
+ );
+}
+
+$package_map = array();
+foreach ($package_spec as $name => $package) {
+ $hashes = array();
+ foreach ($package as $symbol) {
+ if (empty($hash_map[$symbol])) {
+ throw new Exception(
+ "Package specification for '{$name}' includes '{$symbol}', but that ".
+ "symbol is not defined anywhere.");
+ }
+ $hashes[] = $symbol.':'.$hash_map[$symbol];
+ }
+ $key = substr(md5(implode("\n", $hashes)), 0, 8);
+ $package_map['packages'][$key] = array(
+ 'name' => $name,
+ 'symbols' => $package,
+ 'uri' => '/res/pkg/'.$key.'/'.$name,
+ 'type' => 'css', // TODO LOL
);
+ foreach ($package as $symbol) {
+ $package_map['reverse'][$symbol] = $key;
+ }
}
+
$runtime_map = var_export($runtime_map, true);
$runtime_map = preg_replace('/\s+$/m', '', $runtime_map);
$runtime_map = preg_replace('/array \(/', 'array(', $runtime_map);
+$package_map = var_export($package_map, true);
+$pacakge_map = preg_replace('/\s+$/m', '', $package_map);
+$package_map = preg_replace('/array \(/', 'array(', $package_map);
+
$resource_map = <<<EOFILE
<?php
/**
* This file is automatically generated. Use 'celerity_mapper.php' to rebuild
* it.
* @generated
*/
-celerity_register_resource_map({$runtime_map});
+celerity_register_resource_map({$runtime_map}, {$pacakge_map});
EOFILE;
echo "Writing map...\n";
Filesystem::writeFile(
$root.'/../src/__celerity_resource_map__.php',
$resource_map);
echo "Done.\n";
diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
index 9129bbf39d..1500a5ed97 100644
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -1,213 +1,295 @@
<?php
/**
* This file is automatically generated. Use 'celerity_mapper.php' to rebuild
* it.
* @generated
*/
celerity_register_resource_map(array(
'aphront-dialog-view-css' =>
array(
- 'path' => '/res/771b987d/rsrc/css/aphront/dialog-view.css',
+ 'uri' => '/res/771b987d/rsrc/css/aphront/dialog-view.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/aphront/dialog-view.css',
),
'aphront-form-view-css' =>
array(
- 'path' => '/res/785ac1c6/rsrc/css/aphront/form-view.css',
+ 'uri' => '/res/785ac1c6/rsrc/css/aphront/form-view.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/aphront/form-view.css',
),
'aphront-panel-view-css' =>
array(
- 'path' => '/res/fe62e634/rsrc/css/aphront/panel-view.css',
+ 'uri' => '/res/fe62e634/rsrc/css/aphront/panel-view.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/aphront/panel-view.css',
),
'aphront-side-nav-view-css' =>
array(
- 'path' => '/res/0fc0545c/rsrc/css/aphront/side-nav-view.css',
+ 'uri' => '/res/0fc0545c/rsrc/css/aphront/side-nav-view.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/aphront/side-nav-view.css',
),
'aphront-table-view-css' =>
array(
- 'path' => '/res/52b0191f/rsrc/css/aphront/table-view.css',
+ 'uri' => '/res/52b0191f/rsrc/css/aphront/table-view.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/aphront/table-view.css',
),
'aphront-tokenizer-control-css' =>
array(
- 'path' => '/res/a3d23074/rsrc/css/aphront/tokenizer.css',
+ 'uri' => '/res/a3d23074/rsrc/css/aphront/tokenizer.css',
'type' => 'css',
'requires' =>
array(
0 => 'aphront-typeahead-control-css',
),
+ 'disk' => '/rsrc/css/aphront/tokenizer.css',
),
'aphront-typeahead-control-css' =>
array(
- 'path' => '/res/928df9f0/rsrc/css/aphront/typeahead.css',
+ 'uri' => '/res/928df9f0/rsrc/css/aphront/typeahead.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/aphront/typeahead.css',
),
'phabricator-standard-page-view' =>
array(
- 'path' => '/res/1f93ada7/rsrc/css/application/base/standard-page-view.css',
+ 'uri' => '/res/1f93ada7/rsrc/css/application/base/standard-page-view.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/application/base/standard-page-view.css',
),
'differential-changeset-view-css' =>
array(
- 'path' => '/res/658d181a/rsrc/css/application/differential/changeset-view.css',
+ 'uri' => '/res/658d181a/rsrc/css/application/differential/changeset-view.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/application/differential/changeset-view.css',
),
'differential-core-view-css' =>
array(
- 'path' => '/res/525d1a12/rsrc/css/application/differential/core.css',
+ 'uri' => '/res/525d1a12/rsrc/css/application/differential/core.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/application/differential/core.css',
),
'differential-revision-detail-css' =>
array(
- 'path' => '/res/11a36dad/rsrc/css/application/differential/revision-detail.css',
+ 'uri' => '/res/230a67c6/rsrc/css/application/differential/revision-detail.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/application/differential/revision-detail.css',
),
'differential-revision-history-css' =>
array(
- 'path' => '/res/755f3da3/rsrc/css/application/differential/revision-history.css',
+ 'uri' => '/res/755f3da3/rsrc/css/application/differential/revision-history.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/application/differential/revision-history.css',
),
'differential-table-of-contents-css' =>
array(
- 'path' => '/res/a4a7b2b5/rsrc/css/application/differential/table-of-contents.css',
+ 'uri' => '/res/a4a7b2b5/rsrc/css/application/differential/table-of-contents.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/application/differential/table-of-contents.css',
),
'phabricator-directory-css' =>
array(
- 'path' => '/res/6a000601/rsrc/css/application/directory/phabricator-directory.css',
+ 'uri' => '/res/6a000601/rsrc/css/application/directory/phabricator-directory.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/application/directory/phabricator-directory.css',
),
'phabricator-core-buttons-css' =>
array(
- 'path' => '/res/6e348ba4/rsrc/css/core/buttons.css',
+ 'uri' => '/res/6e348ba4/rsrc/css/core/buttons.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/core/buttons.css',
),
'phabricator-core-css' =>
array(
- 'path' => '/res/39ce37c2/rsrc/css/core/core.css',
+ 'uri' => '/res/39ce37c2/rsrc/css/core/core.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/core/core.css',
),
'syntax-highlighting-css' =>
array(
- 'path' => '/res/fb673ece/rsrc/css/core/syntax.css',
+ 'uri' => '/res/fb673ece/rsrc/css/core/syntax.css',
'type' => 'css',
'requires' =>
array(
),
+ 'disk' => '/rsrc/css/core/syntax.css',
),
'javelin-behavior-aphront-basic-tokenizer' =>
array(
- 'path' => '/res/8317d761/rsrc/js/application/core/behavior-tokenizer.js',
+ 'uri' => '/res/8317d761/rsrc/js/application/core/behavior-tokenizer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
),
+ 'disk' => '/rsrc/js/application/core/behavior-tokenizer.js',
),
'javelin-behavior-differential-populate' =>
array(
- 'path' => '/res/9982573c/rsrc/js/application/differential/behavior-populate.js',
+ 'uri' => '/res/9982573c/rsrc/js/application/differential/behavior-populate.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
),
+ 'disk' => '/rsrc/js/application/differential/behavior-populate.js',
),
'javelin-init-dev' =>
array(
- 'path' => '/res/c57a9e89/rsrc/js/javelin/init.dev.js',
+ 'uri' => '/res/c57a9e89/rsrc/js/javelin/init.dev.js',
'type' => 'js',
'requires' =>
array(
),
+ 'disk' => '/rsrc/js/javelin/init.dev.js',
),
'javelin-init-prod' =>
array(
- 'path' => '/res/f0172c54/rsrc/js/javelin/init.min.js',
+ 'uri' => '/res/f0172c54/rsrc/js/javelin/init.min.js',
'type' => 'js',
'requires' =>
array(
),
+ 'disk' => '/rsrc/js/javelin/init.min.js',
),
'javelin-lib-dev' =>
array(
- 'path' => '/res/3e747182/rsrc/js/javelin/javelin.dev.js',
+ 'uri' => '/res/3e747182/rsrc/js/javelin/javelin.dev.js',
'type' => 'js',
'requires' =>
array(
),
+ 'disk' => '/rsrc/js/javelin/javelin.dev.js',
),
'javelin-lib-prod' =>
array(
- 'path' => '/res/9438670e/rsrc/js/javelin/javelin.min.js',
+ 'uri' => '/res/9438670e/rsrc/js/javelin/javelin.min.js',
'type' => 'js',
'requires' =>
array(
),
+ 'disk' => '/rsrc/js/javelin/javelin.min.js',
),
'javelin-typeahead-dev' =>
array(
- 'path' => '/res/c81c0f01/rsrc/js/javelin/typeahead.dev.js',
+ 'uri' => '/res/c81c0f01/rsrc/js/javelin/typeahead.dev.js',
'type' => 'js',
'requires' =>
array(
),
+ 'disk' => '/rsrc/js/javelin/typeahead.dev.js',
),
'javelin-typeahead-prod' =>
array(
- 'path' => '/res/1da2d984/rsrc/js/javelin/typeahead.min.js',
+ 'uri' => '/res/1da2d984/rsrc/js/javelin/typeahead.min.js',
'type' => 'js',
'requires' =>
array(
),
+ 'disk' => '/rsrc/js/javelin/typeahead.min.js',
+ ),
+), array (
+ 'packages' =>
+ array (
+ '4efe7b58' =>
+ array (
+ 'name' => 'core.pkg.css',
+ 'symbols' =>
+ array (
+ 0 => 'phabricator-core-css',
+ 1 => 'phabricator-core-buttons-css',
+ 2 => 'phabricator-standard-page-view',
+ 3 => 'aphront-dialog-view-css',
+ 4 => 'aphront-form-view-css',
+ 5 => 'aphront-panel-view-css',
+ 6 => 'aphront-side-nav-view-css',
+ 7 => 'aphront-table-view-css',
+ 8 => 'aphront-tokenizer-control-css',
+ 9 => 'aphront-typeahead-control-css',
+ 10 => 'phabricator-directory-css',
+ ),
+ 'uri' => '/res/pkg/4efe7b58/core.pkg.css',
+ 'type' => 'css',
+ ),
+ '69b11588' =>
+ array (
+ 'name' => 'differential.pkg.css',
+ 'symbols' =>
+ array (
+ 0 => 'differential-core-view-css',
+ 1 => 'differential-changeset-view-css',
+ 2 => 'differential-revision-detail-css',
+ 3 => 'differential-revision-history-css',
+ 4 => 'differential-table-of-contents-css',
+ ),
+ 'uri' => '/res/pkg/69b11588/differential.pkg.css',
+ 'type' => 'css',
+ ),
+ ),
+ 'reverse' =>
+ array (
+ 'phabricator-core-css' => '4efe7b58',
+ 'phabricator-core-buttons-css' => '4efe7b58',
+ 'phabricator-standard-page-view' => '4efe7b58',
+ 'aphront-dialog-view-css' => '4efe7b58',
+ 'aphront-form-view-css' => '4efe7b58',
+ 'aphront-panel-view-css' => '4efe7b58',
+ 'aphront-side-nav-view-css' => '4efe7b58',
+ 'aphront-table-view-css' => '4efe7b58',
+ 'aphront-tokenizer-control-css' => '4efe7b58',
+ 'aphront-typeahead-control-css' => '4efe7b58',
+ 'phabricator-directory-css' => '4efe7b58',
+ 'differential-core-view-css' => '69b11588',
+ 'differential-changeset-view-css' => '69b11588',
+ 'differential-revision-detail-css' => '69b11588',
+ 'differential-revision-history-css' => '69b11588',
+ 'differential-table-of-contents-css' => '69b11588',
),
));
diff --git a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
index 9f482deb13..a5553423ee 100644
--- a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
+++ b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
@@ -1,159 +1,159 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @group aphront
*/
class AphrontDefaultApplicationConfiguration
extends AphrontApplicationConfiguration {
public function getApplicationName() {
return 'aphront-default';
}
public function getURIMap() {
return array(
'/repository/' => array(
'$' => 'RepositoryListController',
'new/$' => 'RepositoryEditController',
'edit/(?<id>\d+)/$' => 'RepositoryEditController',
'delete/(?<id>\d+)/$' => 'RepositoryDeleteController',
),
'/' => array(
'$' => 'PhabricatorDirectoryMainController',
),
'/directory/' => array(
'item/$'
=> 'PhabricatorDirectoryItemListController',
'item/edit/(?:(?<id>\d+)/)?$'
=> 'PhabricatorDirectoryItemEditController',
'item/delete/(?<id>\d+)/'
=> 'PhabricatorDirectoryItemDeleteController',
'category/$'
=> 'PhabricatorDirectoryCategoryListController',
'category/edit/(?:(?<id>\d+)/)?$'
=> 'PhabricatorDirectoryCategoryEditController',
'category/delete/(?<id>\d+)/'
=> 'PhabricatorDirectoryCategoryDeleteController',
),
'/file/' => array(
'$' => 'PhabricatorFileListController',
'upload/$' => 'PhabricatorFileUploadController',
'(?<view>info)/(?<phid>[^/]+)/' => 'PhabricatorFileViewController',
'(?<view>view)/(?<phid>[^/]+)/' => 'PhabricatorFileViewController',
'(?<view>download)/(?<phid>[^/]+)/' => 'PhabricatorFileViewController',
),
'/phid/' => array(
'$' => 'PhabricatorPHIDLookupController',
'list/$' => 'PhabricatorPHIDListController',
'type/$' => 'PhabricatorPHIDTypeListController',
'type/edit/(?:(?<id>\d+)/)?$' => 'PhabricatorPHIDTypeEditController',
'new/$' => 'PhabricatorPHIDAllocateController',
),
'/people/' => array(
'$' => 'PhabricatorPeopleListController',
'edit/(?:(?<username>\w+)/)?$' => 'PhabricatorPeopleEditController',
),
'/p/(?<username>\w+)/$' => 'PhabricatorPeopleProfileController',
'/conduit/' => array(
'$' => 'PhabricatorConduitConsoleController',
'method/(?<method>[^/]+)$' => 'PhabricatorConduitConsoleController',
'log/$' => 'PhabricatorConduitLogController',
),
'/api/(?<method>[^/]+)$' => 'PhabricatorConduitAPIController',
'/D(?<id>\d+)' => 'DifferentialRevisionViewController',
'/differential/' => array(
'$' => 'DifferentialRevisionListController',
'filter/(?<filter>\w+)/$' => 'DifferentialRevisionListController',
'diff/(?<id>\d+)/$' => 'DifferentialDiffViewController',
'changeset/(?<id>\d+)/$' => 'DifferentialChangesetViewController',
'revision/edit/(?:(?<id>\d+)/)?$'
=> 'DifferentialRevisionEditController',
),
'/res/' => array(
- '(?<hash>[a-f0-9]{8})/(?<path>.+\.(?:css|js))$'
+ '(?<package>pkg/)?(?<hash>[a-f0-9]{8})/(?<path>.+\.(?:css|js))$'
=> 'CelerityResourceController',
),
'/typeahead/' => array(
'common/(?<type>\w+)/$'
=> 'PhabricatorTypeaheadCommonDatasourceController',
),
'/mail/' => array(
'$' => 'PhabricatorMetaMTAListController',
'send/$' => 'PhabricatorMetaMTASendController',
'view/(?<id>\d+)/$' => 'PhabricatorMetaMTAViewController',
'lists/$' => 'PhabricatorMetaMTAMailingListsController',
'lists/edit/(?:(?<id>\d+)/)?$'
=> 'PhabricatorMetaMTAMailingListEditController',
),
'/login/' => 'PhabricatorLoginController',
);
}
public function buildRequest() {
$request = new AphrontRequest($this->getHost(), $this->getPath());
$request->setRequestData($_GET + $_POST);
return $request;
}
public function handleException(Exception $ex) {
$class = phutil_escape_html(get_class($ex));
$message = phutil_escape_html($ex->getMessage());
$content =
'<div class="aphront-unhandled-exception">'.
'<h1>Unhandled Exception "'.$class.'": '.$message.'</h1>'.
'<code>'.phutil_escape_html((string)$ex).'</code>'.
'</div>';
$view = new PhabricatorStandardPageView();
$view->appendChild($content);
$response = new AphrontWebpageResponse();
$response->setContent($view->render());
return $response;
}
public function willSendResponse(AphrontResponse $response) {
$request = $this->getRequest();
if ($response instanceof AphrontDialogResponse) {
if (!$request->isAjax()) {
$view = new PhabricatorStandardPageView();
$view->appendChild(
'<div style="padding: 2em 0;">'.
$response->buildResponseString().
'</div>');
$response = new AphrontWebpageResponse();
$response->setContent($view->render());
return $response;
}
}
return $response;
}
}
diff --git a/src/infratructure/celerity/controller/CelerityResourceController.php b/src/infratructure/celerity/controller/CelerityResourceController.php
index 8634cf2ed4..198a23cc04 100644
--- a/src/infratructure/celerity/controller/CelerityResourceController.php
+++ b/src/infratructure/celerity/controller/CelerityResourceController.php
@@ -1,66 +1,85 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class CelerityResourceController extends AphrontController {
private $path;
private $hash;
+ private $package;
public function willProcessRequest(array $data) {
$this->path = $data['path'];
$this->hash = $data['hash'];
+ $this->package = !empty($data['package']);
}
public function processRequest() {
$path = $this->path;
// Sanity checking to keep this from exposing anything sensitive.
$path = preg_replace('@(//|\\.\\.)@', '', $path);
$matches = null;
if (!preg_match('/\.(css|js)$/', $path, $matches)) {
throw new Exception("Only CSS and JS resources may be served.");
}
-
+
$type = $matches[1];
-
$root = dirname(phutil_get_library_root('phabricator'));
- try {
- $data = Filesystem::readFile($root.'/webroot/'.$path);
- } catch (Exception $ex) {
- return new Aphront404Response();
+ if ($this->package) {
+ $map = CelerityResourceMap::getInstance();
+ $paths = $map->resolvePackage($this->hash);
+ if (!$paths) {
+ return new Aphront404Response();
+ }
+
+ try {
+ $data = array();
+ foreach ($paths as $path) {
+ $data[] = Filesystem::readFile($root.'/webroot/'.$path);
+ }
+ $data = implode("\n\n", $data);
+ } catch (Exception $ex) {
+ return new Aphront404Response();
+ }
+ } else {
+ try {
+ $data = Filesystem::readFile($root.'/webroot/'.$path);
+ } catch (Exception $ex) {
+ return new Aphront404Response();
+ }
}
$response = new AphrontFileResponse();
$response->setContent($data);
switch ($type) {
case 'css':
$response->setMimeType("text/css; charset=utf-8");
break;
case 'js':
$response->setMimeType("text/javascript; charset=utf-8");
break;
}
$response->setCacheDurationInSeconds(60 * 60 * 24 * 30);
return $response;
}
}
diff --git a/src/infratructure/celerity/map/CelerityResourceMap.php b/src/infratructure/celerity/map/CelerityResourceMap.php
index ee3ea1ca17..6ea9d8bdb9 100644
--- a/src/infratructure/celerity/map/CelerityResourceMap.php
+++ b/src/infratructure/celerity/map/CelerityResourceMap.php
@@ -1,75 +1,116 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class CelerityResourceMap {
private static $instance;
private $resourceMap;
+ private $packageMap;
public static function getInstance() {
if (empty(self::$instance)) {
self::$instance = new CelerityResourceMap();
$root = phutil_get_library_root('phabricator');
$ok = @include_once $root.'/__celerity_resource_map__.php';
if (!$ok) {
throw new Exception("Failed to load Celerity resource map!");
}
}
return self::$instance;
}
public function setResourceMap($resource_map) {
$this->resourceMap = $resource_map;
return $this;
}
public function resolveResources(array $symbols) {
$map = array();
foreach ($symbols as $symbol) {
if (!empty($map[$symbol])) {
continue;
}
$this->resolveResource($map, $symbol);
}
return $map;
}
private function resolveResource(array &$map, $symbol) {
if (empty($this->resourceMap[$symbol])) {
throw new Exception(
"Attempting to resolve unknown resource, '{$symbol}'.");
}
$info = $this->resourceMap[$symbol];
foreach ($info['requires'] as $requires) {
if (!empty($map[$requires])) {
continue;
}
$this->resolveResource($map, $requires);
}
$map[$symbol] = $info;
}
+
+ public function setPackageMap($package_map) {
+ $this->packageMap = $package_map;
+ }
+
+ public function packageResources(array $resolved_map) {
+ $packaged = array();
+ $handled = array();
+ foreach ($resolved_map as $symbol => $info) {
+ if (isset($handled[$symbol])) {
+ continue;
+ }
+ if (empty($this->packageMap['reverse'][$symbol])) {
+ $packaged[$symbol] = $info;
+ } else {
+ $package = $this->packageMap['reverse'][$symbol];
+ $package_info = $this->packageMap['packages'][$package];
+ $packaged[$package_info['name']] = $package_info;
+ foreach ($package_info['symbols'] as $symbol) {
+ $handled[$symbol] = true;
+ }
+ }
+ }
+ return $packaged;
+ }
+
+ public function resolvePackage($package_hash) {
+ $package = idx($this->packageMap['packages'], $package_hash);
+ if (!$package) {
+ return null;
+ }
+
+ $paths = array();
+ foreach ($package['symbols'] as $symbol) {
+ $paths[] = $this->resourceMap[$symbol]['disk'];
+ }
+
+ return $paths;
+ }
}
-function celerity_register_resource_map(array $map) {
+function celerity_register_resource_map(array $map, array $package_map) {
$instance = CelerityResourceMap::getInstance();
$instance->setResourceMap($map);
+ $instance->setPackageMap($package_map);
}
diff --git a/src/infratructure/celerity/response/CelerityStaticResourceResponse.php b/src/infratructure/celerity/response/CelerityStaticResourceResponse.php
index 2207602a8a..c8956afaaa 100644
--- a/src/infratructure/celerity/response/CelerityStaticResourceResponse.php
+++ b/src/infratructure/celerity/response/CelerityStaticResourceResponse.php
@@ -1,145 +1,147 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class CelerityStaticResourceResponse {
private $symbols = array();
private $needsResolve = true;
private $resolved;
+ private $packaged;
private $metadata = array();
private $metadataBlock = 0;
private $behaviors = array();
public function __construct() {
if (isset($_REQUEST['__metablock__'])) {
$this->metadataBlock = (int)$_REQUEST['__metablock__'];
}
}
public function addMetadata($metadata) {
$id = count($this->metadata);
$this->metadata[$id] = $metadata;
return $this->metadataBlock.'_'.$id;
}
public function getMetadataBlock() {
return $this->metadataBlock;
}
public function initBehavior($behavior, array $config = array()) {
$this->requireResource('javelin-behavior-'.$behavior);
$this->behaviors[$behavior][] = $config;
return $this;
}
public function requireResource($symbol) {
$this->symbols[$symbol] = true;
$this->needsResolve = true;
return $this;
}
private function resolveResources() {
if ($this->needsResolve) {
$map = CelerityResourceMap::getInstance();
$this->resolved = $map->resolveResources(array_keys($this->symbols));
+ $this->packaged = $map->packageResources($this->resolved);
$this->needsResolve = false;
}
return $this;
}
public function renderResourcesOfType($type) {
$this->resolveResources();
$output = array();
- foreach ($this->resolved as $resource) {
+ foreach ($this->packaged as $resource) {
if ($resource['type'] == $type) {
$output[] = $this->renderResource($resource);
}
}
return implode("\n", $output);
}
private function renderResource(array $resource) {
switch ($resource['type']) {
case 'css':
- $path = phutil_escape_html($resource['path']);
+ $path = phutil_escape_html($resource['uri']);
return '<link rel="stylesheet" type="text/css" href="'.$path.'" />';
case 'js':
- $path = phutil_escape_html($resource['path']);
+ $path = phutil_escape_html($resource['uri']);
return '<script type="text/javascript" src="'.$path.'">'.
'</script>';
}
throw new Exception("Unable to render resource.");
}
public function renderHTMLFooter() {
$data = array();
if ($this->metadata) {
$json_metadata = json_encode($this->metadata);
$this->metadata = array();
} else {
$json_metadata = '{}';
}
// Even if there is no metadata on the page, Javelin uses the mergeData()
// call to start dispatching the event queue.
$data[] = 'JX.Stratcom.mergeData('.$this->metadataBlock.', '.
$json_metadata.');';
$onload = array();
if ($this->behaviors) {
$behavior = json_encode($this->behaviors);
$onload[] = 'JX.initBehaviors('.$behavior.')';
$this->behaviors = array();
}
if ($onload) {
foreach ($onload as $func) {
$data[] = 'JX.onload(function(){'.$func.'});';
}
}
if ($data) {
$data = implode("\n", $data);
return '<script type="text/javascript">//<![CDATA['."\n".
$data.'//]]></script>';
} else {
return '';
}
}
public function renderAjaxResponse($payload, $error = null) {
$response = array(
'error' => $error,
'payload' => $payload,
);
if ($this->metadata) {
$response['javelin_metadata'] = $this->metadata;
$this->metadata = array();
}
if ($this->behaviors) {
$response['javelin_behaviors'] = $this->behaviors;
$this->behaviors = array();
}
$response = 'for (;;);'.json_encode($response);
return $response;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Jul 28, 1:19 PM (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
186874
Default Alt Text
(31 KB)

Event Timeline