@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 169 lines 5.3 kB view raw
1<?php 2 3abstract class DiffusionQueryConduitAPIMethod 4 extends DiffusionConduitAPIMethod { 5 6 public function shouldAllowPublic() { 7 return true; 8 } 9 10 private $diffusionRequest; 11 private $repository; 12 13 protected function setDiffusionRequest(DiffusionRequest $request) { 14 $this->diffusionRequest = $request; 15 return $this; 16 } 17 18 protected function getDiffusionRequest() { 19 return $this->diffusionRequest; 20 } 21 22 protected function getRepository(ConduitAPIRequest $request) { 23 return $this->getDiffusionRequest()->getRepository(); 24 } 25 26 final protected function defineErrorTypes() { 27 return $this->defineCustomErrorTypes() + 28 array( 29 'ERR-UNKNOWN-REPOSITORY' => 30 pht('There is no matching repository.'), 31 'ERR-UNKNOWN-VCS-TYPE' => 32 pht('Unknown repository VCS type.'), 33 'ERR-UNSUPPORTED-VCS' => 34 pht('VCS is not supported for this method.'), 35 ); 36 } 37 38 /** 39 * Subclasses should override this to specify custom error types. 40 */ 41 protected function defineCustomErrorTypes() { 42 return array(); 43 } 44 45 final protected function defineParamTypes() { 46 return $this->defineCustomParamTypes() + 47 array( 48 'callsign' => 'optional string (deprecated)', 49 'repository' => 'optional string', 50 'branch' => 'optional string', 51 ); 52 } 53 54 /** 55 * Subclasses should override this to specify custom param types. 56 */ 57 protected function defineCustomParamTypes() { 58 return array(); 59 } 60 61 /** 62 * Subclasses should override these methods with the proper result for the 63 * pertinent version control system, e.g. getGitResult for Git. 64 * 65 * If the result is not supported for that VCS, do not implement it. e.g. 66 * Subversion (SVN) does not support branches. 67 */ 68 protected function getGitResult(ConduitAPIRequest $request) { 69 throw new ConduitException('ERR-UNSUPPORTED-VCS'); 70 } 71 protected function getSVNResult(ConduitAPIRequest $request) { 72 throw new ConduitException('ERR-UNSUPPORTED-VCS'); 73 } 74 protected function getMercurialResult(ConduitAPIRequest $request) { 75 throw new ConduitException('ERR-UNSUPPORTED-VCS'); 76 } 77 78 /** 79 * This method is final because most queries will need to construct a 80 * @{class:DiffusionRequest} and use it. Consolidating this codepath and 81 * enforcing @{method:getDiffusionRequest} works when we need it is good. 82 * 83 * @{method:getResult} should be overridden by subclasses as necessary, e.g. 84 * there is a common operation across all version control systems that 85 * should occur after @{method:getResult}, like formatting a timestamp. 86 */ 87 final protected function execute(ConduitAPIRequest $request) { 88 $drequest = $this->getDiffusionRequest(); 89 90 // We pass this flag on to prevent proxying of any other Conduit calls 91 // which we need to make in order to respond to this one. Although we 92 // could safely proxy them, we take a big performance hit in the common 93 // case, and doing more proxying wouldn't exercise any additional code so 94 // we wouldn't gain a testability/predictability benefit. 95 $is_cluster_request = $request->getIsClusterRequest(); 96 $drequest->setIsClusterRequest($is_cluster_request); 97 98 $viewer = $request->getViewer(); 99 $repository = $drequest->getRepository(); 100 101 // TODO: Allow web UI queries opt out of this if they don't care about 102 // fetching the most up-to-date data? Synchronization can be slow, and a 103 // lot of web reads are probably fine if they're a few seconds out of 104 // date. 105 id(new DiffusionRepositoryClusterEngine()) 106 ->setViewer($viewer) 107 ->setRepository($repository) 108 ->synchronizeWorkingCopyBeforeRead(); 109 110 return $this->getResult($request); 111 } 112 113 114 protected function newConduitCallProxyClient(ConduitAPIRequest $request) { 115 $viewer = $request->getViewer(); 116 117 $identifier = $request->getValue('repository'); 118 if ($identifier === null) { 119 $identifier = $request->getValue('callsign'); 120 } 121 122 $drequest = DiffusionRequest::newFromDictionary( 123 array( 124 'user' => $viewer, 125 'repository' => $identifier, 126 'branch' => $request->getValue('branch'), 127 'path' => $request->getValue('path'), 128 'commit' => $request->getValue('commit'), 129 )); 130 131 if (!$drequest) { 132 throw new Exception( 133 pht( 134 'Repository "%s" is not a valid repository.', 135 $identifier)); 136 } 137 138 $repository = $drequest->getRepository(); 139 140 $client = $repository->newConduitClientForRequest($request); 141 if ($client) { 142 return $client; 143 } 144 145 $this->setDiffusionRequest($drequest); 146 147 return null; 148 } 149 150 protected function getResult(ConduitAPIRequest $request) { 151 $repository = $this->getRepository($request); 152 $result = null; 153 switch ($repository->getVersionControlSystem()) { 154 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 155 $result = $this->getGitResult($request); 156 break; 157 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 158 $result = $this->getMercurialResult($request); 159 break; 160 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 161 $result = $this->getSVNResult($request); 162 break; 163 default: 164 throw new ConduitException('ERR-UNKNOWN-VCS-TYPE'); 165 } 166 return $result; 167 } 168 169}