Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2893131
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
33 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/applications/diviner/controller/DivinerAtomController.php b/src/applications/diviner/controller/DivinerAtomController.php
index 1785ae6741..bf69497b16 100644
--- a/src/applications/diviner/controller/DivinerAtomController.php
+++ b/src/applications/diviner/controller/DivinerAtomController.php
@@ -1,690 +1,688 @@
<?php
final class DivinerAtomController extends DivinerController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getUser();
$book_name = $request->getURIData('book');
$atom_type = $request->getURIData('type');
$atom_name = $request->getURIData('name');
$atom_context = nonempty($request->getURIData('context'), null);
$atom_index = nonempty($request->getURIData('index'), null);
require_celerity_resource('diviner-shared-css');
$book = id(new DivinerBookQuery())
->setViewer($viewer)
->withNames(array($book_name))
->executeOne();
if (!$book) {
return new Aphront404Response();
}
$symbol = id(new DivinerAtomQuery())
->setViewer($viewer)
->withBookPHIDs(array($book->getPHID()))
->withTypes(array($atom_type))
->withNames(array($atom_name))
->withContexts(array($atom_context))
->withIndexes(array($atom_index))
->withIsDocumentable(true)
->needAtoms(true)
->needExtends(true)
->needChildren(true)
->executeOne();
if (!$symbol) {
return new Aphront404Response();
}
$atom = $symbol->getAtom();
$crumbs = $this->buildApplicationCrumbs();
$crumbs->setBorder(true);
$crumbs->addTextCrumb(
$book->getShortTitle(),
'/book/'.$book->getName().'/');
$atom_short_title = $atom
? $atom->getDocblockMetaValue('short', $symbol->getTitle())
: $symbol->getTitle();
$crumbs->addTextCrumb($atom_short_title);
$header = id(new PHUIHeaderView())
->setHeader($this->renderFullSignature($symbol));
$properties = new PHUIPropertyListView();
$group = $atom ? $atom->getProperty('group') : $symbol->getGroupName();
if ($group) {
$group_name = $book->getGroupName($group);
} else {
$group_name = null;
}
$prop_list = new PHUIPropertyGroupView();
$prop_list->addPropertyList($properties);
$document = id(new PHUIDocumentViewPro())
->setBook($book->getTitle(), $group_name)
->setHeader($header)
->addClass('diviner-view');
if ($atom) {
$this->buildDefined($properties, $symbol);
$this->buildExtendsAndImplements($properties, $symbol);
$this->buildRepository($properties, $symbol);
$warnings = $atom->getWarnings();
if ($warnings) {
$warnings = id(new PHUIInfoView())
->setErrors($warnings)
->setTitle(pht('Documentation Warnings'))
->setSeverity(PHUIInfoView::SEVERITY_WARNING);
}
$document->appendChild($warnings);
}
$methods = $this->composeMethods($symbol);
$field = 'default';
$engine = id(new PhabricatorMarkupEngine())
->setViewer($viewer)
->addObject($symbol, $field);
foreach ($methods as $method) {
foreach ($method['atoms'] as $matom) {
$engine->addObject($matom, $field);
}
}
$engine->process();
if ($atom) {
$content = $this->renderDocumentationText($symbol, $engine);
$document->appendChild($content);
}
$toc = $engine->getEngineMetadata(
$symbol,
$field,
PhutilRemarkupHeaderBlockRule::KEY_HEADER_TOC,
array());
if (!$atom) {
$document->appendChild(
id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->appendChild(pht('This atom no longer exists.')));
}
if ($atom) {
$document->appendChild($this->buildParametersAndReturn(array($symbol)));
}
if ($methods) {
$tasks = $this->composeTasks($symbol);
if ($tasks) {
$methods_by_task = igroup($methods, 'task');
// Add phantom tasks for methods which have a "@task" name that isn't
// documented anywhere, or methods that have no "@task" name.
foreach ($methods_by_task as $task => $ignored) {
if (empty($tasks[$task])) {
$tasks[$task] = array(
'name' => $task,
'title' => $task ? $task : pht('Other Methods'),
'defined' => $symbol,
);
}
}
$section = id(new DivinerSectionView())
->setHeader(pht('Tasks'));
foreach ($tasks as $spec) {
$section->addContent(
id(new PHUIHeaderView())
->setNoBackground(true)
->setHeader($spec['title']));
$task_methods = idx($methods_by_task, $spec['name'], array());
$box_content = array();
if ($task_methods) {
$list_items = array();
foreach ($task_methods as $task_method) {
$atom = last($task_method['atoms']);
$item = $this->renderFullSignature($atom, true);
if (strlen($atom->getSummary())) {
$item = array(
$item,
" \xE2\x80\x94 ",
$atom->getSummary(),
);
}
$list_items[] = phutil_tag('li', array(), $item);
}
$box_content[] = phutil_tag(
'ul',
array(
'class' => 'diviner-list',
),
$list_items);
} else {
$no_methods = pht('No methods for this task.');
$box_content = phutil_tag('em', array(), $no_methods);
}
$inner_box = phutil_tag_div('diviner-task-items', $box_content);
$section->addContent($inner_box);
}
$document->appendChild($section);
}
$section = id(new DivinerSectionView())
->setHeader(pht('Methods'));
foreach ($methods as $spec) {
$matom = last($spec['atoms']);
$method_header = id(new PHUIHeaderView())
->setNoBackground(true);
$inherited = $spec['inherited'];
if ($inherited) {
$method_header->addTag(
id(new PHUITagView())
->setType(PHUITagView::TYPE_STATE)
->setBackgroundColor(PHUITagView::COLOR_GREY)
->setName(pht('Inherited')));
}
$method_header->setHeader($this->renderFullSignature($matom));
$section->addContent(
array(
$method_header,
$this->renderMethodDocumentationText($symbol, $spec, $engine),
$this->buildParametersAndReturn($spec['atoms']),
));
}
$document->appendChild($section);
}
if ($toc) {
$side = new PHUIListView();
$side->addMenuItem(
id(new PHUIListItemView())
->setName(pht('Contents'))
->setType(PHUIListItemView::TYPE_LABEL));
foreach ($toc as $key => $entry) {
$side->addMenuItem(
id(new PHUIListItemView())
->setName($entry[1])
->setHref('#'.$key));
}
$document->setToc($side);
}
$prop_list = phutil_tag_div('phui-document-view-pro-box', $prop_list);
- return $this->buildApplicationPage(
- array(
- $crumbs,
+ return $this->newPage()
+ ->setTitle($symbol->getTitle())
+ ->setCrumbs($crumbs)
+ ->appendChild(array(
$document,
$prop_list,
- ),
- array(
- 'title' => $symbol->getTitle(),
));
}
private function buildExtendsAndImplements(
PHUIPropertyListView $view,
DivinerLiveSymbol $symbol) {
$lineage = $this->getExtendsLineage($symbol);
if ($lineage) {
$tags = array();
foreach ($lineage as $item) {
$tags[] = $this->renderAtomTag($item);
}
$caret = phutil_tag('span', array('class' => 'caret-right msl msr'));
$tags = phutil_implode_html($caret, $tags);
$view->addProperty(pht('Extends'), $tags);
}
$implements = $this->getImplementsLineage($symbol);
if ($implements) {
$items = array();
foreach ($implements as $spec) {
$via = $spec['via'];
$iface = $spec['interface'];
if ($via == $symbol) {
$items[] = $this->renderAtomTag($iface);
} else {
$items[] = array(
$this->renderAtomTag($iface),
" \xE2\x97\x80 ",
$this->renderAtomTag($via),
);
}
}
$view->addProperty(
pht('Implements'),
phutil_implode_html(phutil_tag('br'), $items));
}
}
private function buildRepository(
PHUIPropertyListView $view,
DivinerLiveSymbol $symbol) {
if (!$symbol->getRepositoryPHID()) {
return;
}
$view->addProperty(
pht('Repository'),
$this->getViewer()->renderHandle($symbol->getRepositoryPHID()));
}
private function renderAtomTag(DivinerLiveSymbol $symbol) {
return id(new PHUITagView())
->setType(PHUITagView::TYPE_OBJECT)
->setName($symbol->getName())
->setHref($symbol->getURI());
}
private function getExtendsLineage(DivinerLiveSymbol $symbol) {
foreach ($symbol->getExtends() as $extends) {
if ($extends->getType() == 'class') {
$lineage = $this->getExtendsLineage($extends);
$lineage[] = $extends;
return $lineage;
}
}
return array();
}
private function getImplementsLineage(DivinerLiveSymbol $symbol) {
$implements = array();
// Do these first so we get interfaces ordered from most to least specific.
foreach ($symbol->getExtends() as $extends) {
if ($extends->getType() == 'interface') {
$implements[$extends->getName()] = array(
'interface' => $extends,
'via' => $symbol,
);
}
}
// Now do parent interfaces.
foreach ($symbol->getExtends() as $extends) {
if ($extends->getType() == 'class') {
$implements += $this->getImplementsLineage($extends);
}
}
return $implements;
}
private function buildDefined(
PHUIPropertyListView $view,
DivinerLiveSymbol $symbol) {
$atom = $symbol->getAtom();
$defined = $atom->getFile().':'.$atom->getLine();
$link = $symbol->getBook()->getConfig('uri.source');
if ($link) {
$link = strtr(
$link,
array(
'%%' => '%',
'%f' => phutil_escape_uri($atom->getFile()),
'%l' => phutil_escape_uri($atom->getLine()),
));
$defined = phutil_tag(
'a',
array(
'href' => $link,
'target' => '_blank',
),
$defined);
}
$view->addProperty(pht('Defined'), $defined);
}
private function composeMethods(DivinerLiveSymbol $symbol) {
$methods = $this->findMethods($symbol);
if (!$methods) {
return $methods;
}
foreach ($methods as $name => $method) {
// Check for "@task" on each parent, to find the most recently declared
// "@task".
$task = null;
foreach ($method['atoms'] as $key => $method_symbol) {
$atom = $method_symbol->getAtom();
if ($atom->getDocblockMetaValue('task')) {
$task = $atom->getDocblockMetaValue('task');
}
}
$methods[$name]['task'] = $task;
// Set 'inherited' if this atom has no implementation of the method.
if (last($method['implementations']) !== $symbol) {
$methods[$name]['inherited'] = true;
} else {
$methods[$name]['inherited'] = false;
}
}
return $methods;
}
private function findMethods(DivinerLiveSymbol $symbol) {
$child_specs = array();
foreach ($symbol->getExtends() as $extends) {
if ($extends->getType() == DivinerAtom::TYPE_CLASS) {
$child_specs = $this->findMethods($extends);
}
}
foreach ($symbol->getChildren() as $child) {
if ($child->getType() == DivinerAtom::TYPE_METHOD) {
$name = $child->getName();
if (isset($child_specs[$name])) {
$child_specs[$name]['atoms'][] = $child;
$child_specs[$name]['implementations'][] = $symbol;
} else {
$child_specs[$name] = array(
'atoms' => array($child),
'defined' => $symbol,
'implementations' => array($symbol),
);
}
}
}
return $child_specs;
}
private function composeTasks(DivinerLiveSymbol $symbol) {
$extends_task_specs = array();
foreach ($symbol->getExtends() as $extends) {
$extends_task_specs += $this->composeTasks($extends);
}
$task_specs = array();
$tasks = $symbol->getAtom()->getDocblockMetaValue('task');
if (strlen($tasks)) {
$tasks = phutil_split_lines($tasks, $retain_endings = false);
foreach ($tasks as $task) {
list($name, $title) = explode(' ', $task, 2);
$name = trim($name);
$title = trim($title);
$task_specs[$name] = array(
'name' => $name,
'title' => $title,
'defined' => $symbol,
);
}
}
$specs = $task_specs + $extends_task_specs;
// Reorder "@tasks" in original declaration order. Basically, we want to
// use the documentation of the closest subclass, but put tasks which
// were declared by parents first.
$keys = array_keys($extends_task_specs);
$specs = array_select_keys($specs, $keys) + $specs;
return $specs;
}
private function renderFullSignature(
DivinerLiveSymbol $symbol,
$is_link = false) {
switch ($symbol->getType()) {
case DivinerAtom::TYPE_CLASS:
case DivinerAtom::TYPE_INTERFACE:
case DivinerAtom::TYPE_METHOD:
case DivinerAtom::TYPE_FUNCTION:
break;
default:
return $symbol->getTitle();
}
$atom = $symbol->getAtom();
$out = array();
if ($atom) {
if ($atom->getProperty('final')) {
$out[] = 'final';
}
if ($atom->getProperty('abstract')) {
$out[] = 'abstract';
}
if ($atom->getProperty('access')) {
$out[] = $atom->getProperty('access');
}
if ($atom->getProperty('static')) {
$out[] = 'static';
}
}
switch ($symbol->getType()) {
case DivinerAtom::TYPE_CLASS:
case DivinerAtom::TYPE_INTERFACE:
$out[] = $symbol->getType();
break;
case DivinerAtom::TYPE_FUNCTION:
switch ($atom->getLanguage()) {
case 'php':
$out[] = $symbol->getType();
break;
}
break;
case DivinerAtom::TYPE_METHOD:
switch ($atom->getLanguage()) {
case 'php':
$out[] = DivinerAtom::TYPE_FUNCTION;
break;
}
break;
}
$anchor = null;
switch ($symbol->getType()) {
case DivinerAtom::TYPE_METHOD:
$anchor = $symbol->getType().'/'.$symbol->getName();
break;
default:
break;
}
$out[] = phutil_tag(
$anchor ? 'a' : 'span',
array(
'class' => 'diviner-atom-signature-name',
'href' => $anchor ? '#'.$anchor : null,
'name' => $is_link ? null : $anchor,
),
$symbol->getName());
$out = phutil_implode_html(' ', $out);
if ($atom) {
$parameters = $atom->getProperty('parameters');
if ($parameters !== null) {
$pout = array();
foreach ($parameters as $parameter) {
$pout[] = idx($parameter, 'name', '...');
}
$out = array($out, '('.implode(', ', $pout).')');
}
}
return phutil_tag(
'span',
array(
'class' => 'diviner-atom-signature',
),
$out);
}
private function buildParametersAndReturn(array $symbols) {
assert_instances_of($symbols, 'DivinerLiveSymbol');
$symbols = array_reverse($symbols);
$out = array();
$collected_parameters = null;
foreach ($symbols as $symbol) {
$parameters = $symbol->getAtom()->getProperty('parameters');
if ($parameters !== null) {
if ($collected_parameters === null) {
$collected_parameters = array();
}
foreach ($parameters as $key => $parameter) {
if (isset($collected_parameters[$key])) {
$collected_parameters[$key] += $parameter;
} else {
$collected_parameters[$key] = $parameter;
}
}
}
}
if (nonempty($parameters)) {
$out[] = id(new DivinerParameterTableView())
->setHeader(pht('Parameters'))
->setParameters($parameters);
}
$collected_return = null;
foreach ($symbols as $symbol) {
$return = $symbol->getAtom()->getProperty('return');
if ($return) {
if ($collected_return) {
$collected_return += $return;
} else {
$collected_return = $return;
}
}
}
if (nonempty($return)) {
$out[] = id(new DivinerReturnTableView())
->setHeader(pht('Return'))
->setReturn($collected_return);
}
return $out;
}
private function renderDocumentationText(
DivinerLiveSymbol $symbol,
PhabricatorMarkupEngine $engine) {
$field = 'default';
$content = $engine->getOutput($symbol, $field);
if (strlen(trim($symbol->getMarkupText($field)))) {
$content = phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup diviner-remarkup-section',
),
$content);
} else {
$atom = $symbol->getAtom();
$content = phutil_tag(
'div',
array(
'class' => 'diviner-message-not-documented',
),
DivinerAtom::getThisAtomIsNotDocumentedString($atom->getType()));
}
return $content;
}
private function renderMethodDocumentationText(
DivinerLiveSymbol $parent,
array $spec,
PhabricatorMarkupEngine $engine) {
$symbols = array_values($spec['atoms']);
$implementations = array_values($spec['implementations']);
$field = 'default';
$out = array();
foreach ($symbols as $key => $symbol) {
$impl = $implementations[$key];
if ($impl !== $parent) {
if (!strlen(trim($symbol->getMarkupText($field)))) {
continue;
}
}
$doc = $this->renderDocumentationText($symbol, $engine);
if (($impl !== $parent) || $out) {
$where = id(new PHUIBoxView())
->addClass('diviner-method-implementation-header')
->appendChild($impl->getName());
$doc = array($where, $doc);
if ($impl !== $parent) {
$doc = phutil_tag(
'div',
array(
'class' => 'diviner-method-implementation-inherited',
),
$doc);
}
}
$out[] = $doc;
}
// If we only have inherited implementations but none have documentation,
// render the last one here so we get the "this thing has no documentation"
// element.
if (!$out) {
$out[] = $this->renderDocumentationText($symbol, $engine);
}
return $out;
}
}
diff --git a/src/applications/diviner/controller/DivinerBookController.php b/src/applications/diviner/controller/DivinerBookController.php
index 74b2a8f3d9..1aa8790ffa 100644
--- a/src/applications/diviner/controller/DivinerBookController.php
+++ b/src/applications/diviner/controller/DivinerBookController.php
@@ -1,128 +1,126 @@
<?php
final class DivinerBookController extends DivinerController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$book_name = $request->getURIData('book');
$book = id(new DivinerBookQuery())
->setViewer($viewer)
->withNames(array($book_name))
->needRepositories(true)
->executeOne();
if (!$book) {
return new Aphront404Response();
}
$actions = $this->buildActionView($viewer, $book);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->setBorder(true);
$crumbs->addTextCrumb(
$book->getShortTitle(),
'/book/'.$book->getName().'/');
$header = id(new PHUIHeaderView())
->setHeader($book->getTitle())
->setUser($viewer)
->setPolicyObject($book)
->setEpoch($book->getDateModified())
->setActionList($actions);
// TODO: This could probably look better.
if ($book->getRepositoryPHID()) {
$header->addTag(
id(new PHUITagView())
->setType(PHUITagView::TYPE_STATE)
->setBackgroundColor(PHUITagView::COLOR_BLUE)
->setName($book->getRepository()->getMonogram()));
}
$document = new PHUIDocumentViewPro();
$document->setHeader($header);
$document->addClass('diviner-view');
$atoms = id(new DivinerAtomQuery())
->setViewer($viewer)
->withBookPHIDs(array($book->getPHID()))
->withGhosts(false)
->withIsDocumentable(true)
->execute();
$atoms = msort($atoms, 'getSortKey');
$group_spec = $book->getConfig('groups');
if (!is_array($group_spec)) {
$group_spec = array();
}
$groups = mgroup($atoms, 'getGroupName');
$groups = array_select_keys($groups, array_keys($group_spec)) + $groups;
if (isset($groups[''])) {
$no_group = $groups[''];
unset($groups['']);
$groups[''] = $no_group;
}
$out = array();
foreach ($groups as $group => $atoms) {
$group_name = $book->getGroupName($group);
if (!strlen($group_name)) {
$group_name = pht('Free Radicals');
}
$section = id(new DivinerSectionView())
->setHeader($group_name);
$section->addContent($this->renderAtomList($atoms));
$out[] = $section;
}
$preface = $book->getPreface();
$preface_view = null;
if (strlen($preface)) {
$preface_view = new PHUIRemarkupView($viewer, $preface);
}
$document->appendChild($preface_view);
$document->appendChild($out);
- return $this->buildApplicationPage(
- array(
- $crumbs,
+ return $this->newPage()
+ ->setTitle($book->getTitle())
+ ->setCrumbs($crumbs)
+ ->appendChild(array(
$document,
- ),
- array(
- 'title' => $book->getTitle(),
));
}
private function buildActionView(
PhabricatorUser $user,
DivinerLiveBook $book) {
$can_edit = PhabricatorPolicyFilter::hasCapability(
$user,
$book,
PhabricatorPolicyCapability::CAN_EDIT);
$action_view = id(new PhabricatorActionListView())
->setUser($user)
->setObject($book);
$action_view->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Book'))
->setIcon('fa-pencil')
->setHref('/book/'.$book->getName().'/edit/')
->setDisabled(!$can_edit));
return $action_view;
}
}
diff --git a/src/applications/diviner/controller/DivinerBookEditController.php b/src/applications/diviner/controller/DivinerBookEditController.php
index b5c3e2dea5..2b1f90579b 100644
--- a/src/applications/diviner/controller/DivinerBookEditController.php
+++ b/src/applications/diviner/controller/DivinerBookEditController.php
@@ -1,127 +1,136 @@
<?php
final class DivinerBookEditController extends DivinerController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$book_name = $request->getURIData('book');
$book = id(new DivinerBookQuery())
->setViewer($viewer)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->needProjectPHIDs(true)
->withNames(array($book_name))
->executeOne();
if (!$book) {
return new Aphront404Response();
}
$view_uri = '/book/'.$book->getName().'/';
if ($request->isFormPost()) {
$v_projects = $request->getArr('projectPHIDs');
$v_view = $request->getStr('viewPolicy');
$v_edit = $request->getStr('editPolicy');
$xactions = array();
$xactions[] = id(new DivinerLiveBookTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST)
->setNewValue(
array(
'=' => array_fuse($v_projects),
));
$xactions[] = id(new DivinerLiveBookTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($v_view);
$xactions[] = id(new DivinerLiveBookTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
->setNewValue($v_edit);
id(new DivinerLiveBookEditor())
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request)
->setActor($viewer)
->applyTransactions($book, $xactions);
return id(new AphrontRedirectResponse())->setURI($view_uri);
}
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Edit Basics'));
+ $crumbs->setBorder(true);
- $title = pht('Edit %s', $book->getTitle());
+ $title = pht('Edit Book: %s', $book->getTitle());
+ $header_icon = 'fa-pencil';
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($book)
->execute();
$view_capability = PhabricatorPolicyCapability::CAN_VIEW;
$edit_capability = PhabricatorPolicyCapability::CAN_EDIT;
$form = id(new AphrontFormView())
->setUser($viewer)
->appendControl(
id(new AphrontFormTokenizerControl())
->setDatasource(new PhabricatorProjectDatasource())
->setName('projectPHIDs')
->setLabel(pht('Projects'))
->setValue($book->getProjectPHIDs()))
->appendControl(
id(new AphrontFormTokenizerControl())
->setDatasource(new DiffusionRepositoryDatasource())
->setName('repositoryPHIDs')
->setLabel(pht('Repository'))
->setDisableBehavior(true)
->setLimit(1)
->setValue($book->getRepositoryPHID()
? array($book->getRepositoryPHID())
: null))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('viewPolicy')
->setPolicyObject($book)
->setCapability($view_capability)
->setPolicies($policies)
->setCaption($book->describeAutomaticCapability($view_capability)))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('editPolicy')
->setPolicyObject($book)
->setCapability($edit_capability)
->setPolicies($policies)
->setCaption($book->describeAutomaticCapability($edit_capability)))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Save'))
->addCancelButton($view_uri));
- $object_box = id(new PHUIObjectBoxView())
- ->setHeaderText($title)
+ $box = id(new PHUIObjectBoxView())
+ ->setHeaderText(pht('Book'))
+ ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($form);
$timeline = $this->buildTransactionTimeline(
$book,
new DivinerLiveBookTransactionQuery());
$timeline->setShouldTerminate(true);
- return $this->buildApplicationPage(
- array(
- $crumbs,
- $object_box,
+ $header = id(new PHUIHeaderView())
+ ->setHeader($title)
+ ->setHeaderIcon($header_icon);
+
+ $view = id(new PHUITwoColumnView())
+ ->setHeader($header)
+ ->setFooter(array(
+ $box,
$timeline,
- ),
- array(
- 'title' => $title,
));
+
+ return $this->newPage()
+ ->setTitle($title)
+ ->setCrumbs($crumbs)
+ ->appendChild($view);
}
}
diff --git a/src/applications/diviner/controller/DivinerFindController.php b/src/applications/diviner/controller/DivinerFindController.php
index b9e165fc1d..1bedd65b06 100644
--- a/src/applications/diviner/controller/DivinerFindController.php
+++ b/src/applications/diviner/controller/DivinerFindController.php
@@ -1,94 +1,95 @@
<?php
final class DivinerFindController extends DivinerController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$book_name = $request->getStr('book');
$query_text = $request->getStr('name');
$book = null;
if ($book_name) {
$book = id(new DivinerBookQuery())
->setViewer($viewer)
->withNames(array($book_name))
->executeOne();
if (!$book) {
return new Aphront404Response();
}
}
$query = id(new DivinerAtomQuery())
->setViewer($viewer);
if ($book) {
$query->withBookPHIDs(array($book->getPHID()));
}
$context = $request->getStr('context');
if (strlen($context)) {
$query->withContexts(array($context));
}
$type = $request->getStr('type');
if (strlen($type)) {
$query->withTypes(array($type));
}
$query->withGhosts(false);
$query->withIsDocumentable(true);
$name_query = clone $query;
$name_query->withNames(
array(
$query_text,
// TODO: This could probably be more smartly normalized in the DB,
// but just fake it for now.
phutil_utf8_strtolower($query_text),
));
$atoms = $name_query->execute();
if (!$atoms) {
$title_query = clone $query;
$title_query->withTitles(array($query_text));
$atoms = $title_query->execute();
}
$not_found_uri = $this->getApplicationURI();
if (!$atoms) {
$dialog = id(new AphrontDialogView())
->setUser($viewer)
->setTitle(pht('Documentation Not Found'))
->appendChild(
pht(
'Unable to find the specified documentation. '.
'You may have followed a bad or outdated link.'))
->addCancelButton($not_found_uri, pht('Read More Documentation'));
return id(new AphrontDialogResponse())->setDialog($dialog);
}
if (count($atoms) == 1 && $request->getBool('jump')) {
$atom_uri = head($atoms)->getURI();
return id(new AphrontRedirectResponse())->setURI($atom_uri);
}
$list = $this->renderAtomList($atoms);
- return $this->buildApplicationPage(
- $list,
- array(
- 'title' => array(pht('Find'), pht('"%s"', $query_text)),
+ return $this->newPage()
+ ->setTitle(array(pht('Find'), pht('"%s"', $query_text)))
+ ->appendChild(array(
+ $list,
));
+
}
}
diff --git a/src/applications/diviner/controller/DivinerMainController.php b/src/applications/diviner/controller/DivinerMainController.php
index e85769060f..e7d179c077 100644
--- a/src/applications/diviner/controller/DivinerMainController.php
+++ b/src/applications/diviner/controller/DivinerMainController.php
@@ -1,77 +1,75 @@
<?php
final class DivinerMainController extends DivinerController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$books = id(new DivinerBookQuery())
->setViewer($viewer)
->execute();
$crumbs = $this->buildApplicationCrumbs();
$crumbs->setBorder(true);
$crumbs->addTextCrumb(pht('Books'));
$query_button = id(new PHUIButtonView())
->setTag('a')
->setHref($this->getApplicationURI('query/'))
->setText(pht('Advanced Search'))
->setIcon('fa-search');
$header = id(new PHUIHeaderView())
->setHeader(pht('Documentation Books'))
->addActionLink($query_button);
$document = new PHUIDocumentViewPro();
$document->setHeader($header);
$document->addClass('diviner-view');
if ($books) {
$books = msort($books, 'getTitle');
$list = array();
foreach ($books as $book) {
$item = id(new DivinerBookItemView())
->setTitle($book->getTitle())
->setHref('/book/'.$book->getName().'/')
->setSubtitle($book->getPreface());
$list[] = $item;
}
$list = id(new PHUIBoxView())
->addPadding(PHUI::PADDING_MEDIUM_TOP)
->appendChild($list);
$document->appendChild($list);
} else {
$text = pht(
"(NOTE) **Looking for Phabricator documentation?** ".
"If you're looking for help and information about Phabricator, ".
"you can [[https://secure.phabricator.com/diviner/ | ".
"browse the public Phabricator documentation]] on the live site.\n\n".
"Diviner is the documentation generator used to build the ".
"Phabricator documentation.\n\n".
"You haven't generated any Diviner documentation books yet, so ".
"there's nothing to show here. If you'd like to generate your own ".
"local copy of the Phabricator documentation and have it appear ".
"here, run this command:\n\n".
" %s\n\n",
'phabricator/ $ ./bin/diviner generate');
$text = new PHUIRemarkupView($viewer, $text);
$document->appendChild($text);
}
- return $this->buildApplicationPage(
- array(
- $crumbs,
+ return $this->newPage()
+ ->setTitle(pht('Documentation Books'))
+ ->setCrumbs($crumbs)
+ ->appendChild(array(
$document,
- ),
- array(
- 'title' => pht('Documentation Books'),
));
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Jan 19 2025, 17:55 (6 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1127176
Default Alt Text
(33 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment