Skip to content

Commit 5141890

Browse files
committed
Phame V1 - Phabricator blogging software
Summary: 'cuz we need to be phamous! V1 feature set - posts -- standard thing you'd expect - a title and a remarkup-powered body and... -- "phame" title - a short string that can be used to reference the story. this gets auto-updated when you mess with the title. -- configuration - for now, do you want Facebook, Disqus or no comments? this is a per-post thing but feeds from an instance-wide configuration Please do toss out any must have features or changes. Test Plan: played around with this bad boy like whoa Reviewers: epriestley Reviewed By: epriestley CC: aran, vrana Maniphest Tasks: T1111 Differential Revision: https://secure.phabricator.com/D2202
1 parent 3d6b8bf commit 5141890

35 files changed

+1832
-0
lines changed

conf/default.conf.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,16 @@
489489
// The Phabricator "Client Secret" to use for Phabricator API access.
490490
'phabricator.application-secret' => null,
491491

492+
// -- Disqus Comments ------------------------------------------------------- //
493+
494+
// Should Phame users have Disqus comment widget, and if so what's the
495+
// website shortname to use? For example, secure.phabricator.org uses
496+
// "phabricator", which we registered with Disqus. If you aren't familiar
497+
// with Disqus, see:
498+
// Disqus quick start guide - http://docs.disqus.com/help/4/
499+
// Information on shortnames - http://docs.disqus.com/help/68/
500+
'disqus.shortname' => null,
501+
492502
// -- Recaptcha ------------------------------------------------------------- //
493503

494504
// Is Recaptcha enabled? If disabled, captchas will not appear. You should

resources/sql/patches/132.phame.sql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
CREATE DATABASE IF NOT EXISTS `phabricator_phame` COLLATE utf8_general_ci;
2+
3+
CREATE TABLE `phabricator_phame`.`phame_post` (
4+
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
5+
`phid` VARCHAR(64) BINARY NOT NULL COLLATE utf8_bin,
6+
`bloggerPHID` VARCHAR(64) BINARY NOT NULL COLLATE utf8_bin,
7+
`title` VARCHAR(255) NOT NULL,
8+
`phameTitle` VARCHAR(64) NOT NULL,
9+
`body` LONGTEXT COLLATE utf8_general_ci,
10+
`visibility` INT UNSIGNED NOT NULL DEFAULT 0,
11+
`configData` LONGTEXT COLLATE utf8_general_ci,
12+
`datePublished` INT UNSIGNED NOT NULL,
13+
`dateCreated` INT UNSIGNED NOT NULL,
14+
`dateModified` INT UNSIGNED NOT NULL,
15+
KEY `bloggerPosts` (`bloggerPHID`, `visibility`, `datePublished`, `id`),
16+
UNIQUE KEY `phid` (`phid`),
17+
UNIQUE KEY `phameTitle` (`bloggerPHID`, `phameTitle`)
18+
) ENGINE=InnoDB;

