2011-07-11 17:54:22 +02:00
|
|
|
<?php
|
|
|
|
|
2011-09-14 17:02:31 +02:00
|
|
|
/**
|
|
|
|
* @group phriction
|
|
|
|
*/
|
2012-03-10 00:46:25 +01:00
|
|
|
final class PhrictionDocumentController
|
2011-07-11 17:54:22 +02:00
|
|
|
extends PhrictionController {
|
|
|
|
|
|
|
|
private $slug;
|
|
|
|
|
|
|
|
public function willProcessRequest(array $data) {
|
|
|
|
$this->slug = $data['slug'];
|
|
|
|
}
|
|
|
|
|
|
|
|
public function processRequest() {
|
2011-07-12 05:14:46 +02:00
|
|
|
$request = $this->getRequest();
|
2011-07-13 03:03:20 +02:00
|
|
|
$user = $request->getUser();
|
2011-07-12 05:14:46 +02:00
|
|
|
|
2012-04-10 23:18:20 +02:00
|
|
|
$slug = PhabricatorSlug::normalize($this->slug);
|
2011-07-11 17:54:22 +02:00
|
|
|
if ($slug != $this->slug) {
|
|
|
|
$uri = PhrictionDocument::getSlugURI($slug);
|
|
|
|
// Canonicalize pages to their one true URI.
|
|
|
|
return id(new AphrontRedirectResponse())->setURI($uri);
|
|
|
|
}
|
|
|
|
|
2011-07-11 21:34:53 +02:00
|
|
|
require_celerity_resource('phriction-document-css');
|
|
|
|
|
|
|
|
$document = id(new PhrictionDocument())->loadOneWhere(
|
|
|
|
'slug = %s',
|
|
|
|
$slug);
|
|
|
|
|
2011-07-13 03:03:20 +02:00
|
|
|
$version_note = null;
|
2013-04-12 00:05:50 +02:00
|
|
|
$core_content = '';
|
|
|
|
$byline = '';
|
|
|
|
$move_notice = '';
|
2011-07-12 17:08:03 +02:00
|
|
|
|
2011-07-11 21:34:53 +02:00
|
|
|
if (!$document) {
|
2011-07-12 05:14:46 +02:00
|
|
|
|
2013-01-11 20:39:22 +01:00
|
|
|
$document = new PhrictionDocument();
|
|
|
|
|
2012-05-20 17:54:25 +02:00
|
|
|
if (PhrictionDocument::isProjectSlug($slug)) {
|
|
|
|
$project = id(new PhabricatorProject())->loadOneWhere(
|
|
|
|
'phrictionSlug = %s',
|
|
|
|
PhrictionDocument::getProjectSlugIdentifier($slug));
|
|
|
|
if (!$project) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$create_uri = '/phriction/edit/?slug='.$slug;
|
2013-03-07 17:28:46 +01:00
|
|
|
|
|
|
|
$no_content_head = pht('No content here!');
|
|
|
|
$no_content_body = pht(
|
|
|
|
'No document found at %s. You can <strong>'.
|
|
|
|
'<a href="%s">create a new document here</a></strong>.',
|
|
|
|
phutil_tag('tt', array(), $slug),
|
2013-02-08 21:07:44 +01:00
|
|
|
$create_uri);
|
2013-03-07 17:28:46 +01:00
|
|
|
|
|
|
|
$no_content_text = hsprintf(
|
|
|
|
'<em>%s</em><br />%s',
|
|
|
|
$no_content_head,
|
|
|
|
$no_content_body);
|
|
|
|
|
|
|
|
$page_content = phutil_tag(
|
|
|
|
'div',
|
|
|
|
array('class' => 'phriction-content'),
|
|
|
|
$no_content_text);
|
2013-02-08 18:54:27 +01:00
|
|
|
$page_title = pht('Page Not Found');
|
2011-07-11 21:34:53 +02:00
|
|
|
} else {
|
2011-07-13 03:03:20 +02:00
|
|
|
$version = $request->getInt('v');
|
|
|
|
if ($version) {
|
|
|
|
$content = id(new PhrictionContent())->loadOneWhere(
|
|
|
|
'documentID = %d AND version = %d',
|
|
|
|
$document->getID(),
|
|
|
|
$version);
|
|
|
|
if (!$content) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($content->getID() != $document->getContentID()) {
|
2013-02-08 18:54:27 +01:00
|
|
|
$vdate = phabricator_datetime($content->getDateCreated(), $user);
|
2011-07-13 03:03:20 +02:00
|
|
|
$version_note = new AphrontErrorView();
|
|
|
|
$version_note->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
|
|
|
|
$version_note->setTitle('Older Version');
|
|
|
|
$version_note->appendChild(
|
2013-02-08 18:54:27 +01:00
|
|
|
pht('You are viewing an older version of this document, as it '.
|
|
|
|
'appeared on %s.', $vdate));
|
2011-07-13 03:03:20 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$content = id(new PhrictionContent())->load($document->getContentID());
|
|
|
|
}
|
2011-07-11 21:34:53 +02:00
|
|
|
$page_title = $content->getTitle();
|
2011-07-12 05:14:46 +02:00
|
|
|
|
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
|
|
|
$project_phid = null;
|
|
|
|
if (PhrictionDocument::isProjectSlug($slug)) {
|
|
|
|
$project = id(new PhabricatorProject())->loadOneWhere(
|
|
|
|
'phrictionSlug = %s',
|
|
|
|
PhrictionDocument::getProjectSlugIdentifier($slug));
|
2012-06-14 19:42:37 +02:00
|
|
|
if ($project) {
|
|
|
|
$project_phid = $project->getPHID();
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
$subscribers = PhabricatorSubscribersQuery::loadSubscribersForPHID(
|
|
|
|
$document->getPHID());
|
|
|
|
|
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
|
|
|
$phids = array_filter(
|
|
|
|
array(
|
|
|
|
$content->getAuthorPHID(),
|
|
|
|
$project_phid,
|
|
|
|
));
|
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
|
|
|
|
|
|
|
if ($subscribers) {
|
|
|
|
$phids = array_merge($phids, $subscribers);
|
|
|
|
}
|
|
|
|
|
2012-09-05 04:02:56 +02:00
|
|
|
$handles = $this->loadViewerHandles($phids);
|
2011-07-12 05:14:46 +02:00
|
|
|
|
|
|
|
$age = time() - $content->getDateCreated();
|
|
|
|
$age = floor($age / (60 * 60 * 24));
|
|
|
|
|
|
|
|
if ($age < 1) {
|
2013-03-07 17:28:46 +01:00
|
|
|
$when = pht('today');
|
2011-07-12 05:14:46 +02:00
|
|
|
} else if ($age == 1) {
|
2013-03-07 17:28:46 +01:00
|
|
|
$when = pht('yesterday');
|
2011-07-12 05:14:46 +02:00
|
|
|
} else {
|
2013-03-07 17:28:46 +01:00
|
|
|
$when = pht("%d days ago", $age);
|
2011-07-12 05:14:46 +02:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
$project_info = null;
|
|
|
|
if ($project_phid) {
|
2013-02-13 23:50:15 +01:00
|
|
|
$project_info = hsprintf(
|
2013-03-07 17:28:46 +01:00
|
|
|
'<br />%s',
|
|
|
|
pht('This document is about the project %s.',
|
|
|
|
$handles[$project_phid]->renderLink()));
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
$subscriber_view = null;
|
|
|
|
if ($subscribers) {
|
|
|
|
$subcriber_list = array();
|
|
|
|
foreach ($subscribers as $subscriber) {
|
|
|
|
$subcriber_list[] = $handles[$subscriber];
|
|
|
|
}
|
|
|
|
|
|
|
|
$subcriber_list = phutil_implode_html(', ',
|
|
|
|
mpull($subcriber_list, 'renderLink'));
|
|
|
|
|
|
|
|
$subscriber_view = array(
|
|
|
|
hsprintf('<br />Subscribers: '),
|
|
|
|
$subcriber_list,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2013-02-13 23:50:15 +01:00
|
|
|
$byline = hsprintf(
|
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
|
|
|
'<div class="phriction-byline">%s%s%s</div>',
|
2013-03-07 17:28:46 +01:00
|
|
|
pht('Last updated %s by %s.',
|
|
|
|
$when,
|
|
|
|
$handles[$content->getAuthorPHID()]->renderLink()),
|
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
|
|
|
$project_info,
|
|
|
|
$subscriber_view);
|
2011-07-12 05:14:46 +02:00
|
|
|
|
|
|
|
|
2011-12-17 18:19:08 +01:00
|
|
|
$doc_status = $document->getStatus();
|
2013-03-07 17:28:46 +01:00
|
|
|
$current_status = $content->getChangeType();
|
|
|
|
if ($current_status == PhrictionChangeType::CHANGE_EDIT ||
|
|
|
|
$current_status == PhrictionChangeType::CHANGE_MOVE_HERE) {
|
|
|
|
|
2012-09-05 20:40:48 +02:00
|
|
|
$core_content = $content->renderContent($user);
|
2013-03-07 17:28:46 +01:00
|
|
|
} else if ($current_status == PhrictionChangeType::CHANGE_DELETE) {
|
2011-12-17 18:19:08 +01:00
|
|
|
$notice = new AphrontErrorView();
|
|
|
|
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
|
2013-03-07 17:28:46 +01:00
|
|
|
$notice->setTitle(pht('Document Deleted'));
|
2011-12-17 18:19:08 +01:00
|
|
|
$notice->appendChild(
|
2013-02-08 18:54:27 +01:00
|
|
|
pht('This document has been deleted. You can edit it to put new '.
|
|
|
|
'content here, or use history to revert to an earlier version.'));
|
2011-12-17 18:19:08 +01:00
|
|
|
$core_content = $notice->render();
|
2013-03-07 17:28:46 +01:00
|
|
|
} else if ($current_status == PhrictionChangeType::CHANGE_STUB) {
|
2013-03-04 16:31:59 +01:00
|
|
|
$notice = new AphrontErrorView();
|
|
|
|
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
|
2013-03-07 17:28:46 +01:00
|
|
|
$notice->setTitle(pht('Empty Document'));
|
2013-03-04 16:31:59 +01:00
|
|
|
$notice->appendChild(
|
|
|
|
pht('This document is empty. You can edit it to put some proper '.
|
|
|
|
'content here.'));
|
|
|
|
$core_content = $notice->render();
|
2013-03-07 17:28:46 +01:00
|
|
|
} else if ($current_status == PhrictionChangeType::CHANGE_MOVE_AWAY) {
|
2013-03-06 22:12:04 +01:00
|
|
|
$new_doc_id = $content->getChangeRef();
|
|
|
|
$new_doc = new PhrictionDocument();
|
|
|
|
$new_doc->load($new_doc_id);
|
|
|
|
|
|
|
|
$slug_uri = PhrictionDocument::getSlugURI($new_doc->getSlug());
|
|
|
|
|
|
|
|
$notice = new AphrontErrorView();
|
|
|
|
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
|
|
|
|
$notice->setTitle(pht('Document Moved'));
|
|
|
|
$notice->appendChild(phutil_tag('p', array(),
|
|
|
|
pht('This document has been moved to %s. You can edit it to put new '.
|
|
|
|
'content here, or use history to revert to an earlier version.',
|
|
|
|
phutil_tag('a', array('href' => $slug_uri), $slug_uri))));
|
|
|
|
$core_content = $notice->render();
|
2011-12-17 18:19:08 +01:00
|
|
|
} else {
|
|
|
|
throw new Exception("Unknown document status '{$doc_status}'!");
|
|
|
|
}
|
|
|
|
|
2013-03-06 22:12:04 +01:00
|
|
|
$move_notice = null;
|
2013-03-07 17:28:46 +01:00
|
|
|
if ($current_status == PhrictionChangeType::CHANGE_MOVE_HERE) {
|
2013-03-06 22:12:04 +01:00
|
|
|
$from_doc_id = $content->getChangeRef();
|
|
|
|
$from_doc = id(new PhrictionDocument())->load($from_doc_id);
|
|
|
|
$slug_uri = PhrictionDocument::getSlugURI($from_doc->getSlug());
|
|
|
|
|
|
|
|
$move_notice = id(new AphrontErrorView())
|
|
|
|
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
|
|
|
|
->appendChild(pht('This document was moved from %s',
|
|
|
|
phutil_tag('a', array('href' => $slug_uri), $slug_uri)))
|
|
|
|
->render();
|
|
|
|
}
|
|
|
|
|
2011-07-11 21:34:53 +02:00
|
|
|
}
|
|
|
|
|
2011-07-13 03:03:20 +02:00
|
|
|
if ($version_note) {
|
|
|
|
$version_note = $version_note->render();
|
|
|
|
}
|
|
|
|
|
2013-02-13 23:50:15 +01:00
|
|
|
$children = $this->renderDocumentChildren($slug);
|
2011-07-15 23:56:39 +02:00
|
|
|
|
2013-04-10 22:08:36 +02:00
|
|
|
$actions = $this->buildActionView($user, $document);
|
|
|
|
|
2013-01-11 20:39:22 +01:00
|
|
|
$crumbs = $this->buildApplicationCrumbs();
|
2013-04-10 22:08:36 +02:00
|
|
|
$crumbs->setActionList($actions);
|
2013-01-11 20:39:22 +01:00
|
|
|
$crumb_views = $this->renderBreadcrumbs($slug);
|
|
|
|
foreach ($crumb_views as $view) {
|
|
|
|
$crumbs->addCrumb($view);
|
|
|
|
}
|
|
|
|
|
|
|
|
$header = id(new PhabricatorHeaderView())
|
|
|
|
->setHeader($page_title);
|
|
|
|
|
2013-04-12 00:05:50 +02:00
|
|
|
$page_content = hsprintf(
|
|
|
|
'<div class="phriction-wrap">
|
|
|
|
<div class="phriction-content">
|
|
|
|
%s%s%s%s%s
|
|
|
|
</div>
|
|
|
|
<div class="phriction-fake-space"></div>
|
|
|
|
</div>',
|
|
|
|
$header,
|
|
|
|
$actions,
|
|
|
|
$byline,
|
|
|
|
$move_notice,
|
|
|
|
$core_content);
|
|
|
|
|
|
|
|
$core_page = phutil_tag(
|
|
|
|
'div',
|
|
|
|
array(
|
|
|
|
'class' => 'phriction-offset'
|
|
|
|
),
|
|
|
|
array(
|
|
|
|
$page_content,
|
|
|
|
$children,
|
|
|
|
));
|
|
|
|
|
2013-01-11 20:39:22 +01:00
|
|
|
return $this->buildApplicationPage(
|
2011-07-11 17:54:22 +02:00
|
|
|
array(
|
2013-02-13 23:50:15 +01:00
|
|
|
$crumbs->render(),
|
2013-04-12 00:05:50 +02:00
|
|
|
$core_page,
|
2013-01-11 20:39:22 +01:00
|
|
|
),
|
|
|
|
array(
|
|
|
|
'title' => $page_title,
|
|
|
|
'device' => true,
|
2013-04-12 00:05:50 +02:00
|
|
|
'dust' => true,
|
2011-07-11 17:54:22 +02:00
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-01-11 20:39:22 +01:00
|
|
|
private function buildActionView(
|
|
|
|
PhabricatorUser $user,
|
|
|
|
PhrictionDocument $document) {
|
|
|
|
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
|
|
|
$user,
|
|
|
|
$document,
|
|
|
|
PhabricatorPolicyCapability::CAN_EDIT);
|
2011-07-12 17:08:03 +02:00
|
|
|
|
2013-01-11 20:39:22 +01:00
|
|
|
$slug = PhabricatorSlug::normalize($this->slug);
|
2011-07-12 17:08:03 +02:00
|
|
|
|
2013-01-25 06:26:40 +01:00
|
|
|
$action_view = id(new PhabricatorActionListView())
|
2013-01-11 20:39:22 +01:00
|
|
|
->setUser($user)
|
2013-03-04 16:21:47 +01:00
|
|
|
->setObject($document);
|
|
|
|
|
|
|
|
if (!$document->getID()) {
|
|
|
|
return $action_view->addAction(
|
2013-01-11 20:39:22 +01:00
|
|
|
id(new PhabricatorActionView())
|
2013-03-07 17:28:46 +01:00
|
|
|
->setName(pht('Create This Document'))
|
2013-03-04 16:21:47 +01:00
|
|
|
->setIcon('create')
|
|
|
|
->setHref('/phriction/edit/?slug='.$slug));
|
|
|
|
}
|
|
|
|
|
|
|
|
$action_view->addAction(
|
|
|
|
id(new PhabricatorActionView())
|
|
|
|
->setName(pht('Edit Document'))
|
|
|
|
->setIcon('edit')
|
|
|
|
->setHref('/phriction/edit/'.$document->getID().'/'));
|
2013-01-25 06:26:40 +01:00
|
|
|
|
|
|
|
if ($document->getStatus() == PhrictionDocumentStatus::STATUS_EXISTS) {
|
2013-03-06 22:12:04 +01:00
|
|
|
$action_view->addAction(
|
|
|
|
id(new PhabricatorActionView())
|
|
|
|
->setName(pht('Move Document'))
|
|
|
|
->setIcon('move')
|
|
|
|
->setHref('/phriction/move/'.$document->getID().'/')
|
|
|
|
->setWorkflow(true));
|
|
|
|
|
2013-01-25 06:26:40 +01:00
|
|
|
$action_view->addAction(
|
|
|
|
id(new PhabricatorActionView())
|
|
|
|
->setName(pht('Delete Document'))
|
|
|
|
->setIcon('delete')
|
|
|
|
->setHref('/phriction/delete/'.$document->getID().'/')
|
|
|
|
->setWorkflow(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
$action_view->addAction(
|
2013-01-11 20:39:22 +01:00
|
|
|
id(new PhabricatorActionView())
|
2013-01-25 06:26:40 +01:00
|
|
|
->setName(pht('View History'))
|
|
|
|
->setIcon('history')
|
|
|
|
->setHref(PhrictionDocument::getSlugURI($slug, 'history')));
|
2011-07-12 17:08:03 +02:00
|
|
|
}
|
|
|
|
|
2013-02-13 23:50:15 +01:00
|
|
|
private function renderDocumentChildren($slug) {
|
2011-07-15 23:56:39 +02:00
|
|
|
$document_dao = new PhrictionDocument();
|
|
|
|
$content_dao = new PhrictionContent();
|
|
|
|
$conn = $document_dao->establishConnection('r');
|
|
|
|
|
|
|
|
$limit = 50;
|
2012-04-10 23:18:20 +02:00
|
|
|
$d_child = PhabricatorSlug::getDepth($slug) + 1;
|
|
|
|
$d_grandchild = PhabricatorSlug::getDepth($slug) + 2;
|
2011-07-15 23:56:39 +02:00
|
|
|
|
|
|
|
// Select children and grandchildren.
|
|
|
|
$children = queryfx_all(
|
|
|
|
$conn,
|
|
|
|
'SELECT d.slug, d.depth, c.title FROM %T d JOIN %T c
|
|
|
|
ON d.contentID = c.id
|
|
|
|
WHERE d.slug LIKE %> AND d.depth IN (%d, %d)
|
2013-03-04 16:31:59 +01:00
|
|
|
AND d.status IN (%Ld)
|
2011-07-15 23:56:39 +02:00
|
|
|
ORDER BY d.depth, c.title LIMIT %d',
|
|
|
|
$document_dao->getTableName(),
|
|
|
|
$content_dao->getTableName(),
|
|
|
|
($slug == '/' ? '' : $slug),
|
|
|
|
$d_child,
|
|
|
|
$d_grandchild,
|
2013-03-04 16:31:59 +01:00
|
|
|
array(
|
|
|
|
PhrictionDocumentStatus::STATUS_EXISTS,
|
|
|
|
PhrictionDocumentStatus::STATUS_STUB,
|
|
|
|
),
|
2011-07-15 23:56:39 +02:00
|
|
|
$limit);
|
|
|
|
|
|
|
|
if (!$children) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We're going to render in one of three modes to try to accommodate
|
|
|
|
// different information scales:
|
|
|
|
//
|
|
|
|
// - If we found fewer than $limit rows, we know we have all the children
|
|
|
|
// and grandchildren and there aren't all that many. We can just render
|
|
|
|
// everything.
|
|
|
|
// - If we found $limit rows but the results included some grandchildren,
|
|
|
|
// we just throw them out and render only the children, as we know we
|
|
|
|
// have them all.
|
|
|
|
// - If we found $limit rows and the results have no grandchildren, we
|
|
|
|
// have a ton of children. Render them and then let the user know that
|
|
|
|
// this is not an exhaustive list.
|
|
|
|
|
|
|
|
if (count($children) == $limit) {
|
|
|
|
$more_children = true;
|
|
|
|
foreach ($children as $child) {
|
|
|
|
if ($child['depth'] == $d_grandchild) {
|
|
|
|
$more_children = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$show_grandchildren = false;
|
|
|
|
} else {
|
|
|
|
$show_grandchildren = true;
|
|
|
|
$more_children = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$grandchildren = array();
|
|
|
|
foreach ($children as $key => $child) {
|
|
|
|
if ($child['depth'] == $d_child) {
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
unset($children[$key]);
|
|
|
|
if ($show_grandchildren) {
|
2012-04-10 23:18:20 +02:00
|
|
|
$ancestors = PhabricatorSlug::getAncestry($child['slug']);
|
2011-07-15 23:56:39 +02:00
|
|
|
$grandchildren[end($ancestors)][] = $child;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fill in any missing children.
|
|
|
|
$known_slugs = ipull($children, null, 'slug');
|
|
|
|
foreach ($grandchildren as $slug => $ignored) {
|
|
|
|
if (empty($known_slugs[$slug])) {
|
|
|
|
$children[] = array(
|
|
|
|
'slug' => $slug,
|
|
|
|
'depth' => $d_child,
|
2012-04-10 23:18:20 +02:00
|
|
|
'title' => PhabricatorSlug::getDefaultTitle($slug),
|
2011-07-15 23:56:39 +02:00
|
|
|
'empty' => true,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-31 20:52:24 +02:00
|
|
|
$children = isort($children, 'title');
|
|
|
|
|
2011-07-15 23:56:39 +02:00
|
|
|
$list = array();
|
|
|
|
foreach ($children as $child) {
|
2013-02-13 23:50:15 +01:00
|
|
|
$list[] = hsprintf('<li>');
|
2011-07-15 23:56:39 +02:00
|
|
|
$list[] = $this->renderChildDocumentLink($child);
|
|
|
|
$grand = idx($grandchildren, $child['slug'], array());
|
|
|
|
if ($grand) {
|
2013-02-13 23:50:15 +01:00
|
|
|
$list[] = hsprintf('<ul>');
|
2011-07-15 23:56:39 +02:00
|
|
|
foreach ($grand as $grandchild) {
|
2013-02-13 23:50:15 +01:00
|
|
|
$list[] = hsprintf('<li>');
|
2011-07-15 23:56:39 +02:00
|
|
|
$list[] = $this->renderChildDocumentLink($grandchild);
|
2013-02-13 23:50:15 +01:00
|
|
|
$list[] = hsprintf('</li>');
|
2011-07-15 23:56:39 +02:00
|
|
|
}
|
2013-02-13 23:50:15 +01:00
|
|
|
$list[] = hsprintf('</ul>');
|
2011-07-15 23:56:39 +02:00
|
|
|
}
|
2013-02-13 23:50:15 +01:00
|
|
|
$list[] = hsprintf('</li>');
|
2011-07-15 23:56:39 +02:00
|
|
|
}
|
|
|
|
if ($more_children) {
|
2013-02-13 23:50:15 +01:00
|
|
|
$list[] = phutil_tag('li', array(), pht('More...'));
|
2011-07-15 23:56:39 +02:00
|
|
|
}
|
|
|
|
|
2013-02-13 23:50:15 +01:00
|
|
|
return hsprintf(
|
2013-04-12 00:05:50 +02:00
|
|
|
'<div class="phriction-wrap">
|
|
|
|
<div class="phriction-children">
|
|
|
|
<div class="phriction-children-header">%s</div>
|
|
|
|
%s
|
|
|
|
</div>
|
|
|
|
</div>',
|
2013-02-13 23:50:15 +01:00
|
|
|
pht('Document Hierarchy'),
|
|
|
|
phutil_tag('ul', array(), $list));
|
2011-07-15 23:56:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private function renderChildDocumentLink(array $info) {
|
2013-02-08 18:54:27 +01:00
|
|
|
$title = nonempty($info['title'], pht('(Untitled Document)'));
|
2013-01-18 03:43:35 +01:00
|
|
|
$item = phutil_tag(
|
2011-07-15 23:56:39 +02:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => PhrictionDocument::getSlugURI($info['slug']),
|
|
|
|
),
|
2013-01-18 03:43:35 +01:00
|
|
|
$title);
|
2011-07-15 23:56:39 +02:00
|
|
|
|
|
|
|
if (isset($info['empty'])) {
|
2013-02-13 23:50:15 +01:00
|
|
|
$item = phutil_tag('em', array(), $item);
|
2011-07-15 23:56:39 +02:00
|
|
|
}
|
|
|
|
|
2013-02-13 23:50:15 +01:00
|
|
|
return $item;
|
2011-07-15 23:56:39 +02:00
|
|
|
}
|
|
|
|
|
2013-03-07 17:12:00 +01:00
|
|
|
protected function getDocumentSlug() {
|
|
|
|
return $this->slug;
|
|
|
|
}
|
|
|
|
|
2011-07-11 17:54:22 +02:00
|
|
|
}
|