@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.

Pull file Document Engine rendering out of "Files" application controllers

Summary:
Ref T13105. This separates document rendering from the Controllers which trigger it so it can be reused elsewhere (notably, in Diffusion).

This shouldn't cause any application behavior to change, it just pulls the rendering logic out so it can be reused elsewhere.

Test Plan: Viewed various types of files in Files; toggled rendering, highlighting, and encoding.

Reviewers: mydeveloperday

Reviewed By: mydeveloperday

Maniphest Tasks: T13105

Differential Revision: https://secure.phabricator.com/D19301

+344 -219
+4
src/__phutil_library_map__.php
··· 2819 2819 'PhabricatorDivinerApplication' => 'applications/diviner/application/PhabricatorDivinerApplication.php', 2820 2820 'PhabricatorDocumentEngine' => 'applications/files/document/PhabricatorDocumentEngine.php', 2821 2821 'PhabricatorDocumentRef' => 'applications/files/document/PhabricatorDocumentRef.php', 2822 + 'PhabricatorDocumentRenderingEngine' => 'applications/files/document/render/PhabricatorDocumentRenderingEngine.php', 2822 2823 'PhabricatorDoorkeeperApplication' => 'applications/doorkeeper/application/PhabricatorDoorkeeperApplication.php', 2823 2824 'PhabricatorDraft' => 'applications/draft/storage/PhabricatorDraft.php', 2824 2825 'PhabricatorDraftDAO' => 'applications/draft/storage/PhabricatorDraftDAO.php', ··· 3010 3011 'PhabricatorFileDeleteController' => 'applications/files/controller/PhabricatorFileDeleteController.php', 3011 3012 'PhabricatorFileDeleteTransaction' => 'applications/files/xaction/PhabricatorFileDeleteTransaction.php', 3012 3013 'PhabricatorFileDocumentController' => 'applications/files/controller/PhabricatorFileDocumentController.php', 3014 + 'PhabricatorFileDocumentRenderingEngine' => 'applications/files/document/render/PhabricatorFileDocumentRenderingEngine.php', 3013 3015 'PhabricatorFileDropUploadController' => 'applications/files/controller/PhabricatorFileDropUploadController.php', 3014 3016 'PhabricatorFileEditController' => 'applications/files/controller/PhabricatorFileEditController.php', 3015 3017 'PhabricatorFileEditEngine' => 'applications/files/editor/PhabricatorFileEditEngine.php', ··· 8401 8403 'PhabricatorDivinerApplication' => 'PhabricatorApplication', 8402 8404 'PhabricatorDocumentEngine' => 'Phobject', 8403 8405 'PhabricatorDocumentRef' => 'Phobject', 8406 + 'PhabricatorDocumentRenderingEngine' => 'Phobject', 8404 8407 'PhabricatorDoorkeeperApplication' => 'PhabricatorApplication', 8405 8408 'PhabricatorDraft' => 'PhabricatorDraftDAO', 8406 8409 'PhabricatorDraftDAO' => 'PhabricatorLiskDAO', ··· 8624 8627 'PhabricatorFileDeleteController' => 'PhabricatorFileController', 8625 8628 'PhabricatorFileDeleteTransaction' => 'PhabricatorFileTransactionType', 8626 8629 'PhabricatorFileDocumentController' => 'PhabricatorFileController', 8630 + 'PhabricatorFileDocumentRenderingEngine' => 'PhabricatorDocumentRenderingEngine', 8627 8631 'PhabricatorFileDropUploadController' => 'PhabricatorFileController', 8628 8632 'PhabricatorFileEditController' => 'PhabricatorFileController', 8629 8633 'PhabricatorFileEditEngine' => 'PhabricatorEditEngine',
+1 -1
src/applications/files/application/PhabricatorFilesApplication.php
··· 73 73 => 'PhabricatorFileViewController', 74 74 '/file/' => array( 75 75 '(query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorFileListController', 76 - 'view/(?P<id>[^/]+)/'. 76 + 'view/(?P<id>[1-9]\d*)/'. 77 77 '(?:(?P<engineKey>[^/]+)/)?'. 78 78 '(?:\$(?P<lines>\d+(?:-\d+)?))?' 79 79 => 'PhabricatorFileViewController',
+4 -96
src/applications/files/controller/PhabricatorFileDocumentController.php
··· 3 3 final class PhabricatorFileDocumentController 4 4 extends PhabricatorFileController { 5 5 6 - private $file; 7 - private $engine; 8 - private $ref; 9 - 10 6 public function shouldAllowPublic() { 11 7 return true; 12 8 } ··· 26 22 'This file ("%s") does not exist or could not be loaded.', 27 23 $file_phid)); 28 24 } 29 - $this->file = $file; 30 25 31 26 $ref = id(new PhabricatorDocumentRef()) 32 27 ->setFile($file); 33 - $this->ref = $ref; 34 28 35 - $engines = PhabricatorDocumentEngine::getEnginesForRef($viewer, $ref); 36 - $engine_key = $request->getURIData('engineKey'); 37 - if (!isset($engines[$engine_key])) { 38 - return $this->newErrorResponse( 39 - pht( 40 - 'The engine ("%s") is unknown, or unable to render this document.', 41 - $engine_key)); 42 - } 43 - $engine = $engines[$engine_key]; 44 - $this->engine = $engine; 45 - 46 - $encode_setting = $request->getStr('encode'); 47 - if (strlen($encode_setting)) { 48 - $engine->setEncodingConfiguration($encode_setting); 49 - } 50 - 51 - $highlight_setting = $request->getStr('highlight'); 52 - if (strlen($highlight_setting)) { 53 - $engine->setHighlightingConfiguration($highlight_setting); 54 - } 55 - 56 - try { 57 - $content = $engine->newDocument($ref); 58 - } catch (Exception $ex) { 59 - return $this->newErrorResponse($ex->getMessage()); 60 - } 61 - 62 - return $this->newContentResponse($content); 63 - } 64 - 65 - private function newErrorResponse($message) { 66 - $container = phutil_tag( 67 - 'div', 68 - array( 69 - 'class' => 'document-engine-error', 70 - ), 71 - array( 72 - id(new PHUIIconView()) 73 - ->setIcon('fa-exclamation-triangle red'), 74 - ' ', 75 - $message, 76 - )); 77 - 78 - return $this->newContentResponse($container); 79 - } 80 - 81 - 82 - private function newContentResponse($content) { 83 - $viewer = $this->getViewer(); 84 - $request = $this->getRequest(); 85 - 86 - $file = $this->file; 87 - $engine = $this->engine; 88 - $ref = $this->ref; 89 - 90 - if ($request->isAjax()) { 91 - return id(new AphrontAjaxResponse()) 92 - ->setContent( 93 - array( 94 - 'markup' => hsprintf('%s', $content), 95 - )); 96 - } 97 - 98 - $crumbs = $this->buildApplicationCrumbs(); 99 - if ($file) { 100 - $crumbs->addTextCrumb($file->getMonogram(), $file->getInfoURI()); 101 - } 102 - 103 - $label = $engine->getViewAsLabel($ref); 104 - if ($label) { 105 - $crumbs->addTextCrumb($label); 106 - } 107 - 108 - $crumbs->setBorder(true); 109 - 110 - $content_frame = id(new PHUIObjectBoxView()) 111 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 112 - ->appendChild($content); 113 - 114 - $page_frame = id(new PHUITwoColumnView()) 115 - ->setFooter($content_frame); 116 - 117 - return $this->newPage() 118 - ->setCrumbs($crumbs) 119 - ->setTitle( 120 - array( 121 - $ref->getName(), 122 - pht('Standalone'), 123 - )) 124 - ->appendChild($page_frame); 29 + return id(new PhabricatorFileDocumentRenderingEngine()) 30 + ->setRequest($request) 31 + ->setController($this) 32 + ->newRenderResponse($ref); 125 33 } 126 34 127 35 }
+3 -110
src/applications/files/controller/PhabricatorFileViewController.php
··· 403 403 } 404 404 405 405 private function newFileContent(PhabricatorFile $file) { 406 - $viewer = $this->getViewer(); 407 406 $request = $this->getRequest(); 408 407 409 408 $ref = id(new PhabricatorDocumentRef()) 410 409 ->setFile($file); 411 410 412 - $engines = PhabricatorDocumentEngine::getEnginesForRef($viewer, $ref); 411 + $engine = id(new PhabricatorFileDocumentRenderingEngine()) 412 + ->setRequest($request); 413 413 414 - $engine_key = $request->getURIData('engineKey'); 415 - if (!isset($engines[$engine_key])) { 416 - $engine_key = head_key($engines); 417 - } 418 - $engine = $engines[$engine_key]; 419 - 420 - $lines = $request->getURILineRange('lines', 1000); 421 - if ($lines) { 422 - $engine->setHighlightedLines(range($lines[0], $lines[1])); 423 - } 424 - 425 - $encode_setting = $request->getStr('encode'); 426 - if (strlen($encode_setting)) { 427 - $engine->setEncodingConfiguration($encode_setting); 428 - } 429 - 430 - $highlight_setting = $request->getStr('highlight'); 431 - if (strlen($highlight_setting)) { 432 - $engine->setHighlightingConfiguration($highlight_setting); 433 - } 434 - 435 - $views = array(); 436 - foreach ($engines as $candidate_key => $candidate_engine) { 437 - $label = $candidate_engine->getViewAsLabel($ref); 438 - if ($label === null) { 439 - continue; 440 - } 441 - 442 - $view_uri = '/file/view/'.$file->getID().'/'.$candidate_key.'/'; 443 - 444 - $view_icon = $candidate_engine->getViewAsIconIcon($ref); 445 - $view_color = $candidate_engine->getViewAsIconColor($ref); 446 - $loading = $candidate_engine->newLoadingContent($ref); 447 - 448 - $views[] = array( 449 - 'viewKey' => $candidate_engine->getDocumentEngineKey(), 450 - 'icon' => $view_icon, 451 - 'color' => $view_color, 452 - 'name' => $label, 453 - 'engineURI' => $candidate_engine->getRenderURI($ref), 454 - 'viewURI' => $view_uri, 455 - 'loadingMarkup' => hsprintf('%s', $loading), 456 - 'canEncode' => $candidate_engine->canConfigureEncoding($ref), 457 - 'canHighlight' => $candidate_engine->CanConfigureHighlighting($ref), 458 - ); 459 - } 460 - 461 - $viewport_id = celerity_generate_unique_node_id(); 462 - $control_id = celerity_generate_unique_node_id(); 463 - $icon = $engine->newDocumentIcon($ref); 464 - 465 - if ($engine->shouldRenderAsync($ref)) { 466 - $content = $engine->newLoadingContent($ref); 467 - $config = array( 468 - 'renderControlID' => $control_id, 469 - ); 470 - } else { 471 - $content = $engine->newDocument($ref); 472 - $config = array(); 473 - } 474 - 475 - Javelin::initBehavior('document-engine', $config); 476 - 477 - $viewport = phutil_tag( 478 - 'div', 479 - array( 480 - 'id' => $viewport_id, 481 - ), 482 - $content); 483 - 484 - $meta = array( 485 - 'viewportID' => $viewport_id, 486 - 'viewKey' => $engine->getDocumentEngineKey(), 487 - 'views' => $views, 488 - 'standaloneURI' => $engine->getRenderURI($ref), 489 - 'encode' => array( 490 - 'icon' => 'fa-font', 491 - 'name' => pht('Change Text Encoding...'), 492 - 'uri' => '/services/encoding/', 493 - 'value' => $encode_setting, 494 - ), 495 - 'highlight' => array( 496 - 'icon' => 'fa-lightbulb-o', 497 - 'name' => pht('Highlight As...'), 498 - 'uri' => '/services/highlight/', 499 - 'value' => $highlight_setting, 500 - ), 501 - ); 502 - 503 - $view_button = id(new PHUIButtonView()) 504 - ->setTag('a') 505 - ->setText(pht('View Options')) 506 - ->setIcon('fa-file-image-o') 507 - ->setColor(PHUIButtonView::GREY) 508 - ->setID($control_id) 509 - ->setMetadata($meta) 510 - ->setDropdown(true) 511 - ->addSigil('document-engine-view-dropdown'); 512 - 513 - $header = id(new PHUIHeaderView()) 514 - ->setHeaderIcon($icon) 515 - ->setHeader($ref->getName()) 516 - ->addActionLink($view_button); 517 - 518 - return id(new PHUIObjectBoxView()) 519 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 520 - ->setHeader($header) 521 - ->appendChild($viewport); 414 + return $engine->newDocumentView($ref); 522 415 } 523 416 524 417 }
-12
src/applications/files/document/PhabricatorDocumentEngine.php
··· 152 152 return null; 153 153 } 154 154 155 - public function getRenderURI(PhabricatorDocumentRef $ref) { 156 - $file = $ref->getFile(); 157 - if (!$file) { 158 - throw new PhutilMethodNotImplementedException(); 159 - } 160 - 161 - $engine_key = $this->getDocumentEngineKey(); 162 - $file_phid = $file->getPHID(); 163 - 164 - return "/file/document/{$engine_key}/{$file_phid}/"; 165 - } 166 - 167 155 final public static function getEnginesForRef( 168 156 PhabricatorUser $viewer, 169 157 PhabricatorDocumentRef $ref) {
+285
src/applications/files/document/render/PhabricatorDocumentRenderingEngine.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorDocumentRenderingEngine 4 + extends Phobject { 5 + 6 + private $request; 7 + private $controller; 8 + private $activeEngine; 9 + 10 + final public function setRequest(AphrontRequest $request) { 11 + $this->request = $request; 12 + return $this; 13 + } 14 + 15 + final public function getRequest() { 16 + if (!$this->request) { 17 + throw new PhutilInvalidStateException('setRequest'); 18 + } 19 + 20 + return $this->request; 21 + } 22 + 23 + final public function setController(PhabricatorController $controller) { 24 + $this->controller = $controller; 25 + return $this; 26 + } 27 + 28 + final public function getController() { 29 + if (!$this->controller) { 30 + throw new PhutilInvalidStateException('setController'); 31 + } 32 + 33 + return $this->controller; 34 + } 35 + 36 + final protected function getActiveEngine() { 37 + if (!$this->activeEngine) { 38 + throw new PhutilInvalidStateException('setActiveEngine'); 39 + } 40 + 41 + return $this->activeEngine; 42 + } 43 + 44 + final public function newDocumentView(PhabricatorDocumentRef $ref) { 45 + $request = $this->getRequest(); 46 + $viewer = $request->getViewer(); 47 + 48 + $engines = PhabricatorDocumentEngine::getEnginesForRef($viewer, $ref); 49 + 50 + $engine_key = $this->getSelectedDocumentEngineKey(); 51 + if (!isset($engines[$engine_key])) { 52 + $engine_key = head_key($engines); 53 + } 54 + $engine = $engines[$engine_key]; 55 + 56 + $lines = $request->getURILineRange('lines', 1000); 57 + if ($lines) { 58 + $engine->setHighlightedLines(range($lines[0], $lines[1])); 59 + } 60 + 61 + $encode_setting = $request->getStr('encode'); 62 + if (strlen($encode_setting)) { 63 + $engine->setEncodingConfiguration($encode_setting); 64 + } 65 + 66 + $highlight_setting = $request->getStr('highlight'); 67 + if (strlen($highlight_setting)) { 68 + $engine->setHighlightingConfiguration($highlight_setting); 69 + } 70 + 71 + $views = array(); 72 + foreach ($engines as $candidate_key => $candidate_engine) { 73 + $label = $candidate_engine->getViewAsLabel($ref); 74 + if ($label === null) { 75 + continue; 76 + } 77 + 78 + $view_uri = $this->newRefViewURI($ref, $candidate_engine); 79 + 80 + $view_icon = $candidate_engine->getViewAsIconIcon($ref); 81 + $view_color = $candidate_engine->getViewAsIconColor($ref); 82 + $loading = $candidate_engine->newLoadingContent($ref); 83 + 84 + $views[] = array( 85 + 'viewKey' => $candidate_engine->getDocumentEngineKey(), 86 + 'icon' => $view_icon, 87 + 'color' => $view_color, 88 + 'name' => $label, 89 + 'engineURI' => $this->newRefRenderURI($ref, $candidate_engine), 90 + 'viewURI' => $view_uri, 91 + 'loadingMarkup' => hsprintf('%s', $loading), 92 + 'canEncode' => $candidate_engine->canConfigureEncoding($ref), 93 + 'canHighlight' => $candidate_engine->CanConfigureHighlighting($ref), 94 + ); 95 + } 96 + 97 + $viewport_id = celerity_generate_unique_node_id(); 98 + $control_id = celerity_generate_unique_node_id(); 99 + $icon = $engine->newDocumentIcon($ref); 100 + 101 + if ($engine->shouldRenderAsync($ref)) { 102 + $content = $engine->newLoadingContent($ref); 103 + $config = array( 104 + 'renderControlID' => $control_id, 105 + ); 106 + } else { 107 + $content = $engine->newDocument($ref); 108 + $config = array(); 109 + } 110 + 111 + Javelin::initBehavior('document-engine', $config); 112 + 113 + $viewport = phutil_tag( 114 + 'div', 115 + array( 116 + 'id' => $viewport_id, 117 + ), 118 + $content); 119 + 120 + $meta = array( 121 + 'viewportID' => $viewport_id, 122 + 'viewKey' => $engine->getDocumentEngineKey(), 123 + 'views' => $views, 124 + 'encode' => array( 125 + 'icon' => 'fa-font', 126 + 'name' => pht('Change Text Encoding...'), 127 + 'uri' => '/services/encoding/', 128 + 'value' => $encode_setting, 129 + ), 130 + 'highlight' => array( 131 + 'icon' => 'fa-lightbulb-o', 132 + 'name' => pht('Highlight As...'), 133 + 'uri' => '/services/highlight/', 134 + 'value' => $highlight_setting, 135 + ), 136 + ); 137 + 138 + $view_button = id(new PHUIButtonView()) 139 + ->setTag('a') 140 + ->setText(pht('View Options')) 141 + ->setIcon('fa-file-image-o') 142 + ->setColor(PHUIButtonView::GREY) 143 + ->setID($control_id) 144 + ->setMetadata($meta) 145 + ->setDropdown(true) 146 + ->addSigil('document-engine-view-dropdown'); 147 + 148 + $header = id(new PHUIHeaderView()) 149 + ->setHeaderIcon($icon) 150 + ->setHeader($ref->getName()) 151 + ->addActionLink($view_button); 152 + 153 + return id(new PHUIObjectBoxView()) 154 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 155 + ->setHeader($header) 156 + ->appendChild($viewport); 157 + } 158 + 159 + abstract protected function newRefViewURI( 160 + PhabricatorDocumentRef $ref, 161 + PhabricatorDocumentEngine $engine); 162 + 163 + abstract protected function newRefRenderURI( 164 + PhabricatorDocumentRef $ref, 165 + PhabricatorDocumentEngine $engine); 166 + 167 + protected function getSelectedDocumentEngineKey() { 168 + return $this->getRequest()->getURIData('engineKey'); 169 + } 170 + 171 + final public function newRenderResponse(PhabricatorDocumentRef $ref) { 172 + $request = $this->getRequest(); 173 + $viewer = $request->getViewer(); 174 + 175 + $engines = PhabricatorDocumentEngine::getEnginesForRef($viewer, $ref); 176 + $engine_key = $request->getURIData('engineKey'); 177 + if (!isset($engines[$engine_key])) { 178 + return $this->newErrorResponse( 179 + $ref, 180 + pht( 181 + 'The engine ("%s") is unknown, or unable to render this document.', 182 + $engine_key)); 183 + } 184 + $engine = $engines[$engine_key]; 185 + 186 + $this->activeEngine = $engine; 187 + 188 + $encode_setting = $request->getStr('encode'); 189 + if (strlen($encode_setting)) { 190 + $engine->setEncodingConfiguration($encode_setting); 191 + } 192 + 193 + $highlight_setting = $request->getStr('highlight'); 194 + if (strlen($highlight_setting)) { 195 + $engine->setHighlightingConfiguration($highlight_setting); 196 + } 197 + 198 + try { 199 + $content = $engine->newDocument($ref); 200 + } catch (Exception $ex) { 201 + return $this->newErrorResponse($ref, $ex->getMessage()); 202 + } 203 + 204 + return $this->newContentResponse($ref, $content); 205 + } 206 + 207 + private function newErrorResponse( 208 + PhabricatorDocumentRef $ref, 209 + $message) { 210 + 211 + $container = phutil_tag( 212 + 'div', 213 + array( 214 + 'class' => 'document-engine-error', 215 + ), 216 + array( 217 + id(new PHUIIconView()) 218 + ->setIcon('fa-exclamation-triangle red'), 219 + ' ', 220 + $message, 221 + )); 222 + 223 + return $this->newContentResponse($ref, $container); 224 + } 225 + 226 + private function newContentResponse( 227 + PhabricatorDocumentRef $ref, 228 + $content) { 229 + 230 + $request = $this->getRequest(); 231 + $viewer = $request->getViewer(); 232 + $controller = $this->getController(); 233 + 234 + if ($request->isAjax()) { 235 + return id(new AphrontAjaxResponse()) 236 + ->setContent( 237 + array( 238 + 'markup' => hsprintf('%s', $content), 239 + )); 240 + } 241 + 242 + $crumbs = $this->newCrumbs($ref); 243 + if ($crumbs) { 244 + $crumbs->setBorder(true); 245 + } 246 + 247 + $content_frame = id(new PHUIObjectBoxView()) 248 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 249 + ->appendChild($content); 250 + 251 + $page_frame = id(new PHUITwoColumnView()) 252 + ->setFooter($content_frame); 253 + 254 + return $controller->newPage() 255 + ->setCrumbs($crumbs) 256 + ->setTitle( 257 + array( 258 + $ref->getName(), 259 + pht('Standalone'), 260 + )) 261 + ->appendChild($page_frame); 262 + } 263 + 264 + protected function newCrumbs(PhabricatorDocumentRef $ref) { 265 + $controller = $this->getController(); 266 + $crumbs = $controller->buildApplicationCrumbsForEditEngine(); 267 + 268 + $this->addApplicationCrumbs($ref, $crumbs); 269 + 270 + $engine = $this->getActiveEngine(); 271 + $label = $engine->getViewAsLabel($ref); 272 + if ($label) { 273 + $crumbs->addTextCrumb($label); 274 + } 275 + 276 + return $crumbs; 277 + } 278 + 279 + protected function addApplicationCrumbs( 280 + PhabricatorDocumentRef $ref, 281 + PHUICrumbsView $crumbs) { 282 + return; 283 + } 284 + 285 + }
+47
src/applications/files/document/render/PhabricatorFileDocumentRenderingEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorFileDocumentRenderingEngine 4 + extends PhabricatorDocumentRenderingEngine { 5 + 6 + protected function newRefViewURI( 7 + PhabricatorDocumentRef $ref, 8 + PhabricatorDocumentEngine $engine) { 9 + 10 + $file = $ref->getFile(); 11 + $engine_key = $engine->getDocumentEngineKey(); 12 + 13 + return urisprintf( 14 + '/file/view/%d/%s/', 15 + $file->getID(), 16 + $engine_key); 17 + } 18 + 19 + protected function newRefRenderURI( 20 + PhabricatorDocumentRef $ref, 21 + PhabricatorDocumentEngine $engine) { 22 + $file = $ref->getFile(); 23 + if (!$file) { 24 + throw new PhutilMethodNotImplementedException(); 25 + } 26 + 27 + $engine_key = $engine->getDocumentEngineKey(); 28 + $file_phid = $file->getPHID(); 29 + 30 + return urisprintf( 31 + '/file/document/%s/%s/', 32 + $engine_key, 33 + $file_phid); 34 + } 35 + 36 + protected function addApplicationCrumbs( 37 + PhabricatorDocumentRef $ref, 38 + PHUICrumbsView $crumbs) { 39 + 40 + $file = $ref->getFile(); 41 + if ($file) { 42 + $crumbs->addTextCrumb($file->getMonogram(), $file->getInfoURI()); 43 + } 44 + 45 + } 46 + 47 + }