Path: blob/master/src/applications/paste/query/PhabricatorPasteQuery.php
12241 views
<?php12final class PhabricatorPasteQuery3extends PhabricatorCursorPagedPolicyAwareQuery {45private $ids;6private $phids;7private $authorPHIDs;8private $parentPHIDs;910private $needContent;11private $needRawContent;12private $needSnippets;13private $languages;14private $includeNoLanguage;15private $dateCreatedAfter;16private $dateCreatedBefore;17private $statuses;181920public function withIDs(array $ids) {21$this->ids = $ids;22return $this;23}2425public function withPHIDs(array $phids) {26$this->phids = $phids;27return $this;28}2930public function withAuthorPHIDs(array $phids) {31$this->authorPHIDs = $phids;32return $this;33}3435public function withParentPHIDs(array $phids) {36$this->parentPHIDs = $phids;37return $this;38}3940public function needContent($need_content) {41$this->needContent = $need_content;42return $this;43}4445public function needRawContent($need_raw_content) {46$this->needRawContent = $need_raw_content;47return $this;48}4950public function needSnippets($need_snippets) {51$this->needSnippets = $need_snippets;52return $this;53}5455public function withLanguages(array $languages) {56$this->includeNoLanguage = false;57foreach ($languages as $key => $language) {58if ($language === null) {59$languages[$key] = '';60continue;61}62}63$this->languages = $languages;64return $this;65}6667public function withDateCreatedBefore($date_created_before) {68$this->dateCreatedBefore = $date_created_before;69return $this;70}7172public function withDateCreatedAfter($date_created_after) {73$this->dateCreatedAfter = $date_created_after;74return $this;75}7677public function withStatuses(array $statuses) {78$this->statuses = $statuses;79return $this;80}8182public function newResultObject() {83return new PhabricatorPaste();84}8586protected function didFilterPage(array $pastes) {87if ($this->needRawContent) {88$pastes = $this->loadRawContent($pastes);89}9091if ($this->needContent) {92$pastes = $this->loadContent($pastes);93}9495if ($this->needSnippets) {96$pastes = $this->loadSnippets($pastes);97}9899return $pastes;100}101102protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {103$where = parent::buildWhereClauseParts($conn);104105if ($this->ids !== null) {106$where[] = qsprintf(107$conn,108'paste.id IN (%Ld)',109$this->ids);110}111112if ($this->phids !== null) {113$where[] = qsprintf(114$conn,115'paste.phid IN (%Ls)',116$this->phids);117}118119if ($this->authorPHIDs !== null) {120$where[] = qsprintf(121$conn,122'paste.authorPHID IN (%Ls)',123$this->authorPHIDs);124}125126if ($this->parentPHIDs !== null) {127$where[] = qsprintf(128$conn,129'paste.parentPHID IN (%Ls)',130$this->parentPHIDs);131}132133if ($this->languages !== null) {134$where[] = qsprintf(135$conn,136'paste.language IN (%Ls)',137$this->languages);138}139140if ($this->dateCreatedAfter !== null) {141$where[] = qsprintf(142$conn,143'paste.dateCreated >= %d',144$this->dateCreatedAfter);145}146147if ($this->dateCreatedBefore !== null) {148$where[] = qsprintf(149$conn,150'paste.dateCreated <= %d',151$this->dateCreatedBefore);152}153154if ($this->statuses !== null) {155$where[] = qsprintf(156$conn,157'paste.status IN (%Ls)',158$this->statuses);159}160161return $where;162}163164protected function getPrimaryTableAlias() {165return 'paste';166}167168private function getContentCacheKey(PhabricatorPaste $paste) {169return implode(170':',171array(172'P'.$paste->getID(),173$paste->getFilePHID(),174$paste->getLanguage(),175PhabricatorHash::digestForIndex($paste->getTitle()),176));177}178179private function getSnippetCacheKey(PhabricatorPaste $paste) {180return implode(181':',182array(183'P'.$paste->getID(),184$paste->getFilePHID(),185$paste->getLanguage(),186'snippet',187'v2.1',188PhabricatorHash::digestForIndex($paste->getTitle()),189));190}191192private function loadRawContent(array $pastes) {193$file_phids = mpull($pastes, 'getFilePHID');194$files = id(new PhabricatorFileQuery())195->setParentQuery($this)196->setViewer($this->getViewer())197->withPHIDs($file_phids)198->execute();199$files = mpull($files, null, 'getPHID');200201foreach ($pastes as $key => $paste) {202$file = idx($files, $paste->getFilePHID());203if (!$file) {204unset($pastes[$key]);205continue;206}207try {208$paste->attachRawContent($file->loadFileData());209} catch (Exception $ex) {210// We can hit various sorts of file storage issues here. Just drop the211// paste if the file is dead.212unset($pastes[$key]);213continue;214}215}216217return $pastes;218}219220private function loadContent(array $pastes) {221$cache = new PhabricatorKeyValueDatabaseCache();222223$cache = new PhutilKeyValueCacheProfiler($cache);224$cache->setProfiler(PhutilServiceProfiler::getInstance());225226$keys = array();227foreach ($pastes as $paste) {228$keys[] = $this->getContentCacheKey($paste);229}230231$caches = $cache->getKeys($keys);232233$need_raw = array();234$have_cache = array();235foreach ($pastes as $paste) {236$key = $this->getContentCacheKey($paste);237if (isset($caches[$key])) {238$paste->attachContent(phutil_safe_html($caches[$key]));239$have_cache[$paste->getPHID()] = true;240} else {241$need_raw[$key] = $paste;242}243}244245if (!$need_raw) {246return $pastes;247}248249$write_data = array();250251$have_raw = $this->loadRawContent($need_raw);252$have_raw = mpull($have_raw, null, 'getPHID');253foreach ($pastes as $key => $paste) {254$paste_phid = $paste->getPHID();255if (isset($have_cache[$paste_phid])) {256continue;257}258259if (empty($have_raw[$paste_phid])) {260unset($pastes[$key]);261continue;262}263264$content = $this->buildContent($paste);265$paste->attachContent($content);266$write_data[$this->getContentCacheKey($paste)] = (string)$content;267}268269if ($write_data) {270$cache->setKeys($write_data);271}272273return $pastes;274}275276private function loadSnippets(array $pastes) {277$cache = new PhabricatorKeyValueDatabaseCache();278279$cache = new PhutilKeyValueCacheProfiler($cache);280$cache->setProfiler(PhutilServiceProfiler::getInstance());281282$keys = array();283foreach ($pastes as $paste) {284$keys[] = $this->getSnippetCacheKey($paste);285}286287$caches = $cache->getKeys($keys);288289$need_raw = array();290$have_cache = array();291foreach ($pastes as $paste) {292$key = $this->getSnippetCacheKey($paste);293if (isset($caches[$key])) {294$snippet_data = phutil_json_decode($caches[$key]);295$snippet = new PhabricatorPasteSnippet(296phutil_safe_html($snippet_data['content']),297$snippet_data['type'],298$snippet_data['contentLineCount']);299$paste->attachSnippet($snippet);300$have_cache[$paste->getPHID()] = true;301} else {302$need_raw[$key] = $paste;303}304}305306if (!$need_raw) {307return $pastes;308}309310$write_data = array();311312$have_raw = $this->loadRawContent($need_raw);313$have_raw = mpull($have_raw, null, 'getPHID');314foreach ($pastes as $key => $paste) {315$paste_phid = $paste->getPHID();316if (isset($have_cache[$paste_phid])) {317continue;318}319320if (empty($have_raw[$paste_phid])) {321unset($pastes[$key]);322continue;323}324325$snippet = $this->buildSnippet($paste);326$paste->attachSnippet($snippet);327$snippet_data = array(328'content' => (string)$snippet->getContent(),329'type' => (string)$snippet->getType(),330'contentLineCount' => $snippet->getContentLineCount(),331);332$write_data[$this->getSnippetCacheKey($paste)] = phutil_json_encode(333$snippet_data);334}335336if ($write_data) {337$cache->setKeys($write_data);338}339340return $pastes;341}342343private function buildContent(PhabricatorPaste $paste) {344return $this->highlightSource(345$paste->getRawContent(),346$paste->getTitle(),347$paste->getLanguage());348}349350private function buildSnippet(PhabricatorPaste $paste) {351$snippet_type = PhabricatorPasteSnippet::FULL;352$snippet = $paste->getRawContent();353354$lines = phutil_split_lines($snippet);355$line_count = count($lines);356357if (strlen($snippet) > 1024) {358$snippet_type = PhabricatorPasteSnippet::FIRST_BYTES;359$snippet = id(new PhutilUTF8StringTruncator())360->setMaximumBytes(1024)361->setTerminator('')362->truncateString($snippet);363}364365if ($line_count > 5) {366$snippet_type = PhabricatorPasteSnippet::FIRST_LINES;367$snippet = implode('', array_slice($lines, 0, 5));368}369370return new PhabricatorPasteSnippet(371$this->highlightSource(372$snippet,373$paste->getTitle(),374$paste->getLanguage()),375$snippet_type,376$line_count);377}378379private function highlightSource($source, $title, $language) {380if (empty($language)) {381return PhabricatorSyntaxHighlighter::highlightWithFilename(382$title,383$source);384} else {385return PhabricatorSyntaxHighlighter::highlightWithLanguage(386$language,387$source);388}389}390391public function getQueryApplicationClass() {392return 'PhabricatorPasteApplication';393}394395}396397398