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:
parent
b74f93f229
commit
00f1389f72
5 changed files with 125 additions and 63 deletions
|
@ -3440,6 +3440,7 @@ phutil_register_library_map(array(
|
||||||
'PhamePostPublishController' => 'applications/phame/controller/post/PhamePostPublishController.php',
|
'PhamePostPublishController' => 'applications/phame/controller/post/PhamePostPublishController.php',
|
||||||
'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php',
|
'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php',
|
||||||
'PhamePostReplyHandler' => 'applications/phame/mail/PhamePostReplyHandler.php',
|
'PhamePostReplyHandler' => 'applications/phame/mail/PhamePostReplyHandler.php',
|
||||||
|
'PhamePostSearchConduitAPIMethod' => 'applications/phame/conduit/PhamePostSearchConduitAPIMethod.php',
|
||||||
'PhamePostSearchEngine' => 'applications/phame/query/PhamePostSearchEngine.php',
|
'PhamePostSearchEngine' => 'applications/phame/query/PhamePostSearchEngine.php',
|
||||||
'PhamePostTransaction' => 'applications/phame/storage/PhamePostTransaction.php',
|
'PhamePostTransaction' => 'applications/phame/storage/PhamePostTransaction.php',
|
||||||
'PhamePostTransactionComment' => 'applications/phame/storage/PhamePostTransactionComment.php',
|
'PhamePostTransactionComment' => 'applications/phame/storage/PhamePostTransactionComment.php',
|
||||||
|
@ -7886,6 +7887,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSubscribableInterface',
|
'PhabricatorSubscribableInterface',
|
||||||
'PhabricatorDestructibleInterface',
|
'PhabricatorDestructibleInterface',
|
||||||
'PhabricatorTokenReceiverInterface',
|
'PhabricatorTokenReceiverInterface',
|
||||||
|
'PhabricatorConduitResultInterface',
|
||||||
),
|
),
|
||||||
'PhamePostCommentController' => 'PhamePostController',
|
'PhamePostCommentController' => 'PhamePostController',
|
||||||
'PhamePostController' => 'PhameController',
|
'PhamePostController' => 'PhameController',
|
||||||
|
@ -7900,6 +7902,7 @@ phutil_register_library_map(array(
|
||||||
'PhamePostPublishController' => 'PhamePostController',
|
'PhamePostPublishController' => 'PhamePostController',
|
||||||
'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhamePostReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
|
'PhamePostReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
|
||||||
|
'PhamePostSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
|
||||||
'PhamePostSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'PhamePostSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
'PhamePostTransaction' => 'PhabricatorApplicationTransaction',
|
'PhamePostTransaction' => 'PhabricatorApplicationTransaction',
|
||||||
'PhamePostTransactionComment' => 'PhabricatorApplicationTransactionComment',
|
'PhamePostTransactionComment' => 'PhabricatorApplicationTransactionComment',
|
||||||
|
|
|
@ -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.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -39,38 +39,36 @@ final class PhamePostQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function newResultObject() {
|
||||||
|
return new PhamePost();
|
||||||
|
}
|
||||||
|
|
||||||
protected function loadPage() {
|
protected function loadPage() {
|
||||||
$table = new PhamePost();
|
return $this->loadStandardPage($this->newResultObject());
|
||||||
$conn_r = $table->establishConnection('r');
|
}
|
||||||
|
|
||||||
$where_clause = $this->buildWhereClause($conn_r);
|
protected function willFilterPage(array $posts) {
|
||||||
$order_clause = $this->buildOrderClause($conn_r);
|
// We require blogs to do visibility checks, so load them unconditionally.
|
||||||
$limit_clause = $this->buildLimitClause($conn_r);
|
$blog_phids = mpull($posts, 'getBlogPHID');
|
||||||
|
|
||||||
$data = queryfx_all(
|
$blogs = id(new PhameBlogQuery())
|
||||||
$conn_r,
|
->setViewer($this->getViewer())
|
||||||
'SELECT * FROM %T p %Q %Q %Q',
|
->needProfileImage(true)
|
||||||
$table->getTableName(),
|
->withPHIDs($blog_phids)
|
||||||
$where_clause,
|
->execute();
|
||||||
$order_clause,
|
|
||||||
$limit_clause);
|
|
||||||
|
|
||||||
$posts = $table->loadAllFromArray($data);
|
$blogs = mpull($blogs, null, 'getPHID');
|
||||||
|
foreach ($posts as $key => $post) {
|
||||||
|
$blog_phid = $post->getBlogPHID();
|
||||||
|
|
||||||
if ($posts) {
|
$blog = idx($blogs, $blog_phid);
|
||||||
// We require these to do visibility checks, so load them unconditionally.
|
if (!$blog) {
|
||||||
$blog_phids = mpull($posts, 'getBlogPHID');
|
$this->didRejectResult($post);
|
||||||
$blogs = id(new PhameBlogQuery())
|
unset($posts[$key]);
|
||||||
->setViewer($this->getViewer())
|
continue;
|
||||||
->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()]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$post->attachBlog($blog);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $posts;
|
return $posts;
|
||||||
|
@ -82,42 +80,42 @@ final class PhamePostQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
if ($this->ids) {
|
if ($this->ids) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'p.id IN (%Ld)',
|
'id IN (%Ld)',
|
||||||
$this->ids);
|
$this->ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->phids) {
|
if ($this->phids) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'p.phid IN (%Ls)',
|
'phid IN (%Ls)',
|
||||||
$this->phids);
|
$this->phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->bloggerPHIDs) {
|
if ($this->bloggerPHIDs) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'p.bloggerPHID IN (%Ls)',
|
'bloggerPHID IN (%Ls)',
|
||||||
$this->bloggerPHIDs);
|
$this->bloggerPHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->visibility !== null) {
|
if ($this->visibility !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'p.visibility = %d',
|
'visibility = %d',
|
||||||
$this->visibility);
|
$this->visibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->publishedAfter !== null) {
|
if ($this->publishedAfter !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'p.datePublished > %d',
|
'datePublished > %d',
|
||||||
$this->publishedAfter);
|
$this->publishedAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->blogPHIDs) {
|
if ($this->blogPHIDs !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'p.blogPHID in (%Ls)',
|
'blogPHID in (%Ls)',
|
||||||
$this->blogPHIDs);
|
$this->blogPHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,10 +30,11 @@ final class PhamePostSearchEngine
|
||||||
id(new PhabricatorSearchSelectField())
|
id(new PhabricatorSearchSelectField())
|
||||||
->setKey('visibility')
|
->setKey('visibility')
|
||||||
->setLabel(pht('Visibility'))
|
->setLabel(pht('Visibility'))
|
||||||
->setOptions(array(
|
->setOptions(
|
||||||
'' => pht('All'),
|
array(
|
||||||
PhameConstants::VISIBILITY_PUBLISHED => pht('Published'),
|
'' => pht('All'),
|
||||||
PhameConstants::VISIBILITY_DRAFT => pht('Draft'),
|
PhameConstants::VISIBILITY_PUBLISHED => pht('Published'),
|
||||||
|
PhameConstants::VISIBILITY_DRAFT => pht('Draft'),
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -68,6 +69,8 @@ final class PhamePostSearchEngine
|
||||||
|
|
||||||
return parent::buildSavedQueryFromBuiltin($query_key);
|
return parent::buildSavedQueryFromBuiltin($query_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function renderResultList(
|
protected function renderResultList(
|
||||||
array $posts,
|
array $posts,
|
||||||
PhabricatorSavedQuery $query,
|
PhabricatorSavedQuery $query,
|
||||||
|
@ -82,12 +85,10 @@ final class PhamePostSearchEngine
|
||||||
foreach ($posts as $post) {
|
foreach ($posts as $post) {
|
||||||
$id = $post->getID();
|
$id = $post->getID();
|
||||||
$blog = $post->getBlog();
|
$blog = $post->getBlog();
|
||||||
if ($blog) {
|
|
||||||
$blog_name = $viewer->renderHandle($post->getBlogPHID())->render();
|
$blog_name = $viewer->renderHandle($post->getBlogPHID())->render();
|
||||||
$blog_name = pht('Blog: %s', $blog_name);
|
$blog_name = pht('Blog: %s', $blog_name);
|
||||||
} else {
|
|
||||||
$blog_name = pht('[No Blog]');
|
|
||||||
}
|
|
||||||
$item = id(new PHUIObjectItemView())
|
$item = id(new PHUIObjectItemView())
|
||||||
->setUser($viewer)
|
->setUser($viewer)
|
||||||
->setObject($post)
|
->setObject($post)
|
||||||
|
|
|
@ -9,7 +9,8 @@ final class PhamePost extends PhameDAO
|
||||||
PhabricatorApplicationTransactionInterface,
|
PhabricatorApplicationTransactionInterface,
|
||||||
PhabricatorSubscribableInterface,
|
PhabricatorSubscribableInterface,
|
||||||
PhabricatorDestructibleInterface,
|
PhabricatorDestructibleInterface,
|
||||||
PhabricatorTokenReceiverInterface {
|
PhabricatorTokenReceiverInterface,
|
||||||
|
PhabricatorConduitResultInterface {
|
||||||
|
|
||||||
const MARKUP_FIELD_BODY = 'markup:body';
|
const MARKUP_FIELD_BODY = 'markup:body';
|
||||||
const MARKUP_FIELD_SUMMARY = 'markup:summary';
|
const MARKUP_FIELD_SUMMARY = 'markup:summary';
|
||||||
|
@ -24,7 +25,7 @@ final class PhamePost extends PhameDAO
|
||||||
protected $blogPHID;
|
protected $blogPHID;
|
||||||
protected $mailKey;
|
protected $mailKey;
|
||||||
|
|
||||||
private $blog;
|
private $blog = self::ATTACHABLE;
|
||||||
|
|
||||||
public static function initializePost(
|
public static function initializePost(
|
||||||
PhabricatorUser $blogger,
|
PhabricatorUser $blogger,
|
||||||
|
@ -33,19 +34,20 @@ final class PhamePost extends PhameDAO
|
||||||
$post = id(new PhamePost())
|
$post = id(new PhamePost())
|
||||||
->setBloggerPHID($blogger->getPHID())
|
->setBloggerPHID($blogger->getPHID())
|
||||||
->setBlogPHID($blog->getPHID())
|
->setBlogPHID($blog->getPHID())
|
||||||
->setBlog($blog)
|
->attachBlog($blog)
|
||||||
->setDatePublished(PhabricatorTime::getNow())
|
->setDatePublished(PhabricatorTime::getNow())
|
||||||
->setVisibility(PhameConstants::VISIBILITY_PUBLISHED);
|
->setVisibility(PhameConstants::VISIBILITY_PUBLISHED);
|
||||||
|
|
||||||
return $post;
|
return $post;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setBlog(PhameBlog $blog) {
|
public function attachBlog(PhameBlog $blog) {
|
||||||
$this->blog = $blog;
|
$this->blog = $blog;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBlog() {
|
public function getBlog() {
|
||||||
return $this->blog;
|
return $this->assertAttached($this->blog);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLiveURI() {
|
public function getLiveURI() {
|
||||||
|
@ -146,21 +148,6 @@ final class PhamePost extends PhameDAO
|
||||||
return PhabricatorSlug::normalizeProjectSlug($this->getTitle(), true);
|
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 )-------------------------- */
|
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
|
||||||
|
|
||||||
|
@ -303,4 +290,59 @@ final class PhamePost extends PhameDAO
|
||||||
return true;
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue