1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-19 12:00:55 +01:00

Add phame.post.search Conduit API endpoint

Summary: Ref T9897. Mostly straightforward, but also modernize/fixup the Query a little so that posts never load with no blog.

Test Plan: Queried posts via API.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9897

Differential Revision: https://secure.phabricator.com/D14901
This commit is contained in:
epriestley 2015-12-28 04:25:01 -08:00
parent b74f93f229
commit 00f1389f72
5 changed files with 125 additions and 63 deletions

View file

@ -3440,6 +3440,7 @@ phutil_register_library_map(array(
'PhamePostPublishController' => 'applications/phame/controller/post/PhamePostPublishController.php',
'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php',
'PhamePostReplyHandler' => 'applications/phame/mail/PhamePostReplyHandler.php',
'PhamePostSearchConduitAPIMethod' => 'applications/phame/conduit/PhamePostSearchConduitAPIMethod.php',
'PhamePostSearchEngine' => 'applications/phame/query/PhamePostSearchEngine.php',
'PhamePostTransaction' => 'applications/phame/storage/PhamePostTransaction.php',
'PhamePostTransactionComment' => 'applications/phame/storage/PhamePostTransactionComment.php',
@ -7886,6 +7887,7 @@ phutil_register_library_map(array(
'PhabricatorSubscribableInterface',
'PhabricatorDestructibleInterface',
'PhabricatorTokenReceiverInterface',
'PhabricatorConduitResultInterface',
),
'PhamePostCommentController' => 'PhamePostController',
'PhamePostController' => 'PhameController',
@ -7900,6 +7902,7 @@ phutil_register_library_map(array(
'PhamePostPublishController' => 'PhamePostController',
'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhamePostReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
'PhamePostSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'PhamePostSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhamePostTransaction' => 'PhabricatorApplicationTransaction',
'PhamePostTransactionComment' => 'PhabricatorApplicationTransactionComment',

View file

@ -0,0 +1,18 @@
<?php
final class PhamePostSearchConduitAPIMethod
extends PhabricatorSearchEngineAPIMethod {
public function getAPIMethodName() {
return 'phame.post.search';
}
public function newSearchEngine() {
return new PhamePostSearchEngine();
}
public function getMethodSummary() {
return pht('Read information about blog posts.');
}
}

View file

@ -39,38 +39,36 @@ final class PhamePostQuery extends PhabricatorCursorPagedPolicyAwareQuery {
return $this;
}
public function newResultObject() {
return new PhamePost();
}
protected function loadPage() {
$table = new PhamePost();
$conn_r = $table->establishConnection('r');
return $this->loadStandardPage($this->newResultObject());
}
$where_clause = $this->buildWhereClause($conn_r);
$order_clause = $this->buildOrderClause($conn_r);
$limit_clause = $this->buildLimitClause($conn_r);
protected function willFilterPage(array $posts) {
// We require blogs to do visibility checks, so load them unconditionally.
$blog_phids = mpull($posts, 'getBlogPHID');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T p %Q %Q %Q',
$table->getTableName(),
$where_clause,
$order_clause,
$limit_clause);
$blogs = id(new PhameBlogQuery())
->setViewer($this->getViewer())
->needProfileImage(true)
->withPHIDs($blog_phids)
->execute();
$posts = $table->loadAllFromArray($data);
$blogs = mpull($blogs, null, 'getPHID');
foreach ($posts as $key => $post) {
$blog_phid = $post->getBlogPHID();
if ($posts) {
// We require these to do visibility checks, so load them unconditionally.
$blog_phids = mpull($posts, 'getBlogPHID');
$blogs = id(new PhameBlogQuery())
->setViewer($this->getViewer())
->needProfileImage(true)
->withPHIDs($blog_phids)
->execute();
$blogs = mpull($blogs, null, 'getPHID');
foreach ($posts as $post) {
if (isset($blogs[$post->getBlogPHID()])) {
$post->setBlog($blogs[$post->getBlogPHID()]);
}
$blog = idx($blogs, $blog_phid);
if (!$blog) {
$this->didRejectResult($post);
unset($posts[$key]);
continue;
}
$post->attachBlog($blog);
}
return $posts;
@ -82,42 +80,42 @@ final class PhamePostQuery extends PhabricatorCursorPagedPolicyAwareQuery {
if ($this->ids) {
$where[] = qsprintf(
$conn,
'p.id IN (%Ld)',
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn,
'p.phid IN (%Ls)',
'phid IN (%Ls)',
$this->phids);
}
if ($this->bloggerPHIDs) {
$where[] = qsprintf(
$conn,
'p.bloggerPHID IN (%Ls)',
'bloggerPHID IN (%Ls)',
$this->bloggerPHIDs);
}
if ($this->visibility !== null) {
$where[] = qsprintf(
$conn,
'p.visibility = %d',
'visibility = %d',
$this->visibility);
}
if ($this->publishedAfter !== null) {
$where[] = qsprintf(
$conn,
'p.datePublished > %d',
'datePublished > %d',
$this->publishedAfter);
}
if ($this->blogPHIDs) {
if ($this->blogPHIDs !== null) {
$where[] = qsprintf(
$conn,
'p.blogPHID in (%Ls)',
'blogPHID in (%Ls)',
$this->blogPHIDs);
}

View file

@ -30,10 +30,11 @@ final class PhamePostSearchEngine
id(new PhabricatorSearchSelectField())
->setKey('visibility')
->setLabel(pht('Visibility'))
->setOptions(array(
'' => pht('All'),
PhameConstants::VISIBILITY_PUBLISHED => pht('Published'),
PhameConstants::VISIBILITY_DRAFT => pht('Draft'),
->setOptions(
array(
'' => pht('All'),
PhameConstants::VISIBILITY_PUBLISHED => pht('Published'),
PhameConstants::VISIBILITY_DRAFT => pht('Draft'),
)),
);
}
@ -68,6 +69,8 @@ final class PhamePostSearchEngine
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $posts,
PhabricatorSavedQuery $query,
@ -82,12 +85,10 @@ final class PhamePostSearchEngine
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]');
}
$blog_name = $viewer->renderHandle($post->getBlogPHID())->render();
$blog_name = pht('Blog: %s', $blog_name);
$item = id(new PHUIObjectItemView())
->setUser($viewer)
->setObject($post)

View file

@ -9,7 +9,8 @@ final class PhamePost extends PhameDAO
PhabricatorApplicationTransactionInterface,
PhabricatorSubscribableInterface,
PhabricatorDestructibleInterface,
PhabricatorTokenReceiverInterface {
PhabricatorTokenReceiverInterface,
PhabricatorConduitResultInterface {
const MARKUP_FIELD_BODY = 'markup:body';
const MARKUP_FIELD_SUMMARY = 'markup:summary';
@ -24,7 +25,7 @@ final class PhamePost extends PhameDAO
protected $blogPHID;
protected $mailKey;
private $blog;
private $blog = self::ATTACHABLE;
public static function initializePost(
PhabricatorUser $blogger,
@ -33,19 +34,20 @@ final class PhamePost extends PhameDAO
$post = id(new PhamePost())
->setBloggerPHID($blogger->getPHID())
->setBlogPHID($blog->getPHID())
->setBlog($blog)
->attachBlog($blog)
->setDatePublished(PhabricatorTime::getNow())
->setVisibility(PhameConstants::VISIBILITY_PUBLISHED);
return $post;
}
public function setBlog(PhameBlog $blog) {
public function attachBlog(PhameBlog $blog) {
$this->blog = $blog;
return $this;
}
public function getBlog() {
return $this->blog;
return $this->assertAttached($this->blog);
}
public function getLiveURI() {
@ -146,21 +148,6 @@ final class PhamePost extends PhameDAO
return PhabricatorSlug::normalizeProjectSlug($this->getTitle(), true);
}
public function toDictionary() {
return array(
'id' => $this->getID(),
'phid' => $this->getPHID(),
'blogPHID' => $this->getBlogPHID(),
'bloggerPHID' => $this->getBloggerPHID(),
'viewURI' => $this->getViewURI(),
'title' => $this->getTitle(),
'body' => $this->getBody(),
'summary' => PhabricatorMarkupEngine::summarize($this->getBody()),
'datePublished' => $this->getDatePublished(),
'published' => !$this->isDraft(),
);
}
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
@ -303,4 +290,59 @@ final class PhamePost extends PhameDAO
return true;
}
/* -( PhabricatorConduitResultInterface )---------------------------------- */
public function getFieldSpecificationsForConduit() {
return array(
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('title')
->setType('string')
->setDescription(pht('Title of the post.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('slug')
->setType('string')
->setDescription(pht('Slug for the post.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('blogPHID')
->setType('phid')
->setDescription(pht('PHID of the blog that the post belongs to.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('authorPHID')
->setType('phid')
->setDescription(pht('PHID of the author of the post.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('body')
->setType('string')
->setDescription(pht('Body of the post.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('datePublished')
->setType('epoch?')
->setDescription(pht('Publish date, if the post has been published.')),
);
}
public function getFieldValuesForConduit() {
if ($this->isDraft()) {
$date_published = null;
} else {
$date_published = (int)$this->getDatePublished();
}
return array(
'title' => $this->getTitle(),
'slug' => $this->getSlug(),
'blogPHID' => $this->getBlogPHID(),
'authorPHID' => $this->getBloggerPHID(),
'body' => $this->getBody(),
'datePublished' => $date_published,
);
}
public function getConduitSearchAttachments() {
return array();
}
}