Page MenuHomestyx hydra

No OneTemporary

diff --git a/resources/sql/autopatches/20160623.phame.blog.fulldomain.1.sql b/resources/sql/autopatches/20160623.phame.blog.fulldomain.1.sql
new file mode 100644
index 0000000000..96fc3b27ba
--- /dev/null
+++ b/resources/sql/autopatches/20160623.phame.blog.fulldomain.1.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_phame.phame_blog
+ ADD domainFullURI VARCHAR(128) COLLATE {$COLLATE_TEXT};
diff --git a/resources/sql/autopatches/20160623.phame.blog.fulldomain.2.sql b/resources/sql/autopatches/20160623.phame.blog.fulldomain.2.sql
new file mode 100644
index 0000000000..a323333c85
--- /dev/null
+++ b/resources/sql/autopatches/20160623.phame.blog.fulldomain.2.sql
@@ -0,0 +1,3 @@
+UPDATE {$NAMESPACE}_phame.phame_blog
+ SET domainFullURI = CONCAT('http://', domain, '/')
+ WHERE domain IS NOT NULL;
diff --git a/resources/sql/autopatches/20160623.phame.blog.fulldomain.3.sql b/resources/sql/autopatches/20160623.phame.blog.fulldomain.3.sql
new file mode 100644
index 0000000000..05f6009de1
--- /dev/null
+++ b/resources/sql/autopatches/20160623.phame.blog.fulldomain.3.sql
@@ -0,0 +1,3 @@
+UPDATE {$NAMESPACE}_phame.phame_blogtransaction
+ SET transactionType = 'phame.blog.full.domain'
+ WHERE transactionType = 'phame.blog.domain';
diff --git a/src/applications/phame/controller/blog/PhameBlogManageController.php b/src/applications/phame/controller/blog/PhameBlogManageController.php
index a87b02070d..4085d3ef6b 100644
--- a/src/applications/phame/controller/blog/PhameBlogManageController.php
+++ b/src/applications/phame/controller/blog/PhameBlogManageController.php
@@ -1,242 +1,241 @@
<?php
final class PhameBlogManageController extends PhameBlogController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$blog = id(new PhameBlogQuery())
->setViewer($viewer)
->withIDs(array($id))
->needProfileImage(true)
->needHeaderImage(true)
->executeOne();
if (!$blog) {
return new Aphront404Response();
}
if ($blog->isArchived()) {
$header_icon = 'fa-ban';
$header_name = pht('Archived');
$header_color = 'dark';
} else {
$header_icon = 'fa-check';
$header_name = pht('Active');
$header_color = 'bluegrey';
}
$picture = $blog->getProfileImageURI();
$view = id(new PHUIButtonView())
->setTag('a')
->setText(pht('View Live'))
->setIcon('fa-external-link')
->setHref($blog->getLiveURI());
$header = id(new PHUIHeaderView())
->setHeader($blog->getName())
->setUser($viewer)
->setPolicyObject($blog)
->setImage($picture)
->setStatus($header_icon, $header_color, $header_name)
->addActionLink($view);
$curtain = $this->buildCurtain($blog);
$properties = $this->buildPropertyView($blog);
$file = $this->buildFileView($blog);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
pht('Blogs'),
$this->getApplicationURI('blog/'));
$crumbs->addTextCrumb(
$blog->getName(),
$this->getApplicationURI('blog/view/'.$id));
$crumbs->addTextCrumb(pht('Manage Blog'));
$crumbs->setBorder(true);
$object_box = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
$timeline = $this->buildTransactionTimeline(
$blog,
new PhameBlogTransactionQuery());
$timeline->setShouldTerminate(true);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->addPropertySection(pht('Details'), $properties)
->addPropertySection(pht('Header'), $file)
->setMainColumn(
array(
$timeline,
));
return $this->newPage()
->setTitle($blog->getName())
->setCrumbs($crumbs)
->appendChild(
array(
$view,
));
}
private function buildPropertyView(PhameBlog $blog) {
$viewer = $this->getViewer();
require_celerity_resource('aphront-tooltip-css');
Javelin::initBehavior('phabricator-tooltips');
$properties = id(new PHUIPropertyListView())
->setUser($viewer);
- $domain = $blog->getDomain();
- if (!$domain) {
- $domain = phutil_tag('em', array(), pht('No external domain'));
+ $full_domain = $blog->getDomainFullURI();
+ if (!$full_domain) {
+ $full_domain = phutil_tag('em', array(), pht('No external domain'));
}
-
- $properties->addProperty(pht('Domain'), $domain);
+ $properties->addProperty(pht('Full Domain'), $full_domain);
$parent_site = $blog->getParentSite();
if (!$parent_site) {
$parent_site = phutil_tag('em', array(), pht('No parent site'));
}
$properties->addProperty(pht('Parent Site'), $parent_site);
$parent_domain = $blog->getParentDomain();
if (!$parent_domain) {
$parent_domain = phutil_tag('em', array(), pht('No parent domain'));
}
$properties->addProperty(pht('Parent Domain'), $parent_domain);
$feed_uri = PhabricatorEnv::getProductionURI(
$this->getApplicationURI('blog/feed/'.$blog->getID().'/'));
$properties->addProperty(
pht('Atom URI'),
javelin_tag('a',
array(
'href' => $feed_uri,
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => pht('Atom URI does not support custom domains.'),
'size' => 320,
),
),
$feed_uri));
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
$viewer,
$blog);
$properties->addProperty(
pht('Editable By'),
$descriptions[PhabricatorPolicyCapability::CAN_EDIT]);
$engine = id(new PhabricatorMarkupEngine())
->setViewer($viewer)
->addObject($blog, PhameBlog::MARKUP_FIELD_DESCRIPTION)
->process();
$description = $blog->getDescription();
if (strlen($description)) {
$description = new PHUIRemarkupView($viewer, $description);
$properties->addSectionHeader(
pht('Description'),
PHUIPropertyListView::ICON_SUMMARY);
$properties->addTextContent($description);
}
return $properties;
}
private function buildCurtain(PhameBlog $blog) {
$viewer = $this->getViewer();
$curtain = $this->newCurtainView($blog);
$actions = id(new PhabricatorActionListView())
->setObject($blog)
->setUser($viewer);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$blog,
PhabricatorPolicyCapability::CAN_EDIT);
$curtain->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setHref($this->getApplicationURI('blog/edit/'.$blog->getID().'/'))
->setName(pht('Edit Blog'))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$curtain->addAction(
id(new PhabricatorActionView())
->setIcon('fa-camera')
->setHref($this->getApplicationURI('blog/header/'.$blog->getID().'/'))
->setName(pht('Edit Blog Header'))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$curtain->addAction(
id(new PhabricatorActionView())
->setIcon('fa-picture-o')
->setHref($this->getApplicationURI('blog/picture/'.$blog->getID().'/'))
->setName(pht('Edit Blog Picture'))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
if ($blog->isArchived()) {
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Activate Blog'))
->setIcon('fa-check')
->setHref(
$this->getApplicationURI('blog/archive/'.$blog->getID().'/'))
->setDisabled(!$can_edit)
->setWorkflow(true));
} else {
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Archive Blog'))
->setIcon('fa-ban')
->setHref(
$this->getApplicationURI('blog/archive/'.$blog->getID().'/'))
->setDisabled(!$can_edit)
->setWorkflow(true));
}
return $curtain;
}
private function buildFileView(
PhameBlog $blog) {
$viewer = $this->getViewer();
$view = id(new PHUIPropertyListView())
->setUser($viewer);
if ($blog->getHeaderImagePHID()) {
$view->addImageContent(
phutil_tag(
'img',
array(
'src' => $blog->getHeaderImageURI(),
'class' => 'phabricator-image-macro-hero',
)));
return $view;
}
return null;
}
}
diff --git a/src/applications/phame/editor/PhameBlogEditEngine.php b/src/applications/phame/editor/PhameBlogEditEngine.php
index 70d878e15a..5f96309e8b 100644
--- a/src/applications/phame/editor/PhameBlogEditEngine.php
+++ b/src/applications/phame/editor/PhameBlogEditEngine.php
@@ -1,133 +1,133 @@
<?php
final class PhameBlogEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'phame.blog';
public function getEngineName() {
return pht('Blogs');
}
public function getEngineApplicationClass() {
return 'PhabricatorPhameApplication';
}
public function getSummaryHeader() {
return pht('Configure Phame Blog Forms');
}
public function getSummaryText() {
return pht('Configure how blogs in Phame are created and edited.');
}
protected function newEditableObject() {
return PhameBlog::initializeNewBlog($this->getViewer());
}
protected function newObjectQuery() {
return id(new PhameBlogQuery())
->needProfileImage(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Blog');
}
protected function getObjectEditTitleText($object) {
return pht('Edit %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getName();
}
protected function getObjectCreateShortText() {
return pht('Create Blog');
}
protected function getObjectName() {
return pht('Blog');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('blog/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('blog/edit/');
}
protected function getObjectViewURI($object) {
return $object->getManageURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
PhameBlogCreateCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Blog name.'))
->setConduitDescription(pht('Retitle the blog.'))
->setConduitTypeDescription(pht('New blog title.'))
->setTransactionType(PhameBlogTransaction::TYPE_NAME)
->setValue($object->getName()),
id(new PhabricatorTextEditField())
->setKey('subtitle')
->setLabel(pht('Subtitle'))
->setDescription(pht('Blog subtitle.'))
->setConduitDescription(pht('Change the blog subtitle.'))
->setConduitTypeDescription(pht('New blog subtitle.'))
->setTransactionType(PhameBlogTransaction::TYPE_SUBTITLE)
->setValue($object->getSubtitle()),
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setDescription(pht('Blog description.'))
->setConduitDescription(pht('Change the blog description.'))
->setConduitTypeDescription(pht('New blog description.'))
->setTransactionType(PhameBlogTransaction::TYPE_DESCRIPTION)
->setValue($object->getDescription()),
id(new PhabricatorTextEditField())
- ->setKey('domain')
- ->setLabel(pht('Custom Domain'))
- ->setDescription(pht('Blog domain name.'))
- ->setConduitDescription(pht('Change the blog domain.'))
- ->setConduitTypeDescription(pht('New blog domain.'))
- ->setValue($object->getDomain())
- ->setTransactionType(PhameBlogTransaction::TYPE_DOMAIN),
+ ->setKey('domainFullURI')
+ ->setLabel(pht('Full Domain URI'))
+ ->setDescription(pht('Blog full domain URI.'))
+ ->setConduitDescription(pht('Change the blog full domain URI.'))
+ ->setConduitTypeDescription(pht('New blog full domain URI.'))
+ ->setValue($object->getDomainFullURI())
+ ->setTransactionType(PhameBlogTransaction::TYPE_FULLDOMAIN),
id(new PhabricatorTextEditField())
->setKey('parentSite')
->setLabel(pht('Parent Site'))
->setDescription(pht('Blog parent site name.'))
->setConduitDescription(pht('Change the blog parent site name.'))
->setConduitTypeDescription(pht('New blog parent site name.'))
->setValue($object->getParentSite())
->setTransactionType(PhameBlogTransaction::TYPE_PARENTSITE),
id(new PhabricatorTextEditField())
->setKey('parentDomain')
->setLabel(pht('Parent Domain'))
->setDescription(pht('Blog parent domain name.'))
->setConduitDescription(pht('Change the blog parent domain.'))
->setConduitTypeDescription(pht('New blog parent domain.'))
->setValue($object->getParentDomain())
->setTransactionType(PhameBlogTransaction::TYPE_PARENTDOMAIN),
id(new PhabricatorSelectEditField())
->setKey('status')
->setLabel(pht('Status'))
->setTransactionType(PhameBlogTransaction::TYPE_STATUS)
->setIsConduitOnly(true)
->setOptions(PhameBlog::getStatusNameMap())
->setDescription(pht('Active or archived status.'))
->setConduitDescription(pht('Active or archive the blog.'))
->setConduitTypeDescription(pht('New blog status constant.'))
->setValue($object->getStatus()),
);
}
}
diff --git a/src/applications/phame/editor/PhameBlogEditor.php b/src/applications/phame/editor/PhameBlogEditor.php
index d2a9fcbc1f..197387985b 100644
--- a/src/applications/phame/editor/PhameBlogEditor.php
+++ b/src/applications/phame/editor/PhameBlogEditor.php
@@ -1,287 +1,298 @@
<?php
final class PhameBlogEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
return 'PhabricatorPhameApplication';
}
public function getEditorObjectsDescription() {
return pht('Phame Blogs');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhameBlogTransaction::TYPE_NAME;
$types[] = PhameBlogTransaction::TYPE_SUBTITLE;
$types[] = PhameBlogTransaction::TYPE_DESCRIPTION;
- $types[] = PhameBlogTransaction::TYPE_DOMAIN;
+ $types[] = PhameBlogTransaction::TYPE_FULLDOMAIN;
$types[] = PhameBlogTransaction::TYPE_PARENTSITE;
$types[] = PhameBlogTransaction::TYPE_PARENTDOMAIN;
$types[] = PhameBlogTransaction::TYPE_STATUS;
$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_DOMAIN:
- return $object->getDomain();
+ case PhameBlogTransaction::TYPE_FULLDOMAIN:
+ return $object->getDomainFullURI();
case PhameBlogTransaction::TYPE_PARENTSITE:
return $object->getParentSite();
case PhameBlogTransaction::TYPE_PARENTDOMAIN:
return $object->getParentDomain();
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:
return $xaction->getNewValue();
- case PhameBlogTransaction::TYPE_DOMAIN:
+ 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_DOMAIN:
- return $object->setDomain($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_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_DOMAIN:
+ case PhameBlogTransaction::TYPE_FULLDOMAIN:
case PhameBlogTransaction::TYPE_PARENTSITE:
case PhameBlogTransaction::TYPE_PARENTDOMAIN:
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;
}
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_DOMAIN:
+ 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($custom_domain)
+ ->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) {
return true;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$phids = array();
$phids[] = $this->requireActor()->getPHID();
$phids[] = $object->getCreatorPHID();
return $phids;
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$phid = $object->getPHID();
$name = $object->getName();
return id(new PhabricatorMetaMTAMail())
->setSubject($name)
->addHeader('Thread-Topic', $phid);
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhameBlogReplyHandler())
->setMailReceiver($object);
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addLinkSection(
pht('BLOG DETAIL'),
PhabricatorEnv::getProductionURI($object->getViewURI()));
return $body;
}
public function getMailTagsMap() {
return array(
PhameBlogTransaction::MAILTAG_DETAILS =>
pht("A blog's details change."),
PhameBlogTransaction::MAILTAG_SUBSCRIBERS =>
pht("A blog's subscribers change."),
PhameBlogTransaction::MAILTAG_OTHER =>
pht('Other blog activity not listed above occurs.'),
);
}
protected function getMailSubjectPrefix() {
return '[Phame]';
}
protected function supportsSearch() {
return true;
}
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
return id(new HeraldPhameBlogAdapter())
->setBlog($object);
}
}
diff --git a/src/applications/phame/storage/PhameBlog.php b/src/applications/phame/storage/PhameBlog.php
index 4f092cd3f1..6d9c51071a 100644
--- a/src/applications/phame/storage/PhameBlog.php
+++ b/src/applications/phame/storage/PhameBlog.php
@@ -1,407 +1,405 @@
<?php
final class PhameBlog extends PhameDAO
implements
PhabricatorPolicyInterface,
PhabricatorMarkupInterface,
PhabricatorSubscribableInterface,
PhabricatorFlaggableInterface,
PhabricatorProjectInterface,
PhabricatorDestructibleInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorConduitResultInterface,
PhabricatorFulltextInterface {
const MARKUP_FIELD_DESCRIPTION = 'markup:description';
protected $name;
protected $subtitle;
protected $description;
protected $domain;
+ protected $domainFullURI;
protected $parentSite;
protected $parentDomain;
protected $configData;
protected $creatorPHID;
protected $viewPolicy;
protected $editPolicy;
protected $status;
protected $mailKey;
protected $profileImagePHID;
protected $headerImagePHID;
private $profileImageFile = self::ATTACHABLE;
private $headerImageFile = self::ATTACHABLE;
const STATUS_ACTIVE = 'active';
const STATUS_ARCHIVED = 'archived';
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'configData' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'text64',
'subtitle' => 'text64',
'description' => 'text',
'domain' => 'text128?',
+ 'domainFullURI' => 'text128?',
'parentSite' => 'text128',
'parentDomain' => 'text128',
'status' => 'text32',
'mailKey' => 'bytes20',
'profileImagePHID' => 'phid?',
'headerImagePHID' => 'phid?',
// T6203/NULLABILITY
// These policies should always be non-null.
'editPolicy' => 'policy?',
'viewPolicy' => 'policy?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
'phid' => array(
'columns' => array('phid'),
'unique' => true,
),
'domain' => array(
'columns' => array('domain'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public function save() {
if (!$this->getMailKey()) {
$this->setMailKey(Filesystem::readRandomCharacters(20));
}
return parent::save();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorPhameBlogPHIDType::TYPECONST);
}
public static function initializeNewBlog(PhabricatorUser $actor) {
$blog = id(new PhameBlog())
->setCreatorPHID($actor->getPHID())
->setStatus(self::STATUS_ACTIVE)
->setViewPolicy(PhabricatorPolicies::getMostOpenPolicy())
->setEditPolicy(PhabricatorPolicies::POLICY_USER);
return $blog;
}
public function isArchived() {
return ($this->getStatus() == self::STATUS_ARCHIVED);
}
public static function getStatusNameMap() {
return array(
self::STATUS_ACTIVE => pht('Active'),
self::STATUS_ARCHIVED => pht('Archived'),
);
}
/**
* Makes sure a given custom blog uri is properly configured in DNS
* to point at this Phabricator instance. If there is an error in
* the configuration, return a string describing the error and how
* to fix it. If there is no error, return an empty string.
*
* @return string
*/
- public function validateCustomDomain($custom_domain) {
- $example_domain = 'blog.example.com';
+ public function validateCustomDomain($domain_full_uri) {
+ $example_domain = 'http://blog.example.com/';
$label = pht('Invalid');
// note this "uri" should be pretty busted given the desired input
// so just use it to test if there's a protocol specified
- $uri = new PhutilURI($custom_domain);
- if ($uri->getProtocol()) {
- return array(
- $label,
- pht(
- 'The custom domain should not include a protocol. Just provide '.
- 'the bare domain name (for example, "%s").',
- $example_domain),
- );
- }
+ $uri = new PhutilURI($domain_full_uri);
+ $domain = $uri->getDomain();
+ $protocol = $uri->getProtocol();
+ $path = $uri->getPath();
+ $supported_protocols = array('http', 'https');
- if ($uri->getPort()) {
+ if (!in_array($protocol, $supported_protocols)) {
return array(
$label,
pht(
- 'The custom domain should not include a port number. Just provide '.
- 'the bare domain name (for example, "%s").',
+ 'The custom domain should include a valid protocol in the URI '.
+ '(for example, "%s"). Valid protocols are "http" or "https".',
$example_domain),
- );
+ );
}
- if (strpos($custom_domain, '/') !== false) {
+ if (strlen($path) && $path != '/') {
return array(
$label,
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),
);
}
- if (strpos($custom_domain, '.') === false) {
+ if (strpos($domain, '.') === false) {
return array(
$label,
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),
);
}
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 null;
}
public function getLiveURI() {
if (strlen($this->getDomain())) {
return $this->getExternalLiveURI();
} else {
return $this->getInternalLiveURI();
}
}
public function getExternalLiveURI() {
- $uri = new PhutilURI('http://'.$this->getDomain().'/');
+ $uri = new PhutilURI($this->getDomainFullURI());
+ PhabricatorEnv::requireValidRemoteURIForLink($uri);
return (string)$uri;
}
public function getExternalParentURI() {
$uri = $this->getParentDomain();
PhabricatorEnv::requireValidRemoteURIForLink($uri);
return (string)$uri;
}
public function getInternalLiveURI() {
return '/phame/live/'.$this->getID().'/';
}
public function getViewURI() {
return '/phame/blog/view/'.$this->getID().'/';
}
public function getManageURI() {
return '/phame/blog/manage/'.$this->getID().'/';
}
public function getProfileImageURI() {
return $this->getProfileImageFile()->getBestURI();
}
public function attachProfileImageFile(PhabricatorFile $file) {
$this->profileImageFile = $file;
return $this;
}
public function getProfileImageFile() {
return $this->assertAttached($this->profileImageFile);
}
public function getHeaderImageURI() {
return $this->getHeaderImageFile()->getBestURI();
}
public function attachHeaderImageFile(PhabricatorFile $file) {
$this->headerImageFile = $file;
return $this;
}
public function getHeaderImageFile() {
return $this->assertAttached($this->headerImageFile);
}
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->getEditPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
$can_edit = PhabricatorPolicyCapability::CAN_EDIT;
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
// Users who can edit or post to a blog can always view it.
if (PhabricatorPolicyFilter::hasCapability($user, $this, $can_edit)) {
return true;
}
break;
}
return false;
}
public function describeAutomaticCapability($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return pht(
'Users who can edit a blog can always view it.');
}
return null;
}
/* -( PhabricatorMarkupInterface Implementation )-------------------------- */
public function getMarkupFieldKey($field) {
$hash = PhabricatorHash::digest($this->getMarkupText($field));
return $this->getPHID().':'.$field.':'.$hash;
}
public function newMarkupEngine($field) {
return PhabricatorMarkupEngine::newPhameMarkupEngine();
}
public function getMarkupText($field) {
return $this->getDescription();
}
public function didMarkupText(
$field,
$output,
PhutilMarkupEngine $engine) {
return $output;
}
public function shouldUseMarkupCache($field) {
return (bool)$this->getPHID();
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$this->openTransaction();
$posts = id(new PhamePost())
->loadAllWhere('blogPHID = %s', $this->getPHID());
foreach ($posts as $post) {
$post->delete();
}
$this->delete();
$this->saveTransaction();
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhameBlogEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new PhameBlogTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
/* -( PhabricatorSubscribableInterface Implementation )-------------------- */
public function isAutomaticallySubscribed($phid) {
return ($this->creatorPHID == $phid);
}
/* -( PhabricatorConduitResultInterface )---------------------------------- */
public function getFieldSpecificationsForConduit() {
return array(
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('name')
->setType('string')
->setDescription(pht('The name of the blog.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('description')
->setType('string')
->setDescription(pht('Blog description.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('status')
->setType('string')
->setDescription(pht('Archived or active status.')),
);
}
public function getFieldValuesForConduit() {
return array(
'name' => $this->getName(),
'description' => $this->getDescription(),
'status' => $this->getStatus(),
);
}
public function getConduitSearchAttachments() {
return array();
}
/* -( PhabricatorFulltextInterface )--------------------------------------- */
public function newFulltextEngine() {
return new PhameBlogFulltextEngine();
}
}
diff --git a/src/applications/phame/storage/PhameBlogTransaction.php b/src/applications/phame/storage/PhameBlogTransaction.php
index 91c6552666..2d74ca5cc6 100644
--- a/src/applications/phame/storage/PhameBlogTransaction.php
+++ b/src/applications/phame/storage/PhameBlogTransaction.php
@@ -1,295 +1,295 @@
<?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_DOMAIN = 'phame.blog.domain';
+ 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 MAILTAG_DETAILS = 'phame-blog-details';
const MAILTAG_SUBSCRIBERS = 'phame-blog-subscribers';
const MAILTAG_OTHER = 'phame-blog-other';
public function getApplicationName() {
return 'phame';
}
public function getApplicationTransactionType() {
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 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_DOMAIN:
+ case self::TYPE_FULLDOMAIN:
return 'fa-pencil';
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() {
$tags = parent::getMailTags();
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
$tags[] = self::MAILTAG_SUBSCRIBERS;
break;
case self::TYPE_NAME:
case self::TYPE_SUBTITLE:
case self::TYPE_DESCRIPTION:
- case self::TYPE_DOMAIN:
+ case self::TYPE_FULLDOMAIN:
case self::TYPE_PARENTSITE:
case self::TYPE_PARENTDOMAIN:
$tags[] = self::MAILTAG_DETAILS;
break;
default:
$tags[] = self::MAILTAG_OTHER;
break;
}
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_DOMAIN:
+ case self::TYPE_FULLDOMAIN:
return pht(
- '%s updated the blog\'s domain to "%s".',
+ '%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_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_DOMAIN:
+ case self::TYPE_FULLDOMAIN:
return pht(
- '%s updated the domain for %s.',
+ '%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_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);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Mar 14, 8:41 AM (17 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
71720
Default Alt Text
(45 KB)

Event Timeline