src/__celerity_resource_map__.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,19 @@
12811281
),
12821282
'disk' => '/rsrc/js/application/core/behavior-watch-anchor.js',
12831283
),
1284+
'javelin-behavior-phame-post-preview' =>
1285+
array(
1286+
'uri' => '/res/ac4c503a/rsrc/js/application/phame/phame-post-preview.js',
1287+
'type' => 'js',
1288+
'requires' =>
1289+
array(
1290+
0 => 'javelin-behavior',
1291+
1 => 'javelin-dom',
1292+
2 => 'javelin-util',
1293+
3 => 'phabricator-shaped-request',
1294+
),
1295+
'disk' => '/rsrc/js/application/phame/phame-post-preview.js',
1296+
),
12841297
'javelin-behavior-phriction-document-preview' =>
12851298
array(
12861299
'uri' => '/res/f1665ecd/rsrc/js/application/phriction/phriction-document-preview.js',

src/__phutil_library_map__.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,19 @@
929929
'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/symbol',
930930
'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/toplevel',
931931
'PhabricatorXHProfProfileView' => 'applications/xhprof/view/base',
932+
'PhameController' => 'applications/phame/controller/base',
933+
'PhameDAO' => 'applications/phame/storage/base',
934+
'PhameDraftListController' => 'applications/phame/controller/post/list/drafts',
935+
'PhamePost' => 'applications/phame/storage/post',
936+
'PhamePostDeleteController' => 'applications/phame/controller/post/delete',
937+
'PhamePostDetailView' => 'applications/phame/view/postdetail',
938+
'PhamePostEditController' => 'applications/phame/controller/post/edit',
939+
'PhamePostListBaseController' => 'applications/phame/controller/post/list/base',
940+
'PhamePostListController' => 'applications/phame/controller/post/list/posts',
941+
'PhamePostListView' => 'applications/phame/view/postlist',
942+
'PhamePostPreviewController' => 'applications/phame/controller/post/preview',
943+
'PhamePostQuery' => 'applications/phame/query/post',
944+
'PhamePostViewController' => 'applications/phame/controller/post/view',
932945
'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/monthyearexpiry',
933946
'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/base',
934947
'PhortuneStripePaymentFormView' => 'applications/phortune/stripe/view/paymentform',
@@ -1743,6 +1756,19 @@
17431756
'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView',
17441757
'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView',
17451758
'PhabricatorXHProfProfileView' => 'AphrontView',
1759+
'PhameController' => 'PhabricatorController',
1760+
'PhameDAO' => 'PhabricatorLiskDAO',
1761+
'PhameDraftListController' => 'PhamePostListBaseController',
1762+
'PhamePost' => 'PhameDAO',
1763+
'PhamePostDeleteController' => 'PhameController',
1764+
'PhamePostDetailView' => 'AphrontView',
1765+
'PhamePostEditController' => 'PhameController',
1766+
'PhamePostListBaseController' => 'PhameController',
1767+
'PhamePostListController' => 'PhamePostListBaseController',
1768+
'PhamePostListView' => 'AphrontView',
1769+
'PhamePostPreviewController' => 'PhameController',
1770+
'PhamePostQuery' => 'PhabricatorOffsetPagedQuery',
1771+
'PhamePostViewController' => 'PhameController',
17461772
'PhortuneMonthYearExpiryControl' => 'AphrontFormControl',
17471773
'PhortuneStripeBaseController' => 'PhabricatorController',
17481774
'PhortuneStripePaymentFormView' => 'AphrontView',

src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,28 @@ public function getURIMap() {
385385
'diff/(?P<id>\d+)/' => 'PhrictionDiffController',
386386
),
387387

388+
'/phame/' => array(
389+
'' => 'PhamePostListController',
390+
'post/' => array(
391+
'' => 'PhamePostListController',
392+
'delete/(?P<phid>[^/]+)/' => 'PhamePostDeleteController',
393+
'edit/(?P<phid>[^/]+)/' => 'PhamePostEditController',
394+
'new/' => 'PhamePostEditController',
395+
'preview/' => 'PhamePostPreviewController',
396+
'view/(?P<phid>[^/]+)/' => 'PhamePostViewController',
397+
),
398+
'draft/' => array(
399+
'' => 'PhameDraftListController',
400+
'new/' => 'PhamePostEditController',
401+
),
402+
'posts/' => array(
403+
'' => 'PhamePostListController',
404+
'(?P<bloggername>\w+)/' => 'PhamePostListController',
405+
'(?P<bloggername>\w+)/(?P<phametitle>.+/)'
406+
=> 'PhamePostViewController',
407+
),
408+
),
409+
388410
'/calendar/' => array(
389411
'' => 'PhabricatorCalendarBrowseController',
390412
),

src/applications/markup/engine/PhabricatorMarkupEngine.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ public static function newPhrictionMarkupEngine() {
4949
));
5050
}
5151

