2011-07-11 17:54:22 +02:00
|
|
|
<?php
|
|
|
|
|
2013-01-11 20:39:22 +01:00
|
|
|
final class PhrictionDocument extends PhrictionDAO
|
2013-05-09 23:40:43 +02:00
|
|
|
implements
|
|
|
|
PhabricatorPolicyInterface,
|
|
|
|
PhabricatorSubscribableInterface,
|
2013-10-25 21:52:00 +02:00
|
|
|
PhabricatorFlaggableInterface,
|
2014-07-18 03:38:09 +02:00
|
|
|
PhabricatorTokenReceiverInterface,
|
2014-07-21 15:59:22 +02:00
|
|
|
PhabricatorDestructibleInterface {
|
2011-07-11 17:54:22 +02:00
|
|
|
|
|
|
|
protected $slug;
|
|
|
|
protected $depth;
|
|
|
|
protected $contentID;
|
2011-12-17 18:19:08 +01:00
|
|
|
protected $status;
|
2011-07-11 17:54:22 +02:00
|
|
|
|
2013-07-24 20:32:13 +02:00
|
|
|
private $contentObject = self::ATTACHABLE;
|
2014-05-19 21:41:30 +02:00
|
|
|
private $ancestors = array();
|
2013-07-24 20:32:13 +02:00
|
|
|
|
|
|
|
// TODO: This should be `self::ATTACHABLE`, but there are still a lot of call
|
|
|
|
// sites which load PhrictionDocuments directly.
|
|
|
|
private $project = null;
|
2011-07-12 00:42:12 +02:00
|
|
|
|
2011-07-11 17:54:22 +02:00
|
|
|
public function getConfiguration() {
|
|
|
|
return array(
|
|
|
|
self::CONFIG_AUX_PHID => true,
|
|
|
|
self::CONFIG_TIMESTAMPS => false,
|
|
|
|
) + parent::getConfiguration();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function generatePHID() {
|
|
|
|
return PhabricatorPHID::generateNewPHID(
|
2014-07-24 00:05:46 +02:00
|
|
|
PhrictionDocumentPHIDType::TYPECONST);
|
2011-07-11 17:54:22 +02:00
|
|
|
}
|
|
|
|
|
2011-07-12 00:06:19 +02:00
|
|
|
public static function getSlugURI($slug, $type = 'document') {
|
|
|
|
static $types = array(
|
|
|
|
'document' => '/w/',
|
|
|
|
'history' => '/phriction/history/',
|
|
|
|
);
|
|
|
|
|
|
|
|
if (empty($types[$type])) {
|
|
|
|
throw new Exception("Unknown URI type '{$type}'!");
|
|
|
|
}
|
|
|
|
|
|
|
|
$prefix = $types[$type];
|
|
|
|
|
2011-07-11 17:54:22 +02:00
|
|
|
if ($slug == '/') {
|
2011-07-12 00:06:19 +02:00
|
|
|
return $prefix;
|
2011-07-11 17:54:22 +02:00
|
|
|
} else {
|
Allow slugs to contain most utf8 characters
Summary:
Ref T2632. Fixes T1466.
Currently, we normalize slugs (and thus Phriction URIs and canonical project names) to a small number of latin characters. Instead, blacklist a few characters and permit everything else (including utf8 characters).
When generating Phriction URIs, encode any utf8 characters. This means we render URIs encoded, but browsers handle this fine and display them readably in the URI and address bar, etc.
The blacklisted characters are mostly for practical reasons: \x00-\x19 are control characters, `#%?` are meaningful in URIs, `+` is sometimes configured to be interprted as space by apache, etc., `<>\\` are just silly, `&= ` are largely cosmetic.
This allows some silly stuff, like generating URIs with zero-width spaces and RTL markers in them. Possibly we should go blacklist those characters at some point.
Depends on: D5191
Test Plan: {F34402}
Reviewers: AnhNhan, chad, vrana
Reviewed By: chad
CC: aran
Maniphest Tasks: T1466, T2632
Differential Revision: https://secure.phabricator.com/D5192
2013-03-03 19:56:33 +01:00
|
|
|
// NOTE: The effect here is to escape non-latin characters, since modern
|
|
|
|
// browsers deal with escaped UTF8 characters in a reasonable way (showing
|
|
|
|
// the user a readable URI) but older programs may not.
|
|
|
|
$slug = phutil_escape_uri($slug);
|
2011-07-12 00:06:19 +02:00
|
|
|
return $prefix.$slug;
|
2011-07-11 17:54:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setSlug($slug) {
|
2012-04-10 23:18:20 +02:00
|
|
|
$this->slug = PhabricatorSlug::normalize($slug);
|
|
|
|
$this->depth = PhabricatorSlug::getDepth($slug);
|
2011-07-11 17:54:22 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2011-07-12 00:42:12 +02:00
|
|
|
public function attachContent(PhrictionContent $content) {
|
|
|
|
$this->contentObject = $content;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getContent() {
|
2013-07-24 20:32:13 +02:00
|
|
|
return $this->assertAttached($this->contentObject);
|
2011-07-12 00:42:12 +02:00
|
|
|
}
|
|
|
|
|
2013-03-08 16:12:24 +01:00
|
|
|
public function getProject() {
|
2013-07-24 20:32:13 +02:00
|
|
|
return $this->assertAttached($this->project);
|
2013-03-08 16:12:24 +01:00
|
|
|
}
|
|
|
|
|
2013-07-24 20:32:13 +02:00
|
|
|
public function attachProject(PhabricatorProject $project = null) {
|
2013-03-08 16:12:24 +01:00
|
|
|
$this->project = $project;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function hasProject() {
|
2013-07-24 20:32:13 +02:00
|
|
|
return (bool)$this->getProject();
|
2013-03-08 16:12:24 +01:00
|
|
|
}
|
|
|
|
|
2014-05-19 21:41:30 +02:00
|
|
|
public function getAncestors() {
|
|
|
|
return $this->ancestors;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAncestor($slug) {
|
|
|
|
return $this->assertAttachedKey($this->ancestors, $slug);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function attachAncestor($slug, $ancestor) {
|
|
|
|
$this->ancestors[$slug] = $ancestor;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
Provide wiki pages for projects
Summary:
Provide tighter integration between Projects and Phriction. Partly, I have most
of a rewrite for the Projects homepage ready but it's not currently possible to
publish feed stories about a project so all the feeds are empty/boring. This
partly makes them more useful and partly just provides a tool integration point.
- When you create a project, all the wiki pages in projects/<project_name>/*
are associated with it.
- Publish updates to those pages as being related to the project so they'll
show up in project feeds.
- Show a project link on those pages.
This is very "convention over configuration" but I think it's the right
approach. We could provide some sort of, like, "@project=derp" tag to let you
associated arbitrary pages to projects later, but just letting you move pages is
probably far better.
Test Plan:
- Ran upgrade scripts against stupidly named projects ("der", " der", " der
", "der (2)", " der (2) (2)", etc). Ended up with uniquely named projects.
- Ran unit tests.
- Created /projects/ wiki documents and made sure they displayed correctly.
- Verified feed stories publish as project-related.
- Edited projects, including perfomring a name-colliding edit.
- Created projects, including performing a name-colliding create.
Reviewers: btrahan, jungejason
Reviewed By: btrahan
CC: aran, epriestley, btrahan
Maniphest Tasks: T681
Differential Revision: 1231
2011-12-17 20:58:55 +01:00
|
|
|
public static function isProjectSlug($slug) {
|
2012-04-10 23:18:20 +02:00
|
|
|
$slug = PhabricatorSlug::normalize($slug);
|
Provide wiki pages for projects
Summary:
Provide tighter integration between Projects and Phriction. Partly, I have most
of a rewrite for the Projects homepage ready but it's not currently possible to
publish feed stories about a project so all the feeds are empty/boring. This
partly makes them more useful and partly just provides a tool integration point.
- When you create a project, all the wiki pages in projects/<project_name>/*
are associated with it.
- Publish updates to those pages as being related to the project so they'll
show up in project feeds.
- Show a project link on those pages.
This is very "convention over configuration" but I think it's the right
approach. We could provide some sort of, like, "@project=derp" tag to let you
associated arbitrary pages to projects later, but just letting you move pages is
probably far better.
Test Plan:
- Ran upgrade scripts against stupidly named projects ("der", " der", " der
", "der (2)", " der (2) (2)", etc). Ended up with uniquely named projects.
- Ran unit tests.
- Created /projects/ wiki documents and made sure they displayed correctly.
- Verified feed stories publish as project-related.
- Edited projects, including perfomring a name-colliding edit.
- Created projects, including performing a name-colliding create.
Reviewers: btrahan, jungejason
Reviewed By: btrahan
CC: aran, epriestley, btrahan
Maniphest Tasks: T681
Differential Revision: 1231
2011-12-17 20:58:55 +01:00
|
|
|
$prefix = 'projects/';
|
|
|
|
if ($slug == $prefix) {
|
|
|
|
// The 'projects/' document is not itself a project slug.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return !strncmp($slug, $prefix, strlen($prefix));
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function getProjectSlugIdentifier($slug) {
|
|
|
|
if (!self::isProjectSlug($slug)) {
|
|
|
|
throw new Exception("Slug '{$slug}' is not a project slug!");
|
|
|
|
}
|
|
|
|
|
2012-04-10 23:18:20 +02:00
|
|
|
$slug = PhabricatorSlug::normalize($slug);
|
Provide wiki pages for projects
Summary:
Provide tighter integration between Projects and Phriction. Partly, I have most
of a rewrite for the Projects homepage ready but it's not currently possible to
publish feed stories about a project so all the feeds are empty/boring. This
partly makes them more useful and partly just provides a tool integration point.
- When you create a project, all the wiki pages in projects/<project_name>/*
are associated with it.
- Publish updates to those pages as being related to the project so they'll
show up in project feeds.
- Show a project link on those pages.
This is very "convention over configuration" but I think it's the right
approach. We could provide some sort of, like, "@project=derp" tag to let you
associated arbitrary pages to projects later, but just letting you move pages is
probably far better.
Test Plan:
- Ran upgrade scripts against stupidly named projects ("der", " der", " der
", "der (2)", " der (2) (2)", etc). Ended up with uniquely named projects.
- Ran unit tests.
- Created /projects/ wiki documents and made sure they displayed correctly.
- Verified feed stories publish as project-related.
- Edited projects, including perfomring a name-colliding edit.
- Created projects, including performing a name-colliding create.
Reviewers: btrahan, jungejason
Reviewed By: btrahan
CC: aran, epriestley, btrahan
Maniphest Tasks: T681
Differential Revision: 1231
2011-12-17 20:58:55 +01:00
|
|
|
$parts = explode('/', $slug);
|
|
|
|
return $parts[1].'/';
|
|
|
|
}
|
|
|
|
|
Make Projects a PhabricatorSubscribableInterface, but with restricted defaults
Summary:
Ref T4379. I want project subscriptions to work like this (yell if this seems whacky, since it makes subscriptions mean somethign a little different for projects than they do for other objects):
- You can only subscribe to a project if you're a project member.
- When you're added as a member, you're added as a subscriber.
- When you're removed as a member, you're removed as a subscriber.
- While you're a member, you can optionally unsubscribe.
From a UI perspective:
- We don't show the subscriber list, since it's going to be some uninteresting subset of the member list.
- We don't show CC transactions in history, since they're an uninteresting near-approximation of the membership transactions.
- You only see the subscription controls if you're a member.
To do this, I've augmented `PhabricatorSubscribableInterface` with two new methods. It would be nice if we were on PHP 5.4+ and could just use traits for this, but we should get data about version usage before we think about this. For now, copy/paste the default implementations into every implementing class.
Then, I implemented the interface in `PhabricatorProject` but with alternate defaults.
Test Plan:
- Used the normal interaction on existing objects.
- This has no actual effect on projects, verified no subscription stuff mysteriously appeared.
- Hit the new error case by fiddling with the UI.
Reviewers: btrahan
Reviewed By: btrahan
CC: chad, aran
Maniphest Tasks: T4379
Differential Revision: https://secure.phabricator.com/D8165
2014-02-10 23:29:17 +01:00
|
|
|
|
|
|
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
|
|
|
|
|
|
|
|
2013-01-11 20:39:22 +01:00
|
|
|
public function getCapabilities() {
|
|
|
|
return array(
|
|
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
|
|
PhabricatorPolicyCapability::CAN_EDIT,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPolicy($capability) {
|
2013-03-08 16:12:24 +01:00
|
|
|
if ($this->hasProject()) {
|
|
|
|
return $this->getProject()->getPolicy($capability);
|
|
|
|
}
|
2014-05-19 21:41:30 +02:00
|
|
|
|
2013-01-11 20:39:22 +01:00
|
|
|
return PhabricatorPolicies::POLICY_USER;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
|
2013-03-08 16:12:24 +01:00
|
|
|
if ($this->hasProject()) {
|
|
|
|
return $this->getProject()->hasAutomaticCapability($capability, $user);
|
|
|
|
}
|
2013-01-11 20:39:22 +01:00
|
|
|
return false;
|
|
|
|
}
|
Added subscriptions to Phriction documents
Summary:
Fixes T2694
added edge infrastructure for Phriction
added mail subject prefix option for Phriction
added messy mail support for subscribers
adds edges to the phriction db, along with the subscriber interface
which gives us subscriptions for free.
simple display of subscribers, adequate to the current design and
sufficient fallbacks for exceptional cases. @chad may
be mailed about that one more UI element may be added to his redesign
mail support is messy. not generic at all. only sends to subscribed non-authors.
Test Plan:
tried out all kinds of stuff. applied patch, subscribed, unsubscribed with multiple
accs. verified proper
edited documents, verified that mail was sent in MetaMTA. Verified
contents, tos and stuff by looking into the db, comparing PHIDs etc.
functional testing per serious MTA (that is, AWS SES) worked wonderfully.
Here's how the subscription list looks like:
{F36320, layout=link}
Reviewers: epriestley, chad, btrahan
Reviewed By: epriestley
CC: hfcorriez, aran, Korvin
Maniphest Tasks: T2686, T2694
Differential Revision: https://secure.phabricator.com/D5372
Conflicts:
src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
2013-03-21 18:26:32 +01:00
|
|
|
|
2013-09-27 17:43:41 +02:00
|
|
|
public function describeAutomaticCapability($capability) {
|
|
|
|
if ($this->hasProject()) {
|
|
|
|
return pht(
|
|
|
|
"This is a project wiki page, and inherits the project's policies.");
|
|
|
|
}
|
2014-05-19 21:41:30 +02:00
|
|
|
|
|
|
|
switch ($capability) {
|
|
|
|
case PhabricatorPolicyCapability::CAN_VIEW:
|
|
|
|
return pht(
|
|
|
|
'To view a wiki document, you must also be able to view all '.
|
|
|
|
'of its parents.');
|
|
|
|
}
|
|
|
|
|
2013-09-27 17:43:41 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
Make Projects a PhabricatorSubscribableInterface, but with restricted defaults
Summary:
Ref T4379. I want project subscriptions to work like this (yell if this seems whacky, since it makes subscriptions mean somethign a little different for projects than they do for other objects):
- You can only subscribe to a project if you're a project member.
- When you're added as a member, you're added as a subscriber.
- When you're removed as a member, you're removed as a subscriber.
- While you're a member, you can optionally unsubscribe.
From a UI perspective:
- We don't show the subscriber list, since it's going to be some uninteresting subset of the member list.
- We don't show CC transactions in history, since they're an uninteresting near-approximation of the membership transactions.
- You only see the subscription controls if you're a member.
To do this, I've augmented `PhabricatorSubscribableInterface` with two new methods. It would be nice if we were on PHP 5.4+ and could just use traits for this, but we should get data about version usage before we think about this. For now, copy/paste the default implementations into every implementing class.
Then, I implemented the interface in `PhabricatorProject` but with alternate defaults.
Test Plan:
- Used the normal interaction on existing objects.
- This has no actual effect on projects, verified no subscription stuff mysteriously appeared.
- Hit the new error case by fiddling with the UI.
Reviewers: btrahan
Reviewed By: btrahan
CC: chad, aran
Maniphest Tasks: T4379
Differential Revision: https://secure.phabricator.com/D8165
2014-02-10 23:29:17 +01:00
|
|
|
|
|
|
|
/* -( PhabricatorSubscribableInterface )----------------------------------- */
|
|
|
|
|
|
|
|
|
Added subscriptions to Phriction documents
Summary:
Fixes T2694
added edge infrastructure for Phriction
added mail subject prefix option for Phriction
added messy mail support for subscribers
adds edges to the phriction db, along with the subscriber interface
which gives us subscriptions for free.
simple display of subscribers, adequate to the current design and
sufficient fallbacks for exceptional cases. @chad may
be mailed about that one more UI element may be added to his redesign
mail support is messy. not generic at all. only sends to subscribed non-authors.
Test Plan:
tried out all kinds of stuff. applied patch, subscribed, unsubscribed with multiple
accs. verified proper
edited documents, verified that mail was sent in MetaMTA. Verified
contents, tos and stuff by looking into the db, comparing PHIDs etc.
functional testing per serious MTA (that is, AWS SES) worked wonderfully.
Here's how the subscription list looks like:
{F36320, layout=link}
Reviewers: epriestley, chad, btrahan
Reviewed By: epriestley
CC: hfcorriez, aran, Korvin
Maniphest Tasks: T2686, T2694
Differential Revision: https://secure.phabricator.com/D5372
Conflicts:
src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
2013-03-21 18:26:32 +01:00
|
|
|
public function isAutomaticallySubscribed($phid) {
|
|
|
|
return false;
|
|
|
|
}
|
2013-05-09 23:40:43 +02:00
|
|
|
|
Make Projects a PhabricatorSubscribableInterface, but with restricted defaults
Summary:
Ref T4379. I want project subscriptions to work like this (yell if this seems whacky, since it makes subscriptions mean somethign a little different for projects than they do for other objects):
- You can only subscribe to a project if you're a project member.
- When you're added as a member, you're added as a subscriber.
- When you're removed as a member, you're removed as a subscriber.
- While you're a member, you can optionally unsubscribe.
From a UI perspective:
- We don't show the subscriber list, since it's going to be some uninteresting subset of the member list.
- We don't show CC transactions in history, since they're an uninteresting near-approximation of the membership transactions.
- You only see the subscription controls if you're a member.
To do this, I've augmented `PhabricatorSubscribableInterface` with two new methods. It would be nice if we were on PHP 5.4+ and could just use traits for this, but we should get data about version usage before we think about this. For now, copy/paste the default implementations into every implementing class.
Then, I implemented the interface in `PhabricatorProject` but with alternate defaults.
Test Plan:
- Used the normal interaction on existing objects.
- This has no actual effect on projects, verified no subscription stuff mysteriously appeared.
- Hit the new error case by fiddling with the UI.
Reviewers: btrahan
Reviewed By: btrahan
CC: chad, aran
Maniphest Tasks: T4379
Differential Revision: https://secure.phabricator.com/D8165
2014-02-10 23:29:17 +01:00
|
|
|
public function shouldShowSubscribersProperty() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function shouldAllowSubscription($phid) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-05-09 23:40:43 +02:00
|
|
|
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
|
|
|
|
|
Make Projects a PhabricatorSubscribableInterface, but with restricted defaults
Summary:
Ref T4379. I want project subscriptions to work like this (yell if this seems whacky, since it makes subscriptions mean somethign a little different for projects than they do for other objects):
- You can only subscribe to a project if you're a project member.
- When you're added as a member, you're added as a subscriber.
- When you're removed as a member, you're removed as a subscriber.
- While you're a member, you can optionally unsubscribe.
From a UI perspective:
- We don't show the subscriber list, since it's going to be some uninteresting subset of the member list.
- We don't show CC transactions in history, since they're an uninteresting near-approximation of the membership transactions.
- You only see the subscription controls if you're a member.
To do this, I've augmented `PhabricatorSubscribableInterface` with two new methods. It would be nice if we were on PHP 5.4+ and could just use traits for this, but we should get data about version usage before we think about this. For now, copy/paste the default implementations into every implementing class.
Then, I implemented the interface in `PhabricatorProject` but with alternate defaults.
Test Plan:
- Used the normal interaction on existing objects.
- This has no actual effect on projects, verified no subscription stuff mysteriously appeared.
- Hit the new error case by fiddling with the UI.
Reviewers: btrahan
Reviewed By: btrahan
CC: chad, aran
Maniphest Tasks: T4379
Differential Revision: https://secure.phabricator.com/D8165
2014-02-10 23:29:17 +01:00
|
|
|
|
2013-05-09 23:40:43 +02:00
|
|
|
public function getUsersToNotifyOfTokenGiven() {
|
|
|
|
return PhabricatorSubscribersQuery::loadSubscribersForPHID($this->phid);
|
|
|
|
}
|
2014-07-18 03:38:09 +02:00
|
|
|
|
|
|
|
|
2014-07-21 15:59:22 +02:00
|
|
|
/* -( PhabricatorDestructibleInterface )----------------------------------- */
|
2014-07-18 03:38:09 +02:00
|
|
|
|
|
|
|
|
|
|
|
public function destroyObjectPermanently(
|
|
|
|
PhabricatorDestructionEngine $engine) {
|
|
|
|
|
|
|
|
$this->openTransaction();
|
|
|
|
|
|
|
|
$this->delete();
|
|
|
|
|
|
|
|
$contents = id(new PhrictionContent())->loadAllWhere(
|
|
|
|
'documentID = %d',
|
|
|
|
$this->getID());
|
|
|
|
foreach ($contents as $content) {
|
|
|
|
$content->delete();
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->saveTransaction();
|
|
|
|
}
|
|
|
|
|
2011-07-11 17:54:22 +02:00
|
|
|
}
|