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

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

+187 -653
+4
src/__phutil_library_map__.php
··· 732 732 'DiffusionDiffController' => 'applications/diffusion/controller/DiffusionDiffController.php', 733 733 'DiffusionDiffInlineCommentQuery' => 'applications/diffusion/query/DiffusionDiffInlineCommentQuery.php', 734 734 'DiffusionDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionDiffQueryConduitAPIMethod.php', 735 + 'DiffusionDocumentController' => 'applications/diffusion/controller/DiffusionDocumentController.php', 736 + 'DiffusionDocumentRenderingEngine' => 'applications/diffusion/document/DiffusionDocumentRenderingEngine.php', 735 737 'DiffusionDoorkeeperCommitFeedStoryPublisher' => 'applications/diffusion/doorkeeper/DiffusionDoorkeeperCommitFeedStoryPublisher.php', 736 738 'DiffusionEmptyResultView' => 'applications/diffusion/view/DiffusionEmptyResultView.php', 737 739 'DiffusionExistsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionExistsQueryConduitAPIMethod.php', ··· 5987 5989 'DiffusionDiffController' => 'DiffusionController', 5988 5990 'DiffusionDiffInlineCommentQuery' => 'PhabricatorDiffInlineCommentQuery', 5989 5991 'DiffusionDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 5992 + 'DiffusionDocumentController' => 'DiffusionController', 5993 + 'DiffusionDocumentRenderingEngine' => 'PhabricatorDocumentRenderingEngine', 5990 5994 'DiffusionDoorkeeperCommitFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher', 5991 5995 'DiffusionEmptyResultView' => 'DiffusionView', 5992 5996 'DiffusionExistsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
+2
src/applications/diffusion/application/PhabricatorDiffusionApplication.php
··· 53 53 'history/(?P<dblob>.*)' => 'DiffusionHistoryController', 54 54 'graph/(?P<dblob>.*)' => 'DiffusionGraphController', 55 55 'browse/(?P<dblob>.*)' => 'DiffusionBrowseController', 56 + 'document/(?P<dblob>.*)' 57 + => 'DiffusionDocumentController', 56 58 'lastmodified/(?P<dblob>.*)' => 'DiffusionLastModifiedController', 57 59 'diff/' => 'DiffusionDiffController', 58 60 'tags/(?P<dblob>.*)' => 'DiffusionTagListController',
+16 -609
src/applications/diffusion/controller/DiffusionBrowseController.php
··· 45 45 46 46 if ($is_file) { 47 47 return $this->browseFile(); 48 - } else { 49 - $paths = $results->getPaths(); 50 - $paths = $pager->sliceResults($paths); 51 - $results->setPaths($paths); 52 - 53 - return $this->browseDirectory($results, $pager); 54 48 } 49 + 50 + $paths = $results->getPaths(); 51 + $paths = $pager->sliceResults($paths); 52 + $results->setPaths($paths); 53 + 54 + return $this->browseDirectory($results, $pager); 55 55 } 56 56 57 57 private function browseSearch() { ··· 187 187 } else { 188 188 $corpus = $this->buildGitLFSCorpus($lfs_ref); 189 189 } 190 - } else if (ArcanistDiffUtils::isHeuristicBinaryFile($data)) { 191 - $file_uri = $file->getBestURI(); 192 - 193 - if ($file->isViewableImage()) { 194 - $corpus = $this->buildImageCorpus($file_uri); 195 - } else { 196 - $corpus = $this->buildBinaryCorpus($file_uri, $data); 197 - } 198 190 } else { 199 191 $this->loadLintMessages(); 200 192 $this->coverage = $drequest->loadCoverage(); 201 193 $show_editor = true; 202 194 203 - // Build the content of the file. 204 - $corpus = $this->buildCorpus( 205 - $data, 206 - $needs_blame, 207 - $drequest, 208 - $path, 209 - $data); 195 + $ref = id(new PhabricatorDocumentRef()) 196 + ->setFile($file); 197 + 198 + $engine = id(new DiffusionDocumentRenderingEngine()) 199 + ->setRequest($request) 200 + ->setDiffusionRequest($drequest); 201 + 202 + $corpus = $engine->newDocumentView($ref); 203 + 204 + $this->corpusButtons[] = $this->renderFileButton(); 210 205 } 211 206 } 212 207 ··· 514 509 '/'.$drequest->getPath()); 515 510 } 516 511 517 - private function buildCorpus( 518 - $file_corpus, 519 - $needs_blame, 520 - DiffusionRequest $drequest, 521 - $path, 522 - $data) { 523 - 524 - $viewer = $this->getViewer(); 525 - $blame_timeout = 15; 526 - $blame_failed = false; 527 - 528 - $highlight_limit = DifferentialChangesetParser::HIGHLIGHT_BYTE_LIMIT; 529 - $blame_limit = DifferentialChangesetParser::HIGHLIGHT_BYTE_LIMIT; 530 - $can_highlight = (strlen($file_corpus) <= $highlight_limit); 531 - $can_blame = (strlen($file_corpus) <= $blame_limit); 532 - 533 - if ($needs_blame && $can_blame) { 534 - $blame = $this->loadBlame($path, $drequest->getCommit(), $blame_timeout); 535 - list($blame_list, $blame_commits) = $blame; 536 - if ($blame_list === null) { 537 - $blame_failed = true; 538 - $blame_list = array(); 539 - } 540 - } else { 541 - $blame_list = array(); 542 - $blame_commits = array(); 543 - } 544 - 545 - require_celerity_resource('syntax-highlighting-css'); 546 - if ($can_highlight) { 547 - $highlighted = PhabricatorSyntaxHighlighter::highlightWithFilename( 548 - $path, 549 - $file_corpus); 550 - } else { 551 - // Highlight as plain text to escape the content properly. 552 - $highlighted = PhabricatorSyntaxHighlighter::highlightWithLanguage( 553 - 'txt', 554 - $file_corpus); 555 - } 556 - 557 - $lines = phutil_split_lines($highlighted); 558 - 559 - $rows = $this->buildDisplayRows( 560 - $lines, 561 - $blame_list, 562 - $blame_commits); 563 - 564 - $corpus_table = javelin_tag( 565 - 'table', 566 - array( 567 - 'class' => 'diffusion-source remarkup-code PhabricatorMonospaced', 568 - 'sigil' => 'phabricator-source', 569 - 'meta' => array( 570 - 'uri' => $this->getLineNumberBaseURI(), 571 - ), 572 - ), 573 - $rows); 574 - 575 - $corpus_table = phutil_tag_div('diffusion-source-wrap', $corpus_table); 576 - 577 - if ($this->getRequest()->isAjax()) { 578 - return $corpus_table; 579 - } 580 - 581 - $id = celerity_generate_unique_node_id(); 582 - 583 - $repo = $drequest->getRepository(); 584 - $symbol_repos = nonempty($repo->getSymbolSources(), array()); 585 - $symbol_repos[] = $repo->getPHID(); 586 - 587 - $lang = last(explode('.', $drequest->getPath())); 588 - $repo_languages = $repo->getSymbolLanguages(); 589 - $repo_languages = nonempty($repo_languages, array()); 590 - $repo_languages = array_fill_keys($repo_languages, true); 591 - 592 - $needs_symbols = true; 593 - if ($repo_languages && $symbol_repos) { 594 - $have_symbols = id(new DiffusionSymbolQuery()) 595 - ->existsSymbolsInRepository($repo->getPHID()); 596 - if (!$have_symbols) { 597 - $needs_symbols = false; 598 - } 599 - } 600 - 601 - if ($needs_symbols && $repo_languages) { 602 - $needs_symbols = isset($repo_languages[$lang]); 603 - } 604 - 605 - if ($needs_symbols) { 606 - Javelin::initBehavior( 607 - 'repository-crossreference', 608 - array( 609 - 'container' => $id, 610 - 'lang' => $lang, 611 - 'repositories' => $symbol_repos, 612 - )); 613 - } 614 - 615 - $corpus = phutil_tag( 616 - 'div', 617 - array( 618 - 'id' => $id, 619 - ), 620 - $corpus_table); 621 - 622 - Javelin::initBehavior('load-blame', array('id' => $id)); 623 - 624 - $this->corpusButtons[] = $this->renderFileButton(); 625 - $title = basename($this->getDiffusionRequest()->getPath()); 626 - $icon = 'fa-file-code-o'; 627 - $drequest = $this->getDiffusionRequest(); 628 - $this->buildActionButtons($drequest); 629 - 630 - $header = $this->buildPanelHeaderView($title, $icon); 631 - 632 - $corpus = id(new PHUIObjectBoxView()) 633 - ->setHeader($header) 634 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 635 - ->appendChild($corpus) 636 - ->addClass('diffusion-mobile-view') 637 - ->addSigil('diffusion-file-content-view') 638 - ->setMetadata( 639 - array( 640 - 'path' => $this->getDiffusionRequest()->getPath(), 641 - )) 642 - ->setCollapsed(true); 643 - 644 - $messages = array(); 645 - 646 - if (!$can_highlight) { 647 - $messages[] = pht( 648 - 'This file is larger than %s, so syntax highlighting is disabled '. 649 - 'by default.', 650 - phutil_format_bytes($highlight_limit)); 651 - } 652 - 653 - if (!$can_blame) { 654 - $messages[] = pht( 655 - 'This file is larger than %s, so blame is disabled.', 656 - phutil_format_bytes($blame_limit)); 657 - } 658 - 659 - if ($blame_failed) { 660 - $messages[] = pht( 661 - 'Failed to load blame information for this file in %s second(s).', 662 - new PhutilNumber($blame_timeout)); 663 - } 664 - 665 - if ($messages) { 666 - $corpus->setInfoView( 667 - id(new PHUIInfoView()) 668 - ->setSeverity(PHUIInfoView::SEVERITY_WARNING) 669 - ->setErrors($messages)); 670 - } 671 - 672 - return $corpus; 673 - } 674 - 675 512 private function buildButtonBar( 676 513 DiffusionRequest $drequest, 677 514 $show_editor) { ··· 868 705 ->setColor(PHUIButtonView::GREY); 869 706 } 870 707 871 - private function buildDisplayRows( 872 - array $lines, 873 - array $blame_list, 874 - array $blame_commits) { 875 - 876 - $request = $this->getRequest(); 877 - $viewer = $this->getViewer(); 878 - $drequest = $this->getDiffusionRequest(); 879 - $repository = $drequest->getRepository(); 880 - 881 - $revision_map = array(); 882 - $revisions = array(); 883 - if ($blame_commits) { 884 - $commit_map = mpull($blame_commits, 'getCommitIdentifier', 'getPHID'); 885 - 886 - $revision_ids = id(new DifferentialRevision()) 887 - ->loadIDsByCommitPHIDs(array_keys($commit_map)); 888 - if ($revision_ids) { 889 - $revisions = id(new DifferentialRevisionQuery()) 890 - ->setViewer($viewer) 891 - ->withIDs($revision_ids) 892 - ->execute(); 893 - $revisions = mpull($revisions, null, 'getID'); 894 - } 895 - 896 - foreach ($revision_ids as $commit_phid => $revision_id) { 897 - // If the viewer can't actually see this revision, skip it. 898 - if (!isset($revisions[$revision_id])) { 899 - continue; 900 - } 901 - $revision_map[$commit_map[$commit_phid]] = $revision_id; 902 - } 903 - } 904 - 905 - $phids = array(); 906 - foreach ($blame_commits as $commit) { 907 - $author_phid = $commit->getAuthorPHID(); 908 - if ($author_phid === null) { 909 - continue; 910 - } 911 - $phids[$author_phid] = $author_phid; 912 - } 913 - 914 - foreach ($revisions as $revision) { 915 - $author_phid = $revision->getAuthorPHID(); 916 - if ($author_phid === null) { 917 - continue; 918 - } 919 - $phids[$author_phid] = $author_phid; 920 - } 921 - 922 - $handles = $viewer->loadHandles($phids); 923 - 924 - $author_phids = array(); 925 - $author_map = array(); 926 - foreach ($blame_commits as $commit) { 927 - $commit_identifier = $commit->getCommitIdentifier(); 928 - 929 - $author_phid = ''; 930 - if (isset($revision_map[$commit_identifier])) { 931 - $revision_id = $revision_map[$commit_identifier]; 932 - $revision = $revisions[$revision_id]; 933 - $author_phid = $revision->getAuthorPHID(); 934 - } else { 935 - $author_phid = $commit->getAuthorPHID(); 936 - } 937 - 938 - $author_map[$commit_identifier] = $author_phid; 939 - $author_phids[$author_phid] = $author_phid; 940 - } 941 - 942 - $colors = array(); 943 - if ($blame_commits) { 944 - $epochs = array(); 945 - 946 - foreach ($blame_commits as $identifier => $commit) { 947 - $epochs[$identifier] = $commit->getEpoch(); 948 - } 949 - 950 - $epoch_list = array_filter($epochs); 951 - $epoch_list = array_unique($epoch_list); 952 - $epoch_list = array_values($epoch_list); 953 - 954 - $epoch_min = min($epoch_list); 955 - $epoch_max = max($epoch_list); 956 - $epoch_range = ($epoch_max - $epoch_min) + 1; 957 - 958 - foreach ($blame_commits as $identifier => $commit) { 959 - $epoch = $epochs[$identifier]; 960 - if (!$epoch) { 961 - $color = '#ffffdd'; // Warning color, missing data. 962 - } else { 963 - $color_ratio = ($epoch - $epoch_min) / $epoch_range; 964 - $color_value = 0xE6 * (1.0 - $color_ratio); 965 - $color = sprintf( 966 - '#%02x%02x%02x', 967 - $color_value, 968 - 0xF6, 969 - $color_value); 970 - } 971 - 972 - $colors[$identifier] = $color; 973 - } 974 - } 975 - 976 - $display = array(); 977 - $last_identifier = null; 978 - $last_color = null; 979 - foreach ($lines as $line_index => $line) { 980 - $color = '#f6f6f6'; 981 - $duplicate = false; 982 - if (isset($blame_list[$line_index])) { 983 - $identifier = $blame_list[$line_index]; 984 - if (isset($colors[$identifier])) { 985 - $color = $colors[$identifier]; 986 - } 987 - 988 - if ($identifier === $last_identifier) { 989 - $duplicate = true; 990 - } else { 991 - $last_identifier = $identifier; 992 - } 993 - } 994 - 995 - $display[$line_index] = array( 996 - 'data' => $line, 997 - 'target' => false, 998 - 'highlighted' => false, 999 - 'color' => $color, 1000 - 'duplicate' => $duplicate, 1001 - ); 1002 - } 1003 - 1004 - $line_arr = array(); 1005 - $line_str = $drequest->getLine(); 1006 - $ranges = explode(',', $line_str); 1007 - foreach ($ranges as $range) { 1008 - if (strpos($range, '-') !== false) { 1009 - list($min, $max) = explode('-', $range, 2); 1010 - $line_arr[] = array( 1011 - 'min' => min($min, $max), 1012 - 'max' => max($min, $max), 1013 - ); 1014 - } else if (strlen($range)) { 1015 - $line_arr[] = array( 1016 - 'min' => $range, 1017 - 'max' => $range, 1018 - ); 1019 - } 1020 - } 1021 - 1022 - // Mark the first highlighted line as the target line. 1023 - if ($line_arr) { 1024 - $target_line = $line_arr[0]['min']; 1025 - if (isset($display[$target_line - 1])) { 1026 - $display[$target_line - 1]['target'] = true; 1027 - } 1028 - } 1029 - 1030 - // Mark all other highlighted lines as highlighted. 1031 - foreach ($line_arr as $range) { 1032 - for ($ii = $range['min']; $ii <= $range['max']; $ii++) { 1033 - if (isset($display[$ii - 1])) { 1034 - $display[$ii - 1]['highlighted'] = true; 1035 - } 1036 - } 1037 - } 1038 - 1039 - $engine = null; 1040 - $inlines = array(); 1041 - if ($this->getRequest()->getStr('lint') !== null && $this->lintMessages) { 1042 - $engine = new PhabricatorMarkupEngine(); 1043 - $engine->setViewer($viewer); 1044 - 1045 - foreach ($this->lintMessages as $message) { 1046 - $inline = id(new PhabricatorAuditInlineComment()) 1047 - ->setSyntheticAuthor( 1048 - ArcanistLintSeverity::getStringForSeverity($message['severity']). 1049 - ' '.$message['code'].' ('.$message['name'].')') 1050 - ->setLineNumber($message['line']) 1051 - ->setContent($message['description']); 1052 - $inlines[$message['line']][] = $inline; 1053 - 1054 - $engine->addObject( 1055 - $inline, 1056 - PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY); 1057 - } 1058 - 1059 - $engine->process(); 1060 - require_celerity_resource('differential-changeset-view-css'); 1061 - } 1062 - 1063 - $rows = $this->renderInlines( 1064 - idx($inlines, 0, array()), 1065 - (bool)$this->coverage, 1066 - $engine); 1067 - 1068 - // NOTE: We're doing this manually because rendering is otherwise 1069 - // dominated by URI generation for very large files. 1070 - $line_base = $this->getLineNumberBaseURI(); 1071 - 1072 - require_celerity_resource('aphront-tooltip-css'); 1073 - Javelin::initBehavior('phabricator-oncopy'); 1074 - Javelin::initBehavior('phabricator-tooltips'); 1075 - Javelin::initBehavior('phabricator-line-linker'); 1076 - 1077 - // Render these once, since they tend to get repeated many times in large 1078 - // blame outputs. 1079 - $commit_links = $this->renderCommitLinks($blame_commits, $handles); 1080 - $revision_links = $this->renderRevisionLinks($revisions, $handles); 1081 - $author_links = $this->renderAuthorLinks($author_map, $handles); 1082 - 1083 - if ($this->coverage) { 1084 - require_celerity_resource('differential-changeset-view-css'); 1085 - Javelin::initBehavior( 1086 - 'diffusion-browse-file', 1087 - array( 1088 - 'labels' => array( 1089 - 'cov-C' => pht('Covered'), 1090 - 'cov-N' => pht('Not Covered'), 1091 - 'cov-U' => pht('Not Executable'), 1092 - ), 1093 - )); 1094 - } 1095 - 1096 - $skip_text = pht('Skip Past This Commit'); 1097 - $skip_icon = id(new PHUIIconView()) 1098 - ->setIcon('fa-backward'); 1099 - 1100 - foreach ($display as $line_index => $line) { 1101 - $row = array(); 1102 - 1103 - $line_number = $line_index + 1; 1104 - $line_href = $line_base.'$'.$line_number; 1105 - 1106 - if (isset($blame_list[$line_index])) { 1107 - $identifier = $blame_list[$line_index]; 1108 - } else { 1109 - $identifier = null; 1110 - } 1111 - 1112 - $revision_link = null; 1113 - $commit_link = null; 1114 - $author_link = null; 1115 - $before_link = null; 1116 - 1117 - $style = 'background: '.$line['color'].';'; 1118 - 1119 - if ($identifier && !$line['duplicate']) { 1120 - if (isset($commit_links[$identifier])) { 1121 - $commit_link = $commit_links[$identifier]; 1122 - $author_link = $author_links[$author_map[$identifier]]; 1123 - } 1124 - 1125 - if (isset($revision_map[$identifier])) { 1126 - $revision_id = $revision_map[$identifier]; 1127 - if (isset($revision_links[$revision_id])) { 1128 - $revision_link = $revision_links[$revision_id]; 1129 - } 1130 - } 1131 - 1132 - $skip_href = $line_href.'?before='.$identifier; 1133 - $before_link = javelin_tag( 1134 - 'a', 1135 - array( 1136 - 'href' => $skip_href, 1137 - 'sigil' => 'has-tooltip', 1138 - 'meta' => array( 1139 - 'tip' => $skip_text, 1140 - 'align' => 'E', 1141 - 'size' => 300, 1142 - ), 1143 - ), 1144 - $skip_icon); 1145 - } 1146 - 1147 - $row[] = phutil_tag( 1148 - 'th', 1149 - array( 1150 - 'class' => 'diffusion-blame-link', 1151 - ), 1152 - $before_link); 1153 - 1154 - $object_links = array(); 1155 - $object_links[] = $author_link; 1156 - $object_links[] = $commit_link; 1157 - if ($revision_link) { 1158 - $object_links[] = phutil_tag('span', array(), '/'); 1159 - $object_links[] = $revision_link; 1160 - } 1161 - 1162 - $row[] = phutil_tag( 1163 - 'th', 1164 - array( 1165 - 'class' => 'diffusion-rev-link', 1166 - ), 1167 - $object_links); 1168 - 1169 - $line_link = phutil_tag( 1170 - 'a', 1171 - array( 1172 - 'href' => $line_href, 1173 - 'style' => $style, 1174 - ), 1175 - $line_number); 1176 - 1177 - $row[] = javelin_tag( 1178 - 'th', 1179 - array( 1180 - 'class' => 'diffusion-line-link', 1181 - 'sigil' => 'phabricator-source-line', 1182 - 'style' => $style, 1183 - ), 1184 - $line_link); 1185 - 1186 - if ($line['target']) { 1187 - Javelin::initBehavior( 1188 - 'diffusion-jump-to', 1189 - array( 1190 - 'target' => 'scroll_target', 1191 - )); 1192 - $anchor_text = phutil_tag( 1193 - 'a', 1194 - array( 1195 - 'id' => 'scroll_target', 1196 - ), 1197 - ''); 1198 - } else { 1199 - $anchor_text = null; 1200 - } 1201 - 1202 - $row[] = phutil_tag( 1203 - 'td', 1204 - array( 1205 - ), 1206 - array( 1207 - $anchor_text, 1208 - 1209 - // NOTE: See phabricator-oncopy behavior. 1210 - "\xE2\x80\x8B", 1211 - 1212 - // TODO: [HTML] Not ideal. 1213 - phutil_safe_html(str_replace("\t", ' ', $line['data'])), 1214 - )); 1215 - 1216 - if ($this->coverage) { 1217 - $cov_index = $line_index; 1218 - 1219 - if (isset($this->coverage[$cov_index])) { 1220 - $cov_class = $this->coverage[$cov_index]; 1221 - } else { 1222 - $cov_class = 'N'; 1223 - } 1224 - 1225 - $row[] = phutil_tag( 1226 - 'td', 1227 - array( 1228 - 'class' => 'cov cov-'.$cov_class, 1229 - ), 1230 - ''); 1231 - } 1232 - 1233 - $rows[] = phutil_tag( 1234 - 'tr', 1235 - array( 1236 - 'class' => ($line['highlighted'] ? 1237 - 'phabricator-source-highlight' : 1238 - null), 1239 - ), 1240 - $row); 1241 - 1242 - $cur_inlines = $this->renderInlines( 1243 - idx($inlines, $line_number, array()), 1244 - $this->coverage, 1245 - $engine); 1246 - foreach ($cur_inlines as $cur_inline) { 1247 - $rows[] = $cur_inline; 1248 - } 1249 - } 1250 - 1251 - return $rows; 1252 - } 1253 - 1254 708 private function renderInlines( 1255 709 array $inlines, 1256 710 $has_coverage, ··· 1283 737 } 1284 738 1285 739 return $rows; 1286 - } 1287 - 1288 - private function buildImageCorpus($file_uri) { 1289 - $properties = new PHUIPropertyListView(); 1290 - 1291 - $properties->addImageContent( 1292 - phutil_tag( 1293 - 'img', 1294 - array( 1295 - 'src' => $file_uri, 1296 - ))); 1297 - 1298 - $this->corpusButtons[] = $this->renderFileButton($file_uri); 1299 - $title = basename($this->getDiffusionRequest()->getPath()); 1300 - $icon = 'fa-file-image-o'; 1301 - $drequest = $this->getDiffusionRequest(); 1302 - $this->buildActionButtons($drequest); 1303 - $header = $this->buildPanelHeaderView($title, $icon); 1304 - 1305 - return id(new PHUIObjectBoxView()) 1306 - ->setHeader($header) 1307 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 1308 - ->addClass('diffusion-mobile-view') 1309 - ->addPropertyList($properties); 1310 - } 1311 - 1312 - private function buildBinaryCorpus($file_uri, $data) { 1313 - $size = new PhutilNumber(strlen($data)); 1314 - $text = pht('This is a binary file. It is %s byte(s) in length.', $size); 1315 - $text = id(new PHUIBoxView()) 1316 - ->addPadding(PHUI::PADDING_LARGE) 1317 - ->appendChild($text); 1318 - 1319 - $this->corpusButtons[] = $this->renderFileButton($file_uri); 1320 - $title = basename($this->getDiffusionRequest()->getPath()); 1321 - $icon = 'fa-file'; 1322 - $drequest = $this->getDiffusionRequest(); 1323 - $this->buildActionButtons($drequest); 1324 - $header = $this->buildPanelHeaderView($title, $icon); 1325 - 1326 - $box = id(new PHUIObjectBoxView()) 1327 - ->setHeader($header) 1328 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 1329 - ->addClass('diffusion-mobile-view') 1330 - ->appendChild($text); 1331 - 1332 - return $box; 1333 740 } 1334 741 1335 742 private function buildErrorCorpus($message) {
+45
src/applications/diffusion/controller/DiffusionDocumentController.php
··· 1 + <?php 2 + 3 + final class DiffusionDocumentController extends DiffusionController { 4 + 5 + public function shouldAllowPublic() { 6 + return true; 7 + } 8 + 9 + public function handleRequest(AphrontRequest $request) { 10 + $response = $this->loadDiffusionContext(); 11 + if ($response) { 12 + return $response; 13 + } 14 + 15 + $drequest = $this->getDiffusionRequest(); 16 + 17 + $engine = id(new DiffusionDocumentRenderingEngine()) 18 + ->setRequest($request) 19 + ->setDiffusionRequest($drequest) 20 + ->setController($this); 21 + 22 + $viewer = $this->getViewer(); 23 + $request = $this->getRequest(); 24 + $repository = $drequest->getRepository(); 25 + 26 + $file_phid = $request->getStr('filePHID'); 27 + 28 + $file = id(new PhabricatorFileQuery()) 29 + ->setViewer($viewer) 30 + ->withPHIDs(array($file_phid)) 31 + ->executeOne(); 32 + if (!$file) { 33 + return $engine->newErrorResponse( 34 + pht( 35 + 'This file ("%s") does not exist or could not be loaded.', 36 + $file_phid)); 37 + } 38 + 39 + $ref = id(new PhabricatorDocumentRef()) 40 + ->setFile($file); 41 + 42 + return $engine->newRenderResponse($ref); 43 + } 44 + 45 + }
+67
src/applications/diffusion/document/DiffusionDocumentRenderingEngine.php
··· 1 + <?php 2 + 3 + final class DiffusionDocumentRenderingEngine 4 + extends PhabricatorDocumentRenderingEngine { 5 + 6 + private $diffusionRequest; 7 + 8 + public function setDiffusionRequest(DiffusionRequest $drequest) { 9 + $this->diffusionRequest = $drequest; 10 + return $this; 11 + } 12 + 13 + public function getDiffusionRequest() { 14 + return $this->diffusionRequest; 15 + } 16 + 17 + protected function getSelectedDocumentEngineKey() { 18 + return $this->getRequest()->getStr('as'); 19 + } 20 + 21 + protected function newRefViewURI( 22 + PhabricatorDocumentRef $ref, 23 + PhabricatorDocumentEngine $engine) { 24 + 25 + $file = $ref->getFile(); 26 + $engine_key = $engine->getDocumentEngineKey(); 27 + $drequest = $this->getDiffusionRequest(); 28 + 29 + return (string)$drequest->generateURI( 30 + array( 31 + 'action' => 'browse', 32 + 'stable' => true, 33 + 'params' => array( 34 + 'as' => $engine_key, 35 + ), 36 + )); 37 + } 38 + 39 + protected function newRefRenderURI( 40 + PhabricatorDocumentRef $ref, 41 + PhabricatorDocumentEngine $engine) { 42 + 43 + $engine_key = $engine->getDocumentEngineKey(); 44 + 45 + $file = $ref->getFile(); 46 + $file_phid = $file->getPHID(); 47 + 48 + $drequest = $this->getDiffusionRequest(); 49 + 50 + return (string)$drequest->generateURI( 51 + array( 52 + 'action' => 'document', 53 + 'stable' => true, 54 + 'params' => array( 55 + 'as' => $engine_key, 56 + 'filePHID' => $file_phid, 57 + ), 58 + )); 59 + } 60 + 61 + protected function addApplicationCrumbs( 62 + PHUICrumbsView $crumbs, 63 + PhabricatorDocumentRef $ref = null) { 64 + return; 65 + } 66 + 67 + }
+6 -5
src/applications/files/controller/PhabricatorFileDocumentController.php
··· 8 8 } 9 9 10 10 public function handleRequest(AphrontRequest $request) { 11 + $engine = id(new PhabricatorFileDocumentRenderingEngine()) 12 + ->setRequest($request) 13 + ->setController($this); 14 + 11 15 $viewer = $request->getViewer(); 12 16 13 17 $file_phid = $request->getURIData('phid'); ··· 17 21 ->withPHIDs(array($file_phid)) 18 22 ->executeOne(); 19 23 if (!$file) { 20 - return $this->newErrorResponse( 24 + return $engine->newErrorResponse( 21 25 pht( 22 26 'This file ("%s") does not exist or could not be loaded.', 23 27 $file_phid)); ··· 26 30 $ref = id(new PhabricatorDocumentRef()) 27 31 ->setFile($file); 28 32 29 - return id(new PhabricatorFileDocumentRenderingEngine()) 30 - ->setRequest($request) 31 - ->setController($this) 32 - ->newRenderResponse($ref); 33 + return $engine->newRenderResponse($ref); 33 34 } 34 35 35 36 }
+38 -34
src/applications/files/document/render/PhabricatorDocumentRenderingEngine.php
··· 6 6 private $request; 7 7 private $controller; 8 8 private $activeEngine; 9 + private $ref; 9 10 10 11 final public function setRequest(AphrontRequest $request) { 11 12 $this->request = $request; ··· 34 35 } 35 36 36 37 final protected function getActiveEngine() { 37 - if (!$this->activeEngine) { 38 - throw new PhutilInvalidStateException('setActiveEngine'); 39 - } 40 - 41 38 return $this->activeEngine; 39 + } 40 + 41 + final protected function getRef() { 42 + return $this->ref; 42 43 } 43 44 44 45 final public function newDocumentView(PhabricatorDocumentRef $ref) { ··· 173 174 $viewer = $request->getViewer(); 174 175 175 176 $engines = PhabricatorDocumentEngine::getEnginesForRef($viewer, $ref); 176 - $engine_key = $request->getURIData('engineKey'); 177 + $engine_key = $this->getSelectedDocumentEngineKey(); 177 178 if (!isset($engines[$engine_key])) { 178 179 return $this->newErrorResponse( 179 - $ref, 180 180 pht( 181 181 'The engine ("%s") is unknown, or unable to render this document.', 182 182 $engine_key)); ··· 198 198 try { 199 199 $content = $engine->newDocument($ref); 200 200 } catch (Exception $ex) { 201 - return $this->newErrorResponse($ref, $ex->getMessage()); 201 + return $this->newErrorResponse($ex->getMessage()); 202 202 } 203 203 204 - return $this->newContentResponse($ref, $content); 204 + return $this->newContentResponse($content); 205 205 } 206 206 207 - private function newErrorResponse( 208 - PhabricatorDocumentRef $ref, 209 - $message) { 210 - 207 + public function newErrorResponse($message) { 211 208 $container = phutil_tag( 212 209 'div', 213 210 array( ··· 220 217 $message, 221 218 )); 222 219 223 - return $this->newContentResponse($ref, $container); 220 + return $this->newContentResponse($container); 224 221 } 225 222 226 - private function newContentResponse( 227 - PhabricatorDocumentRef $ref, 228 - $content) { 229 - 223 + private function newContentResponse($content) { 230 224 $request = $this->getRequest(); 231 225 $viewer = $request->getViewer(); 232 226 $controller = $this->getController(); ··· 239 233 )); 240 234 } 241 235 242 - $crumbs = $this->newCrumbs($ref); 243 - if ($crumbs) { 244 - $crumbs->setBorder(true); 245 - } 236 + $crumbs = $this->newCrumbs(); 237 + $crumbs->setBorder(true); 246 238 247 239 $content_frame = id(new PHUIObjectBoxView()) 248 240 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ··· 251 243 $page_frame = id(new PHUITwoColumnView()) 252 244 ->setFooter($content_frame); 253 245 246 + $title = array(); 247 + $ref = $this->getRef(); 248 + if ($ref) { 249 + $title = array( 250 + $ref->getName(), 251 + pht('Standalone'), 252 + ); 253 + } else { 254 + $title = pht('Document'); 255 + } 256 + 254 257 return $controller->newPage() 255 258 ->setCrumbs($crumbs) 256 - ->setTitle( 257 - array( 258 - $ref->getName(), 259 - pht('Standalone'), 260 - )) 259 + ->setTitle($title) 261 260 ->appendChild($page_frame); 262 261 } 263 262 264 - protected function newCrumbs(PhabricatorDocumentRef $ref) { 263 + protected function newCrumbs() { 264 + $engine = $this->getActiveEngine(); 265 265 $controller = $this->getController(); 266 + 266 267 $crumbs = $controller->buildApplicationCrumbsForEditEngine(); 267 268 268 - $this->addApplicationCrumbs($ref, $crumbs); 269 + $ref = $this->getRef(); 270 + 271 + $this->addApplicationCrumbs($crumbs, $ref); 269 272 270 - $engine = $this->getActiveEngine(); 271 - $label = $engine->getViewAsLabel($ref); 272 - if ($label) { 273 - $crumbs->addTextCrumb($label); 273 + if ($ref) { 274 + $label = $engine->getViewAsLabel($ref); 275 + if ($label) { 276 + $crumbs->addTextCrumb($label); 277 + } 274 278 } 275 279 276 280 return $crumbs; 277 281 } 278 282 279 283 protected function addApplicationCrumbs( 280 - PhabricatorDocumentRef $ref, 281 - PHUICrumbsView $crumbs) { 284 + PHUICrumbsView $crumbs, 285 + PhabricatorDocumentRef $ref = null) { 282 286 return; 283 287 } 284 288
+7 -5
src/applications/files/document/render/PhabricatorFileDocumentRenderingEngine.php
··· 34 34 } 35 35 36 36 protected function addApplicationCrumbs( 37 - PhabricatorDocumentRef $ref, 38 - PHUICrumbsView $crumbs) { 37 + PHUICrumbsView $crumbs, 38 + PhabricatorDocumentRef $ref = null) { 39 39 40 - $file = $ref->getFile(); 41 - if ($file) { 42 - $crumbs->addTextCrumb($file->getMonogram(), $file->getInfoURI()); 40 + if ($ref) { 41 + $file = $ref->getFile(); 42 + if ($file) { 43 + $crumbs->addTextCrumb($file->getMonogram(), $file->getInfoURI()); 44 + } 43 45 } 44 46 45 47 }
+2
src/applications/repository/storage/PhabricatorRepository.php
··· 704 704 case 'graph': 705 705 case 'clone': 706 706 case 'browse': 707 + case 'document': 707 708 case 'change': 708 709 case 'lastmodified': 709 710 case 'tags': ··· 782 783 case 'history': 783 784 case 'graph': 784 785 case 'browse': 786 + case 'document': 785 787 case 'lastmodified': 786 788 case 'tags': 787 789 case 'branches':