diff --git a/resources/sql/autopatches/20151106.phame.post.mailkey.1.sql b/resources/sql/autopatches/20151106.phame.post.mailkey.1.sql new file mode 100644 --- /dev/null +++ b/resources/sql/autopatches/20151106.phame.post.mailkey.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_phame.phame_post + ADD mailKey binary(20) NOT NULL; diff --git a/resources/sql/autopatches/20151106.phame.post.mailkey.2.php b/resources/sql/autopatches/20151106.phame.post.mailkey.2.php new file mode 100644 --- /dev/null +++ b/resources/sql/autopatches/20151106.phame.post.mailkey.2.php @@ -0,0 +1,18 @@ +establishConnection('w'); +$iterator = new LiskMigrationIterator($table); +foreach ($iterator as $post) { + $id = $post->getID(); + + echo pht('Adding mail key for Post %d...', $id); + echo "\n"; + + queryfx( + $conn_w, + 'UPDATE %T SET mailKey = %s WHERE id = %d', + $table->getTableName(), + Filesystem::readRandomCharacters(20), + $id); +} diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -3275,6 +3275,7 @@ 'PhamePostPreviewController' => 'applications/phame/controller/post/PhamePostPreviewController.php', 'PhamePostPublishController' => 'applications/phame/controller/post/PhamePostPublishController.php', 'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php', + 'PhamePostReplyHandler' => 'applications/phame/mail/PhamePostReplyHandler.php', 'PhamePostSearchEngine' => 'applications/phame/query/PhamePostSearchEngine.php', 'PhamePostTransaction' => 'applications/phame/storage/PhamePostTransaction.php', 'PhamePostTransactionQuery' => 'applications/phame/query/PhamePostTransactionQuery.php', @@ -7544,6 +7545,7 @@ 'PhamePostPreviewController' => 'PhamePostController', 'PhamePostPublishController' => 'PhamePostController', 'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhamePostReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhamePostSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhamePostTransaction' => 'PhabricatorApplicationTransaction', 'PhamePostTransactionQuery' => 'PhabricatorApplicationTransactionQuery', diff --git a/src/applications/phame/editor/PhameBlogEditor.php b/src/applications/phame/editor/PhameBlogEditor.php --- a/src/applications/phame/editor/PhameBlogEditor.php +++ b/src/applications/phame/editor/PhameBlogEditor.php @@ -8,7 +8,7 @@ } public function getEditorObjectsDescription() { - return pht('Blogs'); + return pht('Phame Blogs'); } public function getTransactionTypes() { diff --git a/src/applications/phame/editor/PhamePostEditor.php b/src/applications/phame/editor/PhamePostEditor.php --- a/src/applications/phame/editor/PhamePostEditor.php +++ b/src/applications/phame/editor/PhamePostEditor.php @@ -8,7 +8,7 @@ } public function getEditorObjectsDescription() { - return pht('Blog Posts'); + return pht('Phame Posts'); } public function getTransactionTypes() { @@ -149,13 +149,76 @@ protected function shouldSendMail( PhabricatorLiskDAO $object, array $xactions) { - return false; + if ($object->isDraft()) { + return false; + } + return true; } protected function shouldPublishFeedStory( PhabricatorLiskDAO $object, array $xactions) { - return false; + if ($object->isDraft()) { + return false; + } + return true; + } + + protected function getMailTo(PhabricatorLiskDAO $object) { + $phids = array(); + $phids[] = $object->getBloggerPHID(); + $phids[] = $this->requireActor()->getPHID(); + + $blog_phid = $object->getBlogPHID($object); + if ($blog_phid) { + $ids = PhabricatorSubscribersQuery::loadSubscribersForPHID($blog_phid); + foreach ($ids as $id) { + $phids[] = $id; + } + } + return $phids; + } + + protected function buildMailTemplate(PhabricatorLiskDAO $object) { + $id = $object->getID(); + $title = $object->getTitle(); + + return id(new PhabricatorMetaMTAMail()) + ->setSubject("{$title}") + ->addHeader('Thread-Topic', "PHAMEPOST{$id}"); + } + + protected function buildReplyHandler(PhabricatorLiskDAO $object) { + return id(new PhamePostReplyHandler()) + ->setMailReceiver($object); + } + + protected function buildMailBody( + PhabricatorLiskDAO $object, + array $xactions) { + + $body = parent::buildMailBody($object, $xactions); + + $body->addLinkSection( + pht('POST DETAIL'), + PhabricatorEnv::getProductionURI($object->getViewURI())); + + return $body; + } + + public function getMailTagsMap() { + return array( + PhamePostTransaction::MAILTAG_CONTENT => + pht("A post's content changes."), + PhamePostTransaction::MAILTAG_COMMENT => + pht('Someone comments on a post.'), + PhamePostTransaction::MAILTAG_OTHER => + pht('Other post activity not listed above occurs.'), + ); + } + + protected function getMailSubjectPrefix() { + return '[Phame]'; } protected function supportsSearch() { diff --git a/src/applications/phame/mail/PhamePostReplyHandler.php b/src/applications/phame/mail/PhamePostReplyHandler.php new file mode 100644 --- /dev/null +++ b/src/applications/phame/mail/PhamePostReplyHandler.php @@ -0,0 +1,21 @@ + 'text255', 'phameTitle' => 'sort64', 'visibility' => 'uint32', + 'mailKey' => 'bytes20', // T6203/NULLABILITY // These seem like they should always be non-null? @@ -135,6 +137,13 @@ ) + parent::getConfiguration(); } + public function save() { + if (!$this->getMailKey()) { + $this->setMailKey(Filesystem::readRandomCharacters(20)); + } + return parent::save(); + } + public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorPhamePostPHIDType::TYPECONST); diff --git a/src/applications/phame/storage/PhamePostTransaction.php b/src/applications/phame/storage/PhamePostTransaction.php --- a/src/applications/phame/storage/PhamePostTransaction.php +++ b/src/applications/phame/storage/PhamePostTransaction.php @@ -3,10 +3,14 @@ final class PhamePostTransaction extends PhabricatorApplicationTransaction { - const TYPE_TITLE = 'phame.post.title'; - const TYPE_PHAME_TITLE = 'phame.post.phame.title'; - const TYPE_BODY = 'phame.post.body'; - const TYPE_COMMENTS_WIDGET = 'phame.post.comments.widget'; + const TYPE_TITLE = 'phame.post.title'; + const TYPE_PHAME_TITLE = 'phame.post.phame.title'; + const TYPE_BODY = 'phame.post.body'; + const TYPE_COMMENTS_WIDGET = 'phame.post.comments.widget'; + + const MAILTAG_CONTENT = 'phame-post-content'; + const MAILTAG_COMMENT = 'phame-post-comment'; + const MAILTAG_OTHER = 'phame-post-other'; public function getApplicationName() { return 'phame'; @@ -57,6 +61,27 @@ return parent::getIcon(); } + public function getMailTags() { + $tags = parent::getMailTags(); + + switch ($this->getTransactionType()) { + case self::TYPE_COMMENTS_WIDGET: + case PhabricatorTransactions::TYPE_COMMENT: + $tags[] = self::MAILTAG_COMMENT; + break; + case self::TYPE_TITLE: + case self::TYPE_PHAME_TITLE: + case self::TYPE_BODY: + $tags[] = self::MAILTAG_CONTENT; + break; + default: + $tags[] = self::MAILTAG_OTHER; + break; + } + return $tags; + } + + public function getTitle() { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID(); @@ -69,7 +94,7 @@ case self::TYPE_TITLE: if ($old === null) { return pht( - '%s created this post.', + '%s authored this post.', $this->renderHandleLink($author_phid)); } else { return pht( @@ -80,12 +105,12 @@ break; case self::TYPE_BODY: return pht( - '%s updated the post\'s body.', + '%s updated the blog post.', $this->renderHandleLink($author_phid)); break; case self::TYPE_PHAME_TITLE: return pht( - '%s updated the post\'s phame title to "%s".', + '%s updated the post\'s Phame title to "%s".', $this->renderHandleLink($author_phid), rtrim($new, '/')); break; @@ -112,7 +137,7 @@ case self::TYPE_TITLE: if ($old === null) { return pht( - '%s created %s.', + '%s authored %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); } else { @@ -124,13 +149,13 @@ break; case self::TYPE_BODY: return pht( - '%s updated the body for %s.', + '%s updated the blog post %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); break; case self::TYPE_PHAME_TITLE: return pht( - '%s updated the phame title for %s.', + '%s updated the Phame title for %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); break; @@ -145,6 +170,23 @@ return parent::getTitleForFeed(); } + public function getBodyForFeed(PhabricatorFeedStory $story) { + $new = $this->getNewValue(); + + $body = null; + + switch ($this->getTransactionType()) { + case self::TYPE_TITLE: + case self::TYPE_BODY: + return phutil_escape_html_newlines( + id(new PhutilUTF8StringTruncator()) + ->setMaximumGlyphs(128) + ->truncateString($new)); + break; + } + return parent::getBodyForFeed($story); + } + public function getColor() { $old = $this->getOldValue();