Changeset View
Changeset View
Standalone View
Standalone View
src/applications/diviner/query/DivinerAtomQuery.php
| Show First 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | public function needAtoms($need) { | ||||
| return $this; | return $this; | ||||
| } | } | ||||
| public function needChildren($need) { | public function needChildren($need) { | ||||
| $this->needChildren = $need; | $this->needChildren = $need; | ||||
| return $this; | return $this; | ||||
| } | } | ||||
| /** | /** | ||||
| * Include or exclude "ghosts", which are symbols which used to exist but do | * Include or exclude "ghosts", which are symbols which used to exist but do | ||||
| * not exist currently (for example, a function which existed in an older | * not exist currently (for example, a function which existed in an older | ||||
| * version of the codebase but was deleted). | * version of the codebase but was deleted). | ||||
| * | * | ||||
| * These symbols had PHIDs assigned to them, and may have other sorts of | * These symbols had PHIDs assigned to them, and may have other sorts of | ||||
| * metadata that we don't want to lose (like comments or flags), so we don't | * metadata that we don't want to lose (like comments or flags), so we don't | ||||
| * delete them outright. They might also come back in the future: the change | * delete them outright. They might also come back in the future: the change | ||||
| ▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | $books = id(new DivinerBookQuery()) | ||||
| ->setViewer($this->getViewer()) | ->setViewer($this->getViewer()) | ||||
| ->withPHIDs($books) | ->withPHIDs($books) | ||||
| ->execute(); | ->execute(); | ||||
| $books = mpull($books, null, 'getPHID'); | $books = mpull($books, null, 'getPHID'); | ||||
| foreach ($atoms as $key => $atom) { | foreach ($atoms as $key => $atom) { | ||||
| $book = idx($books, $atom->getBookPHID()); | $book = idx($books, $atom->getBookPHID()); | ||||
| if (!$book) { | if (!$book) { | ||||
| $this->didRejectResult($atom); | |||||
| unset($atoms[$key]); | unset($atoms[$key]); | ||||
| continue; | continue; | ||||
| } | } | ||||
| $atom->attachBook($book); | $atom->attachBook($book); | ||||
| } | } | ||||
| if ($this->needAtoms) { | if ($this->needAtoms) { | ||||
| $atom_data = id(new DivinerLiveAtom())->loadAllWhere( | $atom_data = id(new DivinerLiveAtom())->loadAllWhere( | ||||
| 'symbolPHID IN (%Ls)', | 'symbolPHID IN (%Ls)', | ||||
| mpull($atoms, 'getPHID')); | mpull($atoms, 'getPHID')); | ||||
| $atom_data = mpull($atom_data, null, 'getSymbolPHID'); | $atom_data = mpull($atom_data, null, 'getSymbolPHID'); | ||||
| foreach ($atoms as $key => $atom) { | foreach ($atoms as $key => $atom) { | ||||
| $data = idx($atom_data, $atom->getPHID()); | $data = idx($atom_data, $atom->getPHID()); | ||||
| $atom->attachAtom($data); | $atom->attachAtom($data); | ||||
| } | } | ||||
| } | } | ||||
| // Load all of the symbols this symbol extends, recursively. Commonly, | // Load all of the symbols this symbol extends, recursively. Commonly, | ||||
| // this means all the ancestor classes and interfaces it extends and | // this means all the ancestor classes and interfaces it extends and | ||||
| // implements. | // implements. | ||||
| if ($this->needExtends) { | if ($this->needExtends) { | ||||
| // First, load all the matching symbols by name. This does 99% of the | // First, load all the matching symbols by name. This does 99% of the | ||||
| // work in most cases, assuming things are named at all reasonably. | // work in most cases, assuming things are named at all reasonably. | ||||
| $names = array(); | $names = array(); | ||||
| foreach ($atoms as $atom) { | foreach ($atoms as $atom) { | ||||
| if (!$atom->getAtom()) { | if (!$atom->getAtom()) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| foreach ($atom->getAtom()->getExtends() as $xref) { | foreach ($atom->getAtom()->getExtends() as $xref) { | ||||
| $names[] = $xref->getName(); | $names[] = $xref->getName(); | ||||
| ▲ Show 20 Lines • Show All 123 Lines • ▼ Show 20 Lines | if ($this->names) { | ||||
| $where[] = qsprintf( | $where[] = qsprintf( | ||||
| $conn_r, | $conn_r, | ||||
| 'name IN (%Ls)', | 'name IN (%Ls)', | ||||
| $this->names); | $this->names); | ||||
| } | } | ||||
| if ($this->titles) { | if ($this->titles) { | ||||
| $hashes = array(); | $hashes = array(); | ||||
| foreach ($this->titles as $title) { | foreach ($this->titles as $title) { | ||||
| $slug = DivinerAtomRef::normalizeTitleString($title); | $slug = DivinerAtomRef::normalizeTitleString($title); | ||||
| $hash = PhabricatorHash::digestForIndex($slug); | $hash = PhabricatorHash::digestForIndex($slug); | ||||
| $hashes[] = $hash; | $hashes[] = $hash; | ||||
| } | } | ||||
| $where[] = qsprintf( | $where[] = qsprintf( | ||||
| $conn_r, | $conn_r, | ||||
| 'titleSlugHash in (%Ls)', | 'titleSlugHash in (%Ls)', | ||||
| $hashes); | $hashes); | ||||
| } | } | ||||
| if ($this->contexts) { | if ($this->contexts) { | ||||
| $with_null = false; | $with_null = false; | ||||
| $contexts = $this->contexts; | $contexts = $this->contexts; | ||||
| foreach ($contexts as $key => $value) { | foreach ($contexts as $key => $value) { | ||||
| if ($value === null) { | if ($value === null) { | ||||
| unset($contexts[$key]); | unset($contexts[$key]); | ||||
| $with_null = true; | $with_null = true; | ||||
| continue; | continue; | ||||
| } | } | ||||
| } | } | ||||
| Show All 39 Lines | protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { | ||||
| if ($this->nodeHashes) { | if ($this->nodeHashes) { | ||||
| $where[] = qsprintf( | $where[] = qsprintf( | ||||
| $conn_r, | $conn_r, | ||||
| 'nodeHash IN (%Ls)', | 'nodeHash IN (%Ls)', | ||||
| $this->nodeHashes); | $this->nodeHashes); | ||||
| } | } | ||||
| if ($this->nameContains) { | if ($this->nameContains) { | ||||
| // NOTE: This CONVERT() call makes queries case-insensitive, since the | // NOTE: This `CONVERT()` call makes queries case-insensitive, since | ||||
| // column has binary collation. Eventually, this should move into | // the column has binary collation. Eventually, this should move into | ||||
| // fulltext. | // fulltext. | ||||
| $where[] = qsprintf( | $where[] = qsprintf( | ||||
| $conn_r, | $conn_r, | ||||
| 'CONVERT(name USING utf8) LIKE %~', | 'CONVERT(name USING utf8) LIKE %~', | ||||
| $this->nameContains); | $this->nameContains); | ||||
| } | } | ||||
| $where[] = $this->buildPagingClause($conn_r); | $where[] = $this->buildPagingClause($conn_r); | ||||
| return $this->formatWhereClause($where); | return $this->formatWhereClause($where); | ||||
| } | } | ||||
| /** | /** | ||||
| * Walk a list of atoms and collect all the node hashes of the atoms' | * Walk a list of atoms and collect all the node hashes of the atoms' | ||||
| * children. When recursing, also walk up the tree and collect children of | * children. When recursing, also walk up the tree and collect children of | ||||
| * atoms they extend. | * atoms they extend. | ||||
| * | * | ||||
| * @param list<DivinerLiveSymbol> List of symbols to collect child hashes of. | * @param list<DivinerLiveSymbol> List of symbols to collect child hashes of. | ||||
| * @param bool True to collect children of extended atoms, | * @param bool True to collect children of extended atoms, | ||||
| * as well. | * as well. | ||||
| * @return map<string, string> Hashes of atoms' children. | * @return map<string, string> Hashes of atoms' children. | ||||
| */ | */ | ||||
| private function getAllChildHashes(array $symbols, $recurse_up) { | private function getAllChildHashes(array $symbols, $recurse_up) { | ||||
| assert_instances_of($symbols, 'DivinerLiveSymbol'); | assert_instances_of($symbols, 'DivinerLiveSymbol'); | ||||
| $hashes = array(); | $hashes = array(); | ||||
| foreach ($symbols as $symbol) { | foreach ($symbols as $symbol) { | ||||
| $child_hashes = array(); | $child_hashes = array(); | ||||
| if ($symbol->getAtom()) { | if ($symbol->getAtom()) { | ||||
| $child_hashes = $symbol->getAtom()->getChildHashes(); | $child_hashes = $symbol->getAtom()->getChildHashes(); | ||||
| } | } | ||||
| foreach ($child_hashes as $hash) { | foreach ($child_hashes as $hash) { | ||||
| $hashes[$hash] = $hash; | $hashes[$hash] = $hash; | ||||
| } | } | ||||
| if ($recurse_up) { | if ($recurse_up) { | ||||
| $hashes += $this->getAllChildHashes($symbol->getExtends(), true); | $hashes += $this->getAllChildHashes($symbol->getExtends(), true); | ||||
| } | } | ||||
| } | } | ||||
| return $hashes; | return $hashes; | ||||
| } | } | ||||
| /** | /** | ||||
| * Attach child atoms to existing atoms. In recursive mode, also attach child | * Attach child atoms to existing atoms. In recursive mode, also attach child | ||||
| * atoms to atoms that these atoms extend. | * atoms to atoms that these atoms extend. | ||||
| * | * | ||||
| * @param list<DivinerLiveSymbol> List of symbols to attach children to. | * @param list<DivinerLiveSymbol> List of symbols to attach children to. | ||||
| * @param map<string, DivinerLiveSymbol> Map of symbols, keyed by node hash. | * @param map<string, DivinerLiveSymbol> Map of symbols, keyed by node hash. | ||||
| * @param bool True to attach children to extended atoms, as well. | * @param bool True to attach children to extended atoms, as well. | ||||
| * @return void | * @return void | ||||
| Show All 14 Lines | foreach ($symbols as $symbol) { | ||||
| $child_hashes = $symbol->getAtom()->getChildHashes(); | $child_hashes = $symbol->getAtom()->getChildHashes(); | ||||
| } | } | ||||
| foreach ($child_hashes as $hash) { | foreach ($child_hashes as $hash) { | ||||
| if (isset($children[$hash])) { | if (isset($children[$hash])) { | ||||
| $symbol_children[] = $children[$hash]; | $symbol_children[] = $children[$hash]; | ||||
| } | } | ||||
| } | } | ||||
| $symbol->attachChildren($symbol_children); | $symbol->attachChildren($symbol_children); | ||||
| if ($recurse_up) { | if ($recurse_up) { | ||||
| $this->attachAllChildren($symbol->getExtends(), $children, true); | $this->attachAllChildren($symbol->getExtends(), $children, true); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| public function getQueryApplicationClass() { | public function getQueryApplicationClass() { | ||||
| return 'PhabricatorDivinerApplication'; | return 'PhabricatorDivinerApplication'; | ||||
| } | } | ||||
| } | } | ||||