From 1fde4a9450610586e76c9e536c88f556cc52683c Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 5 Apr 2018 10:21:48 -0700 Subject: [PATCH] Move Diffusion browse rendering to DocumentEngine, breaking almost all features Summary: Ref T13105. This breaks about 9,000 features but moves Diffusion to DocumentEngine for rendering. See T13105 for a more complete list of all the broken stuff. But you can't bake a software without breaking all the features every time you make a change, right? Test Plan: Viewed various files in Diffusion, used DocumentEngine features like highlighting and rendering engine selection. Reviewers: mydeveloperday Reviewed By: mydeveloperday Subscribers: mydeveloperday Maniphest Tasks: T13105 Differential Revision: https://secure.phabricator.com/D19302 --- src/__phutil_library_map__.php | 4 + .../PhabricatorDiffusionApplication.php | 2 + .../controller/DiffusionBrowseController.php | 625 +----------------- .../DiffusionDocumentController.php | 45 ++ .../DiffusionDocumentRenderingEngine.php | 67 ++ .../PhabricatorFileDocumentController.php | 11 +- .../PhabricatorDocumentRenderingEngine.php | 72 +- ...PhabricatorFileDocumentRenderingEngine.php | 12 +- .../storage/PhabricatorRepository.php | 2 + 9 files changed, 187 insertions(+), 653 deletions(-) create mode 100644 src/applications/diffusion/controller/DiffusionDocumentController.php create mode 100644 src/applications/diffusion/document/DiffusionDocumentRenderingEngine.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 95f8ed45b2..8e2eb24b15 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -732,6 +732,8 @@ phutil_register_library_map(array( 'DiffusionDiffController' => 'applications/diffusion/controller/DiffusionDiffController.php', 'DiffusionDiffInlineCommentQuery' => 'applications/diffusion/query/DiffusionDiffInlineCommentQuery.php', 'DiffusionDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionDiffQueryConduitAPIMethod.php', + 'DiffusionDocumentController' => 'applications/diffusion/controller/DiffusionDocumentController.php', + 'DiffusionDocumentRenderingEngine' => 'applications/diffusion/document/DiffusionDocumentRenderingEngine.php', 'DiffusionDoorkeeperCommitFeedStoryPublisher' => 'applications/diffusion/doorkeeper/DiffusionDoorkeeperCommitFeedStoryPublisher.php', 'DiffusionEmptyResultView' => 'applications/diffusion/view/DiffusionEmptyResultView.php', 'DiffusionExistsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionExistsQueryConduitAPIMethod.php', @@ -5987,6 +5989,8 @@ phutil_register_library_map(array( 'DiffusionDiffController' => 'DiffusionController', 'DiffusionDiffInlineCommentQuery' => 'PhabricatorDiffInlineCommentQuery', 'DiffusionDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', + 'DiffusionDocumentController' => 'DiffusionController', + 'DiffusionDocumentRenderingEngine' => 'PhabricatorDocumentRenderingEngine', 'DiffusionDoorkeeperCommitFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher', 'DiffusionEmptyResultView' => 'DiffusionView', 'DiffusionExistsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', diff --git a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php index 90956077fd..4a1c2fdd95 100644 --- a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php +++ b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php @@ -53,6 +53,8 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication { 'history/(?P.*)' => 'DiffusionHistoryController', 'graph/(?P.*)' => 'DiffusionGraphController', 'browse/(?P.*)' => 'DiffusionBrowseController', + 'document/(?P.*)' + => 'DiffusionDocumentController', 'lastmodified/(?P.*)' => 'DiffusionLastModifiedController', 'diff/' => 'DiffusionDiffController', 'tags/(?P.*)' => 'DiffusionTagListController', diff --git a/src/applications/diffusion/controller/DiffusionBrowseController.php b/src/applications/diffusion/controller/DiffusionBrowseController.php index 8c0c2c19c4..2c2a2f46b9 100644 --- a/src/applications/diffusion/controller/DiffusionBrowseController.php +++ b/src/applications/diffusion/controller/DiffusionBrowseController.php @@ -45,13 +45,13 @@ final class DiffusionBrowseController extends DiffusionController { if ($is_file) { return $this->browseFile(); - } else { - $paths = $results->getPaths(); - $paths = $pager->sliceResults($paths); - $results->setPaths($paths); - - return $this->browseDirectory($results, $pager); } + + $paths = $results->getPaths(); + $paths = $pager->sliceResults($paths); + $results->setPaths($paths); + + return $this->browseDirectory($results, $pager); } private function browseSearch() { @@ -187,26 +187,21 @@ final class DiffusionBrowseController extends DiffusionController { } else { $corpus = $this->buildGitLFSCorpus($lfs_ref); } - } else if (ArcanistDiffUtils::isHeuristicBinaryFile($data)) { - $file_uri = $file->getBestURI(); - - if ($file->isViewableImage()) { - $corpus = $this->buildImageCorpus($file_uri); - } else { - $corpus = $this->buildBinaryCorpus($file_uri, $data); - } } else { $this->loadLintMessages(); $this->coverage = $drequest->loadCoverage(); $show_editor = true; - // Build the content of the file. - $corpus = $this->buildCorpus( - $data, - $needs_blame, - $drequest, - $path, - $data); + $ref = id(new PhabricatorDocumentRef()) + ->setFile($file); + + $engine = id(new DiffusionDocumentRenderingEngine()) + ->setRequest($request) + ->setDiffusionRequest($drequest); + + $corpus = $engine->newDocumentView($ref); + + $this->corpusButtons[] = $this->renderFileButton(); } } @@ -514,164 +509,6 @@ final class DiffusionBrowseController extends DiffusionController { '/'.$drequest->getPath()); } - private function buildCorpus( - $file_corpus, - $needs_blame, - DiffusionRequest $drequest, - $path, - $data) { - - $viewer = $this->getViewer(); - $blame_timeout = 15; - $blame_failed = false; - - $highlight_limit = DifferentialChangesetParser::HIGHLIGHT_BYTE_LIMIT; - $blame_limit = DifferentialChangesetParser::HIGHLIGHT_BYTE_LIMIT; - $can_highlight = (strlen($file_corpus) <= $highlight_limit); - $can_blame = (strlen($file_corpus) <= $blame_limit); - - if ($needs_blame && $can_blame) { - $blame = $this->loadBlame($path, $drequest->getCommit(), $blame_timeout); - list($blame_list, $blame_commits) = $blame; - if ($blame_list === null) { - $blame_failed = true; - $blame_list = array(); - } - } else { - $blame_list = array(); - $blame_commits = array(); - } - - require_celerity_resource('syntax-highlighting-css'); - if ($can_highlight) { - $highlighted = PhabricatorSyntaxHighlighter::highlightWithFilename( - $path, - $file_corpus); - } else { - // Highlight as plain text to escape the content properly. - $highlighted = PhabricatorSyntaxHighlighter::highlightWithLanguage( - 'txt', - $file_corpus); - } - - $lines = phutil_split_lines($highlighted); - - $rows = $this->buildDisplayRows( - $lines, - $blame_list, - $blame_commits); - - $corpus_table = javelin_tag( - 'table', - array( - 'class' => 'diffusion-source remarkup-code PhabricatorMonospaced', - 'sigil' => 'phabricator-source', - 'meta' => array( - 'uri' => $this->getLineNumberBaseURI(), - ), - ), - $rows); - - $corpus_table = phutil_tag_div('diffusion-source-wrap', $corpus_table); - - if ($this->getRequest()->isAjax()) { - return $corpus_table; - } - - $id = celerity_generate_unique_node_id(); - - $repo = $drequest->getRepository(); - $symbol_repos = nonempty($repo->getSymbolSources(), array()); - $symbol_repos[] = $repo->getPHID(); - - $lang = last(explode('.', $drequest->getPath())); - $repo_languages = $repo->getSymbolLanguages(); - $repo_languages = nonempty($repo_languages, array()); - $repo_languages = array_fill_keys($repo_languages, true); - - $needs_symbols = true; - if ($repo_languages && $symbol_repos) { - $have_symbols = id(new DiffusionSymbolQuery()) - ->existsSymbolsInRepository($repo->getPHID()); - if (!$have_symbols) { - $needs_symbols = false; - } - } - - if ($needs_symbols && $repo_languages) { - $needs_symbols = isset($repo_languages[$lang]); - } - - if ($needs_symbols) { - Javelin::initBehavior( - 'repository-crossreference', - array( - 'container' => $id, - 'lang' => $lang, - 'repositories' => $symbol_repos, - )); - } - - $corpus = phutil_tag( - 'div', - array( - 'id' => $id, - ), - $corpus_table); - - Javelin::initBehavior('load-blame', array('id' => $id)); - - $this->corpusButtons[] = $this->renderFileButton(); - $title = basename($this->getDiffusionRequest()->getPath()); - $icon = 'fa-file-code-o'; - $drequest = $this->getDiffusionRequest(); - $this->buildActionButtons($drequest); - - $header = $this->buildPanelHeaderView($title, $icon); - - $corpus = id(new PHUIObjectBoxView()) - ->setHeader($header) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->appendChild($corpus) - ->addClass('diffusion-mobile-view') - ->addSigil('diffusion-file-content-view') - ->setMetadata( - array( - 'path' => $this->getDiffusionRequest()->getPath(), - )) - ->setCollapsed(true); - - $messages = array(); - - if (!$can_highlight) { - $messages[] = pht( - 'This file is larger than %s, so syntax highlighting is disabled '. - 'by default.', - phutil_format_bytes($highlight_limit)); - } - - if (!$can_blame) { - $messages[] = pht( - 'This file is larger than %s, so blame is disabled.', - phutil_format_bytes($blame_limit)); - } - - if ($blame_failed) { - $messages[] = pht( - 'Failed to load blame information for this file in %s second(s).', - new PhutilNumber($blame_timeout)); - } - - if ($messages) { - $corpus->setInfoView( - id(new PHUIInfoView()) - ->setSeverity(PHUIInfoView::SEVERITY_WARNING) - ->setErrors($messages)); - } - - return $corpus; - } - private function buildButtonBar( DiffusionRequest $drequest, $show_editor) { @@ -868,389 +705,6 @@ final class DiffusionBrowseController extends DiffusionController { ->setColor(PHUIButtonView::GREY); } - private function buildDisplayRows( - array $lines, - array $blame_list, - array $blame_commits) { - - $request = $this->getRequest(); - $viewer = $this->getViewer(); - $drequest = $this->getDiffusionRequest(); - $repository = $drequest->getRepository(); - - $revision_map = array(); - $revisions = array(); - if ($blame_commits) { - $commit_map = mpull($blame_commits, 'getCommitIdentifier', 'getPHID'); - - $revision_ids = id(new DifferentialRevision()) - ->loadIDsByCommitPHIDs(array_keys($commit_map)); - if ($revision_ids) { - $revisions = id(new DifferentialRevisionQuery()) - ->setViewer($viewer) - ->withIDs($revision_ids) - ->execute(); - $revisions = mpull($revisions, null, 'getID'); - } - - foreach ($revision_ids as $commit_phid => $revision_id) { - // If the viewer can't actually see this revision, skip it. - if (!isset($revisions[$revision_id])) { - continue; - } - $revision_map[$commit_map[$commit_phid]] = $revision_id; - } - } - - $phids = array(); - foreach ($blame_commits as $commit) { - $author_phid = $commit->getAuthorPHID(); - if ($author_phid === null) { - continue; - } - $phids[$author_phid] = $author_phid; - } - - foreach ($revisions as $revision) { - $author_phid = $revision->getAuthorPHID(); - if ($author_phid === null) { - continue; - } - $phids[$author_phid] = $author_phid; - } - - $handles = $viewer->loadHandles($phids); - - $author_phids = array(); - $author_map = array(); - foreach ($blame_commits as $commit) { - $commit_identifier = $commit->getCommitIdentifier(); - - $author_phid = ''; - if (isset($revision_map[$commit_identifier])) { - $revision_id = $revision_map[$commit_identifier]; - $revision = $revisions[$revision_id]; - $author_phid = $revision->getAuthorPHID(); - } else { - $author_phid = $commit->getAuthorPHID(); - } - - $author_map[$commit_identifier] = $author_phid; - $author_phids[$author_phid] = $author_phid; - } - - $colors = array(); - if ($blame_commits) { - $epochs = array(); - - foreach ($blame_commits as $identifier => $commit) { - $epochs[$identifier] = $commit->getEpoch(); - } - - $epoch_list = array_filter($epochs); - $epoch_list = array_unique($epoch_list); - $epoch_list = array_values($epoch_list); - - $epoch_min = min($epoch_list); - $epoch_max = max($epoch_list); - $epoch_range = ($epoch_max - $epoch_min) + 1; - - foreach ($blame_commits as $identifier => $commit) { - $epoch = $epochs[$identifier]; - if (!$epoch) { - $color = '#ffffdd'; // Warning color, missing data. - } else { - $color_ratio = ($epoch - $epoch_min) / $epoch_range; - $color_value = 0xE6 * (1.0 - $color_ratio); - $color = sprintf( - '#%02x%02x%02x', - $color_value, - 0xF6, - $color_value); - } - - $colors[$identifier] = $color; - } - } - - $display = array(); - $last_identifier = null; - $last_color = null; - foreach ($lines as $line_index => $line) { - $color = '#f6f6f6'; - $duplicate = false; - if (isset($blame_list[$line_index])) { - $identifier = $blame_list[$line_index]; - if (isset($colors[$identifier])) { - $color = $colors[$identifier]; - } - - if ($identifier === $last_identifier) { - $duplicate = true; - } else { - $last_identifier = $identifier; - } - } - - $display[$line_index] = array( - 'data' => $line, - 'target' => false, - 'highlighted' => false, - 'color' => $color, - 'duplicate' => $duplicate, - ); - } - - $line_arr = array(); - $line_str = $drequest->getLine(); - $ranges = explode(',', $line_str); - foreach ($ranges as $range) { - if (strpos($range, '-') !== false) { - list($min, $max) = explode('-', $range, 2); - $line_arr[] = array( - 'min' => min($min, $max), - 'max' => max($min, $max), - ); - } else if (strlen($range)) { - $line_arr[] = array( - 'min' => $range, - 'max' => $range, - ); - } - } - - // Mark the first highlighted line as the target line. - if ($line_arr) { - $target_line = $line_arr[0]['min']; - if (isset($display[$target_line - 1])) { - $display[$target_line - 1]['target'] = true; - } - } - - // Mark all other highlighted lines as highlighted. - foreach ($line_arr as $range) { - for ($ii = $range['min']; $ii <= $range['max']; $ii++) { - if (isset($display[$ii - 1])) { - $display[$ii - 1]['highlighted'] = true; - } - } - } - - $engine = null; - $inlines = array(); - if ($this->getRequest()->getStr('lint') !== null && $this->lintMessages) { - $engine = new PhabricatorMarkupEngine(); - $engine->setViewer($viewer); - - foreach ($this->lintMessages as $message) { - $inline = id(new PhabricatorAuditInlineComment()) - ->setSyntheticAuthor( - ArcanistLintSeverity::getStringForSeverity($message['severity']). - ' '.$message['code'].' ('.$message['name'].')') - ->setLineNumber($message['line']) - ->setContent($message['description']); - $inlines[$message['line']][] = $inline; - - $engine->addObject( - $inline, - PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY); - } - - $engine->process(); - require_celerity_resource('differential-changeset-view-css'); - } - - $rows = $this->renderInlines( - idx($inlines, 0, array()), - (bool)$this->coverage, - $engine); - - // NOTE: We're doing this manually because rendering is otherwise - // dominated by URI generation for very large files. - $line_base = $this->getLineNumberBaseURI(); - - require_celerity_resource('aphront-tooltip-css'); - Javelin::initBehavior('phabricator-oncopy'); - Javelin::initBehavior('phabricator-tooltips'); - Javelin::initBehavior('phabricator-line-linker'); - - // Render these once, since they tend to get repeated many times in large - // blame outputs. - $commit_links = $this->renderCommitLinks($blame_commits, $handles); - $revision_links = $this->renderRevisionLinks($revisions, $handles); - $author_links = $this->renderAuthorLinks($author_map, $handles); - - if ($this->coverage) { - require_celerity_resource('differential-changeset-view-css'); - Javelin::initBehavior( - 'diffusion-browse-file', - array( - 'labels' => array( - 'cov-C' => pht('Covered'), - 'cov-N' => pht('Not Covered'), - 'cov-U' => pht('Not Executable'), - ), - )); - } - - $skip_text = pht('Skip Past This Commit'); - $skip_icon = id(new PHUIIconView()) - ->setIcon('fa-backward'); - - foreach ($display as $line_index => $line) { - $row = array(); - - $line_number = $line_index + 1; - $line_href = $line_base.'$'.$line_number; - - if (isset($blame_list[$line_index])) { - $identifier = $blame_list[$line_index]; - } else { - $identifier = null; - } - - $revision_link = null; - $commit_link = null; - $author_link = null; - $before_link = null; - - $style = 'background: '.$line['color'].';'; - - if ($identifier && !$line['duplicate']) { - if (isset($commit_links[$identifier])) { - $commit_link = $commit_links[$identifier]; - $author_link = $author_links[$author_map[$identifier]]; - } - - if (isset($revision_map[$identifier])) { - $revision_id = $revision_map[$identifier]; - if (isset($revision_links[$revision_id])) { - $revision_link = $revision_links[$revision_id]; - } - } - - $skip_href = $line_href.'?before='.$identifier; - $before_link = javelin_tag( - 'a', - array( - 'href' => $skip_href, - 'sigil' => 'has-tooltip', - 'meta' => array( - 'tip' => $skip_text, - 'align' => 'E', - 'size' => 300, - ), - ), - $skip_icon); - } - - $row[] = phutil_tag( - 'th', - array( - 'class' => 'diffusion-blame-link', - ), - $before_link); - - $object_links = array(); - $object_links[] = $author_link; - $object_links[] = $commit_link; - if ($revision_link) { - $object_links[] = phutil_tag('span', array(), '/'); - $object_links[] = $revision_link; - } - - $row[] = phutil_tag( - 'th', - array( - 'class' => 'diffusion-rev-link', - ), - $object_links); - - $line_link = phutil_tag( - 'a', - array( - 'href' => $line_href, - 'style' => $style, - ), - $line_number); - - $row[] = javelin_tag( - 'th', - array( - 'class' => 'diffusion-line-link', - 'sigil' => 'phabricator-source-line', - 'style' => $style, - ), - $line_link); - - if ($line['target']) { - Javelin::initBehavior( - 'diffusion-jump-to', - array( - 'target' => 'scroll_target', - )); - $anchor_text = phutil_tag( - 'a', - array( - 'id' => 'scroll_target', - ), - ''); - } else { - $anchor_text = null; - } - - $row[] = phutil_tag( - 'td', - array( - ), - array( - $anchor_text, - - // NOTE: See phabricator-oncopy behavior. - "\xE2\x80\x8B", - - // TODO: [HTML] Not ideal. - phutil_safe_html(str_replace("\t", ' ', $line['data'])), - )); - - if ($this->coverage) { - $cov_index = $line_index; - - if (isset($this->coverage[$cov_index])) { - $cov_class = $this->coverage[$cov_index]; - } else { - $cov_class = 'N'; - } - - $row[] = phutil_tag( - 'td', - array( - 'class' => 'cov cov-'.$cov_class, - ), - ''); - } - - $rows[] = phutil_tag( - 'tr', - array( - 'class' => ($line['highlighted'] ? - 'phabricator-source-highlight' : - null), - ), - $row); - - $cur_inlines = $this->renderInlines( - idx($inlines, $line_number, array()), - $this->coverage, - $engine); - foreach ($cur_inlines as $cur_inline) { - $rows[] = $cur_inline; - } - } - - return $rows; - } - private function renderInlines( array $inlines, $has_coverage, @@ -1285,53 +739,6 @@ final class DiffusionBrowseController extends DiffusionController { return $rows; } - private function buildImageCorpus($file_uri) { - $properties = new PHUIPropertyListView(); - - $properties->addImageContent( - phutil_tag( - 'img', - array( - 'src' => $file_uri, - ))); - - $this->corpusButtons[] = $this->renderFileButton($file_uri); - $title = basename($this->getDiffusionRequest()->getPath()); - $icon = 'fa-file-image-o'; - $drequest = $this->getDiffusionRequest(); - $this->buildActionButtons($drequest); - $header = $this->buildPanelHeaderView($title, $icon); - - return id(new PHUIObjectBoxView()) - ->setHeader($header) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->addClass('diffusion-mobile-view') - ->addPropertyList($properties); - } - - private function buildBinaryCorpus($file_uri, $data) { - $size = new PhutilNumber(strlen($data)); - $text = pht('This is a binary file. It is %s byte(s) in length.', $size); - $text = id(new PHUIBoxView()) - ->addPadding(PHUI::PADDING_LARGE) - ->appendChild($text); - - $this->corpusButtons[] = $this->renderFileButton($file_uri); - $title = basename($this->getDiffusionRequest()->getPath()); - $icon = 'fa-file'; - $drequest = $this->getDiffusionRequest(); - $this->buildActionButtons($drequest); - $header = $this->buildPanelHeaderView($title, $icon); - - $box = id(new PHUIObjectBoxView()) - ->setHeader($header) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->addClass('diffusion-mobile-view') - ->appendChild($text); - - return $box; - } - private function buildErrorCorpus($message) { $text = id(new PHUIBoxView()) ->addPadding(PHUI::PADDING_LARGE) diff --git a/src/applications/diffusion/controller/DiffusionDocumentController.php b/src/applications/diffusion/controller/DiffusionDocumentController.php new file mode 100644 index 0000000000..c8956fc84c --- /dev/null +++ b/src/applications/diffusion/controller/DiffusionDocumentController.php @@ -0,0 +1,45 @@ +loadDiffusionContext(); + if ($response) { + return $response; + } + + $drequest = $this->getDiffusionRequest(); + + $engine = id(new DiffusionDocumentRenderingEngine()) + ->setRequest($request) + ->setDiffusionRequest($drequest) + ->setController($this); + + $viewer = $this->getViewer(); + $request = $this->getRequest(); + $repository = $drequest->getRepository(); + + $file_phid = $request->getStr('filePHID'); + + $file = id(new PhabricatorFileQuery()) + ->setViewer($viewer) + ->withPHIDs(array($file_phid)) + ->executeOne(); + if (!$file) { + return $engine->newErrorResponse( + pht( + 'This file ("%s") does not exist or could not be loaded.', + $file_phid)); + } + + $ref = id(new PhabricatorDocumentRef()) + ->setFile($file); + + return $engine->newRenderResponse($ref); + } + +} diff --git a/src/applications/diffusion/document/DiffusionDocumentRenderingEngine.php b/src/applications/diffusion/document/DiffusionDocumentRenderingEngine.php new file mode 100644 index 0000000000..d0b5a4b33a --- /dev/null +++ b/src/applications/diffusion/document/DiffusionDocumentRenderingEngine.php @@ -0,0 +1,67 @@ +diffusionRequest = $drequest; + return $this; + } + + public function getDiffusionRequest() { + return $this->diffusionRequest; + } + + protected function getSelectedDocumentEngineKey() { + return $this->getRequest()->getStr('as'); + } + + protected function newRefViewURI( + PhabricatorDocumentRef $ref, + PhabricatorDocumentEngine $engine) { + + $file = $ref->getFile(); + $engine_key = $engine->getDocumentEngineKey(); + $drequest = $this->getDiffusionRequest(); + + return (string)$drequest->generateURI( + array( + 'action' => 'browse', + 'stable' => true, + 'params' => array( + 'as' => $engine_key, + ), + )); + } + + protected function newRefRenderURI( + PhabricatorDocumentRef $ref, + PhabricatorDocumentEngine $engine) { + + $engine_key = $engine->getDocumentEngineKey(); + + $file = $ref->getFile(); + $file_phid = $file->getPHID(); + + $drequest = $this->getDiffusionRequest(); + + return (string)$drequest->generateURI( + array( + 'action' => 'document', + 'stable' => true, + 'params' => array( + 'as' => $engine_key, + 'filePHID' => $file_phid, + ), + )); + } + + protected function addApplicationCrumbs( + PHUICrumbsView $crumbs, + PhabricatorDocumentRef $ref = null) { + return; + } + +} diff --git a/src/applications/files/controller/PhabricatorFileDocumentController.php b/src/applications/files/controller/PhabricatorFileDocumentController.php index e74b0bc6eb..645b0e8e92 100644 --- a/src/applications/files/controller/PhabricatorFileDocumentController.php +++ b/src/applications/files/controller/PhabricatorFileDocumentController.php @@ -8,6 +8,10 @@ final class PhabricatorFileDocumentController } public function handleRequest(AphrontRequest $request) { + $engine = id(new PhabricatorFileDocumentRenderingEngine()) + ->setRequest($request) + ->setController($this); + $viewer = $request->getViewer(); $file_phid = $request->getURIData('phid'); @@ -17,7 +21,7 @@ final class PhabricatorFileDocumentController ->withPHIDs(array($file_phid)) ->executeOne(); if (!$file) { - return $this->newErrorResponse( + return $engine->newErrorResponse( pht( 'This file ("%s") does not exist or could not be loaded.', $file_phid)); @@ -26,10 +30,7 @@ final class PhabricatorFileDocumentController $ref = id(new PhabricatorDocumentRef()) ->setFile($file); - return id(new PhabricatorFileDocumentRenderingEngine()) - ->setRequest($request) - ->setController($this) - ->newRenderResponse($ref); + return $engine->newRenderResponse($ref); } } diff --git a/src/applications/files/document/render/PhabricatorDocumentRenderingEngine.php b/src/applications/files/document/render/PhabricatorDocumentRenderingEngine.php index 37b0917a65..fb6fe67e62 100644 --- a/src/applications/files/document/render/PhabricatorDocumentRenderingEngine.php +++ b/src/applications/files/document/render/PhabricatorDocumentRenderingEngine.php @@ -6,6 +6,7 @@ abstract class PhabricatorDocumentRenderingEngine private $request; private $controller; private $activeEngine; + private $ref; final public function setRequest(AphrontRequest $request) { $this->request = $request; @@ -34,13 +35,13 @@ abstract class PhabricatorDocumentRenderingEngine } final protected function getActiveEngine() { - if (!$this->activeEngine) { - throw new PhutilInvalidStateException('setActiveEngine'); - } - return $this->activeEngine; } + final protected function getRef() { + return $this->ref; + } + final public function newDocumentView(PhabricatorDocumentRef $ref) { $request = $this->getRequest(); $viewer = $request->getViewer(); @@ -173,10 +174,9 @@ abstract class PhabricatorDocumentRenderingEngine $viewer = $request->getViewer(); $engines = PhabricatorDocumentEngine::getEnginesForRef($viewer, $ref); - $engine_key = $request->getURIData('engineKey'); + $engine_key = $this->getSelectedDocumentEngineKey(); if (!isset($engines[$engine_key])) { return $this->newErrorResponse( - $ref, pht( 'The engine ("%s") is unknown, or unable to render this document.', $engine_key)); @@ -198,16 +198,13 @@ abstract class PhabricatorDocumentRenderingEngine try { $content = $engine->newDocument($ref); } catch (Exception $ex) { - return $this->newErrorResponse($ref, $ex->getMessage()); + return $this->newErrorResponse($ex->getMessage()); } - return $this->newContentResponse($ref, $content); + return $this->newContentResponse($content); } - private function newErrorResponse( - PhabricatorDocumentRef $ref, - $message) { - + public function newErrorResponse($message) { $container = phutil_tag( 'div', array( @@ -220,13 +217,10 @@ abstract class PhabricatorDocumentRenderingEngine $message, )); - return $this->newContentResponse($ref, $container); + return $this->newContentResponse($container); } - private function newContentResponse( - PhabricatorDocumentRef $ref, - $content) { - + private function newContentResponse($content) { $request = $this->getRequest(); $viewer = $request->getViewer(); $controller = $this->getController(); @@ -239,10 +233,8 @@ abstract class PhabricatorDocumentRenderingEngine )); } - $crumbs = $this->newCrumbs($ref); - if ($crumbs) { - $crumbs->setBorder(true); - } + $crumbs = $this->newCrumbs(); + $crumbs->setBorder(true); $content_frame = id(new PHUIObjectBoxView()) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) @@ -251,34 +243,46 @@ abstract class PhabricatorDocumentRenderingEngine $page_frame = id(new PHUITwoColumnView()) ->setFooter($content_frame); + $title = array(); + $ref = $this->getRef(); + if ($ref) { + $title = array( + $ref->getName(), + pht('Standalone'), + ); + } else { + $title = pht('Document'); + } + return $controller->newPage() ->setCrumbs($crumbs) - ->setTitle( - array( - $ref->getName(), - pht('Standalone'), - )) + ->setTitle($title) ->appendChild($page_frame); } - protected function newCrumbs(PhabricatorDocumentRef $ref) { + protected function newCrumbs() { + $engine = $this->getActiveEngine(); $controller = $this->getController(); + $crumbs = $controller->buildApplicationCrumbsForEditEngine(); - $this->addApplicationCrumbs($ref, $crumbs); + $ref = $this->getRef(); - $engine = $this->getActiveEngine(); - $label = $engine->getViewAsLabel($ref); - if ($label) { - $crumbs->addTextCrumb($label); + $this->addApplicationCrumbs($crumbs, $ref); + + if ($ref) { + $label = $engine->getViewAsLabel($ref); + if ($label) { + $crumbs->addTextCrumb($label); + } } return $crumbs; } protected function addApplicationCrumbs( - PhabricatorDocumentRef $ref, - PHUICrumbsView $crumbs) { + PHUICrumbsView $crumbs, + PhabricatorDocumentRef $ref = null) { return; } diff --git a/src/applications/files/document/render/PhabricatorFileDocumentRenderingEngine.php b/src/applications/files/document/render/PhabricatorFileDocumentRenderingEngine.php index f48336bea3..65e9a49681 100644 --- a/src/applications/files/document/render/PhabricatorFileDocumentRenderingEngine.php +++ b/src/applications/files/document/render/PhabricatorFileDocumentRenderingEngine.php @@ -34,12 +34,14 @@ final class PhabricatorFileDocumentRenderingEngine } protected function addApplicationCrumbs( - PhabricatorDocumentRef $ref, - PHUICrumbsView $crumbs) { + PHUICrumbsView $crumbs, + PhabricatorDocumentRef $ref = null) { - $file = $ref->getFile(); - if ($file) { - $crumbs->addTextCrumb($file->getMonogram(), $file->getInfoURI()); + if ($ref) { + $file = $ref->getFile(); + if ($file) { + $crumbs->addTextCrumb($file->getMonogram(), $file->getInfoURI()); + } } } diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php index 435e5749e6..1dfbceead0 100644 --- a/src/applications/repository/storage/PhabricatorRepository.php +++ b/src/applications/repository/storage/PhabricatorRepository.php @@ -704,6 +704,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO case 'graph': case 'clone': case 'browse': + case 'document': case 'change': case 'lastmodified': case 'tags': @@ -782,6 +783,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO case 'history': case 'graph': case 'browse': + case 'document': case 'lastmodified': case 'tags': case 'branches':