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

Implement ngram search for File objects

Summary: Follows the outline in D15656 for implementing ngram search for names of File objects. Also created FileFullTextEngine, because without implementing `PhabricatorFulltextInterface`, `./bin/search` complains that `File` is not an indexable type.

Test Plan:
- ran `./bin/storage upgrade` to apply the schema change
- confirmed the presence of a new `file_filename_ngrams` table
- added a couple file objects
- ran `bin/search index --type file --force`
- confirmed the presence of rows in `file_filename_ngrams`
- did a few keyword searches and saw expected results

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

Maniphest Tasks: T8788

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

+63 -5
+7
resources/sql/autopatches/20170417.files.ngrams.sql
··· 1 + CREATE TABLE {$NAMESPACE}_file.file_filename_ngrams ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + objectID INT UNSIGNED NOT NULL, 4 + ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT}, 5 + KEY `key_object` (objectID), 6 + KEY `key_ngram` (ngram, objectID) 7 + ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+4
src/__phutil_library_map__.php
··· 2781 2781 'PhabricatorFileLightboxController' => 'applications/files/controller/PhabricatorFileLightboxController.php', 2782 2782 'PhabricatorFileLinkView' => 'view/layout/PhabricatorFileLinkView.php', 2783 2783 'PhabricatorFileListController' => 'applications/files/controller/PhabricatorFileListController.php', 2784 + 'PhabricatorFileNameNgrams' => 'applications/files/storage/PhabricatorFileNameNgrams.php', 2784 2785 'PhabricatorFileNameTransaction' => 'applications/files/xaction/PhabricatorFileNameTransaction.php', 2785 2786 'PhabricatorFileQuery' => 'applications/files/query/PhabricatorFileQuery.php', 2786 2787 'PhabricatorFileROT13StorageFormat' => 'applications/files/format/PhabricatorFileROT13StorageFormat.php', ··· 7908 7909 'PhabricatorPolicyInterface', 7909 7910 'PhabricatorDestructibleInterface', 7910 7911 'PhabricatorConduitResultInterface', 7912 + 'PhabricatorIndexableInterface', 7913 + 'PhabricatorNgramsInterface', 7911 7914 ), 7912 7915 'PhabricatorFileAES256StorageFormat' => 'PhabricatorFileStorageFormat', 7913 7916 'PhabricatorFileBundleLoader' => 'Phobject', ··· 7954 7957 'PhabricatorFileLightboxController' => 'PhabricatorFileController', 7955 7958 'PhabricatorFileLinkView' => 'AphrontTagView', 7956 7959 'PhabricatorFileListController' => 'PhabricatorFileController', 7960 + 'PhabricatorFileNameNgrams' => 'PhabricatorSearchNgrams', 7957 7961 'PhabricatorFileNameTransaction' => 'PhabricatorFileTransactionType', 7958 7962 'PhabricatorFileQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 7959 7963 'PhabricatorFileROT13StorageFormat' => 'PhabricatorFileStorageFormat',
+2 -1
src/applications/files/controller/PhabricatorFileDeleteController.php
··· 25 25 } 26 26 27 27 if ($request->isFormPost()) { 28 - $file->delete(); 28 + $engine = new PhabricatorDestructionEngine(); 29 + $engine->destroyObject($file); 29 30 return id(new AphrontRedirectResponse())->setURI('/file/'); 30 31 } 31 32
+1 -1
src/applications/files/editor/PhabricatorFileEditor.php
··· 71 71 } 72 72 73 73 protected function supportsSearch() { 74 - return false; 74 + return true; 75 75 } 76 76 77 77 }
+3 -1
src/applications/files/garbagecollector/PhabricatorFileTemporaryGarbageCollector.php
··· 18 18 'ttl < %d LIMIT 100', 19 19 PhabricatorTime::getNow()); 20 20 21 + $engine = new PhabricatorDestructionEngine(); 22 + 21 23 foreach ($files as $file) { 22 - $file->delete(); 24 + $engine->destroyObject($file); 23 25 } 24 26 25 27 return (count($files) == 100);
+6
src/applications/files/query/PhabricatorFileQuery.php
··· 119 119 return $this; 120 120 } 121 121 122 + public function withNameNgrams($ngrams) { 123 + return $this->withNgramsConstraint( 124 + id(new PhabricatorFileNameNgrams()), 125 + $ngrams); 126 + } 127 + 122 128 public function showOnlyExplicitUploads($explicit_uploads) { 123 129 $this->explicitUploads = $explicit_uploads; 124 130 return $this;
+8
src/applications/files/query/PhabricatorFileSearchEngine.php
··· 38 38 id(new PhabricatorSearchDateField()) 39 39 ->setKey('createdEnd') 40 40 ->setLabel(pht('Created Before')), 41 + id(new PhabricatorSearchTextField()) 42 + ->setLabel(pht('Name Contains')) 43 + ->setKey('name') 44 + ->setDescription(pht('Search for files by name substring.')), 41 45 ); 42 46 } 43 47 ··· 66 70 67 71 if ($map['createdEnd']) { 68 72 $query->withDateCreatedBefore($map['createdEnd']); 73 + } 74 + 75 + if ($map['name'] !== null) { 76 + $query->withNameNgrams($map['name']); 69 77 } 70 78 71 79 return $query;
+14 -2
src/applications/files/storage/PhabricatorFile.php
··· 28 28 PhabricatorFlaggableInterface, 29 29 PhabricatorPolicyInterface, 30 30 PhabricatorDestructibleInterface, 31 - PhabricatorConduitResultInterface { 31 + PhabricatorConduitResultInterface, 32 + PhabricatorIndexableInterface, 33 + PhabricatorNgramsInterface { 32 34 33 35 const METADATA_IMAGE_WIDTH = 'width'; 34 36 const METADATA_IMAGE_HEIGHT = 'height'; ··· 87 89 'metadata' => self::SERIALIZATION_JSON, 88 90 ), 89 91 self::CONFIG_COLUMN_SCHEMA => array( 90 - 'name' => 'text255?', 92 + 'name' => 'sort255?', 91 93 'mimeType' => 'text255?', 92 94 'byteSize' => 'uint64', 93 95 'storageEngine' => 'text32', ··· 1583 1585 1584 1586 public function getConduitSearchAttachments() { 1585 1587 return array(); 1588 + } 1589 + 1590 + /* -( PhabricatorNgramInterface )------------------------------------------ */ 1591 + 1592 + 1593 + public function newNgrams() { 1594 + return array( 1595 + id(new PhabricatorFileNameNgrams()) 1596 + ->setValue($this->getName()), 1597 + ); 1586 1598 } 1587 1599 1588 1600 }
+18
src/applications/files/storage/PhabricatorFileNameNgrams.php
··· 1 + <?php 2 + 3 + final class PhabricatorFileNameNgrams 4 + extends PhabricatorSearchNgrams { 5 + 6 + public function getNgramKey() { 7 + return 'filename'; 8 + } 9 + 10 + public function getColumnName() { 11 + return 'name'; 12 + } 13 + 14 + public function getApplicationName() { 15 + return 'file'; 16 + } 17 + 18 + }