1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-01 19:22:42 +01:00

Add mail/feed to Slowvote

Summary: Adds mailkeys, basic structure for publishing to feed, sending mail.

Test Plan: New Poll, vote, comment, etc.

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: epriestley, Korvin

Differential Revision: https://secure.phabricator.com/D13749
This commit is contained in:
Chad Little 2015-08-01 15:41:08 -07:00
parent 9c39a9b361
commit 42c0dd2b8e
8 changed files with 250 additions and 1 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_slowvote.slowvote_poll
ADD mailKey binary(20) NOT NULL;

View file

@ -0,0 +1,18 @@
<?php
$table = new PhabricatorSlowvotePoll();
$conn_w = $table->establishConnection('w');
$iterator = new LiskMigrationIterator($table);
foreach ($iterator as $slowvote) {
$id = $slowvote->getID();
echo pht('Adding mail key for Slowvote %d...', $id);
echo "\n";
queryfx(
$conn_w,
'UPDATE %T SET mailKey = %s WHERE id = %d',
$table->getTableName(),
Filesystem::readRandomCharacters(20),
$id);
}

View file

@ -2792,11 +2792,13 @@ phutil_register_library_map(array(
'PhabricatorSlowvoteEditController' => 'applications/slowvote/controller/PhabricatorSlowvoteEditController.php', 'PhabricatorSlowvoteEditController' => 'applications/slowvote/controller/PhabricatorSlowvoteEditController.php',
'PhabricatorSlowvoteEditor' => 'applications/slowvote/editor/PhabricatorSlowvoteEditor.php', 'PhabricatorSlowvoteEditor' => 'applications/slowvote/editor/PhabricatorSlowvoteEditor.php',
'PhabricatorSlowvoteListController' => 'applications/slowvote/controller/PhabricatorSlowvoteListController.php', 'PhabricatorSlowvoteListController' => 'applications/slowvote/controller/PhabricatorSlowvoteListController.php',
'PhabricatorSlowvoteMailReceiver' => 'applications/slowvote/mail/PhabricatorSlowvoteMailReceiver.php',
'PhabricatorSlowvoteOption' => 'applications/slowvote/storage/PhabricatorSlowvoteOption.php', 'PhabricatorSlowvoteOption' => 'applications/slowvote/storage/PhabricatorSlowvoteOption.php',
'PhabricatorSlowvotePoll' => 'applications/slowvote/storage/PhabricatorSlowvotePoll.php', 'PhabricatorSlowvotePoll' => 'applications/slowvote/storage/PhabricatorSlowvotePoll.php',
'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/PhabricatorSlowvotePollController.php', 'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/PhabricatorSlowvotePollController.php',
'PhabricatorSlowvotePollPHIDType' => 'applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php', 'PhabricatorSlowvotePollPHIDType' => 'applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php',
'PhabricatorSlowvoteQuery' => 'applications/slowvote/query/PhabricatorSlowvoteQuery.php', 'PhabricatorSlowvoteQuery' => 'applications/slowvote/query/PhabricatorSlowvoteQuery.php',
'PhabricatorSlowvoteReplyHandler' => 'applications/slowvote/mail/PhabricatorSlowvoteReplyHandler.php',
'PhabricatorSlowvoteSchemaSpec' => 'applications/slowvote/storage/PhabricatorSlowvoteSchemaSpec.php', 'PhabricatorSlowvoteSchemaSpec' => 'applications/slowvote/storage/PhabricatorSlowvoteSchemaSpec.php',
'PhabricatorSlowvoteSearchEngine' => 'applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php', 'PhabricatorSlowvoteSearchEngine' => 'applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php',
'PhabricatorSlowvoteTransaction' => 'applications/slowvote/storage/PhabricatorSlowvoteTransaction.php', 'PhabricatorSlowvoteTransaction' => 'applications/slowvote/storage/PhabricatorSlowvoteTransaction.php',
@ -6782,6 +6784,7 @@ phutil_register_library_map(array(
'PhabricatorSlowvoteEditController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteEditController' => 'PhabricatorSlowvoteController',
'PhabricatorSlowvoteEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorSlowvoteEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorSlowvoteListController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteListController' => 'PhabricatorSlowvoteController',
'PhabricatorSlowvoteMailReceiver' => 'PhabricatorObjectMailReceiver',
'PhabricatorSlowvoteOption' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvoteOption' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvotePoll' => array( 'PhabricatorSlowvotePoll' => array(
'PhabricatorSlowvoteDAO', 'PhabricatorSlowvoteDAO',
@ -6797,6 +6800,7 @@ phutil_register_library_map(array(
'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController',
'PhabricatorSlowvotePollPHIDType' => 'PhabricatorPHIDType', 'PhabricatorSlowvotePollPHIDType' => 'PhabricatorPHIDType',
'PhabricatorSlowvoteQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorSlowvoteQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorSlowvoteReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
'PhabricatorSlowvoteSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorSlowvoteSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PhabricatorSlowvoteSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorSlowvoteSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorSlowvoteTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorSlowvoteTransaction' => 'PhabricatorApplicationTransaction',

View file

@ -8,7 +8,7 @@ final class PhabricatorSlowvoteEditor
} }
public function getEditorObjectsDescription() { public function getEditorObjectsDescription() {
return pht('Slowvotes'); return pht('Slowvote');
} }
public function getTransactionTypes() { public function getTransactionTypes() {
@ -111,4 +111,71 @@ final class PhabricatorSlowvoteEditor
return; return;
} }
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
public function getMailTagsMap() {
return array(
PhabricatorSlowvoteTransaction::MAILTAG_DETAILS =>
pht('Someone changes the poll details.'),
PhabricatorSlowvoteTransaction::MAILTAG_RESPONSES =>
pht('Someone votes on a poll.'),
PhabricatorSlowvoteTransaction::MAILTAG_OTHER =>
pht('Other poll activity not listed above occurs.'),
);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$monogram = $object->getMonogram();
$name = $object->getQuestion();
return id(new PhabricatorMetaMTAMail())
->setSubject("{$monogram}: {$name}")
->addHeader('Thread-Topic', $monogram);
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$description = $object->getDescription();
if (strlen($description)) {
$body->addTextSection(
pht('SLOWVOTE DESCRIPTION'),
$object->getDescription());
}
$body->addLinkSection(
pht('SLOWVOTE DETAIL'),
PhabricatorEnv::getProductionURI('/'.$object->getMonogram()));
return $body;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$object->getAuthorPHID(),
$this->requireActor()->getPHID(),
);
}
protected function getMailSubjectPrefix() {
return '[Slowvote]';
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhabricatorSlowvoteReplyHandler())
->setMailReceiver($object);
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
} }

View file

@ -0,0 +1,28 @@
<?php
final class PhabricatorSlowvoteMailReceiver
extends PhabricatorObjectMailReceiver {
public function isEnabled() {
return PhabricatorApplication::isClassInstalled(
'PhabricatorSlowvoteApplication');
}
protected function getObjectPattern() {
return 'V[1-9]\d*';
}
protected function loadObject($pattern, PhabricatorUser $viewer) {
$id = (int)substr($pattern, 4);
return id(new PhabricatorSlowvoteQuery())
->setViewer($viewer)
->withIDs(array($id))
->executeOne();
}
protected function getTransactionReplyHandler() {
return new PhabricatorSlowvoteReplyHandler();
}
}

View file

@ -0,0 +1,16 @@
<?php
final class PhabricatorSlowvoteReplyHandler
extends PhabricatorApplicationTransactionReplyHandler {
public function validateMailReceiver($mail_receiver) {
if (!($mail_receiver instanceof PhabricatorSlowvotePoll)) {
throw new Exception(pht('Mail receiver is not a %s!', 'Slowvote'));
}
}
public function getObjectPrefix() {
return 'V';
}
}

View file

@ -24,6 +24,7 @@ final class PhabricatorSlowvotePoll extends PhabricatorSlowvoteDAO
protected $responseVisibility; protected $responseVisibility;
protected $shuffle; protected $shuffle;
protected $method; protected $method;
protected $mailKey;
protected $viewPolicy; protected $viewPolicy;
protected $isClosed = 0; protected $isClosed = 0;
protected $spacePHID; protected $spacePHID;
@ -57,6 +58,7 @@ final class PhabricatorSlowvotePoll extends PhabricatorSlowvoteDAO
'method' => 'uint32', 'method' => 'uint32',
'description' => 'text', 'description' => 'text',
'isClosed' => 'bool', 'isClosed' => 'bool',
'mailKey' => 'bytes20',
), ),
self::CONFIG_KEY_SCHEMA => array( self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null, 'key_phid' => null,
@ -106,6 +108,17 @@ final class PhabricatorSlowvotePoll extends PhabricatorSlowvoteDAO
return $this; return $this;
} }
public function getMonogram() {
return 'V'.$this->getID();
}
public function save() {
if (!$this->getMailKey()) {
$this->setMailKey(Filesystem::readRandomCharacters(20));
}
return parent::save();
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */ /* -( PhabricatorApplicationTransactionInterface )------------------------- */

View file

@ -9,6 +9,10 @@ final class PhabricatorSlowvoteTransaction
const TYPE_SHUFFLE = 'vote:shuffle'; const TYPE_SHUFFLE = 'vote:shuffle';
const TYPE_CLOSE = 'vote:close'; const TYPE_CLOSE = 'vote:close';
const MAILTAG_DETAILS = 'vote:details';
const MAILTAG_RESPONSES = 'vote:responses';
const MAILTAG_OTHER = 'vote:vote';
public function getApplicationName() { public function getApplicationName() {
return 'slowvote'; return 'slowvote';
} }
@ -93,6 +97,82 @@ final class PhabricatorSlowvoteTransaction
return parent::getTitle(); return parent::getTitle();
} }
public function getTitleForFeed() {
$author_phid = $this->getAuthorPHID();
$object_phid = $this->getObjectPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
$type = $this->getTransactionType();
switch ($type) {
case self::TYPE_QUESTION:
if ($old === null) {
return pht(
'%s created %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
} else {
return pht(
'%s renamed %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
break;
case self::TYPE_DESCRIPTION:
if ($old === null) {
return pht(
'%s set the description of %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
} else {
return pht(
'%s edited the description of %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
break;
case self::TYPE_RESPONSES:
// TODO: This could be more detailed
return pht(
'%s changed who can see the responses of %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
case self::TYPE_SHUFFLE:
if ($new) {
return pht(
'%s made %s responses appear in a random order.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
} else {
return pht(
'%s made %s responses appear in a fixed order.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
case self::TYPE_CLOSE:
if ($new) {
return pht(
'%s closed %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
} else {
return pht(
'%s reopened %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
break;
}
return parent::getTitleForFeed();
}
public function getIcon() { public function getIcon() {
$old = $this->getOldValue(); $old = $this->getOldValue();
$new = $this->getNewValue(); $new = $this->getNewValue();
@ -152,5 +232,26 @@ final class PhabricatorSlowvoteTransaction
$this->getNewValue()); $this->getNewValue());
} }
public function getMailTags() {
$tags = parent::getMailTags();
switch ($this->getTransactionType()) {
case self::TYPE_QUESTION:
case self::TYPE_DESCRIPTION:
case self::TYPE_SHUFFLE:
case self::TYPE_CLOSE:
$tags[] = self::MAILTAG_DETAILS;
break;
case self::TYPE_RESPONSES:
$tags[] = self::MAILTAG_RESPONSES;
break;
default:
$tags[] = self::MAILTAG_OTHER;
break;
}
return $tags;
}
} }