@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
3/**
4 * Performs backgroundable work after applying transactions.
5 *
6 * This class handles email, notifications, feed stories, search indexes, and
7 * other similar backgroundable work.
8 */
9final class PhabricatorApplicationTransactionPublishWorker
10 extends PhabricatorWorker {
11
12
13 /**
14 * Publish information about a set of transactions.
15 */
16 protected function doWork() {
17 $object = $this->loadObject();
18 $editor = $this->buildEditor($object);
19 $xactions = $this->loadTransactions($object);
20
21 $editor->publishTransactions($object, $xactions);
22 }
23
24
25 /**
26 * Load the object the transactions affect.
27 */
28 private function loadObject() {
29 $viewer = PhabricatorUser::getOmnipotentUser();
30
31 $data = $this->getTaskData();
32 if (!is_array($data)) {
33 throw new PhabricatorWorkerPermanentFailureException(
34 pht('Task has invalid task data.'));
35 }
36
37 $phid = idx($data, 'objectPHID');
38 if (!$phid) {
39 throw new PhabricatorWorkerPermanentFailureException(
40 pht('Task has no object PHID!'));
41 }
42
43 $object = id(new PhabricatorObjectQuery())
44 ->setViewer($viewer)
45 ->withPHIDs(array($phid))
46 ->executeOne();
47 if (!$object) {
48 throw new PhabricatorWorkerPermanentFailureException(
49 pht(
50 'Unable to load object with PHID "%s"!',
51 $phid));
52 }
53
54 return $object;
55 }
56
57
58 /**
59 * Build and configure an Editor to publish these transactions.
60 */
61 private function buildEditor(
62 PhabricatorApplicationTransactionInterface $object) {
63 $data = $this->getTaskData();
64
65 $daemon_source = $this->newContentSource();
66
67 $viewer = PhabricatorUser::getOmnipotentUser();
68 $editor = $object->getApplicationTransactionEditor()
69 ->setActor($viewer)
70 ->setContentSource($daemon_source)
71 ->setActingAsPHID(idx($data, 'actorPHID'))
72 ->loadWorkerState(idx($data, 'state', array()));
73
74 return $editor;
75 }
76
77
78 /**
79 * Load the transactions to be published.
80 */
81 private function loadTransactions(
82 PhabricatorApplicationTransactionInterface $object) {
83 $data = $this->getTaskData();
84
85 $xaction_phids = idx($data, 'xactionPHIDs');
86 if (!$xaction_phids) {
87 // It's okay if we don't have any transactions. This can happen when
88 // creating objects or performing no-op updates. We will still apply
89 // meaningful side effects like updating search engine indexes.
90 return array();
91 }
92
93 $viewer = PhabricatorUser::getOmnipotentUser();
94
95 $query = PhabricatorApplicationTransactionQuery::newQueryForObject($object);
96 if (!$query) {
97 throw new PhabricatorWorkerPermanentFailureException(
98 pht(
99 'Unable to load query for transaction object "%s"!',
100 $object->getPHID()));
101 }
102
103 $xactions = $query
104 ->setViewer($viewer)
105 ->withPHIDs($xaction_phids)
106 ->needComments(true)
107 ->execute();
108 $xactions = mpull($xactions, null, 'getPHID');
109
110 $missing = array_diff($xaction_phids, array_keys($xactions));
111 if ($missing) {
112 throw new PhabricatorWorkerPermanentFailureException(
113 pht(
114 'Unable to load transactions: %s.',
115 implode(', ', $missing)));
116 }
117
118 return array_select_keys($xactions, $xaction_phids);
119 }
120
121}