@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<?php
2
3final class AlmanacService
4 extends AlmanacDAO
5 implements
6 PhabricatorPolicyInterface,
7 PhabricatorApplicationTransactionInterface,
8 PhabricatorProjectInterface,
9 AlmanacPropertyInterface,
10 PhabricatorDestructibleInterface,
11 PhabricatorNgramsInterface,
12 PhabricatorConduitResultInterface,
13 PhabricatorExtendedPolicyInterface {
14
15 protected $name;
16 protected $nameIndex;
17 protected $viewPolicy;
18 protected $editPolicy;
19 protected $serviceType;
20
21 private $almanacProperties = self::ATTACHABLE;
22 private $bindings = self::ATTACHABLE;
23 private $activeBindings = self::ATTACHABLE;
24 private $serviceImplementation = self::ATTACHABLE;
25
26 public static function initializeNewService($type) {
27 $type_map = AlmanacServiceType::getAllServiceTypes();
28
29 $implementation = idx($type_map, $type);
30 if (!$implementation) {
31 throw new Exception(
32 pht(
33 'No Almanac service type "%s" exists!',
34 $type));
35 }
36
37 return id(new AlmanacService())
38 ->setViewPolicy(PhabricatorPolicies::POLICY_USER)
39 ->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN)
40 ->attachAlmanacProperties(array())
41 ->setServiceType($type)
42 ->attachServiceImplementation($implementation);
43 }
44
45 protected function getConfiguration() {
46 return array(
47 self::CONFIG_AUX_PHID => true,
48 self::CONFIG_COLUMN_SCHEMA => array(
49 'name' => 'text128',
50 'nameIndex' => 'bytes12',
51 'serviceType' => 'text64',
52 ),
53 self::CONFIG_KEY_SCHEMA => array(
54 'key_name' => array(
55 'columns' => array('nameIndex'),
56 'unique' => true,
57 ),
58 'key_nametext' => array(
59 'columns' => array('name'),
60 ),
61 'key_servicetype' => array(
62 'columns' => array('serviceType'),
63 ),
64 ),
65 ) + parent::getConfiguration();
66 }
67
68 public function getPHIDType() {
69 return AlmanacServicePHIDType::TYPECONST;
70 }
71
72 public function save() {
73 AlmanacNames::validateName($this->getName());
74
75 $this->nameIndex = PhabricatorHash::digestForIndex($this->getName());
76
77 return parent::save();
78 }
79
80 public function getURI() {
81 return '/almanac/service/view/'.$this->getName().'/';
82 }
83
84 public function getBindings() {
85 return $this->assertAttached($this->bindings);
86 }
87
88 public function getActiveBindings() {
89 return $this->assertAttached($this->activeBindings);
90 }
91
92 public function attachBindings(array $bindings) {
93 $active_bindings = array();
94 foreach ($bindings as $key => $binding) {
95 // Filter out disabled bindings.
96 if ($binding->getIsDisabled()) {
97 continue;
98 }
99
100 // Filter out bindings to disabled devices.
101 if ($binding->getDevice()->isDisabled()) {
102 continue;
103 }
104
105 $active_bindings[$key] = $binding;
106 }
107
108 $this->attachActiveBindings($active_bindings);
109
110 $this->bindings = $bindings;
111 return $this;
112 }
113
114 public function attachActiveBindings(array $bindings) {
115 $this->activeBindings = $bindings;
116 return $this;
117 }
118
119 public function getServiceImplementation() {
120 return $this->assertAttached($this->serviceImplementation);
121 }
122
123 public function attachServiceImplementation(AlmanacServiceType $type) {
124 $this->serviceImplementation = $type;
125 return $this;
126 }
127
128 public function isClusterService() {
129 return $this->getServiceImplementation()->isClusterServiceType();
130 }
131
132
133/* -( AlmanacPropertyInterface )------------------------------------------- */
134
135
136 /**
137 * @param array<AlmanacProperty> $properties
138 */
139 public function attachAlmanacProperties(array $properties) {
140 assert_instances_of($properties, AlmanacProperty::class);
141 $this->almanacProperties = mpull($properties, null, 'getFieldName');
142 return $this;
143 }
144
145 public function getAlmanacProperties() {
146 return $this->assertAttached($this->almanacProperties);
147 }
148
149 public function hasAlmanacProperty($key) {
150 $this->assertAttached($this->almanacProperties);
151 return isset($this->almanacProperties[$key]);
152 }
153
154 public function getAlmanacProperty($key) {
155 return $this->assertAttachedKey($this->almanacProperties, $key);
156 }
157
158 public function getAlmanacPropertyValue($key, $default = null) {
159 if ($this->hasAlmanacProperty($key)) {
160 return $this->getAlmanacProperty($key)->getFieldValue();
161 } else {
162 return $default;
163 }
164 }
165
166 public function getAlmanacPropertyFieldSpecifications() {
167 return $this->getServiceImplementation()->getFieldSpecifications();
168 }
169
170 public function getBindingFieldSpecifications(AlmanacBinding $binding) {
171 $impl = $this->getServiceImplementation();
172 return $impl->getBindingFieldSpecifications($binding);
173 }
174
175 public function newAlmanacPropertyEditEngine() {
176 return new AlmanacServicePropertyEditEngine();
177 }
178
179 public function getAlmanacPropertySetTransactionType() {
180 return AlmanacServiceSetPropertyTransaction::TRANSACTIONTYPE;
181 }
182
183 public function getAlmanacPropertyDeleteTransactionType() {
184 return AlmanacServiceDeletePropertyTransaction::TRANSACTIONTYPE;
185 }
186
187
188/* -( PhabricatorPolicyInterface )----------------------------------------- */
189
190
191 public function getCapabilities() {
192 return array(
193 PhabricatorPolicyCapability::CAN_VIEW,
194 PhabricatorPolicyCapability::CAN_EDIT,
195 );
196 }
197
198 public function getPolicy($capability) {
199 switch ($capability) {
200 case PhabricatorPolicyCapability::CAN_VIEW:
201 return $this->getViewPolicy();
202 case PhabricatorPolicyCapability::CAN_EDIT:
203 return $this->getEditPolicy();
204 }
205 }
206
207 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
208 return false;
209 }
210
211
212/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
213
214
215 public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
216 switch ($capability) {
217 case PhabricatorPolicyCapability::CAN_EDIT:
218 if ($this->isClusterService()) {
219 return array(
220 array(
221 new PhabricatorAlmanacApplication(),
222 AlmanacManageClusterServicesCapability::CAPABILITY,
223 ),
224 );
225 }
226 break;
227 }
228
229 return array();
230 }
231
232
233/* -( PhabricatorApplicationTransactionInterface )------------------------- */
234
235
236 public function getApplicationTransactionEditor() {
237 return new AlmanacServiceEditor();
238 }
239
240 public function getApplicationTransactionTemplate() {
241 return new AlmanacServiceTransaction();
242 }
243
244
245/* -( PhabricatorDestructibleInterface )----------------------------------- */
246
247
248 public function destroyObjectPermanently(
249 PhabricatorDestructionEngine $engine) {
250
251 $bindings = id(new AlmanacBindingQuery())
252 ->setViewer($engine->getViewer())
253 ->withServicePHIDs(array($this->getPHID()))
254 ->execute();
255 foreach ($bindings as $binding) {
256 $engine->destroyObject($binding);
257 }
258
259 $this->delete();
260 }
261
262
263/* -( PhabricatorNgramsInterface )----------------------------------------- */
264
265
266 public function newNgrams() {
267 return array(
268 id(new AlmanacServiceNameNgrams())
269 ->setValue($this->getName()),
270 );
271 }
272
273
274/* -( PhabricatorConduitResultInterface )---------------------------------- */
275
276
277 public function getFieldSpecificationsForConduit() {
278 return array(
279 id(new PhabricatorConduitSearchFieldSpecification())
280 ->setKey('name')
281 ->setType('string')
282 ->setDescription(pht('The name of the service.')),
283 id(new PhabricatorConduitSearchFieldSpecification())
284 ->setKey('serviceType')
285 ->setType('string')
286 ->setDescription(pht('The service type constant.')),
287 );
288 }
289
290 public function getFieldValuesForConduit() {
291 return array(
292 'name' => $this->getName(),
293 'serviceType' => $this->getServiceType(),
294 );
295 }
296
297 public function getConduitSearchAttachments() {
298 return array(
299 id(new AlmanacPropertiesSearchEngineAttachment())
300 ->setAttachmentKey('properties'),
301 id(new AlmanacBindingsSearchEngineAttachment())
302 ->setAttachmentKey('bindings'),
303 id(new AlmanacBindingsSearchEngineAttachment())
304 ->setIsActive(true)
305 ->setAttachmentKey('activeBindings'),
306 );
307 }
308
309}