1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-09-20 01:08:50 +02:00

Modernize PhameBlog with modular transactions

Summary: Moves PhameBlog over to the wonderful world of modular transactions and the riches that lay beyond...

Test Plan:
- Create Blog
- Edit Blog
- Set Header
- Delete Header
- Add picture
- Archive blog
- Set incorrect domain values
- Be irresponsible with subtitle length
- Activate blog
- Change description

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

Differential Revision: https://secure.phabricator.com/D17815
This commit is contained in:
Chad Little 2017-05-02 15:11:54 -07:00
parent a067040024
commit 21ac196306
18 changed files with 611 additions and 600 deletions

View file

@ -4232,24 +4232,34 @@ phutil_register_library_map(array(
'PhameBlogController' => 'applications/phame/controller/blog/PhameBlogController.php',
'PhameBlogCreateCapability' => 'applications/phame/capability/PhameBlogCreateCapability.php',
'PhameBlogDatasource' => 'applications/phame/typeahead/PhameBlogDatasource.php',
'PhameBlogDescriptionTransaction' => 'applications/phame/xaction/PhameBlogDescriptionTransaction.php',
'PhameBlogEditConduitAPIMethod' => 'applications/phame/conduit/PhameBlogEditConduitAPIMethod.php',
'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php',
'PhameBlogEditEngine' => 'applications/phame/editor/PhameBlogEditEngine.php',
'PhameBlogEditor' => 'applications/phame/editor/PhameBlogEditor.php',
'PhameBlogFeedController' => 'applications/phame/controller/blog/PhameBlogFeedController.php',
'PhameBlogFullDomainTransaction' => 'applications/phame/xaction/PhameBlogFullDomainTransaction.php',
'PhameBlogFulltextEngine' => 'applications/phame/search/PhameBlogFulltextEngine.php',
'PhameBlogHeaderImageTransaction' => 'applications/phame/xaction/PhameBlogHeaderImageTransaction.php',
'PhameBlogHeaderPictureController' => 'applications/phame/controller/blog/PhameBlogHeaderPictureController.php',
'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php',
'PhameBlogListView' => 'applications/phame/view/PhameBlogListView.php',
'PhameBlogManageController' => 'applications/phame/controller/blog/PhameBlogManageController.php',
'PhameBlogNameTransaction' => 'applications/phame/xaction/PhameBlogNameTransaction.php',
'PhameBlogParentDomainTransaction' => 'applications/phame/xaction/PhameBlogParentDomainTransaction.php',
'PhameBlogParentSiteTransaction' => 'applications/phame/xaction/PhameBlogParentSiteTransaction.php',
'PhameBlogProfileImageTransaction' => 'applications/phame/xaction/PhameBlogProfileImageTransaction.php',
'PhameBlogProfilePictureController' => 'applications/phame/controller/blog/PhameBlogProfilePictureController.php',
'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php',
'PhameBlogReplyHandler' => 'applications/phame/mail/PhameBlogReplyHandler.php',
'PhameBlogSearchConduitAPIMethod' => 'applications/phame/conduit/PhameBlogSearchConduitAPIMethod.php',
'PhameBlogSearchEngine' => 'applications/phame/query/PhameBlogSearchEngine.php',
'PhameBlogSite' => 'applications/phame/site/PhameBlogSite.php',
'PhameBlogStatusTransaction' => 'applications/phame/xaction/PhameBlogStatusTransaction.php',
'PhameBlogSubtitleTransaction' => 'applications/phame/xaction/PhameBlogSubtitleTransaction.php',
'PhameBlogTransaction' => 'applications/phame/storage/PhameBlogTransaction.php',
'PhameBlogTransactionQuery' => 'applications/phame/query/PhameBlogTransactionQuery.php',
'PhameBlogTransactionType' => 'applications/phame/xaction/PhameBlogTransactionType.php',
'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php',
'PhameConstants' => 'applications/phame/constants/PhameConstants.php',
'PhameController' => 'applications/phame/controller/PhameController.php',
@ -9690,24 +9700,34 @@ phutil_register_library_map(array(
'PhameBlogController' => 'PhameController',
'PhameBlogCreateCapability' => 'PhabricatorPolicyCapability',
'PhameBlogDatasource' => 'PhabricatorTypeaheadDatasource',
'PhameBlogDescriptionTransaction' => 'PhameBlogTransactionType',
'PhameBlogEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'PhameBlogEditController' => 'PhameBlogController',
'PhameBlogEditEngine' => 'PhabricatorEditEngine',
'PhameBlogEditor' => 'PhabricatorApplicationTransactionEditor',
'PhameBlogFeedController' => 'PhameBlogController',
'PhameBlogFullDomainTransaction' => 'PhameBlogTransactionType',
'PhameBlogFulltextEngine' => 'PhabricatorFulltextEngine',
'PhameBlogHeaderImageTransaction' => 'PhameBlogTransactionType',
'PhameBlogHeaderPictureController' => 'PhameBlogController',
'PhameBlogListController' => 'PhameBlogController',
'PhameBlogListView' => 'AphrontTagView',
'PhameBlogManageController' => 'PhameBlogController',
'PhameBlogNameTransaction' => 'PhameBlogTransactionType',
'PhameBlogParentDomainTransaction' => 'PhameBlogTransactionType',
'PhameBlogParentSiteTransaction' => 'PhameBlogTransactionType',
'PhameBlogProfileImageTransaction' => 'PhameBlogTransactionType',
'PhameBlogProfilePictureController' => 'PhameBlogController',
'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhameBlogReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
'PhameBlogSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'PhameBlogSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhameBlogSite' => 'PhameSite',
'PhameBlogTransaction' => 'PhabricatorApplicationTransaction',
'PhameBlogStatusTransaction' => 'PhameBlogTransactionType',
'PhameBlogSubtitleTransaction' => 'PhameBlogTransactionType',
'PhameBlogTransaction' => 'PhabricatorModularTransaction',
'PhameBlogTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhameBlogTransactionType' => 'PhabricatorModularTransactionType',
'PhameBlogViewController' => 'PhameLiveController',
'PhameConstants' => 'Phobject',
'PhameController' => 'PhabricatorController',

View file

@ -32,7 +32,7 @@ final class PhameBlogArchiveController
$xactions = array();
$xactions[] = id(new PhameBlogTransaction())
->setTransactionType(PhameBlogTransaction::TYPE_STATUS)
->setTransactionType(PhameBlogStatusTransaction::TRANSACTIONTYPE)
->setNewValue($new_status);
id(new PhameBlogEditor())

View file

@ -61,7 +61,7 @@ final class PhameBlogHeaderPictureController
$xactions = array();
$xactions[] = id(new PhameBlogTransaction())
->setTransactionType(PhameBlogTransaction::TYPE_HEADERIMAGE)
->setTransactionType(PhameBlogHeaderImageTransaction::TRANSACTIONTYPE)
->setNewValue($new_value);
$editor = id(new PhameBlogEditor())

View file

@ -76,7 +76,8 @@ final class PhameBlogProfilePictureController
$xactions = array();
$xactions[] = id(new PhameBlogTransaction())
->setTransactionType(PhameBlogTransaction::TYPE_PROFILEIMAGE)
->setTransactionType(
PhameBlogProfileImageTransaction::TRANSACTIONTYPE)
->setNewValue($new_value);
$editor = id(new PhameBlogEditor())

View file

@ -75,7 +75,7 @@ final class PhameBlogEditEngine
->setDescription(pht('Blog name.'))
->setConduitDescription(pht('Retitle the blog.'))
->setConduitTypeDescription(pht('New blog title.'))
->setTransactionType(PhameBlogTransaction::TYPE_NAME)
->setTransactionType(PhameBlogNameTransaction::TRANSACTIONTYPE)
->setValue($object->getName()),
id(new PhabricatorTextEditField())
->setKey('subtitle')
@ -83,7 +83,7 @@ final class PhameBlogEditEngine
->setDescription(pht('Blog subtitle.'))
->setConduitDescription(pht('Change the blog subtitle.'))
->setConduitTypeDescription(pht('New blog subtitle.'))
->setTransactionType(PhameBlogTransaction::TYPE_SUBTITLE)
->setTransactionType(PhameBlogSubtitleTransaction::TRANSACTIONTYPE)
->setValue($object->getSubtitle()),
id(new PhabricatorRemarkupEditField())
->setKey('description')
@ -91,7 +91,7 @@ final class PhameBlogEditEngine
->setDescription(pht('Blog description.'))
->setConduitDescription(pht('Change the blog description.'))
->setConduitTypeDescription(pht('New blog description.'))
->setTransactionType(PhameBlogTransaction::TYPE_DESCRIPTION)
->setTransactionType(PhameBlogDescriptionTransaction::TRANSACTIONTYPE)
->setValue($object->getDescription()),
id(new PhabricatorTextEditField())
->setKey('domainFullURI')
@ -104,7 +104,7 @@ final class PhameBlogEditEngine
->setConduitDescription(pht('Change the blog full domain URI.'))
->setConduitTypeDescription(pht('New blog full domain URI.'))
->setValue($object->getDomainFullURI())
->setTransactionType(PhameBlogTransaction::TYPE_FULLDOMAIN),
->setTransactionType(PhameBlogFullDomainTransaction::TRANSACTIONTYPE),
id(new PhabricatorTextEditField())
->setKey('parentSite')
->setLabel(pht('Parent Site Name'))
@ -112,7 +112,7 @@ final class PhameBlogEditEngine
->setConduitDescription(pht('Change the blog parent site name.'))
->setConduitTypeDescription(pht('New blog parent site name.'))
->setValue($object->getParentSite())
->setTransactionType(PhameBlogTransaction::TYPE_PARENTSITE),
->setTransactionType(PhameBlogParentSiteTransaction::TRANSACTIONTYPE),
id(new PhabricatorTextEditField())
->setKey('parentDomain')
->setLabel(pht('Parent Site URI'))
@ -120,11 +120,11 @@ final class PhameBlogEditEngine
->setConduitDescription(pht('Change the blog parent domain.'))
->setConduitTypeDescription(pht('New blog parent domain.'))
->setValue($object->getParentDomain())
->setTransactionType(PhameBlogTransaction::TYPE_PARENTDOMAIN),
->setTransactionType(PhameBlogParentDomainTransaction::TRANSACTIONTYPE),
id(new PhabricatorSelectEditField())
->setKey('status')
->setLabel(pht('Status'))
->setTransactionType(PhameBlogTransaction::TYPE_STATUS)
->setTransactionType(PhameBlogStatusTransaction::TRANSACTIONTYPE)
->setIsConduitOnly(true)
->setOptions(PhameBlog::getStatusNameMap())
->setDescription(pht('Active or archived status.'))

View file

@ -11,251 +11,22 @@ final class PhameBlogEditor
return pht('Phame Blogs');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this blog.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhameBlogTransaction::TYPE_NAME;
$types[] = PhameBlogTransaction::TYPE_SUBTITLE;
$types[] = PhameBlogTransaction::TYPE_DESCRIPTION;
$types[] = PhameBlogTransaction::TYPE_FULLDOMAIN;
$types[] = PhameBlogTransaction::TYPE_PARENTSITE;
$types[] = PhameBlogTransaction::TYPE_PARENTDOMAIN;
$types[] = PhameBlogTransaction::TYPE_STATUS;
$types[] = PhameBlogTransaction::TYPE_HEADERIMAGE;
$types[] = PhameBlogTransaction::TYPE_PROFILEIMAGE;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhameBlogTransaction::TYPE_NAME:
return $object->getName();
case PhameBlogTransaction::TYPE_SUBTITLE:
return $object->getSubtitle();
case PhameBlogTransaction::TYPE_DESCRIPTION:
return $object->getDescription();
case PhameBlogTransaction::TYPE_FULLDOMAIN:
return $object->getDomainFullURI();
case PhameBlogTransaction::TYPE_PARENTSITE:
return $object->getParentSite();
case PhameBlogTransaction::TYPE_PARENTDOMAIN:
return $object->getParentDomain();
case PhameBlogTransaction::TYPE_PROFILEIMAGE:
return $object->getProfileImagePHID();
case PhameBlogTransaction::TYPE_HEADERIMAGE:
return $object->getHeaderImagePHID();
case PhameBlogTransaction::TYPE_STATUS:
return $object->getStatus();
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhameBlogTransaction::TYPE_NAME:
case PhameBlogTransaction::TYPE_SUBTITLE:
case PhameBlogTransaction::TYPE_DESCRIPTION:
case PhameBlogTransaction::TYPE_STATUS:
case PhameBlogTransaction::TYPE_PARENTSITE:
case PhameBlogTransaction::TYPE_PARENTDOMAIN:
case PhameBlogTransaction::TYPE_PROFILEIMAGE:
case PhameBlogTransaction::TYPE_HEADERIMAGE:
return $xaction->getNewValue();
case PhameBlogTransaction::TYPE_FULLDOMAIN:
$domain = $xaction->getNewValue();
if (!strlen($xaction->getNewValue())) {
return null;
}
return $domain;
}
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhameBlogTransaction::TYPE_NAME:
return $object->setName($xaction->getNewValue());
case PhameBlogTransaction::TYPE_SUBTITLE:
return $object->setSubtitle($xaction->getNewValue());
case PhameBlogTransaction::TYPE_DESCRIPTION:
return $object->setDescription($xaction->getNewValue());
case PhameBlogTransaction::TYPE_FULLDOMAIN:
$new_value = $xaction->getNewValue();
if (strlen($new_value)) {
$uri = new PhutilURI($new_value);
$domain = $uri->getDomain();
$object->setDomain($domain);
} else {
$object->setDomain(null);
}
$object->setDomainFullURI($new_value);
return;
case PhameBlogTransaction::TYPE_PROFILEIMAGE:
return $object->setProfileImagePHID($xaction->getNewValue());
case PhameBlogTransaction::TYPE_HEADERIMAGE:
return $object->setHeaderImagePHID($xaction->getNewValue());
case PhameBlogTransaction::TYPE_STATUS:
return $object->setStatus($xaction->getNewValue());
case PhameBlogTransaction::TYPE_PARENTSITE:
return $object->setParentSite($xaction->getNewValue());
case PhameBlogTransaction::TYPE_PARENTDOMAIN:
return $object->setParentDomain($xaction->getNewValue());
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhameBlogTransaction::TYPE_NAME:
case PhameBlogTransaction::TYPE_SUBTITLE:
case PhameBlogTransaction::TYPE_DESCRIPTION:
case PhameBlogTransaction::TYPE_FULLDOMAIN:
case PhameBlogTransaction::TYPE_PARENTSITE:
case PhameBlogTransaction::TYPE_PARENTDOMAIN:
case PhameBlogTransaction::TYPE_HEADERIMAGE:
case PhameBlogTransaction::TYPE_PROFILEIMAGE:
case PhameBlogTransaction::TYPE_STATUS:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case PhameBlogTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('Name is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
foreach ($xactions as $xaction) {
$new = $xaction->getNewValue();
if (phutil_utf8_strlen($new) > 64) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'The selected blog title is too long. The maximum length '.
'of a blog title is 64 characters.'),
$xaction);
}
}
break;
case PhameBlogTransaction::TYPE_SUBTITLE:
foreach ($xactions as $xaction) {
$new = $xaction->getNewValue();
if (phutil_utf8_strlen($new) > 64) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'The selected blog subtitle is too long. The maximum length '.
'of a blog subtitle is 64 characters.'),
$xaction);
}
}
break;
case PhameBlogTransaction::TYPE_PARENTDOMAIN:
if (!$xactions) {
continue;
}
$parent_domain = last($xactions)->getNewValue();
if (empty($parent_domain)) {
continue;
}
try {
PhabricatorEnv::requireValidRemoteURIForLink($parent_domain);
} catch (Exception $ex) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid URI'),
pht('Parent Domain must be set to a valid Remote URI.'),
nonempty(last($xactions), null));
$errors[] = $error;
}
break;
case PhameBlogTransaction::TYPE_FULLDOMAIN:
if (!$xactions) {
continue;
}
$custom_domain = last($xactions)->getNewValue();
if (empty($custom_domain)) {
continue;
}
list($error_label, $error_text) =
$object->validateCustomDomain($custom_domain);
if ($error_label) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
$error_label,
$error_text,
nonempty(last($xactions), null));
$errors[] = $error;
}
if ($object->getViewPolicy() != PhabricatorPolicies::POLICY_PUBLIC) {
$error_text = pht(
'For custom domains to work, the blog must have a view policy of '.
'public.');
$error = new PhabricatorApplicationTransactionValidationError(
PhabricatorTransactions::TYPE_VIEW_POLICY,
pht('Invalid Policy'),
$error_text,
nonempty(last($xactions), null));
$errors[] = $error;
}
$domain = new PhutilURI($custom_domain);
$domain = $domain->getDomain();
$duplicate_blog = id(new PhameBlogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withDomain($domain)
->executeOne();
if ($duplicate_blog && $duplicate_blog->getID() != $object->getID()) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Not Unique'),
pht('Domain must be unique; another blog already has this domain.'),
nonempty(last($xactions), null));
$errors[] = $error;
}
break;
}
return $errors;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {

View file

@ -127,53 +127,41 @@ final class PhameBlog extends PhameDAO
$supported_protocols = array('http', 'https');
if (!in_array($protocol, $supported_protocols)) {
return array(
$label,
pht(
return pht(
'The custom domain should include a valid protocol in the URI '.
'(for example, "%s"). Valid protocols are "http" or "https".',
$example_domain),
);
$example_domain);
}
if (strlen($path) && $path != '/') {
return array(
$label,
pht(
return pht(
'The custom domain should not specify a path (hosting a Phame '.
'blog at a path is currently not supported). Instead, just provide '.
'the bare domain name (for example, "%s").',
$example_domain),
);
$example_domain);
}
if (strpos($domain, '.') === false) {
return array(
$label,
pht(
return pht(
'The custom domain should contain at least one dot (.) because '.
'some browsers fail to set cookies on domains without a dot. '.
'Instead, use a normal looking domain name like "%s".',
$example_domain),
);
$example_domain);
}
if (!PhabricatorEnv::getEnvConfig('policy.allow-public')) {
$href = PhabricatorEnv::getProductionURI(
'/config/edit/policy.allow-public/');
return array(
pht('Fix Configuration'),
pht(
'For custom domains to work, this Phabricator instance must be '.
'configured to allow the public access policy. Configure this '.
'setting %s, or ask an administrator to configure this setting. '.
'The domain can be specified later once this setting has been '.
'changed.',
phutil_tag(
'a',
array('href' => $href),
pht('here'))),
);
return pht(
'For custom domains to work, this Phabricator instance must be '.
'configured to allow the public access policy. Configure this '.
'setting %s, or ask an administrator to configure this setting. '.
'The domain can be specified later once this setting has been '.
'changed.',
phutil_tag(
'a',
array('href' => $href),
pht('here')));
}
return null;

View file

@ -1,17 +1,7 @@
<?php
final class PhameBlogTransaction
extends PhabricatorApplicationTransaction {
const TYPE_NAME = 'phame.blog.name';
const TYPE_SUBTITLE = 'phame.blog.subtitle';
const TYPE_DESCRIPTION = 'phame.blog.description';
const TYPE_FULLDOMAIN = 'phame.blog.full.domain';
const TYPE_STATUS = 'phame.blog.status';
const TYPE_PARENTSITE = 'phame.blog.parent.site';
const TYPE_PARENTDOMAIN = 'phame.blog.parent.domain';
const TYPE_PROFILEIMAGE = 'phame.blog.header.image';
const TYPE_HEADERIMAGE = 'phame.blog.profile.image';
extends PhabricatorModularTransaction {
const MAILTAG_DETAILS = 'phame-blog-details';
const MAILTAG_SUBSCRIBERS = 'phame-blog-subscribers';
@ -25,76 +15,8 @@ final class PhameBlogTransaction
return PhabricatorPhameBlogPHIDType::TYPECONST;
}
public function shouldHide() {
$old = $this->getOldValue();
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
if ($old === null) {
return true;
}
}
return parent::shouldHide();
}
public function getRequiredHandlePHIDs() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$req_phids = array();
switch ($this->getTransactionType()) {
case self::TYPE_PROFILEIMAGE:
case self::TYPE_HEADERIMAGE:
$req_phids[] = $old;
$req_phids[] = $new;
break;
}
return array_merge($req_phids, parent::getRequiredHandlePHIDs());
}
public function getIcon() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_NAME:
if ($old === null) {
return 'fa-plus';
} else {
return 'fa-pencil';
}
break;
case self::TYPE_DESCRIPTION:
case self::TYPE_FULLDOMAIN:
return 'fa-pencil';
case self::TYPE_HEADERIMAGE:
return 'fa-image';
case self::TYPE_PROFILEIMAGE:
return 'fa-star';
case self::TYPE_STATUS:
if ($new == PhameBlog::STATUS_ARCHIVED) {
return 'fa-ban';
} else {
return 'fa-check';
}
break;
}
return parent::getIcon();
}
public function getColor() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_STATUS:
if ($new == PhameBlog::STATUS_ARCHIVED) {
return 'violet';
} else {
return 'green';
}
}
return parent::getColor();
public function getBaseTransactionClass() {
return 'PhameBlogTransactionType';
}
public function getMailTags() {
@ -121,247 +43,4 @@ final class PhameBlogTransaction
return $tags;
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$object_phid = $this->getObjectPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
$type = $this->getTransactionType();
switch ($type) {
case PhabricatorTransactions::TYPE_CREATE:
return pht(
'%s created this blog.',
$this->renderHandleLink($author_phid));
case self::TYPE_NAME:
if ($old === null) {
return pht(
'%s created this blog.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s updated the blog\'s name to "%s".',
$this->renderHandleLink($author_phid),
$new);
}
break;
case self::TYPE_SUBTITLE:
if ($old === null) {
return pht(
'%s set this blog\'s subtitle to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s updated the blog\'s subtitle to "%s".',
$this->renderHandleLink($author_phid),
$new);
}
break;
case self::TYPE_DESCRIPTION:
return pht(
'%s updated the blog\'s description.',
$this->renderHandleLink($author_phid));
break;
case self::TYPE_FULLDOMAIN:
return pht(
'%s updated the blog\'s full domain to "%s".',
$this->renderHandleLink($author_phid),
$new);
break;
case self::TYPE_PARENTSITE:
if ($old === null) {
return pht(
'%s set this blog\'s parent site to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s updated the blog\'s parent site to "%s".',
$this->renderHandleLink($author_phid),
$new);
}
break;
case self::TYPE_PARENTDOMAIN:
if ($old === null) {
return pht(
'%s set this blog\'s parent domain to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s updated the blog\'s parent domain to "%s".',
$this->renderHandleLink($author_phid),
$new);
}
break;
case self::TYPE_HEADERIMAGE:
if (!$old) {
return pht(
"%s set this blog's header image to %s.",
$this->renderHandleLink($author_phid),
$this->renderHandleLink($new));
} else if (!$new) {
return pht(
"%s removed this blog's header image.",
$this->renderHandleLink($author_phid));
} else {
return pht(
"%s updated this blog's header image from %s to %s.",
$this->renderHandleLink($author_phid),
$this->renderHandleLink($old),
$this->renderHandleLink($new));
}
break;
case self::TYPE_PROFILEIMAGE:
if (!$old) {
return pht(
"%s set this blog's profile image to %s.",
$this->renderHandleLink($author_phid),
$this->renderHandleLink($new));
} else if (!$new) {
return pht(
"%s removed this blog's profile image.",
$this->renderHandleLink($author_phid));
} else {
return pht(
"%s updated this blog's profile image from %s to %s.",
$this->renderHandleLink($author_phid),
$this->renderHandleLink($old),
$this->renderHandleLink($new));
}
break;
case self::TYPE_STATUS:
switch ($new) {
case PhameBlog::STATUS_ACTIVE:
return pht(
'%s published this blog.',
$this->renderHandleLink($author_phid));
case PhameBlog::STATUS_ARCHIVED:
return pht(
'%s archived this blog.',
$this->renderHandleLink($author_phid));
}
}
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_NAME:
if ($old === null) {
return pht(
'%s created %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
} else {
return pht(
'%s updated the name for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
break;
case self::TYPE_SUBTITLE:
if ($old === null) {
return pht(
'%s set the subtitle for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
} else {
return pht(
'%s updated the subtitle for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
break;
case self::TYPE_DESCRIPTION:
return pht(
'%s updated the description for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case self::TYPE_FULLDOMAIN:
return pht(
'%s updated the full domain for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case self::TYPE_PARENTSITE:
return pht(
'%s updated the parent site for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case self::TYPE_PARENTDOMAIN:
return pht(
'%s updated the parent domain for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case self::TYPE_HEADERIMAGE:
return pht(
'%s updated the header image for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case self::TYPE_PROFILEIMAGE:
return pht(
'%s updated the profile image for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case self::TYPE_STATUS:
switch ($new) {
case PhameBlog::STATUS_ACTIVE:
return pht(
'%s published the blog %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
case PhameBlog::STATUS_ARCHIVED:
return pht(
'%s archived the blog %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
break;
}
return parent::getTitleForFeed();
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
return ($this->getOldValue() !== null);
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
$old = $this->getOldValue();
$new = $this->getNewValue();
return $this->renderTextCorpusChangeDetails(
$viewer,
$old,
$new);
}
return parent::renderChangeDetails($viewer);
}
}

View file

@ -0,0 +1,60 @@
<?php
final class PhameBlogDescriptionTransaction
extends PhameBlogTransactionType {
const TRANSACTIONTYPE = 'phame.blog.description';
public function generateOldValue($object) {
return $object->getDescription();
}
public function applyInternalEffects($object, $value) {
$object->setDescription($value);
}
public function getTitle() {
return pht(
'%s updated the description.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s updated the description for %s.',
$this->renderAuthor(),
$this->renderObject());
}
public function hasChangeDetailView() {
return true;
}
public function getMailDiffSectionHeader() {
return pht('CHANGES TO BLOG DESCRIPTION');
}
public function newChangeDetailView() {
$viewer = $this->getViewer();
return id(new PhabricatorApplicationTransactionTextDiffDetailView())
->setViewer($viewer)
->setOldText($this->getOldValue())
->setNewText($this->getNewValue());
}
public function newRemarkupChanges() {
$changes = array();
$changes[] = $this->newRemarkupChange()
->setOldValue($this->getOldValue())
->setNewValue($this->getNewValue());
return $changes;
}
public function getIcon() {
return 'fa-file-text-o';
}
}

View file

@ -0,0 +1,95 @@
<?php
final class PhameBlogFullDomainTransaction
extends PhameBlogTransactionType {
const TRANSACTIONTYPE = 'phame.blog.full.domain';
public function generateOldValue($object) {
return $object->getDomainFullURI();
}
public function applyInternalEffects($object, $value) {
if (strlen($value)) {
$uri = new PhutilURI($value);
$domain = $uri->getDomain();
$object->setDomain($domain);
} else {
$object->setDomain(null);
}
$object->setDomainFullURI($value);
}
public function getTitle() {
$old = $this->getOldValue();
if (!strlen($old)) {
return pht(
'%s set this blog\'s full domain to %s.',
$this->renderAuthor(),
$this->renderNewValue());
} else {
return pht(
'%s updated the blog\'s full domain from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function getTitleForFeed() {
$old = $this->getOldValue();
if (!strlen($old)) {
return pht(
'%s set %s blog\'s full domain to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderNewValue());
} else {
return pht(
'%s updated %s blog\'s full domain from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if (!$xactions) {
return $errors;
}
$custom_domain = last($xactions)->getNewValue();
if (empty($custom_domain)) {
return $errors;
}
$error_text = $object->validateCustomDomain($custom_domain);
if ($error_text) {
$errors[] = $this->newInvalidError($error_text);
}
if ($object->getViewPolicy() != PhabricatorPolicies::POLICY_PUBLIC) {
$errors[] = $this->newInvalidError(
pht('For custom domains to work, the blog must have a view policy of '.
'public. This blog is currently set to "%s".',
$object->getViewPolicy()));
}
$domain = new PhutilURI($custom_domain);
$domain = $domain->getDomain();
$duplicate_blog = id(new PhameBlogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withDomain($domain)
->executeOne();
if ($duplicate_blog && $duplicate_blog->getID() != $object->getID()) {
$errors[] = $this->newInvalidError(
pht('Domain must be unique; another blog already has this domain.'));
}
return $errors;
}
}

View file

@ -0,0 +1,34 @@
<?php
final class PhameBlogHeaderImageTransaction
extends PhameBlogTransactionType {
// TODO: Migrate these transactions ha ha .... ha
const TRANSACTIONTYPE = 'phame.blog.profile.image';
public function generateOldValue($object) {
return $object->getHeaderImagePHID();
}
public function applyInternalEffects($object, $value) {
$object->setHeaderImagePHID($value);
}
public function getTitle() {
return pht(
'%s changed the header image for this blog.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s changed the header image for blog %s.',
$this->renderAuthor(),
$this->renderObject());
}
public function getIcon() {
return 'fa-camera';
}
}

View file

@ -0,0 +1,59 @@
<?php
final class PhameBlogNameTransaction
extends PhameBlogTransactionType {
const TRANSACTIONTYPE = 'phame.blog.name';
public function generateOldValue($object) {
return $object->getName();
}
public function applyInternalEffects($object, $value) {
$object->setName($value);
}
public function getTitle() {
return pht(
'%s renamed this blog from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function getTitleForFeed() {
return pht(
'%s renamed %s blog froms %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
$errors[] = $this->newRequiredError(
pht('Blogs must have a name.'));
}
$max_length = $object->getColumnMaximumByteLength('name');
foreach ($xactions as $xaction) {
$new_value = $xaction->getNewValue();
$new_length = strlen($new_value);
if ($new_length > $max_length) {
$errors[] = $this->newInvalidError(
pht('The name can be no longer than %s characters.',
new PhutilNumber($max_length)));
}
}
return $errors;
}
public function getIcon() {
return 'fa-rss';
}
}

View file

@ -0,0 +1,82 @@
<?php
final class PhameBlogParentDomainTransaction
extends PhameBlogTransactionType {
const TRANSACTIONTYPE = 'phame.blog.parent.domain';
public function generateOldValue($object) {
return $object->getParentDomain();
}
public function applyInternalEffects($object, $value) {
$object->setParentDomain($value);
}
public function getTitle() {
$old = $this->getOldValue();
if (!strlen($old)) {
return pht(
'%s set this blog\'s parent domain to %s.',
$this->renderAuthor(),
$this->renderNewValue());
} else {
return pht(
'%s updated the blog\'s parent domain from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function getTitleForFeed() {
$old = $this->getOldValue();
if (!strlen($old)) {
return pht(
'%s set %s blog\'s parent domain to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderNewValue());
} else {
return pht(
'%s updated %s blog\'s parent domain from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if (!$xactions) {
return $errors;
}
$parent_domain = last($xactions)->getNewValue();
if (empty($parent_domain)) {
return $errors;
}
try {
PhabricatorEnv::requireValidRemoteURIForLink($parent_domain);
} catch (Exception $ex) {
$errors[] = $this->newInvalidError(
pht('Parent Domain must be set to a valid Remote URI.'));
}
$max_length = $object->getColumnMaximumByteLength('parentDomain');
foreach ($xactions as $xaction) {
$new_value = $xaction->getNewValue();
$new_length = strlen($new_value);
if ($new_length > $max_length) {
$errors[] = $this->newInvalidError(
pht('The parent domain can be no longer than %s characters.',
new PhutilNumber($max_length)));
}
}
return $errors;
}
}

View file

@ -0,0 +1,66 @@
<?php
final class PhameBlogParentSiteTransaction
extends PhameBlogTransactionType {
const TRANSACTIONTYPE = 'phame.blog.parent.site';
public function generateOldValue($object) {
return $object->getParentSite();
}
public function applyInternalEffects($object, $value) {
$object->setParentSite($value);
}
public function getTitle() {
$old = $this->getOldValue();
if (!strlen($old)) {
return pht(
'%s set this blog\'s parent site to %s.',
$this->renderAuthor(),
$this->renderNewValue());
} else {
return pht(
'%s updated the blog\'s parent site from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function getTitleForFeed() {
$old = $this->getOldValue();
if (!strlen($old)) {
return pht(
'%s set %s blog\'s parent site to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderNewValue());
} else {
return pht(
'%s updated %s blog\'s parent site from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$max_length = $object->getColumnMaximumByteLength('parentSite');
foreach ($xactions as $xaction) {
$new_value = $xaction->getNewValue();
$new_length = strlen($new_value);
if ($new_length > $max_length) {
$errors[] = $this->newInvalidError(
pht('The parent site can be no longer than %s characters.',
new PhutilNumber($max_length)));
}
}
return $errors;
}
}

View file

@ -0,0 +1,34 @@
<?php
final class PhameBlogProfileImageTransaction
extends PhameBlogTransactionType {
// TODO: Migrate these transactions ha ha .... ha
const TRANSACTIONTYPE = 'phame.blog.header.image';
public function generateOldValue($object) {
return $object->getProfileImagePHID();
}
public function applyInternalEffects($object, $value) {
$object->setProfileImagePHID($value);
}
public function getTitle() {
return pht(
'%s changed the profile image for this blog.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s changed the profile image for blog %s.',
$this->renderAuthor(),
$this->renderObject());
}
public function getIcon() {
return 'fa-file-image-o';
}
}

View file

@ -0,0 +1,55 @@
<?php
final class PhameBlogStatusTransaction
extends PhameBlogTransactionType {
const TRANSACTIONTYPE = 'phame.blog.status';
public function generateOldValue($object) {
return $object->getStatus();
}
public function applyInternalEffects($object, $value) {
$object->setStatus($value);
}
public function getTitle() {
$new = $this->getNewValue();
switch ($new) {
case PhameBlog::STATUS_ACTIVE:
return pht(
'%s published this blog.',
$this->renderAuthor());
case PhameBlog::STATUS_ARCHIVED:
return pht(
'%s archived this blog.',
$this->renderAuthor());
}
}
public function getTitleForFeed() {
$new = $this->getNewValue();
switch ($new) {
case PhameBlog::STATUS_ACTIVE:
return pht(
'%s published the blog %s.',
$this->renderAuthor(),
$this->renderObject());
case PhameBlog::STATUS_ARCHIVED:
return pht(
'%s archived the blog %s.',
$this->renderAuthor(),
$this->renderObject());
}
}
public function getIcon() {
$new = $this->getNewValue();
if ($new == PhameBlog::STATUS_ARCHIVED) {
return 'fa-ban';
} else {
return 'fa-check';
}
}
}

View file

@ -0,0 +1,63 @@
<?php
final class PhameBlogSubtitleTransaction
extends PhameBlogTransactionType {
const TRANSACTIONTYPE = 'phame.blog.subtitle';
public function generateOldValue($object) {
return $object->getSubtitle();
}
public function applyInternalEffects($object, $value) {
$object->setSubtitle($value);
}
public function getTitle() {
$old = $this->getOldValue();
if ($old === null) {
return pht(
'%s set this blog\'s subtitle to "%s".',
$this->renderAuthor(),
$this->renderNewValue());
} else {
return pht(
'%s updated the blog\'s subtitle to "%s".',
$this->renderAuthor(),
$this->renderNewValue());
}
}
public function getTitleForFeed() {
$old = $this->getOldValue();
if ($old === null) {
return pht(
'%s set the subtitle for %s.',
$this->renderAuthor(),
$this->renderObject());
} else {
return pht(
'%s updated the subtitle for %s.',
$this->renderAuthor(),
$this->renderObject());
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$max_length = $object->getColumnMaximumByteLength('subtitle');
foreach ($xactions as $xaction) {
$new_value = $xaction->getNewValue();
$new_length = strlen($new_value);
if ($new_length > $max_length) {
$errors[] = $this->newInvalidError(
pht('The subtitle can be no longer than %s characters.',
new PhutilNumber($max_length)));
}
}
return $errors;
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class PhameBlogTransactionType
extends PhabricatorModularTransactionType {}