Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 77 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 1 |
TopicListFormatter | |
0.00% |
0 / 77 |
|
0.00% |
0 / 8 |
420 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setContentFormat | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
buildEmptyResult | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
formatApi | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
buildResult | |
0.00% |
0 / 30 |
|
0.00% |
0 / 1 |
90 | |||
buildApiActions | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
generateTopicMetadata | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
12 | |||
buildLinks | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | namespace Flow\Formatter; |
4 | |
5 | use Flow\Data\Pager\PagerPage; |
6 | use Flow\Model\UUID; |
7 | use Flow\Model\Workflow; |
8 | use Flow\UrlGenerator; |
9 | use MediaWiki\Context\IContextSource; |
10 | |
11 | class TopicListFormatter extends BaseTopicListFormatter { |
12 | /** |
13 | * @var UrlGenerator |
14 | */ |
15 | protected $urlGenerator; |
16 | |
17 | /** |
18 | * @var RevisionFormatter |
19 | */ |
20 | protected $serializer; |
21 | |
22 | public function __construct( UrlGenerator $urlGenerator, RevisionFormatter $serializer ) { |
23 | $this->urlGenerator = $urlGenerator; |
24 | $this->serializer = $serializer; |
25 | } |
26 | |
27 | public function setContentFormat( $contentFormat, ?UUID $revisionId = null ) { |
28 | $this->serializer->setContentFormat( $contentFormat, $revisionId ); |
29 | } |
30 | |
31 | public function buildEmptyResult( Workflow $workflow ) { |
32 | $title = $workflow->getArticleTitle(); |
33 | return [ |
34 | 'workflowId' => $workflow->getId()->getAlphadecimal(), |
35 | 'title' => $title->getPrefixedText(), |
36 | 'actions' => $this->buildApiActions( $workflow ), |
37 | 'links' => $this->buildLinks( $workflow ), |
38 | ] + parent::buildEmptyResult( $workflow ); |
39 | } |
40 | |
41 | public function formatApi( |
42 | Workflow $listWorkflow, |
43 | array $workflows, |
44 | array $found, |
45 | PagerPage $page, |
46 | IContextSource $ctx |
47 | ) { |
48 | $res = $this->buildResult( $workflows, $found, $ctx ) + |
49 | $this->buildEmptyResult( $listWorkflow ); |
50 | $pagingOption = $page->getPagingLinksOptions(); |
51 | $res['links']['pagination'] = $this->buildPaginationLinks( |
52 | $listWorkflow, |
53 | $pagingOption |
54 | ); |
55 | |
56 | return $res; |
57 | } |
58 | |
59 | /** |
60 | * Method is called from static::formatApi & ApiFlowSearch::formatApi, to ensure |
61 | * both have similar output. |
62 | * |
63 | * @param Workflow[] $workflows |
64 | * @param FormatterRow[] $found |
65 | * @param IContextSource $ctx |
66 | * @return array |
67 | */ |
68 | public function buildResult( array $workflows, array $found, IContextSource $ctx ) { |
69 | $revisions = $posts = $replies = []; |
70 | foreach ( $found as $formatterRow ) { |
71 | $serialized = $this->serializer->formatApi( $formatterRow, $ctx ); |
72 | if ( !$serialized ) { |
73 | continue; |
74 | } |
75 | $revisions[$serialized['revisionId']] = $serialized; |
76 | $posts[$serialized['postId']][] = $serialized['revisionId']; |
77 | $replies[$serialized['replyToId']][] = $serialized['postId']; |
78 | } |
79 | |
80 | foreach ( $revisions as $i => $serialized ) { |
81 | $alpha = $serialized['postId']; |
82 | $revisions[$i]['replies'] = $replies[$alpha] ?? []; |
83 | } |
84 | |
85 | $list = []; |
86 | if ( $workflows ) { |
87 | $orig = $workflows; |
88 | $workflows = []; |
89 | foreach ( $orig as $workflow ) { |
90 | $alpha = $workflow->getId()->getAlphadecimal(); |
91 | if ( isset( $posts[$alpha] ) ) { |
92 | $list[] = $alpha; |
93 | $workflows[$alpha] = $workflow; |
94 | } else { |
95 | wfDebugLog( 'Flow', __METHOD__ . ": No matching root post for workflow $alpha" ); |
96 | } |
97 | } |
98 | |
99 | foreach ( $list as $alpha ) { |
100 | // Metadata that requires everything to be serialied first |
101 | $metadata = $this->generateTopicMetadata( $posts, $revisions, $workflows, $alpha, $ctx ); |
102 | foreach ( $posts[$alpha] as $revId ) { |
103 | $revisions[$revId] += $metadata; |
104 | } |
105 | } |
106 | } |
107 | |
108 | return [ |
109 | // array_values must be used to ensure 0-indexed array |
110 | 'roots' => $list, |
111 | 'posts' => $posts, |
112 | 'revisions' => $revisions, |
113 | ]; |
114 | } |
115 | |
116 | /** |
117 | * @param Workflow $workflow |
118 | * @return array |
119 | */ |
120 | protected function buildApiActions( Workflow $workflow ) { |
121 | $actions = []; |
122 | |
123 | if ( !$workflow->isDeleted() ) { |
124 | $actions['newtopic'] = $this->urlGenerator->newTopicAction( $workflow->getArticleTitle() ); |
125 | } |
126 | |
127 | return $actions; |
128 | } |
129 | |
130 | protected function generateTopicMetadata( array $posts, array $revisions, array $workflows, $postAlphaId, IContextSource $ctx ) { |
131 | $language = $ctx->getLanguage(); |
132 | $user = $ctx->getUser(); |
133 | |
134 | $replies = -1; |
135 | $stack = new \SplStack; |
136 | $stack->push( $revisions[$posts[$postAlphaId][0]] ); |
137 | do { |
138 | $data = $stack->pop(); |
139 | $replies++; |
140 | foreach ( $data['replies'] as $postId ) { |
141 | $stack->push( $revisions[$posts[$postId][0]] ); |
142 | } |
143 | } while ( !$stack->isEmpty() ); |
144 | |
145 | /** @var Workflow|null $workflow */ |
146 | $workflow = $workflows[$postAlphaId] ?? null; |
147 | $ts = $workflow ? $workflow->getLastUpdatedObj()->getTimestamp() : 0; |
148 | return [ |
149 | 'reply_count' => $replies, |
150 | 'last_updated_readable' => $language->userTimeAndDate( $ts, $user ), |
151 | // ms timestamp |
152 | 'last_updated' => $ts * 1000, |
153 | ]; |
154 | } |
155 | |
156 | /** |
157 | * @param Workflow $workflow |
158 | * @return array |
159 | */ |
160 | private function buildLinks( Workflow $workflow ) { |
161 | $links = []; |
162 | |
163 | if ( !$workflow->isDeleted() ) { |
164 | $title = $workflow->getArticleTitle(); |
165 | $saveSortBy = true; |
166 | $links['board-sort']['updated'] = $this->urlGenerator->boardLink( $title, 'updated', $saveSortBy )->getLinkURL(); |
167 | $links['board-sort']['newest'] = $this->urlGenerator->boardLink( $title, 'newest', $saveSortBy )->getLinkURL(); |
168 | |
169 | // Link to designated new-topic page, for no-JS users |
170 | $links['newtopic'] = $this->urlGenerator->newTopicAction( $title, $workflow->getId() )->getLinkURL(); |
171 | } |
172 | |
173 | return $links; |
174 | } |
175 | } |