Page MenuHomePhabricator

D14313.diff
No OneTemporary

D14313.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2552,6 +2552,7 @@
'PhabricatorPasteRemarkupRule' => 'applications/paste/remarkup/PhabricatorPasteRemarkupRule.php',
'PhabricatorPasteSchemaSpec' => 'applications/paste/storage/PhabricatorPasteSchemaSpec.php',
'PhabricatorPasteSearchEngine' => 'applications/paste/query/PhabricatorPasteSearchEngine.php',
+ 'PhabricatorPasteSnippet' => 'applications/paste/snippet/PhabricatorPasteSnippet.php',
'PhabricatorPasteTestDataGenerator' => 'applications/paste/lipsum/PhabricatorPasteTestDataGenerator.php',
'PhabricatorPasteTransaction' => 'applications/paste/storage/PhabricatorPasteTransaction.php',
'PhabricatorPasteTransactionComment' => 'applications/paste/storage/PhabricatorPasteTransactionComment.php',
@@ -6633,6 +6634,7 @@
'PhabricatorPasteRemarkupRule' => 'PhabricatorObjectRemarkupRule',
'PhabricatorPasteSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PhabricatorPasteSearchEngine' => 'PhabricatorApplicationSearchEngine',
+ 'PhabricatorPasteSnippet' => 'Phobject',
'PhabricatorPasteTestDataGenerator' => 'PhabricatorTestDataGenerator',
'PhabricatorPasteTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorPasteTransactionComment' => 'PhabricatorApplicationTransactionComment',
diff --git a/src/applications/paste/controller/PhabricatorPasteController.php b/src/applications/paste/controller/PhabricatorPasteController.php
--- a/src/applications/paste/controller/PhabricatorPasteController.php
+++ b/src/applications/paste/controller/PhabricatorPasteController.php
@@ -39,13 +39,11 @@
public function buildSourceCodeView(
PhabricatorPaste $paste,
- $max_lines = null,
$highlights = array()) {
$lines = phutil_split_lines($paste->getContent());
return id(new PhabricatorSourceCodeView())
- ->setLimit($max_lines)
->setLines($lines)
->setHighlights($highlights)
->setURI(new PhutilURI($paste->getURI()));
diff --git a/src/applications/paste/controller/PhabricatorPasteViewController.php b/src/applications/paste/controller/PhabricatorPasteViewController.php
--- a/src/applications/paste/controller/PhabricatorPasteViewController.php
+++ b/src/applications/paste/controller/PhabricatorPasteViewController.php
@@ -56,10 +56,7 @@
->setHeader($header)
->addPropertyList($properties);
- $source_code = $this->buildSourceCodeView(
- $paste,
- null,
- $this->highlightMap);
+ $source_code = $this->buildSourceCodeView($paste, $this->highlightMap);
require_celerity_resource('paste-css');
$source_code = phutil_tag(
diff --git a/src/applications/paste/query/PhabricatorPasteQuery.php b/src/applications/paste/query/PhabricatorPasteQuery.php
--- a/src/applications/paste/query/PhabricatorPasteQuery.php
+++ b/src/applications/paste/query/PhabricatorPasteQuery.php
@@ -10,6 +10,7 @@
private $needContent;
private $needRawContent;
+ private $needSnippets;
private $languages;
private $includeNoLanguage;
private $dateCreatedAfter;
@@ -47,6 +48,11 @@
return $this;
}
+ public function needSnippets($need_snippets) {
+ $this->needSnippets = $need_snippets;
+ return $this;
+ }
+
public function withLanguages(array $languages) {
$this->includeNoLanguage = false;
foreach ($languages as $key => $language) {
@@ -91,6 +97,10 @@
$pastes = $this->loadContent($pastes);
}
+ if ($this->needSnippets) {
+ $pastes = $this->loadSnippets($pastes);
+ }
+
return $pastes;
}
@@ -166,6 +176,17 @@
));
}
+ private function getSnippetCacheKey(PhabricatorPaste $paste) {
+ return implode(
+ ':',
+ array(
+ 'P'.$paste->getID(),
+ $paste->getFilePHID(),
+ $paste->getLanguage(),
+ 'snippet',
+ ));
+ }
+
private function loadRawContent(array $pastes) {
$file_phids = mpull($pastes, 'getFilePHID');
$files = id(new PhabricatorFileQuery())
@@ -250,19 +271,114 @@
return $pastes;
}
+ private function loadSnippets(array $pastes) {
+ $cache = new PhabricatorKeyValueDatabaseCache();
+
+ $cache = new PhutilKeyValueCacheProfiler($cache);
+ $cache->setProfiler(PhutilServiceProfiler::getInstance());
+
+ $keys = array();
+ foreach ($pastes as $paste) {
+ $keys[] = $this->getSnippetCacheKey($paste);
+ }
+
+ $caches = $cache->getKeys($keys);
+
+ $need_raw = array();
+ $have_cache = array();
+ foreach ($pastes as $paste) {
+ $key = $this->getSnippetCacheKey($paste);
+ if (isset($caches[$key])) {
+ $snippet_data = phutil_json_decode($caches[$key], true);
+ $snippet = new PhabricatorPasteSnippet(
+ phutil_safe_html($snippet_data['content']),
+ $snippet_data['type']);
+ $paste->attachSnippet($snippet);
+ $have_cache[$paste->getPHID()] = true;
+ } else {
+ $need_raw[$key] = $paste;
+ }
+ }
+
+ if (!$need_raw) {
+ return $pastes;
+ }
+
+ $write_data = array();
+
+ $have_raw = $this->loadRawContent($need_raw);
+ $have_raw = mpull($have_raw, null, 'getPHID');
+ foreach ($pastes as $key => $paste) {
+ $paste_phid = $paste->getPHID();
+ if (isset($have_cache[$paste_phid])) {
+ continue;
+ }
+
+ if (empty($have_raw[$paste_phid])) {
+ unset($pastes[$key]);
+ continue;
+ }
+
+ $snippet = $this->buildSnippet($paste);
+ $paste->attachSnippet($snippet);
+ $snippet_data = array(
+ 'content' => (string)$snippet->getContent(),
+ 'type' => (string)$snippet->getType(),
+ );
+ $write_data[$this->getSnippetCacheKey($paste)] = phutil_json_encode(
+ $snippet_data);
+ }
+
+ if ($write_data) {
+ $cache->setKeys($write_data);
+ }
+
+ return $pastes;
+ }
+
private function buildContent(PhabricatorPaste $paste) {
- $language = $paste->getLanguage();
- $source = $paste->getRawContent();
+ return $this->highlightSource(
+ $paste->getRawContent(),
+ $paste->getTitle(),
+ $paste->getLanguage());
+ }
- if (empty($language)) {
- return PhabricatorSyntaxHighlighter::highlightWithFilename(
- $paste->getTitle(),
- $source);
- } else {
- return PhabricatorSyntaxHighlighter::highlightWithLanguage(
- $language,
- $source);
+ private function buildSnippet(PhabricatorPaste $paste) {
+ $snippet_type = PhabricatorPasteSnippet::FULL;
+ $snippet = $paste->getRawContent();
+
+ if (strlen($snippet) > 1024) {
+ $snippet_type = PhabricatorPasteSnippet::FIRST_BYTES;
+ $snippet = id(new PhutilUTF8StringTruncator())
+ ->setMaximumBytes(1024)
+ ->setTerminator('')
+ ->truncateString($snippet);
+ }
+
+ $lines = phutil_split_lines($snippet);
+ if (count($lines) > 5) {
+ $snippet_type = PhabricatorPasteSnippet::FIRST_LINES;
+ $snippet = implode('', array_slice($lines, 0, 5));
}
+
+ return new PhabricatorPasteSnippet(
+ $this->highlightSource(
+ $snippet,
+ $paste->getTitle(),
+ $paste->getLanguage()),
+ $snippet_type);
+ }
+
+ private function highlightSource($source, $title, $language) {
+ if (empty($language)) {
+ return PhabricatorSyntaxHighlighter::highlightWithFilename(
+ $title,
+ $source);
+ } else {
+ return PhabricatorSyntaxHighlighter::highlightWithLanguage(
+ $language,
+ $source);
+ }
}
public function getQueryApplicationClass() {
diff --git a/src/applications/paste/query/PhabricatorPasteSearchEngine.php b/src/applications/paste/query/PhabricatorPasteSearchEngine.php
--- a/src/applications/paste/query/PhabricatorPasteSearchEngine.php
+++ b/src/applications/paste/query/PhabricatorPasteSearchEngine.php
@@ -13,7 +13,7 @@
public function newQuery() {
return id(new PhabricatorPasteQuery())
- ->needContent(true);
+ ->needSnippets(true);
}
protected function buildQueryFromParameters(array $map) {
@@ -136,11 +136,15 @@
$created = phabricator_date($paste->getDateCreated(), $viewer);
$author = $handles[$paste->getAuthorPHID()]->renderLink();
- $lines = phutil_split_lines($paste->getContent());
+ $snippet_type = $paste->getSnippet()->getType();
+ $lines = phutil_split_lines($paste->getSnippet()->getContent());
$preview = id(new PhabricatorSourceCodeView())
- ->setLimit(5)
->setLines($lines)
+ ->setTruncatedFirstBytes(
+ $snippet_type == PhabricatorPasteSnippet::FIRST_BYTES)
+ ->setTruncatedFirstLines(
+ $snippet_type == PhabricatorPasteSnippet::FIRST_LINES)
->setURI(new PhutilURI($paste->getURI()));
$source_code = phutil_tag(
diff --git a/src/applications/paste/snippet/PhabricatorPasteSnippet.php b/src/applications/paste/snippet/PhabricatorPasteSnippet.php
new file mode 100644
--- /dev/null
+++ b/src/applications/paste/snippet/PhabricatorPasteSnippet.php
@@ -0,0 +1,24 @@
+<?php
+
+final class PhabricatorPasteSnippet extends Phobject {
+
+ const FULL = 'full';
+ const FIRST_LINES = 'first_lines';
+ const FIRST_BYTES = 'first_bytes';
+
+ private $content;
+ private $type;
+
+ public function __construct($content, $type) {
+ $this->content = $content;
+ $this->type = $type;
+ }
+
+ public function getContent() {
+ return $this->content;
+ }
+
+ public function getType() {
+ return $this->type;
+ }
+}
diff --git a/src/applications/paste/storage/PhabricatorPaste.php b/src/applications/paste/storage/PhabricatorPaste.php
--- a/src/applications/paste/storage/PhabricatorPaste.php
+++ b/src/applications/paste/storage/PhabricatorPaste.php
@@ -28,6 +28,7 @@
private $content = self::ATTACHABLE;
private $rawContent = self::ATTACHABLE;
+ private $snippet = self::ATTACHABLE;
public static function initializeNewPaste(PhabricatorUser $actor) {
$app = id(new PhabricatorApplicationQuery())
@@ -135,6 +136,15 @@
return $this;
}
+ public function getSnippet() {
+ return $this->assertAttached($this->snippet);
+ }
+
+ public function attachSnippet(PhabricatorPasteSnippet $snippet) {
+ $this->snippet = $snippet;
+ return $this;
+ }
+
/* -( PhabricatorSubscribableInterface )----------------------------------- */
diff --git a/src/view/layout/PhabricatorSourceCodeView.php b/src/view/layout/PhabricatorSourceCodeView.php
--- a/src/view/layout/PhabricatorSourceCodeView.php
+++ b/src/view/layout/PhabricatorSourceCodeView.php
@@ -3,15 +3,11 @@
final class PhabricatorSourceCodeView extends AphrontView {
private $lines;
- private $limit;
private $uri;
private $highlights = array();
private $canClickHighlight = true;
-
- public function setLimit($limit) {
- $this->limit = $limit;
- return $this;
- }
+ private $truncatedFirstBytes = false;
+ private $truncatedFirstLines = false;
public function setLines(array $lines) {
$this->lines = $lines;
@@ -33,6 +29,16 @@
return $this;
}
+ public function setTruncatedFirstBytes($truncated_first_bytes) {
+ $this->truncatedFirstBytes = $truncated_first_bytes;
+ return $this;
+ }
+
+ public function setTruncatedFirstLines($truncated_first_lines) {
+ $this->truncatedFirstLines = $truncated_first_lines;
+ return $this;
+ }
+
public function render() {
require_celerity_resource('phabricator-source-code-view-css');
require_celerity_resource('syntax-highlighting-css');
@@ -46,24 +52,31 @@
$rows = array();
- foreach ($this->lines as $line) {
- $hit_limit = $this->limit &&
- ($line_number == $this->limit) &&
- (count($this->lines) != $this->limit);
-
- if ($hit_limit) {
- $content_number = '';
- $content_line = phutil_tag(
+ $lines = $this->lines;
+ if ($this->truncatedFirstLines) {
+ $lines[] = phutil_tag(
'span',
array(
'class' => 'c',
),
pht('...'));
- } else {
- $content_number = $line_number;
- // NOTE: See phabricator-oncopy behavior.
- $content_line = hsprintf("\xE2\x80\x8B%s", $line);
- }
+ } else if ($this->truncatedFirstBytes) {
+ $last_key = last_key($lines);
+ $lines[$last_key] = hsprintf(
+ '%s%s',
+ $lines[$last_key],
+ phutil_tag(
+ 'span',
+ array(
+ 'class' => 'c',
+ ),
+ pht('...')));
+ }
+
+ foreach ($lines as $line) {
+
+ // NOTE: See phabricator-oncopy behavior.
+ $content_line = hsprintf("\xE2\x80\x8B%s", $line);
$row_attributes = array();
if (isset($this->highlights[$line_number])) {
@@ -106,10 +119,6 @@
$content_line),
));
- if ($hit_limit) {
- break;
- }
-
$line_number++;
}

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 12, 6:51 AM (1 w, 5 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6745260
Default Alt Text
D14313.diff (12 KB)

Event Timeline