mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-18 01:38:39 +01:00
Allow blog resources to be served without Celerity
Summary: Allow skins to serve arbitrary resources without needing to be mapped, so we can have a vibrant community of amateur skinners. For "basic" skins, just put all the "css/" on the page always. Includes an image to prove that works. @vrana, pretty sure this has no impact outside of Phame but it does change Celerity so it might be to blame if there's any weirdness with static resources. Test Plan: {F21341} {F21340} Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T1373 Differential Revision: https://secure.phabricator.com/D3719
This commit is contained in:
parent
b3ad8507af
commit
26f7425ee2
16 changed files with 341 additions and 52 deletions
|
@ -1086,7 +1086,7 @@ return array(
|
||||||
|
|
||||||
// Directories to look for Phame skins inside of.
|
// Directories to look for Phame skins inside of.
|
||||||
'phame.skins' => array(
|
'phame.skins' => array(
|
||||||
'externals/skin/',
|
'externals/skins/',
|
||||||
),
|
),
|
||||||
|
|
||||||
// -- Remarkup -------------------------------------------------------------- //
|
// -- Remarkup -------------------------------------------------------------- //
|
||||||
|
|
77
externals/skins/oblivious/css/oblivious.css
vendored
Normal file
77
externals/skins/oblivious/css/oblivious.css
vendored
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
html, body, p, h1, h2, h3 {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family: "Helvetica Neue", "Arial", sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
color: #555555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.oblivious-info {
|
||||||
|
position: fixed;
|
||||||
|
width: 15%;
|
||||||
|
border-right: 1px solid #dfdfdf;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
padding: 140px 2% 0;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
background: url(/image/badge.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.oblivious-content {
|
||||||
|
padding-top: 3%;
|
||||||
|
margin-left: 22%;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #222222;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #a00000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phame-post {
|
||||||
|
margin: 0 0 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phame-post-date {
|
||||||
|
font-size: 12px;
|
||||||
|
margin: .25em 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phame-post {
|
||||||
|
line-height: 1.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phame-post p {
|
||||||
|
margin: 0 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.fb-comments,
|
||||||
|
.fb-comments span,
|
||||||
|
.fb-comments iframe[style] {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
3
externals/skins/oblivious/header.php
vendored
3
externals/skins/oblivious/header.php
vendored
|
@ -2,6 +2,9 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title><?php echo _e($title); ?></title>
|
<title><?php echo _e($title); ?></title>
|
||||||
|
|
||||||
|
<?php echo $skin->getCSSResources(); ?>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="oblivious-info">
|
<div class="oblivious-info">
|
||||||
|
|
BIN
externals/skins/oblivious/image/badge.png
vendored
Normal file
BIN
externals/skins/oblivious/image/badge.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
|
@ -91,6 +91,7 @@ phutil_register_library_map(array(
|
||||||
'AphrontView' => 'view/AphrontView.php',
|
'AphrontView' => 'view/AphrontView.php',
|
||||||
'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php',
|
'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php',
|
||||||
'CelerityAPI' => 'infrastructure/celerity/CelerityAPI.php',
|
'CelerityAPI' => 'infrastructure/celerity/CelerityAPI.php',
|
||||||
|
'CelerityPhabricatorResourceController' => 'infrastructure/celerity/CelerityPhabricatorResourceController.php',
|
||||||
'CelerityResourceController' => 'infrastructure/celerity/CelerityResourceController.php',
|
'CelerityResourceController' => 'infrastructure/celerity/CelerityResourceController.php',
|
||||||
'CelerityResourceGraph' => 'infrastructure/celerity/CelerityResourceGraph.php',
|
'CelerityResourceGraph' => 'infrastructure/celerity/CelerityResourceGraph.php',
|
||||||
'CelerityResourceMap' => 'infrastructure/celerity/CelerityResourceMap.php',
|
'CelerityResourceMap' => 'infrastructure/celerity/CelerityResourceMap.php',
|
||||||
|
@ -1174,6 +1175,7 @@ phutil_register_library_map(array(
|
||||||
'PhamePostUnpublishController' => 'applications/phame/controller/post/PhamePostUnpublishController.php',
|
'PhamePostUnpublishController' => 'applications/phame/controller/post/PhamePostUnpublishController.php',
|
||||||
'PhamePostView' => 'applications/phame/view/PhamePostView.php',
|
'PhamePostView' => 'applications/phame/view/PhamePostView.php',
|
||||||
'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php',
|
'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php',
|
||||||
|
'PhameResourceController' => 'applications/phame/controller/PhameResourceController.php',
|
||||||
'PhameSkinSpecification' => 'applications/phame/skins/PhameSkinSpecification.php',
|
'PhameSkinSpecification' => 'applications/phame/skins/PhameSkinSpecification.php',
|
||||||
'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php',
|
'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php',
|
||||||
'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/PhortuneStripeBaseController.php',
|
'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/PhortuneStripeBaseController.php',
|
||||||
|
@ -1334,6 +1336,7 @@ phutil_register_library_map(array(
|
||||||
'AphrontTypeaheadTemplateView' => 'AphrontView',
|
'AphrontTypeaheadTemplateView' => 'AphrontView',
|
||||||
'AphrontUsageException' => 'AphrontException',
|
'AphrontUsageException' => 'AphrontException',
|
||||||
'AphrontWebpageResponse' => 'AphrontResponse',
|
'AphrontWebpageResponse' => 'AphrontResponse',
|
||||||
|
'CelerityPhabricatorResourceController' => 'CelerityResourceController',
|
||||||
'CelerityResourceController' => 'PhabricatorController',
|
'CelerityResourceController' => 'PhabricatorController',
|
||||||
'CelerityResourceGraph' => 'AbstractDirectedGraph',
|
'CelerityResourceGraph' => 'AbstractDirectedGraph',
|
||||||
'CelerityResourceTransformerTestCase' => 'PhabricatorTestCase',
|
'CelerityResourceTransformerTestCase' => 'PhabricatorTestCase',
|
||||||
|
@ -2313,6 +2316,7 @@ phutil_register_library_map(array(
|
||||||
'PhamePostUnpublishController' => 'PhameController',
|
'PhamePostUnpublishController' => 'PhameController',
|
||||||
'PhamePostView' => 'AphrontView',
|
'PhamePostView' => 'AphrontView',
|
||||||
'PhamePostViewController' => 'PhameController',
|
'PhamePostViewController' => 'PhameController',
|
||||||
|
'PhameResourceController' => 'CelerityResourceController',
|
||||||
'PhortuneMonthYearExpiryControl' => 'AphrontFormControl',
|
'PhortuneMonthYearExpiryControl' => 'AphrontFormControl',
|
||||||
'PhortuneStripeBaseController' => 'PhabricatorController',
|
'PhortuneStripeBaseController' => 'PhabricatorController',
|
||||||
'PhortuneStripePaymentFormView' => 'AphrontView',
|
'PhortuneStripePaymentFormView' => 'AphrontView',
|
||||||
|
|
|
@ -155,7 +155,7 @@ class AphrontDefaultApplicationConfiguration
|
||||||
'(?P<package>pkg/)?'.
|
'(?P<package>pkg/)?'.
|
||||||
'(?P<hash>[a-f0-9]{8})/'.
|
'(?P<hash>[a-f0-9]{8})/'.
|
||||||
'(?P<path>.+\.(?:css|js|jpg|png|swf|gif))'
|
'(?P<path>.+\.(?:css|js|jpg|png|swf|gif))'
|
||||||
=> 'CelerityResourceController',
|
=> 'CelerityPhabricatorResourceController',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,9 @@ final class PhabricatorApplicationPhame extends PhabricatorApplication {
|
||||||
return array(
|
return array(
|
||||||
'/phame/' => array(
|
'/phame/' => array(
|
||||||
'' => 'PhamePostListController',
|
'' => 'PhamePostListController',
|
||||||
|
'r/(?P<id>\d+)/(?P<hash>[^/]+)/(?P<name>.*)'
|
||||||
|
=> 'PhameResourceController',
|
||||||
|
|
||||||
'live/(?P<id>[^/]+)/(?P<more>.*)' => 'PhameBlogLiveController',
|
'live/(?P<id>[^/]+)/(?P<more>.*)' => 'PhameBlogLiveController',
|
||||||
'post/' => array(
|
'post/' => array(
|
||||||
'(?:(?P<filter>draft|all)/)?' => 'PhamePostListController',
|
'(?:(?P<filter>draft|all)/)?' => 'PhamePostListController',
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 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 phame
|
||||||
|
*/
|
||||||
|
final class PhameResourceController extends CelerityResourceController {
|
||||||
|
|
||||||
|
private $id;
|
||||||
|
private $hash;
|
||||||
|
private $name;
|
||||||
|
private $root;
|
||||||
|
|
||||||
|
protected function getRootDirectory() {
|
||||||
|
return $this->root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->id = $data['id'];
|
||||||
|
$this->hash = $data['hash'];
|
||||||
|
$this->name = $data['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
|
// We require a visible blog associated with a given skin to serve
|
||||||
|
// resources, so you can't go fishing around where you shouldn't be.
|
||||||
|
|
||||||
|
$blog = id(new PhameBlogQuery())
|
||||||
|
->setViewer($user)
|
||||||
|
->withIDs(array($this->id))
|
||||||
|
->executeOne();
|
||||||
|
if (!$blog) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$skin = $blog->getSkinRenderer($request);
|
||||||
|
$spec = $skin->getSpecification();
|
||||||
|
|
||||||
|
$this->root = $spec->getRootDirectory().DIRECTORY_SEPARATOR;
|
||||||
|
return $this->serveResource($this->name, $package_hash = null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildResourceTransformer() {
|
||||||
|
$xformer = new CelerityResourceTransformer();
|
||||||
|
$xformer->setMinify(false);
|
||||||
|
$xformer->setTranslateURICallback(array($this, 'translateResourceURI'));
|
||||||
|
return $xformer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function translateResourceURI(array $matches) {
|
||||||
|
$uri = trim($matches[1], "'\" \r\t\n");
|
||||||
|
|
||||||
|
if (Filesystem::pathExists($this->root.$uri)) {
|
||||||
|
$hash = filemtime($this->root.$uri);
|
||||||
|
} else {
|
||||||
|
$hash = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
$uri = '/phame/r/'.$this->id.'/'.$hash.'/'.$uri;
|
||||||
|
return 'url('.$uri.')';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -50,19 +50,20 @@ final class PhameBlogLiveController extends PhameController {
|
||||||
->setURI('http://'.$blog->getDomain().'/'.$this->more);
|
->setURI('http://'.$blog->getDomain().'/'.$this->more);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($blog->getDomain()) {
|
|
||||||
$base_path = '/';
|
|
||||||
} else {
|
|
||||||
$base_path = '/phame/live/'.$blog->getID().'/';
|
|
||||||
}
|
|
||||||
|
|
||||||
$phame_request = clone $request;
|
$phame_request = clone $request;
|
||||||
$phame_request->setPath('/'.ltrim($this->more, '/'));
|
$phame_request->setPath('/'.ltrim($this->more, '/'));
|
||||||
|
|
||||||
|
if ($blog->getDomain()) {
|
||||||
|
$uri = new PhutilURI('http://'.$blog->getDomain().'/');
|
||||||
|
} else {
|
||||||
|
$uri = '/phame/live/'.$blog->getID().'/';
|
||||||
|
$uri = PhabricatorEnv::getURI($uri);
|
||||||
|
}
|
||||||
|
|
||||||
$skin = $blog->getSkinRenderer($phame_request);
|
$skin = $blog->getSkinRenderer($phame_request);
|
||||||
$skin
|
$skin
|
||||||
->setBlog($blog)
|
->setBlog($blog)
|
||||||
->setBaseURI($request->getRequestURI()->setPath($base_path));
|
->setBaseURI((string)$uri);
|
||||||
|
|
||||||
$skin->willProcessRequest(array());
|
$skin->willProcessRequest(array());
|
||||||
return $skin->processRequest();
|
return $skin->processRequest();
|
||||||
|
|
|
@ -25,7 +25,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin {
|
||||||
|
|
||||||
private $pager;
|
private $pager;
|
||||||
|
|
||||||
final public function processRequest() {
|
public function processRequest() {
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
|
|
||||||
$content = $this->renderContent($request);
|
$content = $this->renderContent($request);
|
||||||
|
@ -98,6 +98,21 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin {
|
||||||
return '<h2>404 Not Found</h2>';
|
return '<h2>404 Not Found</h2>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final public function getResourceURI($resource) {
|
||||||
|
$root = $this->getSpecification()->getRootDirectory();
|
||||||
|
$path = $root.DIRECTORY_SEPARATOR.$resource;
|
||||||
|
|
||||||
|
$data = Filesystem::readFile($path);
|
||||||
|
$hash = PhabricatorHash::digest($data);
|
||||||
|
$hash = substr($hash, 0, 6);
|
||||||
|
$id = $this->getBlog()->getID();
|
||||||
|
|
||||||
|
$uri = '/phame/r/'.$id.'/'.$hash.'/'.$resource;
|
||||||
|
$uri = PhabricatorEnv::getCDNURI($uri);
|
||||||
|
|
||||||
|
return $uri;
|
||||||
|
}
|
||||||
|
|
||||||
/* -( Paging )------------------------------------------------------------- */
|
/* -( Paging )------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,7 +194,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin {
|
||||||
/**
|
/**
|
||||||
* @task internal
|
* @task internal
|
||||||
*/
|
*/
|
||||||
private function renderContent(AphrontRequest $request) {
|
protected function renderContent(AphrontRequest $request) {
|
||||||
$user = $request->getUser();
|
$user = $request->getUser();
|
||||||
|
|
||||||
$matches = null;
|
$matches = null;
|
||||||
|
|
|
@ -21,11 +21,51 @@
|
||||||
*/
|
*/
|
||||||
final class PhameBasicTemplateBlogSkin extends PhameBasicBlogSkin {
|
final class PhameBasicTemplateBlogSkin extends PhameBasicBlogSkin {
|
||||||
|
|
||||||
public function willProcessRequest(array $data) {
|
private $cssResources;
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
$root = dirname(phutil_get_library_root('phabricator'));
|
$root = dirname(phutil_get_library_root('phabricator'));
|
||||||
require_once $root.'/support/phame/libskin.php';
|
require_once $root.'/support/phame/libskin.php';
|
||||||
|
|
||||||
parent::willProcessRequest($data);
|
$css = $this->getPath('css/');
|
||||||
|
if (Filesystem::pathExists($css)) {
|
||||||
|
$this->cssResources = array();
|
||||||
|
foreach (Filesystem::listDirectory($css) as $path) {
|
||||||
|
if (!preg_match('/.css$/', $path)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$this->cssResources[] = phutil_render_tag(
|
||||||
|
'link',
|
||||||
|
array(
|
||||||
|
'rel' => 'stylesheet',
|
||||||
|
'type' => 'text/css',
|
||||||
|
'href' => $this->getResourceURI('css/'.$path),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
$this->cssResources = implode("\n", $this->cssResources);
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$content = $this->renderContent($request);
|
||||||
|
|
||||||
|
if (!$content) {
|
||||||
|
$content = $this->render404Page();
|
||||||
|
}
|
||||||
|
|
||||||
|
$content = array(
|
||||||
|
$this->renderHeader(),
|
||||||
|
$content,
|
||||||
|
$this->renderFooter(),
|
||||||
|
);
|
||||||
|
|
||||||
|
$response = new AphrontWebpageResponse();
|
||||||
|
$response->setContent(implode("\n", $content));
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCSSResources() {
|
||||||
|
return $this->cssResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() {
|
public function getName() {
|
||||||
|
@ -45,7 +85,9 @@ final class PhameBasicTemplateBlogSkin extends PhameBasicBlogSkin {
|
||||||
ob_start();
|
ob_start();
|
||||||
|
|
||||||
if (Filesystem::pathExists($this->getPath($__template__))) {
|
if (Filesystem::pathExists($this->getPath($__template__))) {
|
||||||
extract($__scope__ + $this->getDefaultScope());
|
// Fool lint.
|
||||||
|
$__evil__ = 'extract';
|
||||||
|
$__evil__($__scope__ + $this->getDefaultScope());
|
||||||
require $this->getPath($__template__);
|
require $this->getPath($__template__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,12 @@ final class PhameBlog extends PhameDAO
|
||||||
self::SKIN_DEFAULT);
|
self::SKIN_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$spec) {
|
||||||
|
throw new Exception(
|
||||||
|
"This blog has an invalid skin, and the default skin failed to ".
|
||||||
|
"load.");
|
||||||
|
}
|
||||||
|
|
||||||
$skin = newv($spec->getSkinClass(), array($request));
|
$skin = newv($spec->getSkinClass(), array($request));
|
||||||
$skin->setSpecification($spec);
|
$skin->setSpecification($spec);
|
||||||
|
|
||||||
|
|
|
@ -169,8 +169,7 @@ final class PhamePostView extends AphrontView {
|
||||||
),
|
),
|
||||||
$this->renderTitle().
|
$this->renderTitle().
|
||||||
$this->renderDatePublished().
|
$this->renderDatePublished().
|
||||||
$this->renderSummary().
|
$this->renderSummary());
|
||||||
$this->renderComments());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderFacebookComments() {
|
private function renderFacebookComments() {
|
||||||
|
@ -198,13 +197,14 @@ final class PhamePostView extends AphrontView {
|
||||||
$c_uri
|
$c_uri
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
$uri = $this->getSkin()->getURI('post/'.$this->getPost()->getPhameTitle());
|
||||||
|
|
||||||
$fb_comments = phutil_render_tag('div',
|
$fb_comments = phutil_render_tag('div',
|
||||||
array(
|
array(
|
||||||
'class' => 'fb-comments',
|
'class' => 'fb-comments',
|
||||||
'data-href' => $this->getRequestURI(),
|
'data-href' => $uri,
|
||||||
'data-num-posts' => 5,
|
'data-num-posts' => 5,
|
||||||
'data-width' => 1080, // we hack this to fluid in css
|
|
||||||
'data-colorscheme' => 'dark',
|
|
||||||
),
|
),
|
||||||
''
|
''
|
||||||
);
|
);
|
||||||
|
@ -249,7 +249,7 @@ final class PhamePostView extends AphrontView {
|
||||||
' document.getElementsByTagName("body")[0]).appendChild(dsq);'.
|
' document.getElementsByTagName("body")[0]).appendChild(dsq);'.
|
||||||
'})(); </script>',
|
'})(); </script>',
|
||||||
$post->getPHID(),
|
$post->getPHID(),
|
||||||
$this->getRequestURI(),
|
$this->getSkin()->getURI('post/'.$this->getPost()->getPhameTitle()),
|
||||||
$post->getTitle()
|
$post->getTitle()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delivers CSS and JS resources to the browser. This controller handles all
|
||||||
|
* ##/res/## requests, and manages caching, package construction, and resource
|
||||||
|
* preprocessing.
|
||||||
|
*
|
||||||
|
* @group celerity
|
||||||
|
*/
|
||||||
|
final class CelerityPhabricatorResourceController
|
||||||
|
extends CelerityResourceController {
|
||||||
|
|
||||||
|
private $path;
|
||||||
|
private $hash;
|
||||||
|
private $package;
|
||||||
|
|
||||||
|
protected function getRootDirectory() {
|
||||||
|
$root = dirname(phutil_get_library_root('phabricator'));
|
||||||
|
return $root.'/webroot/';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->path = $data['path'];
|
||||||
|
$this->hash = $data['hash'];
|
||||||
|
$this->package = !empty($data['package']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$package_hash = null;
|
||||||
|
if ($this->package) {
|
||||||
|
$package_hash = $this->hash;
|
||||||
|
}
|
||||||
|
return $this->serveResource($this->path, $package_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildResourceTransformer() {
|
||||||
|
$xformer = new CelerityResourceTransformer();
|
||||||
|
$xformer->setMinify(PhabricatorEnv::getEnvConfig('celerity.minify'));
|
||||||
|
$xformer->setCelerityMap(CelerityResourceMap::getInstance());
|
||||||
|
return $xformer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,18 +16,13 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
abstract class CelerityResourceController extends PhabricatorController {
|
||||||
* Delivers CSS and JS resources to the browser. This controller handles all
|
|
||||||
* ##/res/## requests, and manages caching, package construction, and resource
|
|
||||||
* preprocessing.
|
|
||||||
*
|
|
||||||
* @group celerity
|
|
||||||
*/
|
|
||||||
final class CelerityResourceController extends PhabricatorController {
|
|
||||||
|
|
||||||
private $path;
|
abstract protected function getRootDirectory();
|
||||||
private $hash;
|
|
||||||
private $package;
|
protected function buildResourceTransformer() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public function shouldRequireLogin() {
|
public function shouldRequireLogin() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -37,15 +32,11 @@ final class CelerityResourceController extends PhabricatorController {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function willProcessRequest(array $data) {
|
private function getDiskPath($to_resource = null) {
|
||||||
$this->path = $data['path'];
|
return $this->getRootDirectory().$to_resource;
|
||||||
$this->hash = $data['hash'];
|
|
||||||
$this->package = !empty($data['package']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processRequest() {
|
protected function serveResource($path, $package_hash = null) {
|
||||||
$path = $this->path;
|
|
||||||
|
|
||||||
// Sanity checking to keep this from exposing anything sensitive, since it
|
// Sanity checking to keep this from exposing anything sensitive, since it
|
||||||
// ultimately boils down to disk reads.
|
// ultimately boils down to disk reads.
|
||||||
if (preg_match('@(//|\.\.)@', $path)) {
|
if (preg_match('@(//|\.\.)@', $path)) {
|
||||||
|
@ -66,11 +57,9 @@ final class CelerityResourceController extends PhabricatorController {
|
||||||
return $this->makeResponseCacheable(new Aphront304Response());
|
return $this->makeResponseCacheable(new Aphront304Response());
|
||||||
}
|
}
|
||||||
|
|
||||||
$root = dirname(phutil_get_library_root('phabricator'));
|
if ($package_hash) {
|
||||||
|
|
||||||
if ($this->package) {
|
|
||||||
$map = CelerityResourceMap::getInstance();
|
$map = CelerityResourceMap::getInstance();
|
||||||
$paths = $map->resolvePackage($this->hash);
|
$paths = $map->resolvePackage($package_hash);
|
||||||
if (!$paths) {
|
if (!$paths) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
@ -78,7 +67,8 @@ final class CelerityResourceController extends PhabricatorController {
|
||||||
try {
|
try {
|
||||||
$data = array();
|
$data = array();
|
||||||
foreach ($paths as $package_path) {
|
foreach ($paths as $package_path) {
|
||||||
$data[] = Filesystem::readFile($root.'/webroot/'.$package_path);
|
$disk_path = $this->getDiskPath($package_path);
|
||||||
|
$data[] = Filesystem::readFile($disk_path);
|
||||||
}
|
}
|
||||||
$data = implode("\n\n", $data);
|
$data = implode("\n\n", $data);
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
|
@ -86,17 +76,17 @@ final class CelerityResourceController extends PhabricatorController {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
$data = Filesystem::readFile($root.'/webroot/'.$path);
|
$disk_path = $this->getDiskPath($path);
|
||||||
|
$data = Filesystem::readFile($disk_path);
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$xformer = new CelerityResourceTransformer();
|
$xformer = $this->buildResourceTransformer();
|
||||||
$xformer->setMinify(PhabricatorEnv::getEnvConfig('celerity.minify'));
|
if ($xformer) {
|
||||||
$xformer->setCelerityMap(CelerityResourceMap::getInstance());
|
$data = $xformer->transformResource($path, $data);
|
||||||
|
}
|
||||||
$data = $xformer->transformResource($path, $data);
|
|
||||||
|
|
||||||
$response = new AphrontFileResponse();
|
$response = new AphrontFileResponse();
|
||||||
$response->setContent($data);
|
$response->setContent($data);
|
||||||
|
@ -104,7 +94,7 @@ final class CelerityResourceController extends PhabricatorController {
|
||||||
return $this->makeResponseCacheable($response);
|
return $this->makeResponseCacheable($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getSupportedResourceTypes() {
|
protected function getSupportedResourceTypes() {
|
||||||
return array(
|
return array(
|
||||||
'css' => 'text/css; charset=utf-8',
|
'css' => 'text/css; charset=utf-8',
|
||||||
'js' => 'text/javascript; charset=utf-8',
|
'js' => 'text/javascript; charset=utf-8',
|
||||||
|
|
|
@ -24,6 +24,12 @@ final class CelerityResourceTransformer {
|
||||||
private $minify;
|
private $minify;
|
||||||
private $rawResourceMap;
|
private $rawResourceMap;
|
||||||
private $celerityMap;
|
private $celerityMap;
|
||||||
|
private $translateURICallback;
|
||||||
|
|
||||||
|
public function setTranslateURICallback($translate_uricallback) {
|
||||||
|
$this->translateURICallback = $translate_uricallback;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function setMinify($minify) {
|
public function setMinify($minify) {
|
||||||
$this->minify = $minify;
|
$this->minify = $minify;
|
||||||
|
@ -46,8 +52,10 @@ final class CelerityResourceTransformer {
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'css':
|
case 'css':
|
||||||
$data = preg_replace_callback(
|
$data = preg_replace_callback(
|
||||||
'@url\s*\((\s*[\'"]?/rsrc/.*?)\)@s',
|
'@url\s*\((\s*[\'"]?.*?)\)@s',
|
||||||
array($this, 'translateResourceURI'),
|
nonempty(
|
||||||
|
$this->translateURICallback,
|
||||||
|
array($this, 'translateResourceURI')),
|
||||||
$data);
|
$data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue