@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+125 -63
+3
src/__phutil_library_map__.php
··· 3440 3440 'PhamePostPublishController' => 'applications/phame/controller/post/PhamePostPublishController.php', 3441 3441 'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php', 3442 3442 'PhamePostReplyHandler' => 'applications/phame/mail/PhamePostReplyHandler.php', 3443 + 'PhamePostSearchConduitAPIMethod' => 'applications/phame/conduit/PhamePostSearchConduitAPIMethod.php', 3443 3444 'PhamePostSearchEngine' => 'applications/phame/query/PhamePostSearchEngine.php', 3444 3445 'PhamePostTransaction' => 'applications/phame/storage/PhamePostTransaction.php', 3445 3446 'PhamePostTransactionComment' => 'applications/phame/storage/PhamePostTransactionComment.php', ··· 7886 7887 'PhabricatorSubscribableInterface', 7887 7888 'PhabricatorDestructibleInterface', 7888 7889 'PhabricatorTokenReceiverInterface', 7890 + 'PhabricatorConduitResultInterface', 7889 7891 ), 7890 7892 'PhamePostCommentController' => 'PhamePostController', 7891 7893 'PhamePostController' => 'PhameController', ··· 7900 7902 'PhamePostPublishController' => 'PhamePostController', 7901 7903 'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 7902 7904 'PhamePostReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 7905 + 'PhamePostSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 7903 7906 'PhamePostSearchEngine' => 'PhabricatorApplicationSearchEngine', 7904 7907 'PhamePostTransaction' => 'PhabricatorApplicationTransaction', 7905 7908 'PhamePostTransactionComment' => 'PhabricatorApplicationTransactionComment',
+18
src/applications/phame/conduit/PhamePostSearchConduitAPIMethod.php
··· 1 + <?php 2 + 3 + final class PhamePostSearchConduitAPIMethod 4 + extends PhabricatorSearchEngineAPIMethod { 5 + 6 + public function getAPIMethodName() { 7 + return 'phame.post.search'; 8 + } 9 + 10 + public function newSearchEngine() { 11 + return new PhamePostSearchEngine(); 12 + } 13 + 14 + public function getMethodSummary() { 15 + return pht('Read information about blog posts.'); 16 + } 17 + 18 + }
+31 -33
src/applications/phame/query/PhamePostQuery.php
··· 39 39 return $this; 40 40 } 41 41 42 + public function newResultObject() { 43 + return new PhamePost(); 44 + } 45 + 42 46 protected function loadPage() { 43 - $table = new PhamePost(); 44 - $conn_r = $table->establishConnection('r'); 47 + return $this->loadStandardPage($this->newResultObject()); 48 + } 45 49 46 - $where_clause = $this->buildWhereClause($conn_r); 47 - $order_clause = $this->buildOrderClause($conn_r); 48 - $limit_clause = $this->buildLimitClause($conn_r); 50 + protected function willFilterPage(array $posts) { 51 + // We require blogs to do visibility checks, so load them unconditionally. 52 + $blog_phids = mpull($posts, 'getBlogPHID'); 49 53 50 - $data = queryfx_all( 51 - $conn_r, 52 - 'SELECT * FROM %T p %Q %Q %Q', 53 - $table->getTableName(), 54 - $where_clause, 55 - $order_clause, 56 - $limit_clause); 54 + $blogs = id(new PhameBlogQuery()) 55 + ->setViewer($this->getViewer()) 56 + ->needProfileImage(true) 57 + ->withPHIDs($blog_phids) 58 + ->execute(); 57 59 58 - $posts = $table->loadAllFromArray($data); 60 + $blogs = mpull($blogs, null, 'getPHID'); 61 + foreach ($posts as $key => $post) { 62 + $blog_phid = $post->getBlogPHID(); 59 63 60 - if ($posts) { 61 - // We require these to do visibility checks, so load them unconditionally. 62 - $blog_phids = mpull($posts, 'getBlogPHID'); 63 - $blogs = id(new PhameBlogQuery()) 64 - ->setViewer($this->getViewer()) 65 - ->needProfileImage(true) 66 - ->withPHIDs($blog_phids) 67 - ->execute(); 68 - $blogs = mpull($blogs, null, 'getPHID'); 69 - foreach ($posts as $post) { 70 - if (isset($blogs[$post->getBlogPHID()])) { 71 - $post->setBlog($blogs[$post->getBlogPHID()]); 72 - } 64 + $blog = idx($blogs, $blog_phid); 65 + if (!$blog) { 66 + $this->didRejectResult($post); 67 + unset($posts[$key]); 68 + continue; 73 69 } 70 + 71 + $post->attachBlog($blog); 74 72 } 75 73 76 74 return $posts; ··· 82 80 if ($this->ids) { 83 81 $where[] = qsprintf( 84 82 $conn, 85 - 'p.id IN (%Ld)', 83 + 'id IN (%Ld)', 86 84 $this->ids); 87 85 } 88 86 89 87 if ($this->phids) { 90 88 $where[] = qsprintf( 91 89 $conn, 92 - 'p.phid IN (%Ls)', 90 + 'phid IN (%Ls)', 93 91 $this->phids); 94 92 } 95 93 96 94 if ($this->bloggerPHIDs) { 97 95 $where[] = qsprintf( 98 96 $conn, 99 - 'p.bloggerPHID IN (%Ls)', 97 + 'bloggerPHID IN (%Ls)', 100 98 $this->bloggerPHIDs); 101 99 } 102 100 103 101 if ($this->visibility !== null) { 104 102 $where[] = qsprintf( 105 103 $conn, 106 - 'p.visibility = %d', 104 + 'visibility = %d', 107 105 $this->visibility); 108 106 } 109 107 110 108 if ($this->publishedAfter !== null) { 111 109 $where[] = qsprintf( 112 110 $conn, 113 - 'p.datePublished > %d', 111 + 'datePublished > %d', 114 112 $this->publishedAfter); 115 113 } 116 114 117 - if ($this->blogPHIDs) { 115 + if ($this->blogPHIDs !== null) { 118 116 $where[] = qsprintf( 119 117 $conn, 120 - 'p.blogPHID in (%Ls)', 118 + 'blogPHID in (%Ls)', 121 119 $this->blogPHIDs); 122 120 } 123 121
+11 -10
src/applications/phame/query/PhamePostSearchEngine.php
··· 30 30 id(new PhabricatorSearchSelectField()) 31 31 ->setKey('visibility') 32 32 ->setLabel(pht('Visibility')) 33 - ->setOptions(array( 34 - '' => pht('All'), 35 - PhameConstants::VISIBILITY_PUBLISHED => pht('Published'), 36 - PhameConstants::VISIBILITY_DRAFT => pht('Draft'), 33 + ->setOptions( 34 + array( 35 + '' => pht('All'), 36 + PhameConstants::VISIBILITY_PUBLISHED => pht('Published'), 37 + PhameConstants::VISIBILITY_DRAFT => pht('Draft'), 37 38 )), 38 39 ); 39 40 } ··· 68 69 69 70 return parent::buildSavedQueryFromBuiltin($query_key); 70 71 } 72 + 73 + 71 74 protected function renderResultList( 72 75 array $posts, 73 76 PhabricatorSavedQuery $query, ··· 82 85 foreach ($posts as $post) { 83 86 $id = $post->getID(); 84 87 $blog = $post->getBlog(); 85 - if ($blog) { 86 - $blog_name = $viewer->renderHandle($post->getBlogPHID())->render(); 87 - $blog_name = pht('Blog: %s', $blog_name); 88 - } else { 89 - $blog_name = pht('[No Blog]'); 90 - } 88 + 89 + $blog_name = $viewer->renderHandle($post->getBlogPHID())->render(); 90 + $blog_name = pht('Blog: %s', $blog_name); 91 + 91 92 $item = id(new PHUIObjectItemView()) 92 93 ->setUser($viewer) 93 94 ->setObject($post)
+62 -20
src/applications/phame/storage/PhamePost.php
··· 9 9 PhabricatorApplicationTransactionInterface, 10 10 PhabricatorSubscribableInterface, 11 11 PhabricatorDestructibleInterface, 12 - PhabricatorTokenReceiverInterface { 12 + PhabricatorTokenReceiverInterface, 13 + PhabricatorConduitResultInterface { 13 14 14 15 const MARKUP_FIELD_BODY = 'markup:body'; 15 16 const MARKUP_FIELD_SUMMARY = 'markup:summary'; ··· 24 25 protected $blogPHID; 25 26 protected $mailKey; 26 27 27 - private $blog; 28 + private $blog = self::ATTACHABLE; 28 29 29 30 public static function initializePost( 30 31 PhabricatorUser $blogger, ··· 33 34 $post = id(new PhamePost()) 34 35 ->setBloggerPHID($blogger->getPHID()) 35 36 ->setBlogPHID($blog->getPHID()) 36 - ->setBlog($blog) 37 + ->attachBlog($blog) 37 38 ->setDatePublished(PhabricatorTime::getNow()) 38 39 ->setVisibility(PhameConstants::VISIBILITY_PUBLISHED); 40 + 39 41 return $post; 40 42 } 41 43 42 - public function setBlog(PhameBlog $blog) { 44 + public function attachBlog(PhameBlog $blog) { 43 45 $this->blog = $blog; 44 46 return $this; 45 47 } 46 48 47 49 public function getBlog() { 48 - return $this->blog; 50 + return $this->assertAttached($this->blog); 49 51 } 50 52 51 53 public function getLiveURI() { ··· 146 148 return PhabricatorSlug::normalizeProjectSlug($this->getTitle(), true); 147 149 } 148 150 149 - public function toDictionary() { 150 - return array( 151 - 'id' => $this->getID(), 152 - 'phid' => $this->getPHID(), 153 - 'blogPHID' => $this->getBlogPHID(), 154 - 'bloggerPHID' => $this->getBloggerPHID(), 155 - 'viewURI' => $this->getViewURI(), 156 - 'title' => $this->getTitle(), 157 - 'body' => $this->getBody(), 158 - 'summary' => PhabricatorMarkupEngine::summarize($this->getBody()), 159 - 'datePublished' => $this->getDatePublished(), 160 - 'published' => !$this->isDraft(), 161 - ); 162 - } 163 - 164 151 165 152 /* -( PhabricatorPolicyInterface Implementation )-------------------------- */ 166 153 ··· 301 288 302 289 public function shouldAllowSubscription($phid) { 303 290 return true; 291 + } 292 + 293 + 294 + /* -( PhabricatorConduitResultInterface )---------------------------------- */ 295 + 296 + 297 + public function getFieldSpecificationsForConduit() { 298 + return array( 299 + id(new PhabricatorConduitSearchFieldSpecification()) 300 + ->setKey('title') 301 + ->setType('string') 302 + ->setDescription(pht('Title of the post.')), 303 + id(new PhabricatorConduitSearchFieldSpecification()) 304 + ->setKey('slug') 305 + ->setType('string') 306 + ->setDescription(pht('Slug for the post.')), 307 + id(new PhabricatorConduitSearchFieldSpecification()) 308 + ->setKey('blogPHID') 309 + ->setType('phid') 310 + ->setDescription(pht('PHID of the blog that the post belongs to.')), 311 + id(new PhabricatorConduitSearchFieldSpecification()) 312 + ->setKey('authorPHID') 313 + ->setType('phid') 314 + ->setDescription(pht('PHID of the author of the post.')), 315 + id(new PhabricatorConduitSearchFieldSpecification()) 316 + ->setKey('body') 317 + ->setType('string') 318 + ->setDescription(pht('Body of the post.')), 319 + id(new PhabricatorConduitSearchFieldSpecification()) 320 + ->setKey('datePublished') 321 + ->setType('epoch?') 322 + ->setDescription(pht('Publish date, if the post has been published.')), 323 + 324 + ); 325 + } 326 + 327 + public function getFieldValuesForConduit() { 328 + if ($this->isDraft()) { 329 + $date_published = null; 330 + } else { 331 + $date_published = (int)$this->getDatePublished(); 332 + } 333 + 334 + return array( 335 + 'title' => $this->getTitle(), 336 + 'slug' => $this->getSlug(), 337 + 'blogPHID' => $this->getBlogPHID(), 338 + 'authorPHID' => $this->getBloggerPHID(), 339 + 'body' => $this->getBody(), 340 + 'datePublished' => $date_published, 341 + ); 342 + } 343 + 344 + public function getConduitSearchAttachments() { 345 + return array(); 304 346 } 305 347 306 348 }