Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/infrastructure/diff/viewstate/PhabricatorChangesetViewStateEngine.php
12242 views
1
<?php
2
3
final class PhabricatorChangesetViewStateEngine
4
extends Phobject {
5
6
private $viewer;
7
private $objectPHID;
8
private $changeset;
9
private $storage;
10
11
public function setViewer(PhabricatorUser $viewer) {
12
$this->viewer = $viewer;
13
return $this;
14
}
15
16
public function getViewer() {
17
return $this->viewer;
18
}
19
20
public function setObjectPHID($object_phid) {
21
$this->objectPHID = $object_phid;
22
return $this;
23
}
24
25
public function getObjectPHID() {
26
return $this->objectPHID;
27
}
28
29
public function setChangeset(DifferentialChangeset $changeset) {
30
$this->changeset = $changeset;
31
return $this;
32
}
33
34
public function getChangeset() {
35
return $this->changeset;
36
}
37
38
public function newViewStateFromRequest(AphrontRequest $request) {
39
$storage = $this->loadViewStateStorage();
40
41
$this->setStorage($storage);
42
43
$highlight = $request->getStr('highlight');
44
if ($highlight !== null) {
45
$this->setChangesetProperty('highlight', $highlight);
46
}
47
48
$encoding = $request->getStr('encoding');
49
if ($encoding !== null) {
50
$this->setChangesetProperty('encoding', $encoding);
51
}
52
53
$engine = $request->getStr('engine');
54
if ($engine !== null) {
55
$this->setChangesetProperty('engine', $engine);
56
}
57
58
$renderer = $request->getStr('renderer');
59
if ($renderer !== null) {
60
$this->setChangesetProperty('renderer', $renderer);
61
}
62
63
$hidden = $request->getStr('hidden');
64
if ($hidden !== null) {
65
$this->setChangesetProperty('hidden', (int)$hidden);
66
}
67
68
$this->saveViewStateStorage();
69
70
$state = new PhabricatorChangesetViewState();
71
72
$highlight_language = $this->getChangesetProperty('highlight');
73
$state->setHighlightLanguage($highlight_language);
74
75
$encoding = $this->getChangesetProperty('encoding');
76
$state->setCharacterEncoding($encoding);
77
78
$document_engine = $this->getChangesetProperty('engine');
79
$state->setDocumentEngineKey($document_engine);
80
81
$renderer = $this->getChangesetProperty('renderer');
82
$state->setRendererKey($renderer);
83
84
$this->updateHiddenState($state);
85
86
// This is the client-selected default renderer based on viewport
87
// dimensions.
88
89
$device_key = $request->getStr('device');
90
if ($device_key !== null) {
91
$state->setDefaultDeviceRendererKey($device_key);
92
}
93
94
$discard_response = $request->getStr('discard');
95
if ($discard_response !== null) {
96
$state->setDiscardResponse(true);
97
}
98
99
return $state;
100
}
101
102
private function setStorage(DifferentialViewState $storage) {
103
$this->storage = $storage;
104
return $this;
105
}
106
107
private function getStorage() {
108
return $this->storage;
109
}
110
111
private function setChangesetProperty(
112
$key,
113
$value) {
114
115
$storage = $this->getStorage();
116
$changeset = $this->getChangeset();
117
118
$storage->setChangesetProperty($changeset, $key, $value);
119
}
120
121
private function getChangesetProperty(
122
$key,
123
$default = null) {
124
125
$storage = $this->getStorage();
126
$changeset = $this->getChangeset();
127
128
return $storage->getChangesetProperty($changeset, $key, $default);
129
}
130
131
private function loadViewStateStorage() {
132
$viewer = $this->getViewer();
133
134
$object_phid = $this->getObjectPHID();
135
$viewer_phid = $viewer->getPHID();
136
137
$storage = null;
138
139
if ($viewer_phid !== null) {
140
$storage = id(new DifferentialViewStateQuery())
141
->setViewer($viewer)
142
->withViewerPHIDs(array($viewer_phid))
143
->withObjectPHIDs(array($object_phid))
144
->executeOne();
145
}
146
147
if ($storage === null) {
148
$storage = id(new DifferentialViewState())
149
->setObjectPHID($object_phid);
150
151
if ($viewer_phid !== null) {
152
$storage->setViewerPHID($viewer_phid);
153
} else {
154
$storage->makeEphemeral();
155
}
156
}
157
158
return $storage;
159
}
160
161
private function saveViewStateStorage() {
162
if (PhabricatorEnv::isReadOnly()) {
163
return;
164
}
165
166
$storage = $this->getStorage();
167
168
$viewer_phid = $storage->getViewerPHID();
169
if ($viewer_phid === null) {
170
return;
171
}
172
173
if (!$storage->getHasModifications()) {
174
return;
175
}
176
177
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
178
179
try {
180
$storage->save();
181
} catch (AphrontDuplicateKeyQueryException $ex) {
182
// We may race another process to save view state. For now, just discard
183
// our state if we do.
184
}
185
186
unset($unguarded);
187
}
188
189
private function updateHiddenState(PhabricatorChangesetViewState $state) {
190
$is_hidden = false;
191
$was_modified = false;
192
193
$storage = $this->getStorage();
194
$changeset = $this->getChangeset();
195
196
$entries = $storage->getChangesetPropertyEntries($changeset, 'hidden');
197
$entries = isort($entries, 'epoch');
198
199
if ($entries) {
200
$other_spec = last($entries);
201
202
$this_version = (int)$changeset->getDiffID();
203
$other_version = (int)idx($other_spec, 'diffID');
204
$other_value = (bool)idx($other_spec, 'value', false);
205
$other_id = (int)idx($other_spec, 'changesetID');
206
207
if ($other_value === false) {
208
$is_hidden = false;
209
} else if ($other_version >= $this_version) {
210
$is_hidden = $other_value;
211
} else {
212
$viewer = $this->getViewer();
213
214
if ($other_id) {
215
$other_changeset = id(new DifferentialChangesetQuery())
216
->setViewer($viewer)
217
->withIDs(array($other_id))
218
->executeOne();
219
} else {
220
$other_changeset = null;
221
}
222
223
$is_modified = false;
224
if ($other_changeset) {
225
if (!$changeset->hasSameEffectAs($other_changeset)) {
226
$is_modified = true;
227
}
228
}
229
230
$is_hidden = false;
231
$was_modified = true;
232
}
233
}
234
235
$state->setHidden($is_hidden);
236
$state->setModifiedSinceHide($was_modified);
237
}
238
239
}
240
241