Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/files/document/render/PhabricatorDocumentRenderingEngine.php
12242 views
1
<?php
2
3
abstract class PhabricatorDocumentRenderingEngine
4
extends Phobject {
5
6
private $request;
7
private $controller;
8
private $activeEngine;
9
private $ref;
10
11
final public function setRequest(AphrontRequest $request) {
12
$this->request = $request;
13
return $this;
14
}
15
16
final public function getRequest() {
17
if (!$this->request) {
18
throw new PhutilInvalidStateException('setRequest');
19
}
20
21
return $this->request;
22
}
23
24
final public function setController(PhabricatorController $controller) {
25
$this->controller = $controller;
26
return $this;
27
}
28
29
final public function getController() {
30
if (!$this->controller) {
31
throw new PhutilInvalidStateException('setController');
32
}
33
34
return $this->controller;
35
}
36
37
final protected function getActiveEngine() {
38
return $this->activeEngine;
39
}
40
41
final protected function getRef() {
42
return $this->ref;
43
}
44
45
final public function newDocumentView(PhabricatorDocumentRef $ref) {
46
$request = $this->getRequest();
47
$viewer = $request->getViewer();
48
49
$engines = PhabricatorDocumentEngine::getEnginesForRef($viewer, $ref);
50
51
$engine_key = $this->getSelectedDocumentEngineKey();
52
if (!isset($engines[$engine_key])) {
53
$engine_key = head_key($engines);
54
}
55
$engine = $engines[$engine_key];
56
57
$lines = $this->getSelectedLineRange();
58
if ($lines) {
59
$engine->setHighlightedLines(range($lines[0], $lines[1]));
60
}
61
62
$encode_setting = $request->getStr('encode');
63
if (phutil_nonempty_string($encode_setting)) {
64
$engine->setEncodingConfiguration($encode_setting);
65
}
66
67
$highlight_setting = $request->getStr('highlight');
68
if (phutil_nonempty_string($highlight_setting)) {
69
$engine->setHighlightingConfiguration($highlight_setting);
70
}
71
72
$blame_setting = ($request->getStr('blame') !== 'off');
73
$engine->setBlameConfiguration($blame_setting);
74
75
$views = array();
76
foreach ($engines as $candidate_key => $candidate_engine) {
77
$label = $candidate_engine->getViewAsLabel($ref);
78
if ($label === null) {
79
continue;
80
}
81
82
$view_uri = $this->newRefViewURI($ref, $candidate_engine);
83
84
$view_icon = $candidate_engine->getViewAsIconIcon($ref);
85
$view_color = $candidate_engine->getViewAsIconColor($ref);
86
$loading = $candidate_engine->newLoadingContent($ref);
87
88
$views[] = array(
89
'viewKey' => $candidate_engine->getDocumentEngineKey(),
90
'icon' => $view_icon,
91
'color' => $view_color,
92
'name' => $label,
93
'engineURI' => $this->newRefRenderURI($ref, $candidate_engine),
94
'viewURI' => $view_uri,
95
'loadingMarkup' => hsprintf('%s', $loading),
96
'canEncode' => $candidate_engine->canConfigureEncoding($ref),
97
'canHighlight' => $candidate_engine->canConfigureHighlighting($ref),
98
'canBlame' => $candidate_engine->canBlame($ref),
99
);
100
}
101
102
$viewport_id = celerity_generate_unique_node_id();
103
$control_id = celerity_generate_unique_node_id();
104
$icon = $engine->newDocumentIcon($ref);
105
106
$config = array(
107
'controlID' => $control_id,
108
);
109
110
$this->willStageRef($ref);
111
112
if ($engine->shouldRenderAsync($ref)) {
113
$content = $engine->newLoadingContent($ref);
114
$config['next'] = 'render';
115
} else {
116
$this->willRenderRef($ref);
117
$content = $engine->newDocument($ref);
118
119
if ($engine->canBlame($ref)) {
120
$config['next'] = 'blame';
121
}
122
}
123
124
Javelin::initBehavior('document-engine', $config);
125
126
$viewport = phutil_tag(
127
'div',
128
array(
129
'id' => $viewport_id,
130
),
131
$content);
132
133
$meta = array(
134
'viewportID' => $viewport_id,
135
'viewKey' => $engine->getDocumentEngineKey(),
136
'views' => $views,
137
'encode' => array(
138
'icon' => 'fa-font',
139
'name' => pht('Change Text Encoding...'),
140
'uri' => '/services/encoding/',
141
'value' => $encode_setting,
142
),
143
'highlight' => array(
144
'icon' => 'fa-lightbulb-o',
145
'name' => pht('Highlight As...'),
146
'uri' => '/services/highlight/',
147
'value' => $highlight_setting,
148
),
149
'blame' => array(
150
'icon' => 'fa-backward',
151
'hide' => pht('Hide Blame'),
152
'show' => pht('Show Blame'),
153
'uri' => $ref->getBlameURI(),
154
'enabled' => $blame_setting,
155
'value' => null,
156
),
157
'coverage' => array(
158
'labels' => array(
159
// TODO: Modularize this properly, see T13125.
160
array(
161
'C' => pht('Covered'),
162
'U' => pht('Not Covered'),
163
'N' => pht('Not Executable'),
164
'X' => pht('Not Reachable'),
165
),
166
),
167
),
168
);
169
170
$view_button = id(new PHUIButtonView())
171
->setTag('a')
172
->setText(pht('View Options'))
173
->setIcon('fa-file-image-o')
174
->setColor(PHUIButtonView::GREY)
175
->setID($control_id)
176
->setMetadata($meta)
177
->setDropdown(true)
178
->addSigil('document-engine-view-dropdown');
179
180
$header = id(new PHUIHeaderView())
181
->setHeaderIcon($icon)
182
->setHeader($ref->getName())
183
->addActionLink($view_button);
184
185
return id(new PHUIObjectBoxView())
186
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
187
->setHeader($header)
188
->appendChild($viewport);
189
}
190
191
final public function newRenderResponse(PhabricatorDocumentRef $ref) {
192
$this->willStageRef($ref);
193
$this->willRenderRef($ref);
194
195
$request = $this->getRequest();
196
$viewer = $request->getViewer();
197
198
$engines = PhabricatorDocumentEngine::getEnginesForRef($viewer, $ref);
199
$engine_key = $this->getSelectedDocumentEngineKey();
200
if (!isset($engines[$engine_key])) {
201
return $this->newErrorResponse(
202
pht(
203
'The engine ("%s") is unknown, or unable to render this document.',
204
$engine_key));
205
}
206
$engine = $engines[$engine_key];
207
208
$this->activeEngine = $engine;
209
210
$encode_setting = $request->getStr('encode');
211
if (phutil_nonempty_string($encode_setting)) {
212
$engine->setEncodingConfiguration($encode_setting);
213
}
214
215
$highlight_setting = $request->getStr('highlight');
216
if (phutil_nonempty_string($highlight_setting)) {
217
$engine->setHighlightingConfiguration($highlight_setting);
218
}
219
220
$blame_setting = ($request->getStr('blame') !== 'off');
221
$engine->setBlameConfiguration($blame_setting);
222
223
try {
224
$content = $engine->newDocument($ref);
225
} catch (Exception $ex) {
226
return $this->newErrorResponse($ex->getMessage());
227
}
228
229
return $this->newContentResponse($content);
230
}
231
232
public function newErrorResponse($message) {
233
$container = phutil_tag(
234
'div',
235
array(
236
'class' => 'document-engine-error',
237
),
238
array(
239
id(new PHUIIconView())
240
->setIcon('fa-exclamation-triangle red'),
241
' ',
242
$message,
243
));
244
245
return $this->newContentResponse($container);
246
}
247
248
private function newContentResponse($content) {
249
$request = $this->getRequest();
250
$viewer = $request->getViewer();
251
$controller = $this->getController();
252
253
if ($request->isAjax()) {
254
return id(new AphrontAjaxResponse())
255
->setContent(
256
array(
257
'markup' => hsprintf('%s', $content),
258
));
259
}
260
261
$crumbs = $this->newCrumbs();
262
$crumbs->setBorder(true);
263
264
$content_frame = id(new PHUIObjectBoxView())
265
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
266
->appendChild($content);
267
268
$page_frame = id(new PHUITwoColumnView())
269
->setFooter($content_frame);
270
271
$title = array();
272
$ref = $this->getRef();
273
if ($ref) {
274
$title = array(
275
$ref->getName(),
276
pht('Standalone'),
277
);
278
} else {
279
$title = pht('Document');
280
}
281
282
return $controller->newPage()
283
->setCrumbs($crumbs)
284
->setTitle($title)
285
->appendChild($page_frame);
286
}
287
288
protected function newCrumbs() {
289
$engine = $this->getActiveEngine();
290
$controller = $this->getController();
291
292
$crumbs = $controller->buildApplicationCrumbsForEditEngine();
293
294
$ref = $this->getRef();
295
296
$this->addApplicationCrumbs($crumbs, $ref);
297
298
if ($ref) {
299
$label = $engine->getViewAsLabel($ref);
300
if ($label) {
301
$crumbs->addTextCrumb($label);
302
}
303
}
304
305
return $crumbs;
306
}
307
308
public function getRefViewURI(
309
PhabricatorDocumentRef $ref,
310
PhabricatorDocumentEngine $engine) {
311
return $this->newRefViewURI($ref, $engine);
312
}
313
314
abstract protected function newRefViewURI(
315
PhabricatorDocumentRef $ref,
316
PhabricatorDocumentEngine $engine);
317
318
abstract protected function newRefRenderURI(
319
PhabricatorDocumentRef $ref,
320
PhabricatorDocumentEngine $engine);
321
322
protected function getSelectedDocumentEngineKey() {
323
return $this->getRequest()->getURIData('engineKey');
324
}
325
326
protected function getSelectedLineRange() {
327
return $this->getRequest()->getURILineRange('lines', 1000);
328
}
329
330
protected function addApplicationCrumbs(
331
PHUICrumbsView $crumbs,
332
PhabricatorDocumentRef $ref = null) {
333
return;
334
}
335
336
protected function willStageRef(PhabricatorDocumentRef $ref) {
337
return;
338
}
339
340
protected function willRenderRef(PhabricatorDocumentRef $ref) {
341
return;
342
}
343
344
}
345
346