@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// TODO: Some "final" modifiers have been VERY TEMPORARILY moved aside to
4// allow DifferentialTransaction to extend this class without converting
5// fully to ModularTransactions.
6
7abstract class PhabricatorModularTransaction
8 extends PhabricatorApplicationTransaction {
9
10 private $implementation;
11
12 abstract public function getBaseTransactionClass();
13
14 public function getModularType() {
15 return $this->getTransactionImplementation();
16 }
17
18 final protected function getTransactionImplementation() {
19 if (!$this->implementation) {
20 $this->implementation = $this->newTransactionImplementation();
21 }
22
23 return $this->implementation;
24 }
25
26 public function newModularTransactionTypes() {
27 $base_class = $this->getBaseTransactionClass();
28
29 $types = id(new PhutilClassMapQuery())
30 ->setAncestorClass($base_class)
31 ->setUniqueMethod('getTransactionTypeConstant')
32 ->execute();
33
34 // Add core transaction types.
35 $types += id(new PhutilClassMapQuery())
36 ->setAncestorClass(PhabricatorCoreTransactionType::class)
37 ->setUniqueMethod('getTransactionTypeConstant')
38 ->execute();
39
40 return $types;
41 }
42
43 private function newTransactionImplementation() {
44 $types = $this->newModularTransactionTypes();
45
46 $key = $this->getTransactionType();
47
48 if (empty($types[$key])) {
49 $type = $this->newFallbackModularTransactionType();
50 } else {
51 $type = clone $types[$key];
52 }
53
54 $type->setStorage($this);
55
56 return $type;
57 }
58
59 protected function newFallbackModularTransactionType() {
60 return new PhabricatorCoreVoidTransaction();
61 }
62
63 final public function generateOldValue($object) {
64 return $this->getTransactionImplementation()->generateOldValue($object);
65 }
66
67 final public function generateNewValue($object) {
68 return $this->getTransactionImplementation()
69 ->generateNewValue($object, $this->getNewValue());
70 }
71
72 final public function applyInternalEffects($object) {
73 return $this->getTransactionImplementation()
74 ->applyInternalEffects($object);
75 }
76
77 final public function applyExternalEffects($object) {
78 return $this->getTransactionImplementation()
79 ->applyExternalEffects($object);
80 }
81
82 /* final */ public function shouldHide() {
83 if ($this->getTransactionImplementation()->shouldHide()) {
84 return true;
85 }
86
87 return parent::shouldHide();
88 }
89
90 final public function shouldHideForFeed() {
91 if ($this->getTransactionImplementation()->shouldHideForFeed()) {
92 return true;
93 }
94
95 return parent::shouldHideForFeed();
96 }
97
98 /* final */ public function shouldHideForMail(array $xactions) {
99 if ($this->getTransactionImplementation()->shouldHideForMail()) {
100 return true;
101 }
102
103 return parent::shouldHideForMail($xactions);
104 }
105
106 final public function shouldHideForNotifications() {
107 $hide = $this->getTransactionImplementation()->shouldHideForNotifications();
108
109 // Returning "null" means "use the default behavior".
110 if ($hide === null) {
111 return parent::shouldHideForNotifications();
112 }
113
114 return $hide;
115 }
116
117 /* final */ public function getIcon() {
118 $icon = $this->getTransactionImplementation()->getIcon();
119 if ($icon !== null) {
120 return $icon;
121 }
122
123 return parent::getIcon();
124 }
125
126 /* final */ public function getTitle() {
127 $title = $this->getTransactionImplementation()->getTitle();
128 if ($title !== null) {
129 return $title;
130 }
131
132 return parent::getTitle();
133 }
134
135 /* final */ public function getActionName() {
136 $action = $this->getTransactionImplementation()->getActionName();
137 if ($action !== null) {
138 return $action;
139 }
140
141 return parent::getActionName();
142 }
143
144 /* final */ public function getActionStrength() {
145 $strength = $this->getTransactionImplementation()->getActionStrength();
146 if ($strength !== null) {
147 return $strength;
148 }
149
150 return parent::getActionStrength();
151 }
152
153 /* final */ public function getTitleForFeed() {
154 $title = $this->getTransactionImplementation()->getTitleForFeed();
155 if ($title !== null) {
156 return $title;
157 }
158
159 return parent::getTitleForFeed();
160 }
161
162 /* final */ public function getColor() {
163 $color = $this->getTransactionImplementation()->getColor();
164 if ($color !== null) {
165 return $color;
166 }
167
168 return parent::getColor();
169 }
170
171 public function attachViewer(PhabricatorUser $viewer) {
172 $this->getTransactionImplementation()->setViewer($viewer);
173 return parent::attachViewer($viewer);
174 }
175
176 final public function hasChangeDetails() {
177 if ($this->getTransactionImplementation()->hasChangeDetailView()) {
178 return true;
179 }
180
181 return parent::hasChangeDetails();
182 }
183
184 final public function renderChangeDetails(PhabricatorUser $viewer) {
185 $impl = $this->getTransactionImplementation();
186 $impl->setViewer($viewer);
187 $view = $impl->newChangeDetailView();
188 if ($view !== null) {
189 return $view;
190 }
191
192 return parent::renderChangeDetails($viewer);
193 }
194
195 final protected function newRemarkupChanges() {
196 return $this->getTransactionImplementation()->newRemarkupChanges();
197 }
198
199 /* final */ public function newWarningForTransactions(
200 $object,
201 array $xactions) {
202 throw new PhutilMethodNotImplementedException();
203 }
204
205}