1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-03-26 03:00:45 +01: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', 'PhameBlogController' => 'applications/phame/controller/blog/PhameBlogController.php',
'PhameBlogCreateCapability' => 'applications/phame/capability/PhameBlogCreateCapability.php', 'PhameBlogCreateCapability' => 'applications/phame/capability/PhameBlogCreateCapability.php',
'PhameBlogDatasource' => 'applications/phame/typeahead/PhameBlogDatasource.php', 'PhameBlogDatasource' => 'applications/phame/typeahead/PhameBlogDatasource.php',
'PhameBlogDescriptionTransaction' => 'applications/phame/xaction/PhameBlogDescriptionTransaction.php',
'PhameBlogEditConduitAPIMethod' => 'applications/phame/conduit/PhameBlogEditConduitAPIMethod.php', 'PhameBlogEditConduitAPIMethod' => 'applications/phame/conduit/PhameBlogEditConduitAPIMethod.php',
'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php', 'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php',
'PhameBlogEditEngine' => 'applications/phame/editor/PhameBlogEditEngine.php', 'PhameBlogEditEngine' => 'applications/phame/editor/PhameBlogEditEngine.php',
'PhameBlogEditor' => 'applications/phame/editor/PhameBlogEditor.php', 'PhameBlogEditor' => 'applications/phame/editor/PhameBlogEditor.php',
'PhameBlogFeedController' => 'applications/phame/controller/blog/PhameBlogFeedController.php', 'PhameBlogFeedController' => 'applications/phame/controller/blog/PhameBlogFeedController.php',
'PhameBlogFullDomainTransaction' => 'applications/phame/xaction/PhameBlogFullDomainTransaction.php',
'PhameBlogFulltextEngine' => 'applications/phame/search/PhameBlogFulltextEngine.php', 'PhameBlogFulltextEngine' => 'applications/phame/search/PhameBlogFulltextEngine.php',
'PhameBlogHeaderImageTransaction' => 'applications/phame/xaction/PhameBlogHeaderImageTransaction.php',
'PhameBlogHeaderPictureController' => 'applications/phame/controller/blog/PhameBlogHeaderPictureController.php', 'PhameBlogHeaderPictureController' => 'applications/phame/controller/blog/PhameBlogHeaderPictureController.php',
'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php', 'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php',
'PhameBlogListView' => 'applications/phame/view/PhameBlogListView.php', 'PhameBlogListView' => 'applications/phame/view/PhameBlogListView.php',
'PhameBlogManageController' => 'applications/phame/controller/blog/PhameBlogManageController.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', 'PhameBlogProfilePictureController' => 'applications/phame/controller/blog/PhameBlogProfilePictureController.php',
'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php', 'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php',
'PhameBlogReplyHandler' => 'applications/phame/mail/PhameBlogReplyHandler.php', 'PhameBlogReplyHandler' => 'applications/phame/mail/PhameBlogReplyHandler.php',
'PhameBlogSearchConduitAPIMethod' => 'applications/phame/conduit/PhameBlogSearchConduitAPIMethod.php', 'PhameBlogSearchConduitAPIMethod' => 'applications/phame/conduit/PhameBlogSearchConduitAPIMethod.php',
'PhameBlogSearchEngine' => 'applications/phame/query/PhameBlogSearchEngine.php', 'PhameBlogSearchEngine' => 'applications/phame/query/PhameBlogSearchEngine.php',
'PhameBlogSite' => 'applications/phame/site/PhameBlogSite.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', 'PhameBlogTransaction' => 'applications/phame/storage/PhameBlogTransaction.php',
'PhameBlogTransactionQuery' => 'applications/phame/query/PhameBlogTransactionQuery.php', 'PhameBlogTransactionQuery' => 'applications/phame/query/PhameBlogTransactionQuery.php',
'PhameBlogTransactionType' => 'applications/phame/xaction/PhameBlogTransactionType.php',
'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php', 'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php',
'PhameConstants' => 'applications/phame/constants/PhameConstants.php', 'PhameConstants' => 'applications/phame/constants/PhameConstants.php',
'PhameController' => 'applications/phame/controller/PhameController.php', 'PhameController' => 'applications/phame/controller/PhameController.php',
@ -9690,24 +9700,34 @@ phutil_register_library_map(array(
'PhameBlogController' => 'PhameController', 'PhameBlogController' => 'PhameController',
'PhameBlogCreateCapability' => 'PhabricatorPolicyCapability', 'PhameBlogCreateCapability' => 'PhabricatorPolicyCapability',
'PhameBlogDatasource' => 'PhabricatorTypeaheadDatasource', 'PhameBlogDatasource' => 'PhabricatorTypeaheadDatasource',
'PhameBlogDescriptionTransaction' => 'PhameBlogTransactionType',
'PhameBlogEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhameBlogEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'PhameBlogEditController' => 'PhameBlogController', 'PhameBlogEditController' => 'PhameBlogController',
'PhameBlogEditEngine' => 'PhabricatorEditEngine', 'PhameBlogEditEngine' => 'PhabricatorEditEngine',
'PhameBlogEditor' => 'PhabricatorApplicationTransactionEditor', 'PhameBlogEditor' => 'PhabricatorApplicationTransactionEditor',
'PhameBlogFeedController' => 'PhameBlogController', 'PhameBlogFeedController' => 'PhameBlogController',
'PhameBlogFullDomainTransaction' => 'PhameBlogTransactionType',
'PhameBlogFulltextEngine' => 'PhabricatorFulltextEngine', 'PhameBlogFulltextEngine' => 'PhabricatorFulltextEngine',
'PhameBlogHeaderImageTransaction' => 'PhameBlogTransactionType',
'PhameBlogHeaderPictureController' => 'PhameBlogController', 'PhameBlogHeaderPictureController' => 'PhameBlogController',
'PhameBlogListController' => 'PhameBlogController', 'PhameBlogListController' => 'PhameBlogController',
'PhameBlogListView' => 'AphrontTagView', 'PhameBlogListView' => 'AphrontTagView',
'PhameBlogManageController' => 'PhameBlogController', 'PhameBlogManageController' => 'PhameBlogController',
'PhameBlogNameTransaction' => 'PhameBlogTransactionType',
'PhameBlogParentDomainTransaction' => 'PhameBlogTransactionType',
'PhameBlogParentSiteTransaction' => 'PhameBlogTransactionType',
'PhameBlogProfileImageTransaction' => 'PhameBlogTransactionType',
'PhameBlogProfilePictureController' => 'PhameBlogController', 'PhameBlogProfilePictureController' => 'PhameBlogController',
'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhameBlogReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhameBlogReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
'PhameBlogSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhameBlogSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'PhameBlogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhameBlogSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhameBlogSite' => 'PhameSite', 'PhameBlogSite' => 'PhameSite',
'PhameBlogTransaction' => 'PhabricatorApplicationTransaction', 'PhameBlogStatusTransaction' => 'PhameBlogTransactionType',
'PhameBlogSubtitleTransaction' => 'PhameBlogTransactionType',
'PhameBlogTransaction' => 'PhabricatorModularTransaction',
'PhameBlogTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhameBlogTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhameBlogTransactionType' => 'PhabricatorModularTransactionType',
'PhameBlogViewController' => 'PhameLiveController', 'PhameBlogViewController' => 'PhameLiveController',
'PhameConstants' => 'Phobject', 'PhameConstants' => 'Phobject',
'PhameController' => 'PhabricatorController', 'PhameController' => 'PhabricatorController',

View file

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

View file

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

View file

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

View file

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

View file

@ -11,251 +11,22 @@ final class PhameBlogEditor
return pht('Phame Blogs'); 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() { public function getTransactionTypes() {
$types = parent::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_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types; 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( protected function shouldSendMail(
PhabricatorLiskDAO $object, PhabricatorLiskDAO $object,
array $xactions) { array $xactions) {

View file

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

View file

@ -1,17 +1,7 @@
<?php <?php
final class PhameBlogTransaction final class PhameBlogTransaction
extends PhabricatorApplicationTransaction { extends PhabricatorModularTransaction {
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';
const MAILTAG_DETAILS = 'phame-blog-details'; const MAILTAG_DETAILS = 'phame-blog-details';
const MAILTAG_SUBSCRIBERS = 'phame-blog-subscribers'; const MAILTAG_SUBSCRIBERS = 'phame-blog-subscribers';
@ -25,76 +15,8 @@ final class PhameBlogTransaction
return PhabricatorPhameBlogPHIDType::TYPECONST; return PhabricatorPhameBlogPHIDType::TYPECONST;
} }
public function shouldHide() { public function getBaseTransactionClass() {
$old = $this->getOldValue(); return 'PhameBlogTransactionType';
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 getMailTags() { public function getMailTags() {
@ -121,247 +43,4 @@ final class PhameBlogTransaction
return $tags; 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 {}