52+
public static function newPhameMarkupEngine() {
53+
return self::newMarkupEngine(array(
54+
'macros' => false,
55+
));
56+
}
57+
58+
5259
public static function newDifferentialMarkupEngine(array $options = array()) {
5360
return self::newMarkupEngine(array(
5461
'custom-inline' => PhabricatorEnv::getEnvConfig(
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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+
abstract class PhameController extends PhabricatorController {
23+
private $showSideNav;
24+
25+
protected function setShowSideNav($value) {
26+
$this->showSideNav = (bool) $value;
27+
return $this;
28+
}
29+
private function showSideNav() {
30+
return $this->showSideNav;
31+
}
32+
33+
public function buildStandardPageResponse($view, array $data) {
34+
35+
$page = $this->buildStandardPageView();
36+
37+
$page->setApplicationName('Phame');
38+
$page->setBaseURI('/phame/');
39+
$page->setTitle(idx($data, 'title'));
40+
$page->setGlyph("\xe2\x9c\xa9");
41+
42+
$tabs = array(
43+
'help' => array(
44+
'name' => 'Help',
45+
'href' =>
46+
PhabricatorEnv::getDoclink('article/Phame_User_Guide.html'),
47+
),
48+
);
49+
$page->setTabs($tabs, idx($data, 'tab'));
50+
if ($this->showSideNav()) {
51+
$nav = $this->renderSideNavFilterView($this->getSideNavFilter());
52+
$nav->appendChild($view);
53+
$page->appendChild($nav);
54+
} else {
55+
$page->appendChild($view);
56+
}
57+
58+
$response = new AphrontWebpageResponse();
59+
return $response->setContent($page->render());
60+
}
61+
62+
private function renderSideNavFilterView($filter) {
63+
$nav = new AphrontSideNavFilterView();
64+
$nav->setBaseURI(new PhutilURI('/phame/'));
65+
$nav->addLabel('Drafts');
66+
$nav->addFilter('post/new',
67+
'New Draft');
68+
$nav->addFilter('draft',
69+
'My Drafts');
70+
$nav->addSpacer();
71+
$nav->addLabel('Posts');
72+
$nav->addFilter('post',
73+
'My Posts');
74+
foreach ($this->getSideNavExtraPostFilters() as $post_filter) {
75+
$nav->addFilter($post_filter['key'],
76+
$post_filter['name']);
77+
}
78+
79+
$nav->selectFilter($filter, 'post');
80+
81+
return $nav;
82+
}
83+
84+
protected function getSideNavExtraPostFilters() {
85+
return array();
86+
}
87+
protected function getSideNavFilter() {
88+
return 'post';
89+
}
90+
91+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
/**
3+
* This file is automatically generated. Lint this module to rebuild it.
4+
* @generated
5+
*/
6+
7+
8+
9+
phutil_require_module('phabricator', 'aphront/response/webpage');
10+
phutil_require_module('phabricator', 'applications/base/controller/base');
11+
phutil_require_module('phabricator', 'infrastructure/env');
12+
phutil_require_module('phabricator', 'view/layout/sidenavfilter');
13+
14+
phutil_require_module('phutil', 'parser/uri');
15+
phutil_require_module('phutil', 'utils');
16+
17+
18+
phutil_require_source('PhameController.php');
Lines changed: 81 additions & 0 deletions
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 PhamePostDeleteController
23+
extends PhameController {
24+
25+
private $phid;
26+
27+
private function setPostPHID($phid) {
28+
$this->phid = $phid;
29+
return $this;
30+
}
31+
private function getPostPHID() {
32+
return $this->phid;
33+
}
34+
35+
protected function getSideNavFilter() {
36+
return 'post/delete/'.$this->getPostPHID();
37+
}
38+
39+
protected function getSideNavExtraPostFilters() {
40+
$filters = array(
41+
array('key' => $this->getSideNavFilter(),
42+
'name' => 'Delete Post')
43+
);
44+
45+
return $filters;
46+
}
47+
48+
public function willProcessRequest(array $data) {
49+
$phid = $data['phid'];
50+
$this->setPostPHID($phid);
51+
}
52+
53+
public function processRequest() {
54+
$request = $this->getRequest();
55+
$user = $request->getUser();
56+
$post = id(new PhamePost())->loadOneWhere(
57+
'phid = %s',
58+
$this->getPostPHID());
59+
if (empty($post)) {
60+
return new Aphront404Response();
61+
}
62+
if ($post->getBloggerPHID() != $user->getPHID()) {
63+
return new Aphront403Response();
64+
}
65+
$edit_uri = $post->getEditURI();
66+
67+
if ($request->isFormPost()) {
68+
$post->delete();
69+
return id(new AphrontRedirectResponse())->setURI('/phame/?deleted');
70+
}
71+
72+
$dialog = id(new AphrontDialogView())
73+
->setUser($user)
74+
->setTitle('Delete post?')
75+
->appendChild('Really delete this post? It will be gone forever.')
76+
->addSubmitButton('Delete')
77+
->addCancelButton($edit_uri);
78+
79+
return id(new AphrontDialogResponse())->setDialog($dialog);
80+
}
81+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
/**
3+
* This file is automatically generated. Lint this module to rebuild it.
4+
* @generated
5+
*/
6+
7+
8+
9+
phutil_require_module('phabricator', 'aphront/response/403');
10+
phutil_require_module('phabricator', 'aphront/response/404');
11+
phutil_require_module('phabricator', 'aphront/response/dialog');
12+
phutil_require_module('phabricator', 'aphront/response/redirect');
13+
phutil_require_module('phabricator', 'applications/phame/controller/base');
14+
phutil_require_module('phabricator', 'applications/phame/storage/post');
15+
phutil_require_module('phabricator', 'view/dialog');
16+
17+
phutil_require_module('phutil', 'utils');
18+
19+
20+
phutil_require_source('PhamePostDeleteController.php');

0 commit comments

Comments
 (0)