Correct a parameter order swap in "diffusion.historyquery" for Mercurial
[phabricator.git] / src / applications / phame / storage / PhamePost.php
blob300579b0862b88502ece45b9485c690fc708bd0e
1 <?php
3 final class PhamePost extends PhameDAO
4 implements
5 PhabricatorPolicyInterface,
6 PhabricatorMarkupInterface,
7 PhabricatorFlaggableInterface,
8 PhabricatorProjectInterface,
9 PhabricatorApplicationTransactionInterface,
10 PhabricatorSubscribableInterface,
11 PhabricatorDestructibleInterface,
12 PhabricatorTokenReceiverInterface,
13 PhabricatorConduitResultInterface,
14 PhabricatorFulltextInterface,
15 PhabricatorFerretInterface {
17 const MARKUP_FIELD_BODY = 'markup:body';
18 const MARKUP_FIELD_SUMMARY = 'markup:summary';
20 protected $bloggerPHID;
21 protected $title;
22 protected $subtitle;
23 protected $phameTitle;
24 protected $body;
25 protected $visibility;
26 protected $configData;
27 protected $datePublished;
28 protected $blogPHID;
29 protected $mailKey;
30 protected $headerImagePHID;
32 private $blog = self::ATTACHABLE;
33 private $headerImageFile = self::ATTACHABLE;
35 public static function initializePost(
36 PhabricatorUser $blogger,
37 PhameBlog $blog) {
39 $post = id(new PhamePost())
40 ->setBloggerPHID($blogger->getPHID())
41 ->setBlogPHID($blog->getPHID())
42 ->attachBlog($blog)
43 ->setDatePublished(PhabricatorTime::getNow())
44 ->setVisibility(PhameConstants::VISIBILITY_PUBLISHED);
46 return $post;
49 public function attachBlog(PhameBlog $blog) {
50 $this->blog = $blog;
51 return $this;
54 public function getBlog() {
55 return $this->assertAttached($this->blog);
58 public function getMonogram() {
59 return 'J'.$this->getID();
62 public function getLiveURI() {
63 $blog = $this->getBlog();
64 $is_draft = $this->isDraft();
65 $is_archived = $this->isArchived();
66 if (strlen($blog->getDomain()) && !$is_draft && !$is_archived) {
67 return $this->getExternalLiveURI();
68 } else {
69 return $this->getInternalLiveURI();
73 public function getExternalLiveURI() {
74 $id = $this->getID();
75 $slug = $this->getSlug();
76 $path = "/post/{$id}/{$slug}/";
78 $domain = $this->getBlog()->getDomain();
80 return (string)id(new PhutilURI('http://'.$domain))
81 ->setPath($path);
84 public function getInternalLiveURI() {
85 $id = $this->getID();
86 $slug = $this->getSlug();
87 $blog_id = $this->getBlog()->getID();
88 return "/phame/live/{$blog_id}/post/{$id}/{$slug}/";
91 public function getViewURI() {
92 $id = $this->getID();
93 $slug = $this->getSlug();
94 return "/phame/post/view/{$id}/{$slug}/";
97 public function getBestURI($is_live, $is_external) {
98 if ($is_live) {
99 if ($is_external) {
100 return $this->getExternalLiveURI();
101 } else {
102 return $this->getInternalLiveURI();
104 } else {
105 return $this->getViewURI();
109 public function getEditURI() {
110 return '/phame/post/edit/'.$this->getID().'/';
113 public function isDraft() {
114 return ($this->getVisibility() == PhameConstants::VISIBILITY_DRAFT);
117 public function isArchived() {
118 return ($this->getVisibility() == PhameConstants::VISIBILITY_ARCHIVED);
121 protected function getConfiguration() {
122 return array(
123 self::CONFIG_AUX_PHID => true,
124 self::CONFIG_SERIALIZATION => array(
125 'configData' => self::SERIALIZATION_JSON,
127 self::CONFIG_COLUMN_SCHEMA => array(
128 'title' => 'text255',
129 'subtitle' => 'text64',
130 'phameTitle' => 'sort64?',
131 'visibility' => 'uint32',
132 'mailKey' => 'bytes20',
133 'headerImagePHID' => 'phid?',
135 // T6203/NULLABILITY
136 // These seem like they should always be non-null?
137 'blogPHID' => 'phid?',
138 'body' => 'text?',
139 'configData' => 'text?',
141 // T6203/NULLABILITY
142 // This one probably should be nullable?
143 'datePublished' => 'epoch',
145 self::CONFIG_KEY_SCHEMA => array(
146 'key_phid' => null,
147 'phid' => array(
148 'columns' => array('phid'),
149 'unique' => true,
151 'bloggerPosts' => array(
152 'columns' => array(
153 'bloggerPHID',
154 'visibility',
155 'datePublished',
156 'id',
160 ) + parent::getConfiguration();
163 public function save() {
164 if (!$this->getMailKey()) {
165 $this->setMailKey(Filesystem::readRandomCharacters(20));
167 return parent::save();
170 public function generatePHID() {
171 return PhabricatorPHID::generateNewPHID(
172 PhabricatorPhamePostPHIDType::TYPECONST);
175 public function getSlug() {
176 return PhabricatorSlug::normalizeProjectSlug($this->getTitle());
179 public function getHeaderImageURI() {
180 return $this->getHeaderImageFile()->getBestURI();
183 public function attachHeaderImageFile(PhabricatorFile $file) {
184 $this->headerImageFile = $file;
185 return $this;
188 public function getHeaderImageFile() {
189 return $this->assertAttached($this->headerImageFile);
193 /* -( PhabricatorPolicyInterface Implementation )-------------------------- */
196 public function getCapabilities() {
197 return array(
198 PhabricatorPolicyCapability::CAN_VIEW,
199 PhabricatorPolicyCapability::CAN_EDIT,
203 public function getPolicy($capability) {
204 // Draft and archived posts are visible only to the author and other
205 // users who can edit the blog. Published posts are visible to whoever
206 // the blog is visible to.
208 switch ($capability) {
209 case PhabricatorPolicyCapability::CAN_VIEW:
210 if (!$this->isDraft() && !$this->isArchived() && $this->getBlog()) {
211 return $this->getBlog()->getViewPolicy();
212 } else if ($this->getBlog()) {
213 return $this->getBlog()->getEditPolicy();
214 } else {
215 return PhabricatorPolicies::POLICY_NOONE;
217 break;
218 case PhabricatorPolicyCapability::CAN_EDIT:
219 if ($this->getBlog()) {
220 return $this->getBlog()->getEditPolicy();
221 } else {
222 return PhabricatorPolicies::POLICY_NOONE;
227 public function hasAutomaticCapability($capability, PhabricatorUser $user) {
228 // A blog post's author can always view it.
230 switch ($capability) {
231 case PhabricatorPolicyCapability::CAN_VIEW:
232 case PhabricatorPolicyCapability::CAN_EDIT:
233 return ($user->getPHID() == $this->getBloggerPHID());
237 public function describeAutomaticCapability($capability) {
238 return pht('The author of a blog post can always view and edit it.');
242 /* -( PhabricatorMarkupInterface Implementation )-------------------------- */
245 public function getMarkupFieldKey($field) {
246 $content = $this->getMarkupText($field);
247 return PhabricatorMarkupEngine::digestRemarkupContent($this, $content);
250 public function newMarkupEngine($field) {
251 return PhabricatorMarkupEngine::newPhameMarkupEngine();
254 public function getMarkupText($field) {
255 switch ($field) {
256 case self::MARKUP_FIELD_BODY:
257 return $this->getBody();
258 case self::MARKUP_FIELD_SUMMARY:
259 return PhabricatorMarkupEngine::summarize($this->getBody());
263 public function didMarkupText(
264 $field,
265 $output,
266 PhutilMarkupEngine $engine) {
267 return $output;
270 public function shouldUseMarkupCache($field) {
271 return (bool)$this->getPHID();
275 /* -( PhabricatorApplicationTransactionInterface )------------------------- */
278 public function getApplicationTransactionEditor() {
279 return new PhamePostEditor();
282 public function getApplicationTransactionTemplate() {
283 return new PhamePostTransaction();
287 /* -( PhabricatorDestructibleInterface )----------------------------------- */
290 public function destroyObjectPermanently(
291 PhabricatorDestructionEngine $engine) {
293 $this->openTransaction();
294 $this->delete();
295 $this->saveTransaction();
299 /* -( PhabricatorTokenReceiverInterface )---------------------------------- */
302 public function getUsersToNotifyOfTokenGiven() {
303 return array(
304 $this->getBloggerPHID(),
309 /* -( PhabricatorSubscribableInterface Implementation )-------------------- */
312 public function isAutomaticallySubscribed($phid) {
313 return ($this->bloggerPHID == $phid);
317 /* -( PhabricatorConduitResultInterface )---------------------------------- */
320 public function getFieldSpecificationsForConduit() {
321 return array(
322 id(new PhabricatorConduitSearchFieldSpecification())
323 ->setKey('title')
324 ->setType('string')
325 ->setDescription(pht('Title of the post.')),
326 id(new PhabricatorConduitSearchFieldSpecification())
327 ->setKey('slug')
328 ->setType('string')
329 ->setDescription(pht('Slug for the post.')),
330 id(new PhabricatorConduitSearchFieldSpecification())
331 ->setKey('blogPHID')
332 ->setType('phid')
333 ->setDescription(pht('PHID of the blog that the post belongs to.')),
334 id(new PhabricatorConduitSearchFieldSpecification())
335 ->setKey('authorPHID')
336 ->setType('phid')
337 ->setDescription(pht('PHID of the author of the post.')),
338 id(new PhabricatorConduitSearchFieldSpecification())
339 ->setKey('body')
340 ->setType('string')
341 ->setDescription(pht('Body of the post.')),
342 id(new PhabricatorConduitSearchFieldSpecification())
343 ->setKey('datePublished')
344 ->setType('epoch?')
345 ->setDescription(pht('Publish date, if the post has been published.')),
350 public function getFieldValuesForConduit() {
351 if ($this->isDraft()) {
352 $date_published = null;
353 } else if ($this->isArchived()) {
354 $date_published = null;
355 } else {
356 $date_published = (int)$this->getDatePublished();
359 return array(
360 'title' => $this->getTitle(),
361 'slug' => $this->getSlug(),
362 'blogPHID' => $this->getBlogPHID(),
363 'authorPHID' => $this->getBloggerPHID(),
364 'body' => $this->getBody(),
365 'datePublished' => $date_published,
369 public function getConduitSearchAttachments() {
370 return array();
374 /* -( PhabricatorFulltextInterface )--------------------------------------- */
376 public function newFulltextEngine() {
377 return new PhamePostFulltextEngine();
381 /* -( PhabricatorFerretInterface )----------------------------------------- */
384 public function newFerretEngine() {
385 return new PhamePostFerretEngine();