Skip to content

Commit 26f7425

Browse files
author
epriestley
committedOct 17, 2012
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
1 parent b3ad850 commit 26f7425

16 files changed

+340
-51
lines changed
 

‎conf/default.conf.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@
10861086

10871087
// Directories to look for Phame skins inside of.
10881088
'phame.skins' => array(
1089-
'externals/skin/',
1089+
'externals/skins/',
10901090
),
10911091

10921092
// -- Remarkup -------------------------------------------------------------- //
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
html, body, p, h1, h2, h3 {
2+
padding: 0;
3+
margin: 0;
4+
font-weight: normal;
5+
}
6+
7+
html {
8+
font-family: "Helvetica Neue", "Arial", sans-serif;
9+
font-size: 16px;
10+
overflow-y: scroll;
11+
color: #555555;
12+
}
13+
14+
.oblivious-info {
15+
position: fixed;
16+
width: 15%;
17+
border-right: 1px solid #dfdfdf;
18+
top: 0;
19+
bottom: 0;
20+
left: 0;
21+
padding: 140px 2% 0;
22+
overflow: hidden;
23+
24+
background: url(/image/badge.png);
25+
background-repeat: no-repeat;
26+
background-position: 20px 20px;
27+
}
28+
29+
.oblivious-content {
30+
padding-top: 3%;
31+
margin-left: 22%;
32+
max-width: 600px;
33+
}
34+
35+
a {
36+
color: #222222;
37+
text-decoration: none;
38+
}
39+
40+
a:hover {
41+
color: #a00000;
42+
}
43+
44+
45+
h1 {
46+
font-size: 24px;
47+
font-weight: normal;
48+
}
49+
50+
h2 {
51+
font-size: 22px;
52+
font-weight: bold;
53+
}
54+
55+
.phame-post {
56+
margin: 0 0 2em;
57+
}
58+
59+
.phame-post-date {
60+
font-size: 12px;
61+
margin: .25em 0 1em;
62+
}
63+
64+
.phame-post {
65+
line-height: 1.6em;
66+
}
67+
68+
.phame-post p {
69+
margin: 0 0 1em;
70+
}
71+
72+
73+
.fb-comments,
74+
.fb-comments span,
75+
.fb-comments iframe[style] {
76+
width: 100% !important;
77+
}

‎externals/skins/oblivious/header.php

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
<html>
33
<head>
44
<title><?php echo _e($title); ?></title>
5+
6+
<?php echo $skin->getCSSResources(); ?>
7+
58
</head>
69
<body>
710
<div class="oblivious-info">
1.8 KB
Loading

‎src/__phutil_library_map__.php

+4
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
'AphrontView' => 'view/AphrontView.php',
9292
'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php',
9393
'CelerityAPI' => 'infrastructure/celerity/CelerityAPI.php',
94+
'CelerityPhabricatorResourceController' => 'infrastructure/celerity/CelerityPhabricatorResourceController.php',
9495
'CelerityResourceController' => 'infrastructure/celerity/CelerityResourceController.php',
9596
'CelerityResourceGraph' => 'infrastructure/celerity/CelerityResourceGraph.php',
9697
'CelerityResourceMap' => 'infrastructure/celerity/CelerityResourceMap.php',
@@ -1174,6 +1175,7 @@
11741175
'PhamePostUnpublishController' => 'applications/phame/controller/post/PhamePostUnpublishController.php',
11751176
'PhamePostView' => 'applications/phame/view/PhamePostView.php',
11761177
'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php',
1178+
'PhameResourceController' => 'applications/phame/controller/PhameResourceController.php',
11771179
'PhameSkinSpecification' => 'applications/phame/skins/PhameSkinSpecification.php',
11781180
'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php',
11791181
'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/PhortuneStripeBaseController.php',
@@ -1334,6 +1336,7 @@
13341336
'AphrontTypeaheadTemplateView' => 'AphrontView',
13351337
'AphrontUsageException' => 'AphrontException',
13361338
'AphrontWebpageResponse' => 'AphrontResponse',
1339+
'CelerityPhabricatorResourceController' => 'CelerityResourceController',
13371340
'CelerityResourceController' => 'PhabricatorController',
13381341
'CelerityResourceGraph' => 'AbstractDirectedGraph',
13391342
'CelerityResourceTransformerTestCase' => 'PhabricatorTestCase',
@@ -2313,6 +2316,7 @@
23132316
'PhamePostUnpublishController' => 'PhameController',
23142317
'PhamePostView' => 'AphrontView',
23152318
'PhamePostViewController' => 'PhameController',
2319+
'PhameResourceController' => 'CelerityResourceController',
23162320
'PhortuneMonthYearExpiryControl' => 'AphrontFormControl',
23172321
'PhortuneStripeBaseController' => 'PhabricatorController',
23182322
'PhortuneStripePaymentFormView' => 'AphrontView',

