diff --git a/src/applications/diviner/controller/DivinerAtomController.php b/src/applications/diviner/controller/DivinerAtomController.php --- a/src/applications/diviner/controller/DivinerAtomController.php +++ b/src/applications/diviner/controller/DivinerAtomController.php @@ -35,11 +35,6 @@ return new Aphront404Response(); } - // TODO: This query won't load ghosts, because they'll fail `needAtoms()`. - // Instead, we might want to load ghosts and render a message like - // "this thing existed in an older version, but no longer does", especially - // if we add content like comments. - $symbol = id(new DivinerAtomQuery()) ->setViewer($viewer) ->withBookPHIDs(array($book->getPHID())) @@ -47,6 +42,7 @@ ->withNames(array($this->atomName)) ->withContexts(array($this->atomContext)) ->withIndexes(array($this->atomIndex)) + ->withIncludeGhosts(true) ->needAtoms(true) ->needExtends(true) ->needChildren(true) @@ -64,6 +60,22 @@ $book->getShortTitle(), '/book/'.$book->getName().'/'); + if (!$atom) { + $document = id(new PHUIDocumentView()) + ->setBook($book->getTitle(), null) + ->addClass('diviner-view') + ->setFontKit(PHUIDocumentView::FONT_SOURCE_SANS); + + return $this->buildApplicationPage( + array( + $crumbs, + $document, + ), + array( + 'title' => $symbol->getTitle(), + )); + } + $atom_short_title = $atom->getDocblockMetaValue( 'short', $symbol->getTitle()); diff --git a/src/applications/diviner/query/DivinerAtomQuery.php b/src/applications/diviner/query/DivinerAtomQuery.php --- a/src/applications/diviner/query/DivinerAtomQuery.php +++ b/src/applications/diviner/query/DivinerAtomQuery.php @@ -155,7 +155,7 @@ foreach ($atoms as $key => $atom) { $data = idx($atom_data, $atom->getPHID()); if (!$data) { - unset($atoms[$key]); + $atom->attachAtom(null); continue; } $atom->attachAtom($data); @@ -173,6 +173,10 @@ $names = array(); foreach ($atoms as $atom) { + if (!$atom->getAtom()) { + continue; + } + foreach ($atom->getAtom()->getExtends() as $xref) { $names[] = $xref->getName(); } @@ -192,10 +196,17 @@ } foreach ($atoms as $atom) { - $alang = $atom->getAtom()->getLanguage(); + $alang = null; + $aextends = array(); + + if ($atom->getAtom()) { + $alang = $atom->getAtom()->getLanguage(); + $aextends = $atom->getAtom()->getExtends(); + } + $extends = array(); - foreach ($atom->getAtom()->getExtends() as $xref) { + foreach ($aextends as $xref) { // If there are no symbols of the matching name and type, we can't // resolve this. if (empty($xatoms[$xref->getName()][$xref->getType()])) { @@ -397,7 +408,13 @@ $hashes = array(); foreach ($symbols as $symbol) { - foreach ($symbol->getAtom()->getChildHashes() as $hash) { + $child_hashes = array(); + + if ($symbol->getAtom()) { + $child_hashes = $symbol->getAtom()->getChildHashes(); + } + + foreach ($child_hashes as $hash) { $hashes[$hash] = $hash; } if ($recurse_up) { @@ -427,8 +444,14 @@ assert_instances_of($children, 'DivinerLiveSymbol'); foreach ($symbols as $symbol) { + $child_hashes = array(); $symbol_children = array(); - foreach ($symbol->getAtom()->getChildHashes() as $hash) { + + if ($symbol->getAtom()) { + $child_hashes = $symbol->getAtom()->getChildHashes(); + } + + foreach ($child_hashes as $hash) { if (isset($children[$hash])) { $symbol_children[] = $children[$hash]; } diff --git a/src/applications/diviner/storage/DivinerLiveSymbol.php b/src/applications/diviner/storage/DivinerLiveSymbol.php --- a/src/applications/diviner/storage/DivinerLiveSymbol.php +++ b/src/applications/diviner/storage/DivinerLiveSymbol.php @@ -110,8 +110,12 @@ return $this->assertAttached($this->atom); } - public function attachAtom(DivinerLiveAtom $atom) { - $this->atom = DivinerAtom::newFromDictionary($atom->getAtomData()); + public function attachAtom(DivinerLiveAtom $atom = null) { + if ($atom === null) { + $this->atom = null; + } else { + $this->atom = DivinerAtom::newFromDictionary($atom->getAtomData()); + } return $this; }