mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-25 16:22:43 +01:00
Allow simple template-based skin definitions
Summary: Lower the barrier to entry for installing and creating skins, so we can kill Wordpress. You can now install skins by dropping them into a directory, and build either "advanced" (full phutil library) skins or "basic" (simple PHP templates) skins. Next up is getting static resources working in an easy way for skins. I put these in `externals/` for now so they don't get hit by lint. Test Plan: Viewed the Pokeblog with the Oblivious skin. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T1373 Differential Revision: https://secure.phabricator.com/D3717
This commit is contained in:
parent
44c6109bf2
commit
b3ad8507af
17 changed files with 384 additions and 64 deletions
|
@ -1084,6 +1084,11 @@ return array(
|
||||||
// Information on shortnames - http://docs.disqus.com/help/68/
|
// Information on shortnames - http://docs.disqus.com/help/68/
|
||||||
'disqus.shortname' => null,
|
'disqus.shortname' => null,
|
||||||
|
|
||||||
|
// Directories to look for Phame skins inside of.
|
||||||
|
'phame.skins' => array(
|
||||||
|
'externals/skin/',
|
||||||
|
),
|
||||||
|
|
||||||
// -- Remarkup -------------------------------------------------------------- //
|
// -- Remarkup -------------------------------------------------------------- //
|
||||||
|
|
||||||
// If you enable this, linked YouTube videos will be embeded inline. This has
|
// If you enable this, linked YouTube videos will be embeded inline. This has
|
||||||
|
|
1
externals/skins/oblivious/404.php
vendored
Normal file
1
externals/skins/oblivious/404.php
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<h2>404 Not Found</h2>
|
3
externals/skins/oblivious/footer.php
vendored
Normal file
3
externals/skins/oblivious/footer.php
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
15
externals/skins/oblivious/header.php
vendored
Normal file
15
externals/skins/oblivious/header.php
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title><?php echo _e($title); ?></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="oblivious-info">
|
||||||
|
<h1>
|
||||||
|
<a href="<?php echo _e($uri); ?>"><?php
|
||||||
|
echo _e($blog->getName());
|
||||||
|
?></a>
|
||||||
|
</h1>
|
||||||
|
<p><?php echo _e($blog->getDescription()); ?></p>
|
||||||
|
</div>
|
||||||
|
<div class="oblivious-content">
|
1
externals/skins/oblivious/post-detail.php
vendored
Normal file
1
externals/skins/oblivious/post-detail.php
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<?php echo $post->render(); ?>
|
13
externals/skins/oblivious/post-list.php
vendored
Normal file
13
externals/skins/oblivious/post-list.php
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<div class="oblivious-post-list">
|
||||||
|
<?php
|
||||||
|
|
||||||
|
foreach ($posts as $post) {
|
||||||
|
echo $post->renderWithSummary();
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
<div class="oblivious-pager">
|
||||||
|
<?php echo $older; ?>
|
||||||
|
<?php echo $newer; ?>
|
||||||
|
</div>
|
3
externals/skins/oblivious/skin.json
vendored
Normal file
3
externals/skins/oblivious/skin.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"name": "Oblivious"
|
||||||
|
}
|
|
@ -1150,6 +1150,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorXHProfSampleListController' => 'applications/xhprof/controller/PhabricatorXHProfSampleListController.php',
|
'PhabricatorXHProfSampleListController' => 'applications/xhprof/controller/PhabricatorXHProfSampleListController.php',
|
||||||
'PhabricatorXHProfSampleListView' => 'applications/xhprof/view/PhabricatorXHProfSampleListView.php',
|
'PhabricatorXHProfSampleListView' => 'applications/xhprof/view/PhabricatorXHProfSampleListView.php',
|
||||||
'PhameBasicBlogSkin' => 'applications/phame/skins/PhameBasicBlogSkin.php',
|
'PhameBasicBlogSkin' => 'applications/phame/skins/PhameBasicBlogSkin.php',
|
||||||
|
'PhameBasicTemplateBlogSkin' => 'applications/phame/skins/PhameBasicTemplateBlogSkin.php',
|
||||||
'PhameBlog' => 'applications/phame/storage/PhameBlog.php',
|
'PhameBlog' => 'applications/phame/storage/PhameBlog.php',
|
||||||
'PhameBlogDeleteController' => 'applications/phame/controller/blog/PhameBlogDeleteController.php',
|
'PhameBlogDeleteController' => 'applications/phame/controller/blog/PhameBlogDeleteController.php',
|
||||||
'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php',
|
'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php',
|
||||||
|
@ -1157,7 +1158,6 @@ phutil_register_library_map(array(
|
||||||
'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.php',
|
'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.php',
|
||||||
'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php',
|
'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php',
|
||||||
'PhameBlogSkin' => 'applications/phame/skins/PhameBlogSkin.php',
|
'PhameBlogSkin' => 'applications/phame/skins/PhameBlogSkin.php',
|
||||||
'PhameBlogSkinTenEleven' => 'applications/phame/skins/PhameBlogSkinTenEleven.php',
|
|
||||||
'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php',
|
'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php',
|
||||||
'PhameController' => 'applications/phame/controller/PhameController.php',
|
'PhameController' => 'applications/phame/controller/PhameController.php',
|
||||||
'PhameDAO' => 'applications/phame/storage/PhameDAO.php',
|
'PhameDAO' => 'applications/phame/storage/PhameDAO.php',
|
||||||
|
@ -1174,6 +1174,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',
|
||||||
|
'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',
|
||||||
'PhortuneStripePaymentFormView' => 'applications/phortune/stripe/view/PhortuneStripePaymentFormView.php',
|
'PhortuneStripePaymentFormView' => 'applications/phortune/stripe/view/PhortuneStripePaymentFormView.php',
|
||||||
|
@ -2278,6 +2279,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorXHProfSampleListController' => 'PhabricatorXHProfController',
|
'PhabricatorXHProfSampleListController' => 'PhabricatorXHProfController',
|
||||||
'PhabricatorXHProfSampleListView' => 'AphrontView',
|
'PhabricatorXHProfSampleListView' => 'AphrontView',
|
||||||
'PhameBasicBlogSkin' => 'PhameBlogSkin',
|
'PhameBasicBlogSkin' => 'PhameBlogSkin',
|
||||||
|
'PhameBasicTemplateBlogSkin' => 'PhameBasicBlogSkin',
|
||||||
'PhameBlog' =>
|
'PhameBlog' =>
|
||||||
array(
|
array(
|
||||||
0 => 'PhameDAO',
|
0 => 'PhameDAO',
|
||||||
|
@ -2290,7 +2292,6 @@ phutil_register_library_map(array(
|
||||||
'PhameBlogLiveController' => 'PhameController',
|
'PhameBlogLiveController' => 'PhameController',
|
||||||
'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhameBlogSkin' => 'PhabricatorController',
|
'PhameBlogSkin' => 'PhabricatorController',
|
||||||
'PhameBlogSkinTenEleven' => 'PhameBasicBlogSkin',
|
|
||||||
'PhameBlogViewController' => 'PhameController',
|
'PhameBlogViewController' => 'PhameController',
|
||||||
'PhameController' => 'PhabricatorController',
|
'PhameController' => 'PhabricatorController',
|
||||||
'PhameDAO' => 'PhabricatorLiskDAO',
|
'PhameDAO' => 'PhabricatorLiskDAO',
|
||||||
|
|
|
@ -118,6 +118,9 @@ final class PhameBlogEditController
|
||||||
->setObject($blog)
|
->setObject($blog)
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
|
$skins = PhameSkinSpecification::loadAllSkinSpecifications();
|
||||||
|
$skins = mpull($skins, 'getName');
|
||||||
|
|
||||||
$form = id(new AphrontFormView())
|
$form = id(new AphrontFormView())
|
||||||
->setUser($user)
|
->setUser($user)
|
||||||
->setFlexible(true)
|
->setFlexible(true)
|
||||||
|
@ -171,7 +174,7 @@ final class PhameBlogEditController
|
||||||
->setLabel('Skin')
|
->setLabel('Skin')
|
||||||
->setName('skin')
|
->setName('skin')
|
||||||
->setValue($blog->getSkin())
|
->setValue($blog->getSkin())
|
||||||
->setOptions(PhameBlog::getSkinOptionsForSelect())
|
->setOptions($skins)
|
||||||
)
|
)
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormSubmitControl())
|
id(new AphrontFormSubmitControl())
|
||||||
|
|
|
@ -64,6 +64,7 @@ final class PhameBlogLiveController extends PhameController {
|
||||||
->setBlog($blog)
|
->setBlog($blog)
|
||||||
->setBaseURI($request->getRequestURI()->setPath($base_path));
|
->setBaseURI($request->getRequestURI()->setPath($base_path));
|
||||||
|
|
||||||
|
$skin->willProcessRequest(array());
|
||||||
return $skin->processRequest();
|
return $skin->processRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin {
|
||||||
|
|
||||||
$response = new AphrontWebpageResponse();
|
$response = new AphrontWebpageResponse();
|
||||||
$response->setContent($view->render());
|
$response->setContent($view->render());
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +128,9 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin {
|
||||||
*/
|
*/
|
||||||
protected function renderOlderPageLink() {
|
protected function renderOlderPageLink() {
|
||||||
$uri = $this->getOlderPageURI();
|
$uri = $this->getOlderPageURI();
|
||||||
|
if (!$uri) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return phutil_render_tag(
|
return phutil_render_tag(
|
||||||
'a',
|
'a',
|
||||||
array(
|
array(
|
||||||
|
@ -156,6 +160,9 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin {
|
||||||
*/
|
*/
|
||||||
protected function renderNewerPageLink() {
|
protected function renderNewerPageLink() {
|
||||||
$uri = $this->getNewerPageURI();
|
$uri = $this->getNewerPageURI();
|
||||||
|
if (!$uri) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return phutil_render_tag(
|
return phutil_render_tag(
|
||||||
'a',
|
'a',
|
||||||
array(
|
array(
|
||||||
|
|
97
src/applications/phame/skins/PhameBasicTemplateBlogSkin.php
Normal file
97
src/applications/phame/skins/PhameBasicTemplateBlogSkin.php
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
<?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 PhameBasicTemplateBlogSkin extends PhameBasicBlogSkin {
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$root = dirname(phutil_get_library_root('phabricator'));
|
||||||
|
require_once $root.'/support/phame/libskin.php';
|
||||||
|
|
||||||
|
parent::willProcessRequest($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName() {
|
||||||
|
return $this->getSpecification()->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPath($to_file = null) {
|
||||||
|
$path = $this->getSpecification()->getRootDirectory();
|
||||||
|
if ($to_file) {
|
||||||
|
$path = $path.DIRECTORY_SEPARATOR.$to_file;
|
||||||
|
}
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderTemplate($__template__, array $__scope__) {
|
||||||
|
chdir($this->getPath());
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
if (Filesystem::pathExists($this->getPath($__template__))) {
|
||||||
|
extract($__scope__ + $this->getDefaultScope());
|
||||||
|
require $this->getPath($__template__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ob_get_clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDefaultScope() {
|
||||||
|
return array(
|
||||||
|
'skin' => $this,
|
||||||
|
'blog' => $this->getBlog(),
|
||||||
|
'uri' => $this->getURI(''),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderHeader() {
|
||||||
|
return $this->renderTemplate(
|
||||||
|
'header.php',
|
||||||
|
array(
|
||||||
|
'title' => $this->getBlog()->getName(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderFooter() {
|
||||||
|
return $this->renderTemplate('footer.php', array());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function render404Page() {
|
||||||
|
return $this->renderTemplate('404.php', array());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderPostDetail(PhamePostView $post) {
|
||||||
|
return $this->renderTemplate(
|
||||||
|
'post-detail.php',
|
||||||
|
array(
|
||||||
|
'post' => $post,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderPostList(array $posts) {
|
||||||
|
return $this->renderTemplate(
|
||||||
|
'post-list.php',
|
||||||
|
array(
|
||||||
|
'posts' => $posts,
|
||||||
|
'older' => $this->renderNewerPageLink(),
|
||||||
|
'newer' => $this->renderOlderPageLink(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,6 +24,16 @@ abstract class PhameBlogSkin extends PhabricatorController {
|
||||||
private $blog;
|
private $blog;
|
||||||
private $baseURI;
|
private $baseURI;
|
||||||
private $preview;
|
private $preview;
|
||||||
|
private $specification;
|
||||||
|
|
||||||
|
public function setSpecification(PhameSkinSpecification $specification) {
|
||||||
|
$this->specification = $specification;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSpecification() {
|
||||||
|
return $this->specification;
|
||||||
|
}
|
||||||
|
|
||||||
public function setPreview($preview) {
|
public function setPreview($preview) {
|
||||||
$this->preview = $preview;
|
$this->preview = $preview;
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
<?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 PhameBlogSkinTenEleven extends PhameBasicBlogSkin {
|
|
||||||
|
|
||||||
public function getName() {
|
|
||||||
return 'Ten Eleven (Default)';
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function renderHeader() {
|
|
||||||
$blog_name = $this->getBlog()->getName();
|
|
||||||
$about = $this->getBlog()->getDescription();
|
|
||||||
|
|
||||||
$about = phutil_escape_html($about);
|
|
||||||
|
|
||||||
return <<<EOHTML
|
|
||||||
<div class="main-panel">
|
|
||||||
<div class="header">
|
|
||||||
<h1>{$blog_name}</h1>
|
|
||||||
<div class="about">{$about}</div>
|
|
||||||
</div>
|
|
||||||
<div class="splash">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="content">
|
|
||||||
EOHTML;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function renderFooter() {
|
|
||||||
return <<<EOHTML
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
EOHTML;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
190
src/applications/phame/skins/PhameSkinSpecification.php
Normal file
190
src/applications/phame/skins/PhameSkinSpecification.php
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
<?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 PhameSkinSpecification {
|
||||||
|
|
||||||
|
const TYPE_ADVANCED = 'advanced';
|
||||||
|
const TYPE_BASIC = 'basic';
|
||||||
|
|
||||||
|
private $type;
|
||||||
|
private $rootDirectory;
|
||||||
|
private $skinClass;
|
||||||
|
private $phutilLibraries = array();
|
||||||
|
private $name;
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
public static function loadAllSkinSpecifications() {
|
||||||
|
|
||||||
|
static $specs;
|
||||||
|
|
||||||
|
if ($specs === null) {
|
||||||
|
$paths = PhabricatorEnv::getEnvConfig('phame.skins');
|
||||||
|
$base = dirname(phutil_get_library_root('phabricator'));
|
||||||
|
|
||||||
|
$specs = array();
|
||||||
|
|
||||||
|
foreach ($paths as $path) {
|
||||||
|
$path = Filesystem::resolvePath($path, $base);
|
||||||
|
foreach (Filesystem::listDirectory($path) as $skin_directory) {
|
||||||
|
$skin_path = $path.DIRECTORY_SEPARATOR.$skin_directory;
|
||||||
|
|
||||||
|
if (!is_dir($skin_path)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$spec = self::loadSkinSpecification($skin_path);
|
||||||
|
if (!$spec) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = trim($skin_directory, DIRECTORY_SEPARATOR);
|
||||||
|
|
||||||
|
$spec->setName($name);
|
||||||
|
|
||||||
|
if (isset($specs[$name])) {
|
||||||
|
$that_dir = $specs[$name]->getRootDirectory();
|
||||||
|
$this_dir = $spec->getRootDirectory();
|
||||||
|
throw new Exception(
|
||||||
|
"Two skins have the same name ('{$name}'), in '{$this_dir}' and ".
|
||||||
|
"'{$that_dir}'. Rename one or adjust your 'phame.skins' ".
|
||||||
|
"configuration.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$specs[$name] = $spec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $specs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadOneSkinSpecification($name) {
|
||||||
|
$paths = PhabricatorEnv::getEnvConfig('phame.skins');
|
||||||
|
$base = dirname(phutil_get_library_root('phabricator'));
|
||||||
|
foreach ($paths as $path) {
|
||||||
|
$path = Filesystem::resolvePath($path, $base);
|
||||||
|
$skin_path = $path.DIRECTORY_SEPARATOR.$name;
|
||||||
|
if (is_dir($skin_path)) {
|
||||||
|
$spec = self::loadSkinSpecification($skin_path);
|
||||||
|
if ($spec) {
|
||||||
|
$spec->setName($name);
|
||||||
|
return $spec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadSkinSpecification($path) {
|
||||||
|
|
||||||
|
$config_path = $path.DIRECTORY_SEPARATOR.'skin.json';
|
||||||
|
$config = array();
|
||||||
|
if (Filesystem::pathExists($config_path)) {
|
||||||
|
$config = Filesystem::readFile($config_path);
|
||||||
|
$config = json_decode($config, true);
|
||||||
|
if (!is_array($config)) {
|
||||||
|
throw new Exception(
|
||||||
|
"Skin configuration file '{$config_path}' is not a valid JSON file.");
|
||||||
|
}
|
||||||
|
$type = idx($config, 'type', self::TYPE_BASIC);
|
||||||
|
} else {
|
||||||
|
$type = self::TYPE_BASIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
$spec = new PhameSkinSpecification();
|
||||||
|
$spec->setRootDirectory($path);
|
||||||
|
$spec->setConfig($config);
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case self::TYPE_BASIC:
|
||||||
|
$spec->setSkinClass('PhameBasicTemplateBlogSkin');
|
||||||
|
break;
|
||||||
|
case self::TYPE_ADVANCED:
|
||||||
|
$spec->setSkinClass($config['class']);
|
||||||
|
$spec->addPhutilLibrary($path.DIRECTORY_SEPARATOR.'src');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Unknown skin type!");
|
||||||
|
}
|
||||||
|
|
||||||
|
$spec->setType($type);
|
||||||
|
|
||||||
|
return $spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setConfig(array $config) {
|
||||||
|
$this->config = $config;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConfig($key, $default = null) {
|
||||||
|
return idx($this->config, $key, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName($name) {
|
||||||
|
$this->name = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName() {
|
||||||
|
return $this->getConfig('name', $this->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRootDirectory($root_directory) {
|
||||||
|
$this->rootDirectory = $root_directory;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRootDirectory() {
|
||||||
|
return $this->rootDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setType($type) {
|
||||||
|
$this->type = $type;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getType() {
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSkinClass($skin_class) {
|
||||||
|
$this->skinClass = $skin_class;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSkinClass() {
|
||||||
|
return $this->skinClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addPhutilLibrary($library) {
|
||||||
|
$this->phutilLibraries[] = $library;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildSkin(AphrontRequest $request) {
|
||||||
|
foreach ($this->phutilLibraries as $library) {
|
||||||
|
phutil_load_library($library);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newv($this->getSkinClass(), array($request, $this));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,7 +24,7 @@ final class PhameBlog extends PhameDAO
|
||||||
|
|
||||||
const MARKUP_FIELD_DESCRIPTION = 'markup:description';
|
const MARKUP_FIELD_DESCRIPTION = 'markup:description';
|
||||||
|
|
||||||
const SKIN_DEFAULT = 'PhameBlogSkinTenEleven';
|
const SKIN_DEFAULT = 'oblivious';
|
||||||
|
|
||||||
protected $id;
|
protected $id;
|
||||||
protected $phid;
|
protected $phid;
|
||||||
|
@ -57,14 +57,17 @@ final class PhameBlog extends PhameDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSkinRenderer(AphrontRequest $request) {
|
public function getSkinRenderer(AphrontRequest $request) {
|
||||||
try {
|
$spec = PhameSkinSpecification::loadOneSkinSpecification(
|
||||||
$skin = newv($this->getSkin(), array($request));
|
$this->getSkin());
|
||||||
} catch (PhutilMissingSymbolException $ex) {
|
|
||||||
// If this blog has a skin but it's no longer available (for example,
|
if (!$spec) {
|
||||||
// it was uninstalled) just return the default skin.
|
$spec = PhameSkinSpecification::loadOneSkinSpecification(
|
||||||
$skin = newv(self::SKIN_DEFAULT, array($request));
|
self::SKIN_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$skin = newv($spec->getSkinClass(), array($request));
|
||||||
|
$skin->setSpecification($spec);
|
||||||
|
|
||||||
return $skin;
|
return $skin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
support/phame/libskin.php
Normal file
21
support/phame/libskin.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function _e($text) {
|
||||||
|
return phutil_escape_html($text);
|
||||||
|
}
|
Loading…
Reference in a new issue