‎src/aphront/configuration/AphrontDefaultApplicationConfiguration.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ protected function getResourceURIMapRules() {
155155
'(?P<package>pkg/)?'.
156156
'(?P<hash>[a-f0-9]{8})/'.
157157
'(?P<path>.+\.(?:css|js|jpg|png|swf|gif))'
158-
=> 'CelerityResourceController',
158+
=> 'CelerityPhabricatorResourceController',
159159
),
160160
);
161161
}

‎src/applications/phame/application/PhabricatorApplicationPhame.php

+3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public function getRoutes() {
4646
return array(
4747
'/phame/' => array(
4848
'' => 'PhamePostListController',
49+
'r/(?P<id>\d+)/(?P<hash>[^/]+)/(?P<name>.*)'
50+
=> 'PhameResourceController',
51+
4952
'live/(?P<id>[^/]+)/(?P<more>.*)' => 'PhameBlogLiveController',
5053
'post/' => array(
5154
'(?:(?P<filter>draft|all)/)?' => 'PhamePostListController',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
/*
4+
* Copyright 2012 Facebook, Inc.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
/**
20+
* @group phame
21+
*/
22+
final class PhameResourceController extends CelerityResourceController {
23+
24+
private $id;
25+
private $hash;
26+
private $name;
27+
private $root;
28+
29+
protected function getRootDirectory() {
30+
return $this->root;
31+
}
32+
33+
public function willProcessRequest(array $data) {
34+
$this->id = $data['id'];
35+
$this->hash = $data['hash'];
36+
$this->name = $data['name'];
37+
}
38+
39+
public function processRequest() {
40+
$request = $this->getRequest();
41+
$user = $request->getUser();
42+
43+
// We require a visible blog associated with a given skin to serve
44+
// resources, so you can't go fishing around where you shouldn't be.
45+
46+
$blog = id(new PhameBlogQuery())
47+
->setViewer($user)
48+
->withIDs(array($this->id))
49+
->executeOne();
50+
if (!$blog) {
51+
return new Aphront404Response();
52+
}
53+
54+
$skin = $blog->getSkinRenderer($request);
55+
$spec = $skin->getSpecification();
56+
57+
$this->root = $spec->getRootDirectory().DIRECTORY_SEPARATOR;
58+
return $this->serveResource($this->name, $package_hash = null);
59+
}
60+
61+
protected function buildResourceTransformer() {
62+
$xformer = new CelerityResourceTransformer();
63+
$xformer->setMinify(false);
64+
$xformer->setTranslateURICallback(array($this, 'translateResourceURI'));
65+
return $xformer;
66+
}
67+
68+
public function translateResourceURI(array $matches) {
69+
$uri = trim($matches[1], "'\" \r\t\n");
70+
71+
if (Filesystem::pathExists($this->root.$uri)) {
72+
$hash = filemtime($this->root.$uri);
73+
} else {
74+
$hash = '-';
75+
}
76+
77+
$uri = '/phame/r/'.$this->id.'/'.$hash.'/'.$uri;
78+
return 'url('.$uri.')';
79+
}
80+
81+
}

‎src/applications/phame/controller/blog/PhameBlogLiveController.php

+7-6
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,20 @@ public function processRequest() {
5050
->setURI('http://'.$blog->getDomain().'/'.$this->more);
5151
}
5252

53+
$phame_request = clone $request;
54+
$phame_request->setPath('/'.ltrim($this->more, '/'));
55+
5356
if ($blog->getDomain()) {
54-
$base_path = '/';
57+
$uri = new PhutilURI('http://'.$blog->getDomain().'/');
5558
} else {
56-
$base_path = '/phame/live/'.$blog->getID().'/';
59+
$uri = '/phame/live/'.$blog->getID().'/';
60+
$uri = PhabricatorEnv::getURI($uri);
5761
}
5862

59-
$phame_request = clone $request;
60-
$phame_request->setPath('/'.ltrim($this->more, '/'));
61-
6263
$skin = $blog->getSkinRenderer($phame_request);
6364
$skin
6465
->setBlog($blog)
65-
->setBaseURI($request->getRequestURI()->setPath($base_path));
66+
->setBaseURI((string)$uri);
6667

6768
$skin->willProcessRequest(array());
6869
return $skin->processRequest();

‎src/applications/phame/skins/PhameBasicBlogSkin.php

+17-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin {
2525

2626
private $pager;
2727

28-
final public function processRequest() {
28+
public function processRequest() {
2929
$request = $this->getRequest();
3030

3131
$content = $this->renderContent($request);
@@ -98,6 +98,21 @@ protected function render404Page() {
9898
return '<h2>404 Not Found</h2>';
9999
}
100100

101+
final public function getResourceURI($resource) {
102+
$root = $this->getSpecification()->getRootDirectory();
103+
$path = $root.DIRECTORY_SEPARATOR.$resource;
104+
105+
$data = Filesystem::readFile($path);
106+
$hash = PhabricatorHash::digest($data);
107+
$hash = substr($hash, 0, 6);
108+
$id = $this->getBlog()->getID();
109+
110+
$uri = '/phame/r/'.$id.'/'.$hash.'/'.$resource;
111+
$uri = PhabricatorEnv::getCDNURI($uri);
112+
113+
return $uri;
114+
}
115+
101116
/* -( Paging )------------------------------------------------------------- */
102117

103118

@@ -179,7 +194,7 @@ protected function renderNewerPageLink() {
179194
/**
180195
* @task internal
181196
*/
182-
private function renderContent(AphrontRequest $request) {
197+
protected function renderContent(AphrontRequest $request) {
183198
$user = $request->getUser();
184199

185200
$matches = null;

‎src/applications/phame/skins/PhameBasicTemplateBlogSkin.php

+45-3
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,51 @@
2121
*/
2222
final class PhameBasicTemplateBlogSkin extends PhameBasicBlogSkin {
2323

24-
public function willProcessRequest(array $data) {
24+
private $cssResources;
25+
26+
public function processRequest() {
2527
$root = dirname(phutil_get_library_root('phabricator'));
2628
require_once $root.'/support/phame/libskin.php';
2729

28-
parent::willProcessRequest($data);
30+
$css = $this->getPath('css/');
31+
if (Filesystem::pathExists($css)) {
32+
$this->cssResources = array();
33+
foreach (Filesystem::listDirectory($css) as $path) {
34+
if (!preg_match('/.css$/', $path)) {
35+
continue;
36+
}
37+
$this->cssResources[] = phutil_render_tag(
38+
'link',
39+
array(
40+
'rel' => 'stylesheet',
41+
'type' => 'text/css',
42+
'href' => $this->getResourceURI('css/'.$path),
43+
));
44+
}
45+
$this->cssResources = implode("\n", $this->cssResources);
46+
}
47+
48+
$request = $this->getRequest();
49+
$content = $this->renderContent($request);
50+
51+
if (!$content) {
52+
$content = $this->render404Page();
53+
}
54+
55+
$content = array(
56+
$this->renderHeader(),
57+
$content,
58+
$this->renderFooter(),
59+
);
60+
61+
$response = new AphrontWebpageResponse();
62+
$response->setContent(implode("\n", $content));
63+
64+
return $response;
65+
}
66+
67+
public function getCSSResources() {
68+
return $this->cssResources;
2969
}
3070

3171
public function getName() {
@@ -45,7 +85,9 @@ private function renderTemplate($__template__, array $__scope__) {
4585
ob_start();
4686

4787
if (Filesystem::pathExists($this->getPath($__template__))) {
48-
extract($__scope__ + $this->getDefaultScope());
88+
// Fool lint.
89+
$__evil__ = 'extract';
90+
$__evil__($__scope__ + $this->getDefaultScope());
4991
require $this->getPath($__template__);
5092
}
5193

‎src/applications/phame/storage/PhameBlog.php

+6
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ public function getSkinRenderer(AphrontRequest $request) {
6565
self::SKIN_DEFAULT);
6666
}
6767

68+
if (!$spec) {
69+
throw new Exception(
70+
"This blog has an invalid skin, and the default skin failed to ".
71+
"load.");
72+
}
73+
6874
$skin = newv($spec->getSkinClass(), array($request));
6975
$skin->setSpecification($spec);
7076

0 commit comments

Comments
 (0)
Failed to load comments.