Add very basic scaffolding for Pholio
Summary:
I'm not going to land this until it's a bit more fleshed out since it would just confuse users, but this is probably more reviewable as a few diffs adding a couple features than one ULTRA-diff adding everything. Implement application basics for Pholio. This does more or less nothing, but adds storage, subscribe, flag, markup, indexing, query basics, PHIDs, handle loads, a couple of realy really basic controllers, etc.
Basic hierarchy is:
- **Moleskine**: Top-level object like a Differential Revision, like "Ponder Feed Ideas".
- **Image**: Each Moleskine has one or more images, like the unexpanded / expanded / mobile / empty states of feed.
- **Transaction**: Comment or edit, like Maniphest. I generally want to move most apps to a transaction model so we can log edits.
- **PixelComment**: Equivalent of an inline comment.
Test Plan: Created a fake object and viewed it.
Reviewers: btrahan, chad
Reviewed By: btrahan
CC: aran, davidreuss
Maniphest Tasks: T2097
Differential Revision: https://secure.phabricator.com/D3817
2012-11-21 17:22:36 -08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @group pholio
|
|
|
|
*/
|
2012-12-11 13:59:20 -08:00
|
|
|
final class PholioMockEditor extends PhabricatorApplicationTransactionEditor {
|
Add very basic scaffolding for Pholio
Summary:
I'm not going to land this until it's a bit more fleshed out since it would just confuse users, but this is probably more reviewable as a few diffs adding a couple features than one ULTRA-diff adding everything. Implement application basics for Pholio. This does more or less nothing, but adds storage, subscribe, flag, markup, indexing, query basics, PHIDs, handle loads, a couple of realy really basic controllers, etc.
Basic hierarchy is:
- **Moleskine**: Top-level object like a Differential Revision, like "Ponder Feed Ideas".
- **Image**: Each Moleskine has one or more images, like the unexpanded / expanded / mobile / empty states of feed.
- **Transaction**: Comment or edit, like Maniphest. I generally want to move most apps to a transaction model so we can log edits.
- **PixelComment**: Equivalent of an inline comment.
Test Plan: Created a fake object and viewed it.
Reviewers: btrahan, chad
Reviewed By: btrahan
CC: aran, davidreuss
Maniphest Tasks: T2097
Differential Revision: https://secure.phabricator.com/D3817
2012-11-21 17:22:36 -08:00
|
|
|
|
2013-07-16 13:31:20 -07:00
|
|
|
private $newImages = array();
|
|
|
|
private function setNewImages(array $new_images) {
|
|
|
|
assert_instances_of($new_images, 'PholioImage');
|
|
|
|
$this->newImages = $new_images;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
private function getNewImages() {
|
|
|
|
return $this->newImages;
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
public function getTransactionTypes() {
|
|
|
|
$types = parent::getTransactionTypes();
|
Add very basic scaffolding for Pholio
Summary:
I'm not going to land this until it's a bit more fleshed out since it would just confuse users, but this is probably more reviewable as a few diffs adding a couple features than one ULTRA-diff adding everything. Implement application basics for Pholio. This does more or less nothing, but adds storage, subscribe, flag, markup, indexing, query basics, PHIDs, handle loads, a couple of realy really basic controllers, etc.
Basic hierarchy is:
- **Moleskine**: Top-level object like a Differential Revision, like "Ponder Feed Ideas".
- **Image**: Each Moleskine has one or more images, like the unexpanded / expanded / mobile / empty states of feed.
- **Transaction**: Comment or edit, like Maniphest. I generally want to move most apps to a transaction model so we can log edits.
- **PixelComment**: Equivalent of an inline comment.
Test Plan: Created a fake object and viewed it.
Reviewers: btrahan, chad
Reviewed By: btrahan
CC: aran, davidreuss
Maniphest Tasks: T2097
Differential Revision: https://secure.phabricator.com/D3817
2012-11-21 17:22:36 -08:00
|
|
|
|
2013-01-01 18:14:41 -08:00
|
|
|
$types[] = PhabricatorTransactions::TYPE_COMMENT;
|
2012-12-11 13:59:20 -08:00
|
|
|
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
|
|
|
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
2012-11-21 17:27:44 -08:00
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
$types[] = PholioTransactionType::TYPE_NAME;
|
|
|
|
$types[] = PholioTransactionType::TYPE_DESCRIPTION;
|
2013-02-07 08:02:52 -08:00
|
|
|
$types[] = PholioTransactionType::TYPE_INLINE;
|
2013-07-16 13:31:20 -07:00
|
|
|
|
|
|
|
$types[] = PholioTransactionType::TYPE_IMAGE_FILE;
|
|
|
|
$types[] = PholioTransactionType::TYPE_IMAGE_NAME;
|
|
|
|
$types[] = PholioTransactionType::TYPE_IMAGE_DESCRIPTION;
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
return $types;
|
2012-11-21 17:27:44 -08:00
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
protected function getCustomTransactionOldValue(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
PhabricatorApplicationTransaction $xaction) {
|
2012-11-21 17:38:57 -08:00
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case PholioTransactionType::TYPE_NAME:
|
|
|
|
return $object->getName();
|
|
|
|
case PholioTransactionType::TYPE_DESCRIPTION:
|
|
|
|
return $object->getDescription();
|
2013-07-16 13:31:20 -07:00
|
|
|
case PholioTransactionType::TYPE_IMAGE_FILE:
|
|
|
|
$images = $object->getImages();
|
|
|
|
return mpull($images, 'getPHID');
|
|
|
|
case PholioTransactionType::TYPE_IMAGE_NAME:
|
|
|
|
$name = null;
|
|
|
|
$phid = null;
|
|
|
|
$image = $this->getImageForXaction($object, $xaction);
|
2013-07-18 14:19:43 -07:00
|
|
|
if ($image) {
|
2013-07-16 13:31:20 -07:00
|
|
|
$name = $image->getName();
|
|
|
|
$phid = $image->getPHID();
|
|
|
|
}
|
|
|
|
return array ($phid => $name);
|
|
|
|
case PholioTransactionType::TYPE_IMAGE_DESCRIPTION:
|
|
|
|
$description = null;
|
|
|
|
$phid = null;
|
|
|
|
$image = $this->getImageForXaction($object, $xaction);
|
2013-07-18 14:19:43 -07:00
|
|
|
if ($image) {
|
2013-07-16 13:31:20 -07:00
|
|
|
$description = $image->getDescription();
|
|
|
|
$phid = $image->getPHID();
|
|
|
|
}
|
|
|
|
return array($phid => $description);
|
2012-11-21 17:38:57 -08:00
|
|
|
}
|
2012-12-11 13:59:20 -08:00
|
|
|
}
|
2012-11-21 17:38:57 -08:00
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
protected function getCustomTransactionNewValue(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
PhabricatorApplicationTransaction $xaction) {
|
2012-11-21 17:27:44 -08:00
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case PholioTransactionType::TYPE_NAME:
|
|
|
|
case PholioTransactionType::TYPE_DESCRIPTION:
|
2013-07-16 13:31:20 -07:00
|
|
|
case PholioTransactionType::TYPE_IMAGE_NAME:
|
|
|
|
case PholioTransactionType::TYPE_IMAGE_DESCRIPTION:
|
2012-12-11 13:59:20 -08:00
|
|
|
return $xaction->getNewValue();
|
2013-07-16 13:31:20 -07:00
|
|
|
case PholioTransactionType::TYPE_IMAGE_FILE:
|
|
|
|
$raw_new_value = $xaction->getNewValue();
|
|
|
|
$new_value = array();
|
|
|
|
foreach ($raw_new_value as $key => $images) {
|
|
|
|
$new_value[$key] = mpull($images, 'getPHID');
|
|
|
|
}
|
|
|
|
$xaction->setNewValue($new_value);
|
|
|
|
return $this->getPHIDTransactionNewValue($xaction);
|
2012-11-21 17:27:44 -08:00
|
|
|
}
|
2012-12-11 13:59:20 -08:00
|
|
|
}
|
2012-11-21 17:27:44 -08:00
|
|
|
|
2013-02-07 08:02:52 -08:00
|
|
|
protected function transactionHasEffect(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
PhabricatorApplicationTransaction $xaction) {
|
|
|
|
|
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case PholioTransactionType::TYPE_INLINE:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent::transactionHasEffect($object, $xaction);
|
|
|
|
}
|
|
|
|
|
2013-07-16 13:31:20 -07:00
|
|
|
protected function shouldApplyInitialEffects(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
array $xactions) {
|
|
|
|
|
|
|
|
foreach ($xactions as $xaction) {
|
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case PholioTransactionType::TYPE_IMAGE_FILE:
|
|
|
|
return true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function applyInitialEffects(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
array $xactions) {
|
|
|
|
|
|
|
|
$new_images = array();
|
|
|
|
foreach ($xactions as $xaction) {
|
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case PholioTransactionType::TYPE_IMAGE_FILE:
|
|
|
|
$new_value = $xaction->getNewValue();
|
|
|
|
foreach ($new_value as $key => $txn_images) {
|
|
|
|
if ($key != '+') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
foreach ($txn_images as $image) {
|
|
|
|
$image->save();
|
|
|
|
$new_images[] = $image;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$this->setNewImages($new_images);
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
protected function applyCustomInternalTransaction(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
PhabricatorApplicationTransaction $xaction) {
|
2012-11-21 17:27:44 -08:00
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case PholioTransactionType::TYPE_NAME:
|
|
|
|
$object->setName($xaction->getNewValue());
|
|
|
|
if ($object->getOriginalName() === null) {
|
|
|
|
$object->setOriginalName($xaction->getNewValue());
|
2012-11-21 17:38:57 -08:00
|
|
|
}
|
2012-12-11 13:59:20 -08:00
|
|
|
break;
|
|
|
|
case PholioTransactionType::TYPE_DESCRIPTION:
|
|
|
|
$object->setDescription($xaction->getNewValue());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-11-21 17:38:57 -08:00
|
|
|
|
2013-07-16 13:31:20 -07:00
|
|
|
private function getImageForXaction(
|
|
|
|
PholioMock $mock,
|
|
|
|
PhabricatorApplicationTransaction $xaction) {
|
|
|
|
$raw_new_value = $xaction->getNewValue();
|
|
|
|
$image_phid = key($raw_new_value);
|
|
|
|
$images = $mock->getImages();
|
|
|
|
foreach ($images as $image) {
|
|
|
|
if ($image->getPHID() == $image_phid) {
|
|
|
|
return $image;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
protected function applyCustomExternalTransaction(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
PhabricatorApplicationTransaction $xaction) {
|
2013-07-16 13:31:20 -07:00
|
|
|
|
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case PholioTransactionType::TYPE_IMAGE_FILE:
|
|
|
|
$old_map = array_fuse($xaction->getOldValue());
|
|
|
|
$new_map = array_fuse($xaction->getNewValue());
|
|
|
|
|
|
|
|
$obsolete_map = array_diff_key($old_map, $new_map);
|
|
|
|
$images = $object->getImages();
|
|
|
|
foreach ($images as $seq => $image) {
|
|
|
|
if (isset($obsolete_map[$image->getPHID()])) {
|
|
|
|
$image->setIsObsolete(1);
|
|
|
|
$image->save();
|
|
|
|
unset($images[$seq]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$object->attachImages($images);
|
|
|
|
break;
|
|
|
|
case PholioTransactionType::TYPE_IMAGE_NAME:
|
|
|
|
$image = $this->getImageForXaction($object, $xaction);
|
|
|
|
$value = (string) head($xaction->getNewValue());
|
|
|
|
$image->setName($value);
|
|
|
|
$image->save();
|
|
|
|
break;
|
|
|
|
case PholioTransactionType::TYPE_IMAGE_DESCRIPTION:
|
|
|
|
$image = $this->getImageForXaction($object, $xaction);
|
|
|
|
$value = (string) head($xaction->getNewValue());
|
|
|
|
$image->setDescription($value);
|
|
|
|
$image->save();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function applyFinalEffects(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
array $xactions) {
|
|
|
|
|
|
|
|
$images = $this->getNewImages();
|
|
|
|
foreach ($images as $image) {
|
|
|
|
$image->setMockID($object->getID());
|
|
|
|
$image->save();
|
|
|
|
}
|
2012-12-11 13:59:20 -08:00
|
|
|
}
|
2012-11-21 17:27:44 -08:00
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
protected function mergeTransactions(
|
|
|
|
PhabricatorApplicationTransaction $u,
|
|
|
|
PhabricatorApplicationTransaction $v) {
|
2012-11-21 17:39:46 -08:00
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
$type = $u->getTransactionType();
|
|
|
|
switch ($type) {
|
|
|
|
case PholioTransactionType::TYPE_NAME:
|
|
|
|
case PholioTransactionType::TYPE_DESCRIPTION:
|
|
|
|
return $v;
|
2013-07-16 13:31:20 -07:00
|
|
|
case PholioTransactionType::TYPE_IMAGE_FILE:
|
|
|
|
return $this->mergePHIDOrEdgeTransactions($u, $v);
|
|
|
|
case PholioTransactionType::TYPE_IMAGE_NAME:
|
|
|
|
case PholioTransactionType::TYPE_IMAGE_DESCRIPTION:
|
|
|
|
$raw_new_value_u = $u->getNewValue();
|
|
|
|
$raw_new_value_v = $v->getNewValue();
|
|
|
|
$phid_u = key($raw_new_value_u);
|
|
|
|
$phid_v = key($raw_new_value_v);
|
|
|
|
if ($phid_u == $phid_v) {
|
|
|
|
return $v;
|
|
|
|
}
|
|
|
|
break;
|
2012-12-11 13:59:20 -08:00
|
|
|
}
|
2012-11-21 17:27:44 -08:00
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
return parent::mergeTransactions($u, $v);
|
2012-11-21 17:27:44 -08:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:00:07 -08:00
|
|
|
protected function supportsMail() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
|
|
|
|
return id(new PholioReplyHandler())
|
|
|
|
->setMailReceiver($object);
|
|
|
|
}
|
2012-12-11 13:59:20 -08:00
|
|
|
|
2012-12-11 14:00:07 -08:00
|
|
|
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
|
|
|
$id = $object->getID();
|
|
|
|
$name = $object->getName();
|
|
|
|
$original_name = $object->getOriginalName();
|
2012-11-21 17:39:46 -08:00
|
|
|
|
2012-12-11 14:00:07 -08:00
|
|
|
return id(new PhabricatorMetaMTAMail())
|
|
|
|
->setSubject("M{$id}: {$name}")
|
|
|
|
->addHeader('Thread-Topic', "M{$id}: {$original_name}");
|
|
|
|
}
|
2012-11-21 17:39:46 -08:00
|
|
|
|
2012-12-11 14:00:07 -08:00
|
|
|
protected function getMailTo(PhabricatorLiskDAO $object) {
|
|
|
|
return array(
|
|
|
|
$object->getAuthorPHID(),
|
2012-11-21 17:39:46 -08:00
|
|
|
$this->requireActor()->getPHID(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:00:07 -08:00
|
|
|
protected function buildMailBody(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
array $xactions) {
|
2012-11-21 17:39:46 -08:00
|
|
|
|
2013-06-20 17:13:48 -07:00
|
|
|
$body = new PhabricatorMetaMTAMailBody();
|
|
|
|
$headers = array();
|
|
|
|
$comments = array();
|
|
|
|
$inline_comments = array();
|
|
|
|
|
|
|
|
foreach ($xactions as $xaction) {
|
2013-07-16 13:31:20 -07:00
|
|
|
if ($xaction->shouldHide()) {
|
|
|
|
continue;
|
|
|
|
}
|
2013-06-20 17:13:48 -07:00
|
|
|
$comment = $xaction->getComment();
|
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case PholioTransactionType::TYPE_INLINE:
|
|
|
|
if ($comment && strlen($comment->getContent())) {
|
|
|
|
$inline_comments[] = $comment;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PhabricatorTransactions::TYPE_COMMENT:
|
|
|
|
if ($comment && strlen($comment->getContent())) {
|
|
|
|
$comments[] = $comment->getContent();
|
|
|
|
}
|
|
|
|
// fallthrough
|
|
|
|
default:
|
|
|
|
$headers[] = id(clone $xaction)
|
|
|
|
->setRenderingTarget('text')
|
|
|
|
->getTitle();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$body->addRawSection(implode("\n", $headers));
|
|
|
|
|
|
|
|
foreach ($comments as $comment) {
|
|
|
|
$body->addRawSection($comment);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($inline_comments) {
|
|
|
|
$body->addRawSection(pht('INLINE COMMENTS'));
|
|
|
|
foreach ($inline_comments as $comment) {
|
|
|
|
$text = pht(
|
|
|
|
'Image %d: %s',
|
|
|
|
$comment->getImageID(),
|
|
|
|
$comment->getContent());
|
|
|
|
$body->addRawSection($text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:00:07 -08:00
|
|
|
$body->addTextSection(
|
|
|
|
pht('MOCK DETAIL'),
|
|
|
|
PhabricatorEnv::getProductionURI('/M'.$object->getID()));
|
2012-11-21 17:39:46 -08:00
|
|
|
|
2012-12-11 14:00:07 -08:00
|
|
|
return $body;
|
2012-11-21 17:39:46 -08:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:00:07 -08:00
|
|
|
protected function getMailSubjectPrefix() {
|
2012-11-21 17:39:46 -08:00
|
|
|
return PhabricatorEnv::getEnvConfig('metamta.pholio.subject-prefix');
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:00:21 -08:00
|
|
|
protected function supportsFeed() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-12-21 14:21:50 -08:00
|
|
|
protected function supportsSearch() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-02-25 06:19:03 -08:00
|
|
|
protected function sortTransactions(array $xactions) {
|
|
|
|
$head = array();
|
|
|
|
$tail = array();
|
|
|
|
|
2013-06-04 15:28:24 -07:00
|
|
|
// Move inline comments to the end, so the comments precede them.
|
2013-02-25 06:19:03 -08:00
|
|
|
foreach ($xactions as $xaction) {
|
|
|
|
$type = $xaction->getTransactionType();
|
|
|
|
if ($type == PholioTransactionType::TYPE_INLINE) {
|
|
|
|
$tail[] = $xaction;
|
|
|
|
} else {
|
|
|
|
$head[] = $xaction;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return array_values(array_merge($head, $tail));
|
|
|
|
}
|
|
|
|
|
2013-03-09 17:55:14 -08:00
|
|
|
protected function shouldImplyCC(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
PhabricatorApplicationTransaction $xaction) {
|
|
|
|
|
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case PholioTransactionType::TYPE_INLINE:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent::shouldImplyCC($object, $xaction);
|
|
|
|
}
|
|
|
|
|
Add very basic scaffolding for Pholio
Summary:
I'm not going to land this until it's a bit more fleshed out since it would just confuse users, but this is probably more reviewable as a few diffs adding a couple features than one ULTRA-diff adding everything. Implement application basics for Pholio. This does more or less nothing, but adds storage, subscribe, flag, markup, indexing, query basics, PHIDs, handle loads, a couple of realy really basic controllers, etc.
Basic hierarchy is:
- **Moleskine**: Top-level object like a Differential Revision, like "Ponder Feed Ideas".
- **Image**: Each Moleskine has one or more images, like the unexpanded / expanded / mobile / empty states of feed.
- **Transaction**: Comment or edit, like Maniphest. I generally want to move most apps to a transaction model so we can log edits.
- **PixelComment**: Equivalent of an inline comment.
Test Plan: Created a fake object and viewed it.
Reviewers: btrahan, chad
Reviewed By: btrahan
CC: aran, davidreuss
Maniphest Tasks: T2097
Differential Revision: https://secure.phabricator.com/D3817
2012-11-21 17:22:36 -08:00
|
|
|
}
|