@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
at upstream/main 241 lines 5.7 kB view raw
1<?php 2 3/** 4 * @extends PhabricatorCursorPagedPolicyAwareQuery<PhabricatorSpacesNamespace> 5 */ 6final class PhabricatorSpacesNamespaceQuery 7 extends PhabricatorCursorPagedPolicyAwareQuery { 8 9 const KEY_ALL = 'spaces.all'; 10 const KEY_DEFAULT = 'spaces.default'; 11 const KEY_VIEWER = 'spaces.viewer'; 12 13 private $ids; 14 private $phids; 15 private $isDefaultNamespace; 16 private $isArchived; 17 18 public function withIDs(array $ids) { 19 $this->ids = $ids; 20 return $this; 21 } 22 23 public function withPHIDs(array $phids) { 24 $this->phids = $phids; 25 return $this; 26 } 27 28 public function withIsDefaultNamespace($default) { 29 $this->isDefaultNamespace = $default; 30 return $this; 31 } 32 33 public function withIsArchived($archived) { 34 $this->isArchived = $archived; 35 return $this; 36 } 37 38 public function getQueryApplicationClass() { 39 return PhabricatorSpacesApplication::class; 40 } 41 42 public function newResultObject() { 43 return new PhabricatorSpacesNamespace(); 44 } 45 46 protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { 47 $where = parent::buildWhereClauseParts($conn); 48 49 if ($this->ids !== null) { 50 $where[] = qsprintf( 51 $conn, 52 'id IN (%Ld)', 53 $this->ids); 54 } 55 56 if ($this->phids !== null) { 57 $where[] = qsprintf( 58 $conn, 59 'phid IN (%Ls)', 60 $this->phids); 61 } 62 63 if ($this->isDefaultNamespace !== null) { 64 if ($this->isDefaultNamespace) { 65 $where[] = qsprintf( 66 $conn, 67 'isDefaultNamespace = 1'); 68 } else { 69 $where[] = qsprintf( 70 $conn, 71 'isDefaultNamespace IS NULL'); 72 } 73 } 74 75 if ($this->isArchived !== null) { 76 $where[] = qsprintf( 77 $conn, 78 'isArchived = %d', 79 (int)$this->isArchived); 80 } 81 82 return $where; 83 } 84 85 public static function destroySpacesCache() { 86 $cache = PhabricatorCaches::getRequestCache(); 87 $cache->deleteKeys( 88 array( 89 self::KEY_ALL, 90 self::KEY_DEFAULT, 91 )); 92 } 93 94 public static function getSpacesExist() { 95 return (bool)self::getAllSpaces(); 96 } 97 98 public static function getViewerSpacesExist(PhabricatorUser $viewer) { 99 if (!self::getSpacesExist()) { 100 return false; 101 } 102 103 // If the viewer has access to only one space, pretend spaces simply don't 104 // exist. 105 $spaces = self::getViewerSpaces($viewer); 106 return (count($spaces) > 1); 107 } 108 109 public static function getAllSpaces() { 110 $cache = PhabricatorCaches::getRequestCache(); 111 $cache_key = self::KEY_ALL; 112 113 $spaces = $cache->getKey($cache_key); 114 if ($spaces === null) { 115 $spaces = id(new PhabricatorSpacesNamespaceQuery()) 116 ->setViewer(PhabricatorUser::getOmnipotentUser()) 117 ->execute(); 118 $spaces = mpull($spaces, null, 'getPHID'); 119 $cache->setKey($cache_key, $spaces); 120 } 121 122 return $spaces; 123 } 124 125 public static function getDefaultSpace() { 126 $cache = PhabricatorCaches::getRequestCache(); 127 $cache_key = self::KEY_DEFAULT; 128 129 $default_space = $cache->getKey($cache_key, false); 130 if ($default_space === false) { 131 $default_space = null; 132 133 $spaces = self::getAllSpaces(); 134 foreach ($spaces as $space) { 135 if ($space->getIsDefaultNamespace()) { 136 $default_space = $space; 137 break; 138 } 139 } 140 141 $cache->setKey($cache_key, $default_space); 142 } 143 144 return $default_space; 145 } 146 147 public static function getViewerSpaces(PhabricatorUser $viewer) { 148 $cache = PhabricatorCaches::getRequestCache(); 149 $cache_key = self::KEY_VIEWER.'('.$viewer->getCacheFragment().')'; 150 151 $result = $cache->getKey($cache_key); 152 if ($result === null) { 153 $spaces = self::getAllSpaces(); 154 155 $result = array(); 156 foreach ($spaces as $key => $space) { 157 $can_see = PhabricatorPolicyFilter::hasCapability( 158 $viewer, 159 $space, 160 PhabricatorPolicyCapability::CAN_VIEW); 161 if ($can_see) { 162 $result[$key] = $space; 163 } 164 } 165 166 $cache->setKey($cache_key, $result); 167 } 168 169 return $result; 170 } 171 172 173 public static function getViewerActiveSpaces(PhabricatorUser $viewer) { 174 $spaces = self::getViewerSpaces($viewer); 175 176 foreach ($spaces as $key => $space) { 177 if ($space->getIsArchived()) { 178 unset($spaces[$key]); 179 } 180 } 181 182 return $spaces; 183 } 184 185 public static function getSpaceOptionsForViewer( 186 PhabricatorUser $viewer, 187 $space_phid) { 188 189 $viewer_spaces = self::getViewerSpaces($viewer); 190 $viewer_spaces = msort($viewer_spaces, 'getNamespaceName'); 191 192 $map = array(); 193 foreach ($viewer_spaces as $space) { 194 195 // Skip archived spaces, unless the object is already in that space. 196 if ($space->getIsArchived()) { 197 if ($space->getPHID() != $space_phid) { 198 continue; 199 } 200 } 201 202 $map[$space->getPHID()] = pht( 203 'Space %s: %s', 204 $space->getMonogram(), 205 $space->getNamespaceName()); 206 } 207 208 return $map; 209 } 210 211 212 /** 213 * Get the Space PHID for an object, if one exists. 214 * 215 * This is intended to simplify performing a bunch of redundant checks; you 216 * can intentionally pass any value in (including `null`). 217 * 218 * @param object $object 219 * @return string|null Space PHID of the object, or null. 220 */ 221 public static function getObjectSpacePHID($object) { 222 if (!$object) { 223 return null; 224 } 225 226 if (!($object instanceof PhabricatorSpacesInterface)) { 227 return null; 228 } 229 230 $space_phid = $object->getSpacePHID(); 231 if ($space_phid === null) { 232 $default_space = self::getDefaultSpace(); 233 if ($default_space) { 234 $space_phid = $default_space->getPHID(); 235 } 236 } 237 238 return $space_phid; 239 } 240 241}