@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<?php
2
3final class PhabricatorFeedBuilder extends Phobject {
4
5 private $user;
6 private $stories;
7 private $hovercards = false;
8 private $noDataString;
9
10 /**
11 * @param array<PhabricatorFeedStory> $stories
12 */
13 public function __construct(array $stories) {
14 assert_instances_of($stories, PhabricatorFeedStory::class);
15 $this->stories = $stories;
16 }
17
18 public function setUser(PhabricatorUser $user) {
19 $this->user = $user;
20 return $this;
21 }
22
23 public function setShowHovercards($hover) {
24 $this->hovercards = $hover;
25 return $this;
26 }
27
28 public function setNoDataString($string) {
29 $this->noDataString = $string;
30 return $this;
31 }
32
33 public function buildView() {
34 if (!$this->user) {
35 throw new PhutilInvalidStateException('setUser');
36 }
37
38 $user = $this->user;
39 $stories = $this->stories;
40
41 $null_view = new AphrontNullView();
42
43 $last_date = null;
44 foreach ($stories as $story) {
45 $story->setHovercard($this->hovercards);
46
47 $date = ucfirst(phabricator_relative_date($story->getEpoch(), $user));
48
49 if ($date !== $last_date) {
50 if ($last_date !== null) {
51 $null_view->appendChild(
52 phutil_tag_div('phabricator-feed-story-date-separator'));
53 }
54 $last_date = $date;
55 $header = new PHUIHeaderView();
56 $header->setHeader($date);
57 $header->setHeaderIcon('fa-calendar msr');
58
59 $null_view->appendChild($header);
60 }
61
62 try {
63 $view = $story->renderView();
64 $view->setViewer($user);
65 $view = $view->render();
66 } catch (Exception $ex) {
67 // If rendering failed for any reason, don't fail the entire feed,
68 // just this one story.
69 $view = id(new PHUIFeedStoryView())
70 ->setUser($user)
71 ->setChronologicalKey($story->getChronologicalKey())
72 ->setEpoch($story->getEpoch())
73 ->setTitle(
74 pht('Feed Story Failed to Render (%s)', get_class($story)))
75 ->appendChild(pht('%s: %s', get_class($ex), $ex->getMessage()));
76 }
77
78 $null_view->appendChild($view);
79 }
80
81 $box = id(new PHUIObjectBoxView())
82 ->appendChild($null_view);
83
84 if (empty($stories)) {
85 $nodatastring = pht('No Stories.');
86 if ($this->noDataString) {
87 $nodatastring = $this->noDataString;
88 }
89
90 $view = id(new PHUIBoxView())
91 ->addClass('mlt mlb msr msl')
92 ->appendChild($nodatastring);
93 $box->appendChild($view);
94 }
95
96 return $box;
97
98 }
99
100}