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

at recaptime-dev/main 155 lines 4.2 kB view raw
1<?php 2 3/** 4 * Run a conduit method in-process, without requiring HTTP requests. Usage: 5 * 6 * $call = new ConduitCall('method.name', array('param' => 'value')); 7 * $call->setUser($user); 8 * $result = $call->execute(); 9 * 10 */ 11final class ConduitCall extends Phobject { 12 13 private $method; 14 private $handler; 15 private $request; 16 private $user; 17 18 public function __construct($method, array $params, $strictly_typed = true) { 19 $this->method = $method; 20 $this->handler = $this->buildMethodHandler($method); 21 22 $param_types = $this->handler->getParamTypes(); 23 24 foreach ($param_types as $key => $spec) { 25 if (ConduitAPIMethod::getParameterMetadataKey($key) !== null) { 26 throw new ConduitException( 27 pht( 28 'API Method "%s" defines a disallowed parameter, "%s". This '. 29 'parameter name is reserved.', 30 $method, 31 $key)); 32 } 33 } 34 35 $invalid_params = array_diff_key($params, $param_types); 36 if ($invalid_params) { 37 throw new ConduitException( 38 pht( 39 'API Method "%s" does not define these parameters: %s.', 40 $method, 41 "'".implode("', '", array_keys($invalid_params))."'")); 42 } 43 44 $this->request = new ConduitAPIRequest($params, $strictly_typed); 45 } 46 47 public function getAPIRequest() { 48 return $this->request; 49 } 50 51 public function setUser(PhabricatorUser $user) { 52 $this->user = $user; 53 return $this; 54 } 55 56 public function getUser() { 57 return $this->user; 58 } 59 60 public function shouldRequireAuthentication() { 61 return $this->handler->shouldRequireAuthentication(); 62 } 63 64 public function shouldAllowUnguardedWrites() { 65 return $this->handler->shouldAllowUnguardedWrites(); 66 } 67 68 public function getErrorDescription($code) { 69 return $this->handler->getErrorDescription($code); 70 } 71 72 public function execute() { 73 $profiler = PhutilServiceProfiler::getInstance(); 74 $call_id = $profiler->beginServiceCall( 75 array( 76 'type' => 'conduit', 77 'method' => $this->method, 78 )); 79 80 try { 81 $result = $this->executeMethod(); 82 } catch (Exception $ex) { 83 $profiler->endServiceCall($call_id, array()); 84 throw $ex; 85 } 86 87 $profiler->endServiceCall($call_id, array()); 88 return $result; 89 } 90 91 private function executeMethod() { 92 $user = $this->getUser(); 93 if (!$user) { 94 $user = new PhabricatorUser(); 95 } 96 97 $this->request->setUser($user); 98 99 if (!$this->shouldRequireAuthentication()) { 100 // No auth requirement here. 101 } else { 102 103 $allow_public = $this->handler->shouldAllowPublic() && 104 PhabricatorEnv::getEnvConfig('policy.allow-public'); 105 if (!$allow_public) { 106 if (!$user->isLoggedIn() && !$user->isOmnipotent()) { 107 // TODO: As per below, this should get centralized and cleaned up. 108 throw new ConduitException('ERR-INVALID-AUTH'); 109 } 110 } 111 112 // TODO: This would be slightly cleaner by just using a Query, but the 113 // Conduit auth workflow requires the Call and User be built separately. 114 // Just do it this way for the moment. 115 $application = $this->handler->getApplication(); 116 if ($application) { 117 $can_view = PhabricatorPolicyFilter::hasCapability( 118 $user, 119 $application, 120 PhabricatorPolicyCapability::CAN_VIEW); 121 122 if (!$can_view) { 123 throw new ConduitException( 124 pht( 125 'You do not have access to the application which provides this '. 126 'API method.')); 127 } 128 } 129 } 130 131 return $this->handler->executeMethod($this->request); 132 } 133 134 protected function buildMethodHandler($method_name) { 135 $method = ConduitAPIMethod::getConduitMethod($method_name); 136 137 if (!$method) { 138 throw new ConduitMethodDoesNotExistException($method_name); 139 } 140 141 $application = $method->getApplication(); 142 if ($application && !$application->isInstalled()) { 143 $app_name = $application->getName(); 144 throw new ConduitApplicationNotInstalledException($method, $app_name); 145 } 146 147 return $method; 148 } 149 150 public function getMethodImplementation() { 151 return $this->handler; 152 } 153 154 155}