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

Don't show document types in search for uninstalled applications

Summary:
Fixes T4917. Currently, if a user doesn't have access to, e.g., Phriction, they still get a checkbox in the search results to search for Wiki Documents. Those results will be filtered anyway, so this is confusing at best.

Instead, bind PHID types to applications. This is a relatively tailored fix; some areas for potential future work:

- Go through every PHID type and bind them all to applications. Vaguely nice to have, but doesn't get us anything for now.
- If no searchable application is installed, we don't show you an error state. This isn't currently possible ("People" is always installed) but in the interest of generality we could throw an exception or something at least.
- The elasticserach thing could probably constrain types to visible types, but we don't have a viewer there easily right now.

Test Plan: Uninstalled Phriction, saw the checkbox vanish.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T4917

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

+108 -6
+4
src/applications/differential/phid/DifferentialPHIDTypeRevision.php
··· 12 12 return pht('Revision'); 13 13 } 14 14 15 + public function getPHIDTypeApplicationClass() { 16 + return 'PhabricatorApplicationDifferential'; 17 + } 18 + 15 19 public function newObject() { 16 20 return new DifferentialRevision(); 17 21 }
+4
src/applications/maniphest/phid/ManiphestPHIDTypeTask.php
··· 12 12 return pht('Task'); 13 13 } 14 14 15 + public function getPHIDTypeApplicationClass() { 16 + return 'PhabricatorApplicationManiphest'; 17 + } 18 + 15 19 public function newObject() { 16 20 return new ManiphestTask(); 17 21 }
+4
src/applications/people/phid/PhabricatorPeoplePHIDTypeUser.php
··· 12 12 return pht('User'); 13 13 } 14 14 15 + public function getPHIDTypeApplicationClass() { 16 + return 'PhabricatorApplicationPeople'; 17 + } 18 + 15 19 public function getTypeIcon() { 16 20 return 'policy-all'; 17 21 }
+67
src/applications/phid/type/PhabricatorPHIDType.php
··· 13 13 return null; 14 14 } 15 15 16 + 17 + /** 18 + * Get the class name for the application this type belongs to. 19 + * 20 + * @return string|null Class name of the corresponding application, or null 21 + * if the type is not bound to an application. 22 + */ 23 + public function getPHIDTypeApplicationClass() { 24 + // TODO: Some day this should probably be abstract, but for now it only 25 + // affects global search and there's no real burning need to go classify 26 + // every PHID type. 27 + return null; 28 + } 29 + 16 30 /** 17 31 * Build a @{class:PhabricatorPolicyAwareQuery} to load objects of this type 18 32 * by PHID. ··· 103 117 throw new Exception("Not implemented!"); 104 118 } 105 119 120 + 121 + /** 122 + * Get all known PHID types. 123 + * 124 + * To get PHID types a given user has access to, see 125 + * @{method:getAllInstalledTypes}. 126 + * 127 + * @return dict<string, PhabricatorPHIDType> Map of type constants to types. 128 + */ 106 129 public static function getAllTypes() { 107 130 static $types; 108 131 if ($types === null) { ··· 131 154 } 132 155 133 156 return $types; 157 + } 158 + 159 + 160 + /** 161 + * Get all PHID types of applications installed for a given viewer. 162 + * 163 + * @param PhabricatorUser Viewing user. 164 + * @return dict<string, PhabricatorPHIDType> Map of constants to installed 165 + * types. 166 + */ 167 + public static function getAllInstalledTypes(PhabricatorUser $viewer) { 168 + $all_types = self::getAllTypes(); 169 + 170 + $installed_types = array(); 171 + 172 + $app_classes = array(); 173 + foreach ($all_types as $key => $type) { 174 + $app_class = $type->getPHIDTypeApplicationClass(); 175 + 176 + if ($app_class === null) { 177 + // If the PHID type isn't bound to an application, include it as 178 + // installed. 179 + $installed_types[$key] = $type; 180 + continue; 181 + } 182 + 183 + // Otherwise, we need to check if this application is installed before 184 + // including the PHID type. 185 + $app_classes[$app_class][$key] = $type; 186 + } 187 + 188 + if ($app_classes) { 189 + $apps = id(new PhabricatorApplicationQuery()) 190 + ->setViewer($viewer) 191 + ->withInstalled(true) 192 + ->withClasses(array_keys($app_classes)) 193 + ->execute(); 194 + 195 + foreach ($apps as $app_class => $app) { 196 + $installed_types += $app_classes[$app_class]; 197 + } 198 + } 199 + 200 + return $installed_types; 134 201 } 135 202 136 203 }
+4
src/applications/pholio/phid/PholioPHIDTypeMock.php
··· 12 12 return pht('Mock'); 13 13 } 14 14 15 + public function getPHIDTypeApplicationClass() { 16 + return 'PhabricatorApplicationPholio'; 17 + } 18 + 15 19 public function newObject() { 16 20 return new PholioMock(); 17 21 }
+4
src/applications/phriction/phid/PhrictionPHIDTypeDocument.php
··· 12 12 return pht('Wiki Document'); 13 13 } 14 14 15 + public function getPHIDTypeApplicationClass() { 16 + return 'PhabricatorApplicationPhriction'; 17 + } 18 + 15 19 public function newObject() { 16 20 return new PhrictionDocument(); 17 21 }
+4
src/applications/ponder/phid/PonderPHIDTypeQuestion.php
··· 12 12 return pht('Question'); 13 13 } 14 14 15 + public function getPHIDTypeApplicationClass() { 16 + return 'PhabricatorApplicationPonder'; 17 + } 18 + 15 19 public function newObject() { 16 20 return new PonderQuestion(); 17 21 }
+4
src/applications/project/phid/PhabricatorProjectPHIDTypeProject.php
··· 12 12 return pht('Project'); 13 13 } 14 14 15 + public function getPHIDTypeApplicationClass() { 16 + return 'PhabricatorApplicationProject'; 17 + } 18 + 15 19 public function getTypeIcon() { 16 20 return 'policy-project'; 17 21 }
+4
src/applications/repository/phid/PhabricatorRepositoryPHIDTypeCommit.php
··· 12 12 return pht('Commit'); 13 13 } 14 14 15 + public function getPHIDTypeApplicationClass() { 16 + return 'PhabricatorApplicationDiffusion'; 17 + } 18 + 15 19 public function newObject() { 16 20 return new PhabricatorRepositoryCommit(); 17 21 }
+9 -6
src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php
··· 96 96 $type_values = $saved->getParameter('types', array()); 97 97 $type_values = array_fuse($type_values); 98 98 99 - $types = self::getIndexableDocumentTypes(); 99 + $types = self::getIndexableDocumentTypes($this->requireViewer()); 100 100 101 101 $types_control = id(new AphrontFormCheckboxControl()) 102 102 ->setLabel(pht('Document Types')); ··· 190 190 return parent::buildSavedQueryFromBuiltin($query_key); 191 191 } 192 192 193 - public static function getIndexableDocumentTypes() { 193 + public static function getIndexableDocumentTypes( 194 + PhabricatorUser $viewer = null) { 195 + 194 196 // TODO: This is inelegant and not very efficient, but gets us reasonable 195 197 // results. It would be nice to do this more elegantly. 196 - 197 - // TODO: We should hide types associated with applications the user can 198 - // not access. There's no reasonable way to do this right now. 199 198 200 199 $indexers = id(new PhutilSymbolLoader()) 201 200 ->setAncestorClass('PhabricatorSearchDocumentIndexer') 202 201 ->loadObjects(); 203 202 204 - $types = PhabricatorPHIDType::getAllTypes(); 203 + if ($viewer) { 204 + $types = PhabricatorPHIDType::getAllInstalledTypes($viewer); 205 + } else { 206 + $types = PhabricatorPHIDType::getAllTypes(); 207 + } 205 208 206 209 $results = array(); 207 210 foreach ($types as $type) {