Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/phame/application/PhabricatorPhameApplication.php b/src/applications/phame/application/PhabricatorPhameApplication.php
index 4fb907b929..2c2d749bc1 100644
--- a/src/applications/phame/application/PhabricatorPhameApplication.php
+++ b/src/applications/phame/application/PhabricatorPhameApplication.php
@@ -1,118 +1,119 @@
<?php
final class PhabricatorPhameApplication extends PhabricatorApplication {
public function getName() {
return pht('Phame');
}
public function getBaseURI() {
return '/phame/';
}
public function getFontIcon() {
return 'fa-star';
}
public function getShortDescription() {
return pht('Blog');
}
public function getTitleGlyph() {
return "\xe2\x9c\xa9";
}
public function getHelpDocumentationArticles(PhabricatorUser $viewer) {
return array(
array(
'name' => pht('Phame User Guide'),
'href' => PhabricatorEnv::getDoclink('Phame User Guide'),
),
);
}
public function isPrototype() {
return true;
}
public function getRoutes() {
return array(
'/phame/' => array(
'' => 'PhameHomeController',
'live/(?P<id>[^/]+)/(?P<more>.*)' => 'PhameBlogLiveController',
'post/' => array(
'(?:(?P<filter>draft|all)/)?' => 'PhamePostListController',
'(?:query/(?P<queryKey>[^/]+)/)?' => 'PhamePostListController',
'blogger/(?P<bloggername>[\w\.-_]+)/' => 'PhamePostListController',
'edit/(?:(?P<id>[^/]+)/)?' => 'PhamePostEditController',
'history/(?P<id>\d+)/' => 'PhamePostHistoryController',
'view/(?P<id>\d+)/' => 'PhamePostViewController',
+ 'view/(?P<id>\d+)/(?P<slug>[^/]+)/' => 'PhamePostViewController',
'publish/(?P<id>\d+)/' => 'PhamePostPublishController',
'preview/(?P<id>\d+)/' => 'PhamePostPreviewController',
'unpublish/(?P<id>\d+)/' => 'PhamePostUnpublishController',
'notlive/(?P<id>\d+)/' => 'PhamePostNotLiveController',
'preview/' => 'PhabricatorMarkupPreviewController',
'framed/(?P<id>\d+)/' => 'PhamePostFramedController',
'new/' => 'PhamePostNewController',
'move/(?P<id>\d+)/' => 'PhamePostMoveController',
'comment/(?P<id>[1-9]\d*)/' => 'PhamePostCommentController',
),
'blog/' => array(
'(?:(?P<filter>user|all)/)?' => 'PhameBlogListController',
'(?:query/(?P<queryKey>[^/]+)/)?' => 'PhameBlogListController',
'archive/(?P<id>[^/]+)/' => 'PhameBlogArchiveController',
'edit/(?P<id>[^/]+)/' => 'PhameBlogEditController',
'view/(?P<id>[^/]+)/' => 'PhameBlogViewController',
'manage/(?P<id>[^/]+)/' => 'PhameBlogManageController',
'feed/(?P<id>[^/]+)/' => 'PhameBlogFeedController',
'new/' => 'PhameBlogEditController',
'picture/(?P<id>[1-9]\d*)/' => 'PhameBlogProfilePictureController',
),
) + $this->getResourceSubroutes(),
);
}
public function getResourceRoutes() {
return array(
'/phame/' => $this->getResourceSubroutes(),
);
}
private function getResourceSubroutes() {
return array(
'r/(?P<id>\d+)/(?P<hash>[^/]+)/(?P<name>.*)' =>
'PhameResourceController',
);
}
public function getBlogRoutes() {
return array(
'/(?P<more>.*)' => 'PhameBlogLiveController',
);
}
public function getBlogCDNRoutes() {
return array(
'/phame/' => array(
'r/(?P<id>\d+)/(?P<hash>[^/]+)/(?P<name>.*)' =>
'PhameResourceController',
),
);
}
public function getQuicksandURIPatternBlacklist() {
return array(
'/phame/live/.*',
);
}
protected function getCustomCapabilities() {
return array(
PhameBlogCreateCapability::CAPABILITY => array(
'default' => PhabricatorPolicies::POLICY_USER,
'caption' => pht('Default create policy for blogs.'),
),
);
}
}
diff --git a/src/applications/phame/controller/blog/PhameBlogFeedController.php b/src/applications/phame/controller/blog/PhameBlogFeedController.php
index b74465ef5e..b8b47c019f 100644
--- a/src/applications/phame/controller/blog/PhameBlogFeedController.php
+++ b/src/applications/phame/controller/blog/PhameBlogFeedController.php
@@ -1,98 +1,98 @@
<?php
final class PhameBlogFeedController extends PhameBlogController {
public function shouldRequireLogin() {
return false;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$blog = id(new PhameBlogQuery())
->setViewer($viewer)
->withIDs(array($id))
->executeOne();
if (!$blog) {
return new Aphront404Response();
}
$posts = id(new PhamePostQuery())
->setViewer($viewer)
->withBlogPHIDs(array($blog->getPHID()))
->withVisibility(PhameConstants::VISIBILITY_PUBLISHED)
->execute();
$blog_uri = PhabricatorEnv::getProductionURI(
$this->getApplicationURI('blog/feed/'.$blog->getID().'/'));
$content = array();
$content[] = phutil_tag('title', array(), $blog->getName());
$content[] = phutil_tag('id', array(), $blog_uri);
$content[] = phutil_tag('link',
array(
'rel' => 'self',
'type' => 'application/atom+xml',
'href' => $blog_uri,
));
$updated = $blog->getDateModified();
if ($posts) {
$updated = max($updated, max(mpull($posts, 'getDateModified')));
}
$content[] = phutil_tag('updated', array(), date('c', $updated));
$description = $blog->getDescription();
if ($description != '') {
$content[] = phutil_tag('subtitle', array(), $description);
}
$engine = id(new PhabricatorMarkupEngine())->setViewer($viewer);
foreach ($posts as $post) {
$engine->addObject($post, PhamePost::MARKUP_FIELD_BODY);
}
$engine->process();
$blogger_phids = mpull($posts, 'getBloggerPHID');
$bloggers = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs($blogger_phids)
->execute();
foreach ($posts as $post) {
$content[] = hsprintf('<entry>');
$content[] = phutil_tag('title', array(), $post->getTitle());
- $content[] = phutil_tag('link', array('href' => $post->getViewURI()));
+ $content[] = phutil_tag('link', array('href' => $post->getLiveURI()));
$content[] = phutil_tag('id', array(), PhabricatorEnv::getProductionURI(
'/phame/post/view/'.$post->getID().'/'));
$content[] = hsprintf(
'<author><name>%s</name></author>',
$bloggers[$post->getBloggerPHID()]->getFullName());
$content[] = phutil_tag(
'updated',
array(),
date('c', $post->getDateModified()));
$content[] = hsprintf(
'<content type="xhtml">'.
'<div xmlns="http://www.w3.org/1999/xhtml">%s</div>'.
'</content>',
$engine->getOutput($post, PhamePost::MARKUP_FIELD_BODY));
$content[] = hsprintf('</entry>');
}
$content = phutil_tag(
'feed',
array('xmlns' => 'http://www.w3.org/2005/Atom'),
$content);
return id(new AphrontFileResponse())
->setMimeType('application/xml')
->setContent($content);
}
}
diff --git a/src/applications/phame/controller/post/PhamePostEditController.php b/src/applications/phame/controller/post/PhamePostEditController.php
index a6bf1732fb..9672150ab2 100644
--- a/src/applications/phame/controller/post/PhamePostEditController.php
+++ b/src/applications/phame/controller/post/PhamePostEditController.php
@@ -1,210 +1,219 @@
<?php
final class PhamePostEditController extends PhamePostController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb(
+ pht('Blogs'),
+ $this->getApplicationURI('blog/'));
if ($id) {
$post = id(new PhamePostQuery())
->setViewer($viewer)
->withIDs(array($id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$post) {
return new Aphront404Response();
}
$cancel_uri = $this->getApplicationURI('/post/view/'.$id.'/');
$submit_button = pht('Save Changes');
$page_title = pht('Edit Post');
$v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs(
$post->getPHID(),
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
$v_projects = array_reverse($v_projects);
$v_cc = PhabricatorSubscribersQuery::loadSubscribersForPHID(
$post->getPHID());
+ $blog = $post->getBlog();
+
+
} else {
$blog = id(new PhameBlogQuery())
->setViewer($viewer)
->withIDs(array($request->getInt('blog')))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$blog) {
return new Aphront404Response();
}
$v_projects = array();
$v_cc = array();
$post = PhamePost::initializePost($viewer, $blog);
$cancel_uri = $this->getApplicationURI('/blog/view/'.$blog->getID().'/');
$submit_button = pht('Create Post');
$page_title = pht('Create Post');
}
$title = $post->getTitle();
$phame_title = $post->getPhameTitle();
$body = $post->getBody();
$visibility = $post->getVisibility();
$e_title = true;
$e_phame_title = true;
$validation_exception = null;
if ($request->isFormPost()) {
$title = $request->getStr('title');
$phame_title = $request->getStr('phame_title');
$phame_title = PhabricatorSlug::normalize($phame_title);
$body = $request->getStr('body');
$v_projects = $request->getArr('projects');
$v_cc = $request->getArr('cc');
$visibility = $request->getInt('visibility');
$xactions = array(
id(new PhamePostTransaction())
->setTransactionType(PhamePostTransaction::TYPE_TITLE)
->setNewValue($title),
id(new PhamePostTransaction())
->setTransactionType(PhamePostTransaction::TYPE_PHAME_TITLE)
->setNewValue($phame_title),
id(new PhamePostTransaction())
->setTransactionType(PhamePostTransaction::TYPE_BODY)
->setNewValue($body),
id(new PhamePostTransaction())
->setTransactionType(PhamePostTransaction::TYPE_VISIBILITY)
->setNewValue($visibility),
id(new PhamePostTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setNewValue(array('=' => $v_cc)),
);
$proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$xactions[] = id(new PhamePostTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $proj_edge_type)
->setNewValue(array('=' => array_fuse($v_projects)));
$editor = id(new PhamePostEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true);
try {
$editor->applyTransactions($post, $xactions);
- $uri = $this->getApplicationURI('/post/view/'.$post->getID().'/');
+ $uri = $post->getViewURI();
return id(new AphrontRedirectResponse())->setURI($uri);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$e_title = $validation_exception->getShortMessage(
PhamePostTransaction::TYPE_TITLE);
$e_phame_title = $validation_exception->getShortMessage(
PhamePostTransaction::TYPE_PHAME_TITLE);
}
}
$handle = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(array($post->getBlogPHID()))
->executeOne();
$form = id(new AphrontFormView())
->setUser($viewer)
->addHiddenInput('blog', $request->getInt('blog'))
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Blog'))
->setValue($handle->renderLink()))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Title'))
->setName('title')
->setValue($title)
->setID('post-title')
->setError($e_title))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Phame Title'))
->setName('phame_title')
->setValue(rtrim($phame_title, '/'))
->setID('post-phame-title')
->setCaption(pht('Up to 64 alphanumeric characters '.
'with underscores for spaces.'))
->setError($e_phame_title))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Visibility'))
->setName('visibility')
->setValue($visibility)
->setOptions(PhameConstants::getPhamePostStatusMap()))
->appendChild(
id(new PhabricatorRemarkupControl())
->setLabel(pht('Body'))
->setName('body')
->setValue($body)
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
->setID('post-body')
->setUser($viewer)
->setDisableMacros(true))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Subscribers'))
->setName('cc')
->setValue($v_cc)
->setUser($viewer)
->setDatasource(new PhabricatorMetaMTAMailableDatasource()))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Projects'))
->setName('projects')
->setValue($v_projects)
->setDatasource(new PhabricatorProjectDatasource()))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton($cancel_uri)
->setValue($submit_button));
$preview = id(new PHUIRemarkupPreviewPanel())
->setHeader($post->getTitle())
->setPreviewURI($this->getApplicationURI('post/preview/'))
->setControlID('post-body')
->setPreviewType(PHUIRemarkupPreviewPanel::DOCUMENT);
Javelin::initBehavior(
'phame-post-preview',
array(
'title' => 'post-title',
'phame_title' => 'post-phame-title',
));
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($page_title)
->setValidationException($validation_exception)
->setForm($form);
- $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb(
+ $blog->getName(),
+ $blog->getViewURI());
$crumbs->addTextCrumb(
$page_title,
- $this->getApplicationURI('/post/view/'.$id.'/'));
+ $cancel_uri);
return $this->newPage()
->setTitle($page_title)
->setCrumbs($crumbs)
->appendChild(
array(
$form_box,
$preview,
));
}
}
diff --git a/src/applications/phame/controller/post/PhamePostNotLiveController.php b/src/applications/phame/controller/post/PhamePostNotLiveController.php
index c0f986ffda..f09759e801 100644
--- a/src/applications/phame/controller/post/PhamePostNotLiveController.php
+++ b/src/applications/phame/controller/post/PhamePostNotLiveController.php
@@ -1,52 +1,45 @@
<?php
final class PhamePostNotLiveController extends PhamePostController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$post = id(new PhamePostQuery())
->setViewer($viewer)
->withIDs(array($id))
->executeOne();
if (!$post) {
return new Aphront404Response();
}
$reasons = array();
- if (!$post->getBlog()) {
- $reasons[] = phutil_tag('p', array(), pht(
- 'You can not view the live version of this post because it '.
- 'is not associated with a blog. Move the post to a blog in order to '.
- 'view it live.'));
- }
-
if ($post->isDraft()) {
$reasons[] = phutil_tag('p', array(), pht(
'You can not view the live version of this post because it '.
- 'is still a draft. Use "Preview/Publish" to publish the post.'));
+ 'is still a draft. Use "Preview" or "Publish" to publish the post.'));
}
if ($reasons) {
$cancel_uri = $this->getApplicationURI('/post/view/'.$post->getID().'/');
$dialog = id(new AphrontDialogView())
->setUser($viewer)
->setTitle(pht('Post Not Live'))
->addCancelButton($cancel_uri);
foreach ($reasons as $reason) {
$dialog->appendChild($reason);
}
return id(new AphrontDialogResponse())->setDialog($dialog);
}
// No reason this can't go live, maybe an old link. Kick them live and see
// what happens.
- $live_uri = $post->getViewURI();
+ $live_uri = $post->getLiveURI();
return id(new AphrontRedirectResponse())->setURI($live_uri);
}
}
diff --git a/src/applications/phame/controller/post/PhamePostViewController.php b/src/applications/phame/controller/post/PhamePostViewController.php
index 89541de268..c3a1da5026 100644
--- a/src/applications/phame/controller/post/PhamePostViewController.php
+++ b/src/applications/phame/controller/post/PhamePostViewController.php
@@ -1,259 +1,253 @@
<?php
final class PhamePostViewController extends PhamePostController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$moved = $request->getStr('moved');
$post = id(new PhamePostQuery())
->setViewer($viewer)
->withIDs(array($request->getURIData('id')))
->executeOne();
if (!$post) {
return new Aphront404Response();
}
$blog = $post->getBlog();
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
pht('Blogs'),
$this->getApplicationURI('blog/'));
- if ($blog) {
- $crumbs->addTextCrumb(
- $blog->getName(),
- $this->getApplicationURI('blog/view/'.$blog->getID().'/'));
- } else {
- $crumbs->addTextCrumb(
- pht('[No Blog]'),
- null);
- }
+ $crumbs->addTextCrumb(
+ $blog->getName(),
+ $this->getApplicationURI('blog/view/'.$blog->getID().'/'));
$crumbs->addTextCrumb(
$post->getTitle(),
$this->getApplicationURI('post/view/'.$post->getID().'/'));
$crumbs->setBorder(true);
$actions = $this->renderActions($post, $viewer);
$action_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Actions'))
->setHref('#')
->setIconFont('fa-bars')
->addClass('phui-mobile-menu')
->setDropdownMenu($actions);
$header = id(new PHUIHeaderView())
->setHeader($post->getTitle())
->setUser($viewer)
->setPolicyObject($post)
->addActionLink($action_button);
$document = id(new PHUIDocumentViewPro())
->setHeader($header);
if ($moved) {
$document->appendChild(
id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->appendChild(pht('Post moved successfully.')));
}
if ($post->isDraft()) {
$document->appendChild(
id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->setTitle(pht('Draft Post'))
->appendChild(
pht(
'Only you can see this draft until you publish it. '.
'Use "Preview or Publish" to publish this post.')));
}
if (!$post->getBlog()) {
$document->appendChild(
id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
->setTitle(pht('Not On A Blog'))
->appendChild(
pht(
'This post is not associated with a blog (the blog may have '.
'been deleted). Use "Move Post" to move it to a new blog.')));
}
$engine = id(new PhabricatorMarkupEngine())
->setViewer($viewer)
->addObject($post, PhamePost::MARKUP_FIELD_BODY)
->process();
$document->appendChild(
phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup',
),
$engine->getOutput($post, PhamePost::MARKUP_FIELD_BODY)));
$blogger = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withPHIDs(array($post->getBloggerPHID()))
->needProfileImage(true)
->executeOne();
$blogger_profile = $blogger->loadUserProfile();
$author = phutil_tag(
'a',
array(
'href' => '/p/'.$blogger->getUsername().'/',
),
$blogger->getUsername());
$date = phabricator_datetime($post->getDatePublished(), $viewer);
if ($post->isDraft()) {
$subtitle = pht('Unpublished draft by %s.', $author);
} else {
$subtitle = pht('Written by %s on %s.', $author, $date);
}
$about = id(new PhameDescriptionView())
->setTitle($subtitle)
->setDescription($blogger_profile->getTitle())
->setImage($blogger->getProfileImageURI())
->setImageHref('/p/'.$blogger->getUsername());
$timeline = $this->buildTransactionTimeline(
$post,
id(new PhamePostTransactionQuery())
->withTransactionTypes(array(PhabricatorTransactions::TYPE_COMMENT)));
$timeline = phutil_tag_div('phui-document-view-pro-box', $timeline);
$add_comment = $this->buildCommentForm($post);
$add_comment = phutil_tag_div('mlb mlt', $add_comment);
$properties = id(new PHUIPropertyListView())
->setUser($viewer)
->setObject($post);
$properties->invokeWillRenderEvent();
return $this->newPage()
->setTitle($post->getTitle())
->setPageObjectPHIDs(array($post->getPHID()))
->setCrumbs($crumbs)
->appendChild(
array(
$document,
$about,
$properties,
$timeline,
$add_comment,
));
}
private function renderActions(
PhamePost $post,
PhabricatorUser $viewer) {
$actions = id(new PhabricatorActionListView())
->setObject($post)
->setObjectURI($this->getRequest()->getRequestURI())
->setUser($viewer);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$post,
PhabricatorPolicyCapability::CAN_EDIT);
$id = $post->getID();
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setHref($this->getApplicationURI('post/edit/'.$id.'/'))
->setName(pht('Edit Post'))
->setDisabled(!$can_edit));
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-arrows')
->setHref($this->getApplicationURI('post/move/'.$id.'/'))
->setName(pht('Move Post'))
->setDisabled(!$can_edit)
->setWorkflow(true));
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-history')
->setHref($this->getApplicationURI('post/history/'.$id.'/'))
->setName(pht('View History')));
if ($post->isDraft()) {
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-eye')
->setHref($this->getApplicationURI('post/publish/'.$id.'/'))
->setDisabled(!$can_edit)
->setName(pht('Publish'))
->setWorkflow(true));
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-eye')
->setHref($this->getApplicationURI('post/preview/'.$id.'/'))
->setDisabled(!$can_edit)
->setName(pht('Preview in Skin')));
} else {
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-eye-slash')
->setHref($this->getApplicationURI('post/unpublish/'.$id.'/'))
->setName(pht('Unpublish'))
->setDisabled(!$can_edit)
->setWorkflow(true));
}
$blog = $post->getBlog();
$can_view_live = $blog && !$post->isDraft();
if ($can_view_live) {
$live_uri = $blog->getLiveURI($post);
} else {
$live_uri = 'post/notlive/'.$post->getID().'/';
$live_uri = $this->getApplicationURI($live_uri);
}
$actions->addAction(
id(new PhabricatorActionView())
->setUser($viewer)
->setIcon('fa-globe')
->setHref($live_uri)
->setName(pht('View Live'))
->setDisabled(!$can_view_live)
->setWorkflow(!$can_view_live));
return $actions;
}
private function buildCommentForm(PhamePost $post) {
$viewer = $this->getViewer();
$draft = PhabricatorDraft::newFromUserAndKey(
$viewer, $post->getPHID());
$box = id(new PhabricatorApplicationTransactionCommentView())
->setUser($viewer)
->setObjectPHID($post->getPHID())
->setDraft($draft)
->setHeaderText(pht('Add Comment'))
->setAction($this->getApplicationURI('post/comment/'.$post->getID().'/'))
->setSubmitButtonName(pht('Add Comment'));
return phutil_tag_div('phui-document-view-pro-box', $box);
}
}
diff --git a/src/applications/phame/query/PhamePostSearchEngine.php b/src/applications/phame/query/PhamePostSearchEngine.php
index 68c94552bb..5002c84e0d 100644
--- a/src/applications/phame/query/PhamePostSearchEngine.php
+++ b/src/applications/phame/query/PhamePostSearchEngine.php
@@ -1,116 +1,116 @@
<?php
final class PhamePostSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Phame Posts');
}
public function getApplicationClassName() {
return 'PhabricatorPhameApplication';
}
public function newQuery() {
return new PhamePostQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if (strlen($map['visibility'])) {
$query->withVisibility($map['visibility']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchSelectField())
->setKey('visibility')
->setLabel(pht('Visibility'))
->setOptions(array(
'' => pht('All'),
PhameConstants::VISIBILITY_PUBLISHED => pht('Published'),
PhameConstants::VISIBILITY_DRAFT => pht('Draft'),
)),
);
}
protected function getURI($path) {
return '/phame/post/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Posts'),
'live' => pht('Published Posts'),
'draft' => pht('Draft Posts'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'live':
return $query->setParameter(
'visibility', PhameConstants::VISIBILITY_PUBLISHED);
case 'draft':
return $query->setParameter(
'visibility', PhameConstants::VISIBILITY_DRAFT);
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $posts,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($posts, 'PhamePost');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($posts as $post) {
$id = $post->getID();
$blog = $post->getBlog();
if ($blog) {
$blog_name = $viewer->renderHandle($post->getBlogPHID())->render();
$blog_name = pht('Blog: %s', $blog_name);
} else {
$blog_name = pht('[No Blog]');
}
$item = id(new PHUIObjectItemView())
->setUser($viewer)
->setObject($post)
->setHeader($post->getTitle())
->setStatusIcon('fa-star')
- ->setHref($this->getApplicationURI("/post/view/{$id}/"))
+ ->setHref($post->getViewURI())
->addAttribute($blog_name);
if ($post->isDraft()) {
$item->setStatusIcon('fa-star-o grey');
$item->setDisabled(true);
$item->addIcon('none', pht('Draft Post'));
} else {
$date = $post->getDatePublished();
$item->setEpoch($date);
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No blogs posts found.'));
return $result;
}
}
diff --git a/src/applications/phame/storage/PhamePost.php b/src/applications/phame/storage/PhamePost.php
index 3212f128b2..5fa74857c5 100644
--- a/src/applications/phame/storage/PhamePost.php
+++ b/src/applications/phame/storage/PhamePost.php
@@ -1,294 +1,299 @@
<?php
final class PhamePost extends PhameDAO
implements
PhabricatorPolicyInterface,
PhabricatorMarkupInterface,
PhabricatorFlaggableInterface,
PhabricatorProjectInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorSubscribableInterface,
PhabricatorDestructibleInterface,
PhabricatorTokenReceiverInterface {
const MARKUP_FIELD_BODY = 'markup:body';
const MARKUP_FIELD_SUMMARY = 'markup:summary';
protected $bloggerPHID;
protected $title;
protected $phameTitle;
protected $body;
protected $visibility;
protected $configData;
protected $datePublished;
protected $blogPHID;
protected $mailKey;
private $blog;
public static function initializePost(
PhabricatorUser $blogger,
PhameBlog $blog) {
$post = id(new PhamePost())
->setBloggerPHID($blogger->getPHID())
->setBlogPHID($blog->getPHID())
->setBlog($blog)
->setDatePublished(PhabricatorTime::getNow())
->setVisibility(PhameConstants::VISIBILITY_PUBLISHED);
return $post;
}
public function setBlog(PhameBlog $blog) {
$this->blog = $blog;
return $this;
}
public function getBlog() {
return $this->blog;
}
- public function getViewURI() {
+ public function getLiveURI() {
// go for the pretty uri if we can
$domain = ($this->blog ? $this->blog->getDomain() : '');
if ($domain) {
$phame_title = PhabricatorSlug::normalize($this->getPhameTitle());
return 'http://'.$domain.'/post/'.$phame_title;
}
$uri = '/phame/post/view/'.$this->getID().'/';
return PhabricatorEnv::getProductionURI($uri);
}
+ public function getViewURI() {
+ $phame_title = PhabricatorSlug::normalize($this->getPhameTitle());
+ return '/phame/post/view/'.$this->getID().'/'.$phame_title;
+ }
+
public function getEditURI() {
return '/phame/post/edit/'.$this->getID().'/';
}
public function isDraft() {
return $this->getVisibility() == PhameConstants::VISIBILITY_DRAFT;
}
public function getHumanName() {
if ($this->isDraft()) {
$name = 'draft';
} else {
$name = 'post';
}
return $name;
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'configData' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'title' => 'text255',
'phameTitle' => 'sort64',
'visibility' => 'uint32',
'mailKey' => 'bytes20',
// T6203/NULLABILITY
// These seem like they should always be non-null?
'blogPHID' => 'phid?',
'body' => 'text?',
'configData' => 'text?',
// T6203/NULLABILITY
// This one probably should be nullable?
'datePublished' => 'epoch',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
'phid' => array(
'columns' => array('phid'),
'unique' => true,
),
'phameTitle' => array(
'columns' => array('bloggerPHID', 'phameTitle'),
'unique' => true,
),
'bloggerPosts' => array(
'columns' => array(
'bloggerPHID',
'visibility',
'datePublished',
'id',
),
),
),
) + parent::getConfiguration();
}
public function save() {
if (!$this->getMailKey()) {
$this->setMailKey(Filesystem::readRandomCharacters(20));
}
return parent::save();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorPhamePostPHIDType::TYPECONST);
}
public function toDictionary() {
return array(
'id' => $this->getID(),
'phid' => $this->getPHID(),
'blogPHID' => $this->getBlogPHID(),
'bloggerPHID' => $this->getBloggerPHID(),
'viewURI' => $this->getViewURI(),
'title' => $this->getTitle(),
'phameTitle' => $this->getPhameTitle(),
'body' => $this->getBody(),
'summary' => PhabricatorMarkupEngine::summarize($this->getBody()),
'datePublished' => $this->getDatePublished(),
'published' => !$this->isDraft(),
);
}
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
// Draft posts are visible only to the author. Published posts are visible
// to whoever the blog is visible to.
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
if (!$this->isDraft() && $this->getBlog()) {
return $this->getBlog()->getViewPolicy();
} else if ($this->getBlog()) {
return $this->getBlog()->getEditPolicy();
} else {
return PhabricatorPolicies::POLICY_NOONE;
}
break;
case PhabricatorPolicyCapability::CAN_EDIT:
if ($this->getBlog()) {
return $this->getBlog()->getEditPolicy();
} else {
return PhabricatorPolicies::POLICY_NOONE;
}
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
// A blog post's author can always view it.
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
case PhabricatorPolicyCapability::CAN_EDIT:
return ($user->getPHID() == $this->getBloggerPHID());
}
}
public function describeAutomaticCapability($capability) {
return pht('The author of a blog post can always view and edit it.');
}
/* -( PhabricatorMarkupInterface Implementation )-------------------------- */
public function getMarkupFieldKey($field) {
$hash = PhabricatorHash::digest($this->getMarkupText($field));
return $this->getPHID().':'.$field.':'.$hash;
}
public function newMarkupEngine($field) {
return PhabricatorMarkupEngine::newPhameMarkupEngine();
}
public function getMarkupText($field) {
switch ($field) {
case self::MARKUP_FIELD_BODY:
return $this->getBody();
case self::MARKUP_FIELD_SUMMARY:
return PhabricatorMarkupEngine::summarize($this->getBody());
}
}
public function didMarkupText(
$field,
$output,
PhutilMarkupEngine $engine) {
return $output;
}
public function shouldUseMarkupCache($field) {
return (bool)$this->getPHID();
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhamePostEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new PhamePostTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$this->openTransaction();
$this->delete();
$this->saveTransaction();
}
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
public function getUsersToNotifyOfTokenGiven() {
return array(
$this->getBloggerPHID(),
);
}
/* -( PhabricatorSubscribableInterface Implementation )-------------------- */
public function isAutomaticallySubscribed($phid) {
return ($this->bloggerPHID == $phid);
}
public function shouldShowSubscribersProperty() {
return true;
}
public function shouldAllowSubscription($phid) {
return true;
}
}
diff --git a/src/applications/phame/view/PhamePostListView.php b/src/applications/phame/view/PhamePostListView.php
index e8272d81bf..aaa014c9dc 100644
--- a/src/applications/phame/view/PhamePostListView.php
+++ b/src/applications/phame/view/PhamePostListView.php
@@ -1,111 +1,111 @@
<?php
final class PhamePostListView extends AphrontTagView {
private $posts;
private $nodata;
private $viewer;
private $showBlog = false;
public function setPosts($posts) {
assert_instances_of($posts, 'PhamePost');
$this->posts = $posts;
return $this;
}
public function setNodata($nodata) {
$this->nodata = $nodata;
return $this;
}
public function showBlog($show) {
$this->showBlog = $show;
return $this;
}
public function setViewer($viewer) {
$this->viewer = $viewer;
return $this;
}
protected function getTagAttributes() {
return array();
}
protected function getTagContent() {
$viewer = $this->viewer;
$posts = $this->posts;
$nodata = $this->nodata;
$handle_phids = array();
foreach ($posts as $post) {
$handle_phids[] = $post->getBloggerPHID();
if ($post->getBlog()) {
$handle_phids[] = $post->getBlog()->getPHID();
}
}
$handles = $viewer->loadHandles($handle_phids);
$list = array();
foreach ($posts as $post) {
$blogger = $handles[$post->getBloggerPHID()]->renderLink();
$blogger_uri = $handles[$post->getBloggerPHID()]->getURI();
$blogger_image = $handles[$post->getBloggerPHID()]->getImageURI();
$phame_post = null;
if ($post->getBody()) {
$phame_post = PhabricatorMarkupEngine::summarize($post->getBody());
$phame_post = new PHUIRemarkupView($viewer, $phame_post);
} else {
$phame_post = phutil_tag('em', array(), pht('(Empty Post)'));
}
$blogger = phutil_tag('strong', array(), $blogger);
$date = phabricator_datetime($post->getDatePublished(), $viewer);
$blog = null;
if ($post->getBlog()) {
$blog = phutil_tag(
'a',
array(
'href' => '/phame/blog/view/'.$post->getBlog()->getID().'/',
),
$post->getBlog()->getName());
}
if ($this->showBlog && $blog) {
if ($post->isDraft()) {
$subtitle = pht('Unpublished draft by %s in %s.', $blogger, $blog);
} else {
$subtitle = pht('By %s on %s in %s.', $blogger, $date, $blog);
}
} else {
if ($post->isDraft()) {
$subtitle = pht('Unpublished draft by %s.', $blogger);
} else {
$subtitle = pht('Written by %s on %s.', $blogger, $date);
}
}
$item = id(new PHUIDocumentSummaryView())
->setTitle($post->getTitle())
- ->setHref('/phame/post/view/'.$post->getID().'/')
+ ->setHref($post->getViewURI())
->setSubtitle($subtitle)
->setImage($blogger_image)
->setImageHref($blogger_uri)
->setSummary($phame_post)
->setDraft($post->isDraft());
$list[] = $item;
}
if (empty($list)) {
$list = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NODATA)
->appendChild($nodata);
}
return $list;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Apr 28, 1:56 AM (7 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
107638
Default Alt Text
(40 KB)

Event Timeline