@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 PhrictionDocument extends PhrictionDAO
4 implements
5 PhabricatorPolicyInterface,
6 PhabricatorSubscribableInterface,
7 PhabricatorFlaggableInterface,
8 PhabricatorTokenReceiverInterface,
9 PhabricatorDestructibleInterface,
10 PhabricatorFulltextInterface,
11 PhabricatorFerretInterface,
12 PhabricatorProjectInterface,
13 PhabricatorApplicationTransactionInterface,
14 PhabricatorConduitResultInterface,
15 PhabricatorPolicyCodexInterface,
16 PhabricatorSpacesInterface {
17
18 protected $slug;
19 protected $depth;
20 protected $contentPHID;
21 protected $status;
22 protected $viewPolicy;
23 protected $editPolicy;
24 protected $spacePHID;
25 protected $editedEpoch;
26 protected $maxVersion;
27
28 private $contentObject = self::ATTACHABLE;
29 private $ancestors = array();
30
31 protected function getConfiguration() {
32 return array(
33 self::CONFIG_AUX_PHID => true,
34 self::CONFIG_TIMESTAMPS => false,
35 self::CONFIG_COLUMN_SCHEMA => array(
36 'slug' => 'sort128',
37 'depth' => 'uint32',
38 'status' => 'text32',
39 'editedEpoch' => 'epoch',
40 'maxVersion' => 'uint32',
41 ),
42 self::CONFIG_KEY_SCHEMA => array(
43 'slug' => array(
44 'columns' => array('slug'),
45 'unique' => true,
46 ),
47 'depth' => array(
48 'columns' => array('depth', 'slug'),
49 'unique' => true,
50 ),
51 ),
52 ) + parent::getConfiguration();
53 }
54
55 public function getPHIDType() {
56 return PhrictionDocumentPHIDType::TYPECONST;
57 }
58
59 public static function initializeNewDocument(PhabricatorUser $actor, $slug) {
60 $document = id(new self())
61 ->setSlug($slug);
62
63 $content = id(new PhrictionContent())
64 ->setSlug($slug);
65
66 $default_title = PhabricatorSlug::getDefaultTitle($slug);
67 $content->setTitle($default_title);
68 $document->attachContent($content);
69
70 $parent_doc = null;
71 $ancestral_slugs = PhabricatorSlug::getAncestry($slug);
72 if ($ancestral_slugs) {
73 $parent = end($ancestral_slugs);
74 $parent_doc = id(new PhrictionDocumentQuery())
75 ->setViewer($actor)
76 ->withSlugs(array($parent))
77 ->executeOne();
78 }
79
80 if ($parent_doc) {
81 $space_phid = PhabricatorSpacesNamespaceQuery::getObjectSpacePHID(
82 $parent_doc);
83
84 $document
85 ->setViewPolicy($parent_doc->getViewPolicy())
86 ->setEditPolicy($parent_doc->getEditPolicy())
87 ->setSpacePHID($space_phid);
88 } else {
89 $default_view_policy = PhabricatorPolicies::getMostOpenPolicy();
90 $document
91 ->setViewPolicy($default_view_policy)
92 ->setEditPolicy(PhabricatorPolicies::POLICY_USER)
93 ->setSpacePHID($actor->getDefaultSpacePHID());
94 }
95
96 $document->setEditedEpoch(PhabricatorTime::getNow());
97 $document->setMaxVersion(0);
98
99 return $document;
100 }
101
102 public static function getSlugURI($slug, $type = 'document') {
103 static $types = array(
104 'document' => '/w/',
105 'history' => '/phriction/history/',
106 );
107
108 if (empty($types[$type])) {
109 throw new Exception(pht("Unknown URI type '%s'!", $type));
110 }
111
112 $prefix = $types[$type];
113
114 if ($slug == '/') {
115 return $prefix;
116 } else {
117 // NOTE: The effect here is to escape non-latin characters, since modern
118 // browsers deal with escaped UTF8 characters in a reasonable way (showing
119 // the user a readable URI) but older programs may not.
120 $slug = phutil_escape_uri($slug);
121 return $prefix.$slug;
122 }
123 }
124
125 public function setSlug($slug) {
126 $this->slug = PhabricatorSlug::normalize($slug);
127 $this->depth = PhabricatorSlug::getDepth($slug);
128 return $this;
129 }
130
131 public function attachContent(PhrictionContent $content) {
132 $this->contentObject = $content;
133 return $this;
134 }
135
136 public function getContent() {
137 return $this->assertAttached($this->contentObject);
138 }
139
140 public function getAncestors() {
141 return $this->ancestors;
142 }
143
144 public function getAncestor($slug) {
145 return $this->assertAttachedKey($this->ancestors, $slug);
146 }
147
148 public function attachAncestor($slug, $ancestor) {
149 $this->ancestors[$slug] = $ancestor;
150 return $this;
151 }
152
153 public function getURI() {
154 return self::getSlugURI($this->getSlug());
155 }
156
157/* -( Status )------------------------------------------------------------- */
158
159
160 public function getStatusObject() {
161 return PhrictionDocumentStatus::newStatusObject($this->getStatus());
162 }
163
164 public function getStatusIcon() {
165 return $this->getStatusObject()->getIcon();
166 }
167
168 public function getStatusColor() {
169 return $this->getStatusObject()->getColor();
170 }
171
172 public function getStatusDisplayName() {
173 return $this->getStatusObject()->getDisplayName();
174 }
175
176 public function isActive() {
177 return $this->getStatusObject()->isActive();
178 }
179
180
181/* -( PhabricatorPolicyInterface )----------------------------------------- */
182
183
184 public function getCapabilities() {
185 return array(
186 PhabricatorPolicyCapability::CAN_VIEW,
187 PhabricatorPolicyCapability::CAN_EDIT,
188 );
189 }
190
191 public function getPolicy($capability) {
192 switch ($capability) {
193 case PhabricatorPolicyCapability::CAN_VIEW:
194 return $this->getViewPolicy();
195 case PhabricatorPolicyCapability::CAN_EDIT:
196 return $this->getEditPolicy();
197 }
198 }
199
200 public function hasAutomaticCapability($capability, PhabricatorUser $user) {
201 return false;
202 }
203
204
205/* -( PhabricatorSpacesInterface )----------------------------------------- */
206
207
208 public function getSpacePHID() {
209 return $this->spacePHID;
210 }
211
212
213
214/* -( PhabricatorSubscribableInterface )----------------------------------- */
215
216
217 public function isAutomaticallySubscribed($phid) {
218 return false;
219 }
220
221
222/* -( PhabricatorApplicationTransactionInterface )------------------------- */
223
224
225 public function getApplicationTransactionEditor() {
226 return new PhrictionTransactionEditor();
227 }
228
229 public function getApplicationTransactionTemplate() {
230 return new PhrictionTransaction();
231 }
232
233
234/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
235
236
237 public function getUsersToNotifyOfTokenGiven() {
238 return PhabricatorSubscribersQuery::loadSubscribersForPHID($this->phid);
239 }
240
241
242/* -( PhabricatorDestructibleInterface )----------------------------------- */
243
244
245 public function destroyObjectPermanently(
246 PhabricatorDestructionEngine $engine) {
247
248 $this->openTransaction();
249
250 $contents = id(new PhrictionContentQuery())
251 ->setViewer($engine->getViewer())
252 ->withDocumentPHIDs(array($this->getPHID()))
253 ->execute();
254 foreach ($contents as $content) {
255 $engine->destroyObject($content);
256 }
257
258 $this->delete();
259
260 $this->saveTransaction();
261 }
262
263
264/* -( PhabricatorFulltextInterface )--------------------------------------- */
265
266
267 public function newFulltextEngine() {
268 return new PhrictionDocumentFulltextEngine();
269 }
270
271
272/* -( PhabricatorFerretInterface )----------------------------------------- */
273
274
275 public function newFerretEngine() {
276 return new PhrictionDocumentFerretEngine();
277 }
278
279
280/* -( PhabricatorConduitResultInterface )---------------------------------- */
281
282
283 public function getFieldSpecificationsForConduit() {
284 return array(
285 id(new PhabricatorConduitSearchFieldSpecification())
286 ->setKey('path')
287 ->setType('string')
288 ->setDescription(pht('The path to the document.')),
289 id(new PhabricatorConduitSearchFieldSpecification())
290 ->setKey('status')
291 ->setType('map<string, wild>')
292 ->setDescription(pht('Status information about the document.')),
293 );
294 }
295
296 public function getFieldValuesForConduit() {
297 $status = array(
298 'value' => $this->getStatus(),
299 'name' => $this->getStatusDisplayName(),
300 );
301
302 return array(
303 'path' => $this->getSlug(),
304 'status' => $status,
305 );
306 }
307
308 public function getConduitSearchAttachments() {
309 return array(
310 id(new PhrictionContentSearchEngineAttachment())
311 ->setAttachmentKey('content'),
312 );
313 }
314
315/* -( PhabricatorPolicyCodexInterface )------------------------------------ */
316
317
318 public function newPolicyCodex() {
319 return new PhrictionDocumentPolicyCodex();
320 }
321
322
323}