2011-01-25 18:59:31 +01:00
|
|
|
<?php
|
|
|
|
|
2011-07-04 20:22:42 +02:00
|
|
|
/**
|
|
|
|
* Tracks and resolves dependencies the page declares with
|
|
|
|
* @{function:require_celerity_resource}, and then builds appropriate HTML or
|
|
|
|
* Ajax responses.
|
|
|
|
*
|
|
|
|
* @group celerity
|
|
|
|
*/
|
2011-01-25 18:59:31 +01:00
|
|
|
final class CelerityStaticResourceResponse {
|
|
|
|
|
|
|
|
private $symbols = array();
|
|
|
|
private $needsResolve = true;
|
|
|
|
private $resolved;
|
2011-01-30 01:10:05 +01:00
|
|
|
private $packaged;
|
2011-01-25 20:57:47 +01:00
|
|
|
private $metadata = array();
|
|
|
|
private $metadataBlock = 0;
|
|
|
|
private $behaviors = array();
|
Bring Javelin into Phabricator via git submodule, not copy-and-paste
Summary:
Javelin is currently embedded in Phabricator via copy-and-paste of prebuilt
packages. This is not so great.
Pull it in as a submodule instead and make all the Phabriator resources declare
proper dependency trees. Add Javelin linting.
Test Plan:
I tried to run through pretty much all the JS functionality on the site. This is
still a high-risk change, but I did a pretty thorough test
Differential: inline comments, revealing diffs, list tokenizers, comment
preview, editing/deleting comments, add review action.
Maniphest: list tokenizer, comment actions
Herald: rule editing, tokenizers, add/remove rows
Reviewed By: tomo
Reviewers: aran, tomo, mroch, jungejason, tuomaspelkonen
CC: aran, tomo, epriestley
Differential Revision: 223
2011-05-04 00:11:55 +02:00
|
|
|
private $hasRendered = array();
|
2011-01-25 20:57:47 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-05-31 19:23:31 +02:00
|
|
|
/**
|
|
|
|
* Register a behavior for initialization. NOTE: if $config is empty,
|
|
|
|
* a behavior will execute only once even if it is initialized multiple times.
|
|
|
|
* If $config is nonempty, the behavior will be invoked once for each config.
|
|
|
|
*/
|
2011-01-25 20:57:47 +01:00
|
|
|
public function initBehavior($behavior, array $config = array()) {
|
|
|
|
$this->requireResource('javelin-behavior-'.$behavior);
|
2011-05-31 19:23:31 +02:00
|
|
|
|
|
|
|
if (empty($this->behaviors[$behavior])) {
|
|
|
|
$this->behaviors[$behavior] = array();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($config) {
|
|
|
|
$this->behaviors[$behavior][] = $config;
|
|
|
|
}
|
|
|
|
|
2011-01-25 20:57:47 +01:00
|
|
|
return $this;
|
|
|
|
}
|
2011-01-25 18:59:31 +01:00
|
|
|
|
|
|
|
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));
|
2011-01-30 01:10:05 +01:00
|
|
|
$this->packaged = $map->packageResources($this->resolved);
|
2011-01-25 18:59:31 +01:00
|
|
|
$this->needsResolve = false;
|
|
|
|
}
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
Bring Javelin into Phabricator via git submodule, not copy-and-paste
Summary:
Javelin is currently embedded in Phabricator via copy-and-paste of prebuilt
packages. This is not so great.
Pull it in as a submodule instead and make all the Phabriator resources declare
proper dependency trees. Add Javelin linting.
Test Plan:
I tried to run through pretty much all the JS functionality on the site. This is
still a high-risk change, but I did a pretty thorough test
Differential: inline comments, revealing diffs, list tokenizers, comment
preview, editing/deleting comments, add review action.
Maniphest: list tokenizer, comment actions
Herald: rule editing, tokenizers, add/remove rows
Reviewed By: tomo
Reviewers: aran, tomo, mroch, jungejason, tuomaspelkonen
CC: aran, tomo, epriestley
Differential Revision: 223
2011-05-04 00:11:55 +02:00
|
|
|
public function renderSingleResource($symbol) {
|
|
|
|
$map = CelerityResourceMap::getInstance();
|
|
|
|
$resolved = $map->resolveResources(array($symbol));
|
|
|
|
$packaged = $map->packageResources($resolved);
|
|
|
|
return $this->renderPackagedResources($packaged);
|
|
|
|
}
|
|
|
|
|
2011-01-25 18:59:31 +01:00
|
|
|
public function renderResourcesOfType($type) {
|
|
|
|
$this->resolveResources();
|
Bring Javelin into Phabricator via git submodule, not copy-and-paste
Summary:
Javelin is currently embedded in Phabricator via copy-and-paste of prebuilt
packages. This is not so great.
Pull it in as a submodule instead and make all the Phabriator resources declare
proper dependency trees. Add Javelin linting.
Test Plan:
I tried to run through pretty much all the JS functionality on the site. This is
still a high-risk change, but I did a pretty thorough test
Differential: inline comments, revealing diffs, list tokenizers, comment
preview, editing/deleting comments, add review action.
Maniphest: list tokenizer, comment actions
Herald: rule editing, tokenizers, add/remove rows
Reviewed By: tomo
Reviewers: aran, tomo, mroch, jungejason, tuomaspelkonen
CC: aran, tomo, epriestley
Differential Revision: 223
2011-05-04 00:11:55 +02:00
|
|
|
|
|
|
|
$resources = array();
|
2011-01-30 01:10:05 +01:00
|
|
|
foreach ($this->packaged as $resource) {
|
2011-01-25 18:59:31 +01:00
|
|
|
if ($resource['type'] == $type) {
|
Bring Javelin into Phabricator via git submodule, not copy-and-paste
Summary:
Javelin is currently embedded in Phabricator via copy-and-paste of prebuilt
packages. This is not so great.
Pull it in as a submodule instead and make all the Phabriator resources declare
proper dependency trees. Add Javelin linting.
Test Plan:
I tried to run through pretty much all the JS functionality on the site. This is
still a high-risk change, but I did a pretty thorough test
Differential: inline comments, revealing diffs, list tokenizers, comment
preview, editing/deleting comments, add review action.
Maniphest: list tokenizer, comment actions
Herald: rule editing, tokenizers, add/remove rows
Reviewed By: tomo
Reviewers: aran, tomo, mroch, jungejason, tuomaspelkonen
CC: aran, tomo, epriestley
Differential Revision: 223
2011-05-04 00:11:55 +02:00
|
|
|
$resources[] = $resource;
|
2011-01-25 18:59:31 +01:00
|
|
|
}
|
|
|
|
}
|
Bring Javelin into Phabricator via git submodule, not copy-and-paste
Summary:
Javelin is currently embedded in Phabricator via copy-and-paste of prebuilt
packages. This is not so great.
Pull it in as a submodule instead and make all the Phabriator resources declare
proper dependency trees. Add Javelin linting.
Test Plan:
I tried to run through pretty much all the JS functionality on the site. This is
still a high-risk change, but I did a pretty thorough test
Differential: inline comments, revealing diffs, list tokenizers, comment
preview, editing/deleting comments, add review action.
Maniphest: list tokenizer, comment actions
Herald: rule editing, tokenizers, add/remove rows
Reviewed By: tomo
Reviewers: aran, tomo, mroch, jungejason, tuomaspelkonen
CC: aran, tomo, epriestley
Differential Revision: 223
2011-05-04 00:11:55 +02:00
|
|
|
|
|
|
|
return $this->renderPackagedResources($resources);
|
|
|
|
}
|
|
|
|
|
|
|
|
private function renderPackagedResources(array $resources) {
|
|
|
|
$output = array();
|
|
|
|
foreach ($resources as $resource) {
|
|
|
|
if (isset($this->hasRendered[$resource['uri']])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$this->hasRendered[$resource['uri']] = true;
|
|
|
|
|
|
|
|
$output[] = $this->renderResource($resource);
|
|
|
|
}
|
2012-10-16 18:44:53 +02:00
|
|
|
return implode("\n", $output)."\n";
|
2011-01-25 18:59:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private function renderResource(array $resource) {
|
2012-10-16 18:44:53 +02:00
|
|
|
$uri = PhabricatorEnv::getCDNURI($resource['uri']);
|
2011-01-25 18:59:31 +01:00
|
|
|
switch ($resource['type']) {
|
|
|
|
case 'css':
|
2013-01-18 03:39:02 +01:00
|
|
|
return phutil_tag(
|
2012-10-16 18:44:53 +02:00
|
|
|
'link',
|
|
|
|
array(
|
|
|
|
'rel' => 'stylesheet',
|
|
|
|
'type' => 'text/css',
|
|
|
|
'href' => $uri,
|
|
|
|
));
|
2011-01-25 18:59:31 +01:00
|
|
|
case 'js':
|
2013-01-18 03:57:09 +01:00
|
|
|
return phutil_tag(
|
2012-10-16 18:44:53 +02:00
|
|
|
'script',
|
|
|
|
array(
|
|
|
|
'type' => 'text/javascript',
|
|
|
|
'src' => $uri,
|
|
|
|
),
|
|
|
|
'');
|
2011-01-25 18:59:31 +01:00
|
|
|
}
|
|
|
|
throw new Exception("Unable to render resource.");
|
|
|
|
}
|
|
|
|
|
2011-01-25 20:57:47 +01:00
|
|
|
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) {
|
2011-12-07 22:49:56 +01:00
|
|
|
$behaviors = $this->behaviors;
|
2011-01-25 20:57:47 +01:00
|
|
|
$this->behaviors = array();
|
2011-12-07 22:49:56 +01:00
|
|
|
|
|
|
|
$higher_priority_names = array(
|
|
|
|
'refresh-csrf',
|
2011-12-23 02:59:00 +01:00
|
|
|
'aphront-basic-tokenizer',
|
2011-12-07 22:49:56 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
$higher_priority_behaviors = array_select_keys(
|
|
|
|
$behaviors,
|
|
|
|
$higher_priority_names);
|
|
|
|
|
|
|
|
foreach ($higher_priority_names as $name) {
|
|
|
|
unset($behaviors[$name]);
|
|
|
|
}
|
|
|
|
|
|
|
|
$behavior_groups = array(
|
|
|
|
$higher_priority_behaviors,
|
|
|
|
$behaviors);
|
|
|
|
|
|
|
|
foreach ($behavior_groups as $group) {
|
|
|
|
if (!$group) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$onload[] = 'JX.initBehaviors('.json_encode($group).')';
|
|
|
|
}
|
2011-01-25 20:57:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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 '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-14 23:51:51 +01:00
|
|
|
public function buildAjaxResponse($payload, $error = null) {
|
2011-01-25 20:57:47 +01:00
|
|
|
$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();
|
|
|
|
}
|
|
|
|
|
2012-11-21 17:37:01 +01:00
|
|
|
$this->resolveResources();
|
|
|
|
$resources = array();
|
|
|
|
foreach ($this->packaged as $resource) {
|
|
|
|
$resources[] = PhabricatorEnv::getCDNURI($resource['uri']);
|
|
|
|
}
|
|
|
|
if ($resources) {
|
|
|
|
$response['javelin_resources'] = $resources;
|
|
|
|
}
|
|
|
|
|
2011-01-25 20:57:47 +01:00
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
|
2011-01-25 18:59:31 +01:00
|
|
|
}
|