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-12 17:08:03 +02:00
|
|
|
$breadcrumbs = $this->renderBreadcrumbs($slug);
|
2011-07-13 03:03:20 +02:00
|
|
|
$version_note = null;
|
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
|
|
|
|
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;
|
|
|
|
$create_sentence =
|
|
|
|
'You can <strong>'.
|
|
|
|
phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => $create_uri,
|
|
|
|
),
|
|
|
|
'create a new document').
|
|
|
|
'</strong>.';
|
2011-07-11 21:34:53 +02:00
|
|
|
$button = phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
2011-07-12 05:14:46 +02:00
|
|
|
'href' => $create_uri,
|
2011-07-11 21:34:53 +02:00
|
|
|
'class' => 'green button',
|
|
|
|
),
|
|
|
|
'Create Page');
|
2012-05-20 17:54:25 +02:00
|
|
|
|
|
|
|
$page_content =
|
|
|
|
'<div class="phriction-content">'.
|
|
|
|
'<em>No content here!</em><br />'.
|
|
|
|
'No document found at <tt>'.phutil_escape_html($slug).'</tt>. '.
|
|
|
|
$create_sentence.
|
|
|
|
'</div>';
|
|
|
|
$page_title = 'Page Not Found';
|
2011-12-15 21:00:17 +01:00
|
|
|
$buttons = $button;
|
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()) {
|
|
|
|
$version_note = new AphrontErrorView();
|
|
|
|
$version_note->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
|
|
|
|
$version_note->setTitle('Older Version');
|
|
|
|
$version_note->appendChild(
|
|
|
|
'You are viewing an older version of this document, as it '.
|
|
|
|
'appeared on '.
|
|
|
|
phabricator_datetime($content->getDateCreated(), $user).'.');
|
|
|
|
}
|
|
|
|
} 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
|
|
|
}
|
|
|
|
|
|
|
|
$phids = array_filter(
|
|
|
|
array(
|
|
|
|
$content->getAuthorPHID(),
|
|
|
|
$project_phid,
|
|
|
|
));
|
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) {
|
|
|
|
$when = 'today';
|
|
|
|
} else if ($age == 1) {
|
|
|
|
$when = 'yesterday';
|
|
|
|
} else {
|
|
|
|
$when = "{$age} days ago";
|
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
$project_info =
|
|
|
|
'<br />This document is about the project '.
|
|
|
|
$handles[$project_phid]->renderLink().'.';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-07-12 05:14:46 +02:00
|
|
|
$byline =
|
|
|
|
'<div class="phriction-byline">'.
|
|
|
|
"Last updated {$when} by ".
|
|
|
|
$handles[$content->getAuthorPHID()]->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
|
|
|
$project_info.
|
2011-07-12 05:14:46 +02:00
|
|
|
'</div>';
|
|
|
|
|
|
|
|
|
2011-12-17 18:19:08 +01:00
|
|
|
$doc_status = $document->getStatus();
|
|
|
|
if ($doc_status == PhrictionDocumentStatus::STATUS_EXISTS) {
|
2012-09-05 20:40:48 +02:00
|
|
|
$core_content = $content->renderContent($user);
|
2011-12-17 18:19:08 +01:00
|
|
|
} else if ($doc_status == PhrictionDocumentStatus::STATUS_DELETED) {
|
|
|
|
$notice = new AphrontErrorView();
|
|
|
|
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
|
|
|
|
$notice->setTitle('Document Deleted');
|
|
|
|
$notice->appendChild(
|
|
|
|
'This document has been deleted. You can edit it to put new content '.
|
|
|
|
'here, or use history to revert to an earlier version.');
|
|
|
|
$core_content = $notice->render();
|
|
|
|
} else {
|
|
|
|
throw new Exception("Unknown document status '{$doc_status}'!");
|
|
|
|
}
|
|
|
|
|
2011-07-12 05:14:46 +02:00
|
|
|
$page_content =
|
|
|
|
'<div class="phriction-content">'.
|
|
|
|
$byline.
|
2011-12-17 18:19:08 +01:00
|
|
|
$core_content.
|
2011-07-12 05:14:46 +02:00
|
|
|
'</div>';
|
|
|
|
|
2011-12-15 21:00:17 +01:00
|
|
|
$edit_button = phutil_render_tag(
|
2011-07-11 21:34:53 +02:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => '/phriction/edit/'.$document->getID().'/',
|
|
|
|
'class' => 'button',
|
|
|
|
),
|
2011-12-17 18:19:08 +01:00
|
|
|
'Edit Document');
|
2011-12-15 21:00:17 +01:00
|
|
|
$history_button = phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => PhrictionDocument::getSlugURI($slug, 'history'),
|
|
|
|
'class' => 'button grey',
|
|
|
|
),
|
|
|
|
'View History');
|
2011-12-15 23:37:44 +01:00
|
|
|
// these float right so history_button which is right most goes first
|
2011-12-15 21:00:17 +01:00
|
|
|
$buttons = $history_button.$edit_button;
|
2011-07-11 21:34:53 +02:00
|
|
|
}
|
|
|
|
|
2011-07-13 03:03:20 +02:00
|
|
|
if ($version_note) {
|
|
|
|
$version_note = $version_note->render();
|
|
|
|
}
|
|
|
|
|
2011-07-15 23:56:39 +02:00
|
|
|
$children = $this->renderChildren($slug);
|
|
|
|
|
2011-07-11 21:34:53 +02:00
|
|
|
$page =
|
|
|
|
'<div class="phriction-header">'.
|
2011-12-15 21:00:17 +01:00
|
|
|
$buttons.
|
2011-07-11 21:34:53 +02:00
|
|
|
'<h1>'.phutil_escape_html($page_title).'</h1>'.
|
2011-07-12 17:08:03 +02:00
|
|
|
$breadcrumbs.
|
2011-07-11 21:34:53 +02:00
|
|
|
'</div>'.
|
2011-07-13 03:03:20 +02:00
|
|
|
$version_note.
|
2011-07-15 23:56:39 +02:00
|
|
|
$page_content.
|
|
|
|
$children;
|
2011-07-11 17:54:22 +02:00
|
|
|
|
|
|
|
return $this->buildStandardPageResponse(
|
2011-07-11 21:34:53 +02:00
|
|
|
$page,
|
2011-07-11 17:54:22 +02:00
|
|
|
array(
|
2011-07-12 00:06:19 +02:00
|
|
|
'title' => 'Phriction - '.$page_title,
|
2011-07-11 17:54:22 +02:00
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-07-12 17:08:03 +02:00
|
|
|
private function renderBreadcrumbs($slug) {
|
|
|
|
|
|
|
|
$ancestor_handles = array();
|
2012-04-10 23:18:20 +02:00
|
|
|
$ancestral_slugs = PhabricatorSlug::getAncestry($slug);
|
2011-07-12 17:08:03 +02:00
|
|
|
$ancestral_slugs[] = $slug;
|
|
|
|
if ($ancestral_slugs) {
|
|
|
|
$empty_slugs = array_fill_keys($ancestral_slugs, null);
|
|
|
|
$ancestors = id(new PhrictionDocument())->loadAllWhere(
|
|
|
|
'slug IN (%Ls)',
|
|
|
|
$ancestral_slugs);
|
|
|
|
$ancestors = mpull($ancestors, null, 'getSlug');
|
|
|
|
|
|
|
|
$ancestor_phids = mpull($ancestors, 'getPHID');
|
|
|
|
$handles = array();
|
|
|
|
if ($ancestor_phids) {
|
2012-09-05 04:02:56 +02:00
|
|
|
$handles = $this->loadViewerHandles($ancestor_phids);
|
2011-07-12 17:08:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$ancestor_handles = array();
|
|
|
|
foreach ($ancestral_slugs as $slug) {
|
|
|
|
if (isset($ancestors[$slug])) {
|
|
|
|
$ancestor_handles[] = $handles[$ancestors[$slug]->getPHID()];
|
|
|
|
} else {
|
|
|
|
$handle = new PhabricatorObjectHandle();
|
2012-04-10 23:18:20 +02:00
|
|
|
$handle->setName(PhabricatorSlug::getDefaultTitle($slug));
|
2011-07-12 17:08:03 +02:00
|
|
|
$handle->setURI(PhrictionDocument::getSlugURI($slug));
|
|
|
|
$ancestor_handles[] = $handle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$breadcrumbs = array();
|
|
|
|
foreach ($ancestor_handles as $ancestor_handle) {
|
|
|
|
$breadcrumbs[] = $ancestor_handle->renderLink();
|
|
|
|
}
|
|
|
|
|
|
|
|
$list = phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => '/phriction/',
|
|
|
|
),
|
|
|
|
'Document Index');
|
|
|
|
|
|
|
|
return
|
|
|
|
'<div class="phriction-breadcrumbs">'.
|
|
|
|
$list.' · '.
|
|
|
|
'<span class="phriction-document-crumbs">'.
|
|
|
|
implode(" \xC2\xBB ", $breadcrumbs).
|
|
|
|
'</span>'.
|
|
|
|
'</div>';
|
|
|
|
}
|
|
|
|
|
2011-07-15 23:56:39 +02:00
|
|
|
private function renderChildren($slug) {
|
|
|
|
$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)
|
2011-12-17 18:19:08 +01:00
|
|
|
AND d.status = %d
|
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,
|
2011-12-17 18:19:08 +01:00
|
|
|
PhrictionDocumentStatus::STATUS_EXISTS,
|
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();
|
|
|
|
$list[] = '<ul>';
|
|
|
|
foreach ($children as $child) {
|
|
|
|
$list[] = $this->renderChildDocumentLink($child);
|
|
|
|
$grand = idx($grandchildren, $child['slug'], array());
|
|
|
|
if ($grand) {
|
|
|
|
$list[] = '<ul>';
|
|
|
|
foreach ($grand as $grandchild) {
|
|
|
|
$list[] = $this->renderChildDocumentLink($grandchild);
|
|
|
|
}
|
|
|
|
$list[] = '</ul>';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($more_children) {
|
|
|
|
$list[] = '<li>More...</li>';
|
|
|
|
}
|
|
|
|
$list[] = '</ul>';
|
|
|
|
$list = implode("\n", $list);
|
|
|
|
|
|
|
|
return
|
|
|
|
'<div class="phriction-children">'.
|
|
|
|
'<div class="phriction-children-header">Document Hierarchy</div>'.
|
|
|
|
$list.
|
|
|
|
'</div>';
|
|
|
|
}
|
|
|
|
|
|
|
|
private function renderChildDocumentLink(array $info) {
|
2011-12-17 18:19:08 +01:00
|
|
|
$title = nonempty($info['title'], '(Untitled Document)');
|
2011-07-15 23:56:39 +02:00
|
|
|
$item = phutil_render_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => PhrictionDocument::getSlugURI($info['slug']),
|
|
|
|
),
|
2011-12-17 18:19:08 +01:00
|
|
|
phutil_escape_html($title));
|
2011-07-15 23:56:39 +02:00
|
|
|
|
|
|
|
if (isset($info['empty'])) {
|
|
|
|
$item = '<em>'.$item.'</em>';
|
|
|
|
}
|
|
|
|
|
|
|
|
return '<li>'.$item.'</li>';
|
|
|
|
}
|
|
|
|
|
2011-07-11 17:54:22 +02:00
|
|
|
}
|