@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 PholioMockImagesView extends AphrontView {
4
5 private $mock;
6 private $imageID;
7 private $requestURI;
8 private $commentFormID;
9
10 private $panelID;
11 private $viewportID;
12 private $behaviorConfig;
13
14 public function setCommentFormID($comment_form_id) {
15 $this->commentFormID = $comment_form_id;
16 return $this;
17 }
18
19 public function getCommentFormID() {
20 return $this->commentFormID;
21 }
22
23 public function setRequestURI(PhutilURI $request_uri) {
24 $this->requestURI = $request_uri;
25 return $this;
26 }
27
28 public function getRequestURI() {
29 return $this->requestURI;
30 }
31
32 public function setImageID($image_id) {
33 $this->imageID = $image_id;
34 return $this;
35 }
36
37 public function getImageID() {
38 return $this->imageID;
39 }
40
41 public function setMock(PholioMock $mock) {
42 $this->mock = $mock;
43 return $this;
44 }
45
46 public function getMock() {
47 return $this->mock;
48 }
49
50 public function __construct() {
51 $this->panelID = celerity_generate_unique_node_id();
52 $this->viewportID = celerity_generate_unique_node_id();
53 }
54
55 public function getBehaviorConfig() {
56 if (!$this->getMock()) {
57 throw new PhutilInvalidStateException('setMock');
58 }
59
60 if ($this->behaviorConfig === null) {
61 $this->behaviorConfig = $this->calculateBehaviorConfig();
62 }
63 return $this->behaviorConfig;
64 }
65
66 private function calculateBehaviorConfig() {
67 $mock = $this->getMock();
68
69 // TODO: We could maybe do a better job with tailoring this, which is the
70 // image shown on the review stage.
71 $viewer = $this->getUser();
72
73 $default = PhabricatorFile::loadBuiltin($viewer, 'image-100x100.png');
74
75 $images = array();
76 $current_set = 0;
77 foreach ($mock->getImages() as $image) {
78 $file = $image->getFile();
79 $metadata = $file->getMetadata();
80 $x = idx($metadata, PhabricatorFile::METADATA_IMAGE_WIDTH);
81 $y = idx($metadata, PhabricatorFile::METADATA_IMAGE_HEIGHT);
82
83 $is_obs = (bool)$image->getIsObsolete();
84 if (!$is_obs) {
85 $current_set++;
86 }
87
88 $description = $image->getDescription();
89 if (strlen($description)) {
90 $description = new PHUIRemarkupView($viewer, $description);
91 }
92
93 $history_uri = '/pholio/image/history/'.$image->getID().'/';
94 $images[] = array(
95 'id' => $image->getID(),
96 'fullURI' => $file->getBestURI(),
97 'stageURI' => ($file->isViewableImage()
98 ? $file->getBestURI()
99 : $default->getBestURI()),
100 'pageURI' => $this->getImagePageURI($image, $mock),
101 'downloadURI' => $file->getDownloadURI(),
102 'historyURI' => $history_uri,
103 'width' => $x,
104 'height' => $y,
105 'title' => $image->getName(),
106 'descriptionMarkup' => hsprintf('%s', $description),
107 'isObsolete' => (bool)$image->getIsObsolete(),
108 'isImage' => $file->isViewableImage(),
109 'isViewable' => $file->isViewableInBrowser(),
110 );
111 }
112
113 $ids = mpull($mock->getActiveImages(), null, 'getID');
114 if ($this->imageID && isset($ids[$this->imageID])) {
115 $selected_id = $this->imageID;
116 } else {
117 $selected_id = head_key($ids);
118 }
119
120 $navsequence = array();
121 foreach ($mock->getActiveImages() as $image) {
122 $navsequence[] = $image->getID();
123 }
124
125 $full_icon = array(
126 javelin_tag('span', array('aural' => true), pht('View Raw File')),
127 id(new PHUIIconView())->setIcon('fa-file-image-o'),
128 );
129
130 $download_icon = array(
131 javelin_tag('span', array('aural' => true), pht('Download File')),
132 id(new PHUIIconView())->setIcon('fa-download'),
133 );
134
135 $login_uri = id(new PhutilURI('/login/'))
136 ->replaceQueryParam('next', (string)$this->getRequestURI());
137
138 $config = array(
139 'mockID' => $mock->getID(),
140 'panelID' => $this->panelID,
141 'viewportID' => $this->viewportID,
142 'commentFormID' => $this->getCommentFormID(),
143 'images' => $images,
144 'selectedID' => $selected_id,
145 'loggedIn' => $this->getUser()->isLoggedIn(),
146 'logInLink' => (string)$login_uri,
147 'navsequence' => $navsequence,
148 'fullIcon' => hsprintf('%s', $full_icon),
149 'downloadIcon' => hsprintf('%s', $download_icon),
150 'currentSetSize' => $current_set,
151 );
152 return $config;
153 }
154
155 public function render() {
156 if (!$this->getMock()) {
157 throw new PhutilInvalidStateException('setMock');
158 }
159 $mock = $this->getMock();
160
161 require_celerity_resource('javelin-behavior-pholio-mock-view');
162
163 $panel_id = $this->panelID;
164 $viewport_id = $this->viewportID;
165
166 $config = $this->getBehaviorConfig();
167 Javelin::initBehavior(
168 'pholio-mock-view',
169 $this->getBehaviorConfig());
170
171 $mock_wrapper = javelin_tag(
172 'div',
173 array(
174 'id' => $this->viewportID,
175 'sigil' => 'mock-viewport',
176 'class' => 'pholio-mock-image-viewport',
177 ),
178 '');
179
180 $image_header = javelin_tag(
181 'div',
182 array(
183 'id' => 'mock-image-header',
184 'class' => 'pholio-mock-image-header',
185 ),
186 '');
187
188 $mock_wrapper = javelin_tag(
189 'div',
190 array(
191 'id' => $this->panelID,
192 'sigil' => 'mock-panel touchable',
193 'class' => 'pholio-mock-image-panel',
194 ),
195 array(
196 $image_header,
197 $mock_wrapper,
198 ));
199
200 $inline_comments_holder = javelin_tag(
201 'div',
202 array(
203 'id' => 'mock-image-description',
204 'sigil' => 'mock-image-description',
205 'class' => 'mock-image-description',
206 ),
207 '');
208
209 return phutil_tag(
210 'div',
211 array(
212 'class' => 'pholio-mock-image-container',
213 'id' => 'pholio-mock-image-container',
214 ),
215 array($mock_wrapper, $inline_comments_holder));
216
217 }
218
219 private function getImagePageURI(PholioImage $image, PholioMock $mock) {
220 $uri = '/M'.$mock->getID().'/'.$image->getID().'/';
221 return $uri;
222 }
223}