Path: blob/master/src/applications/diviner/workflow/DivinerAtomizeWorkflow.php
12256 views
<?php12final class DivinerAtomizeWorkflow extends DivinerWorkflow {34protected function didConstruct() {5$this6->setName('atomize')7->setSynopsis(pht('Build atoms from source.'))8->setArguments(9array(10array(11'name' => 'atomizer',12'param' => 'class',13'help' => pht('Specify a subclass of %s.', 'DivinerAtomizer'),14),15array(16'name' => 'book',17'param' => 'path',18'help' => pht('Path to a Diviner book configuration.'),19),20array(21'name' => 'files',22'wildcard' => true,23),24array(25'name' => 'ugly',26'help' => pht('Produce ugly (but faster) output.'),27),28));29}3031public function execute(PhutilArgumentParser $args) {32$this->readBookConfiguration($args->getArg('book'));3334$console = PhutilConsole::getConsole();3536$atomizer_class = $args->getArg('atomizer');37if (!$atomizer_class) {38throw new PhutilArgumentUsageException(39pht(40'Specify an atomizer class with %s.',41'--atomizer'));42}4344$symbols = id(new PhutilSymbolLoader())45->setName($atomizer_class)46->setConcreteOnly(true)47->setAncestorClass('DivinerAtomizer')48->selectAndLoadSymbols();49if (!$symbols) {50throw new PhutilArgumentUsageException(51pht(52"Atomizer class '%s' must be a concrete subclass of %s.",53$atomizer_class,54'DivinerAtomizer'));55}5657$atomizer = newv($atomizer_class, array());5859$files = $args->getArg('files');60if (!$files) {61throw new Exception(pht('Specify one or more files to atomize.'));62}6364$file_atomizer = new DivinerFileAtomizer();6566foreach (array($atomizer, $file_atomizer) as $configure) {67$configure->setBook($this->getConfig('name'));68}6970$group_rules = array();71foreach ($this->getConfig('groups', array()) as $group => $spec) {72$include = (array)idx($spec, 'include', array());73foreach ($include as $pattern) {74$group_rules[$pattern] = $group;75}76}7778$all_atoms = array();79$context = array(80'group' => null,81);82foreach ($files as $file) {83$abs_path = Filesystem::resolvePath($file, $this->getConfig('root'));84$data = Filesystem::readFile($abs_path);8586if (!$this->shouldAtomizeFile($file, $data)) {87$console->writeLog("%s\n", pht('Skipping %s...', $file));88continue;89} else {90$console->writeLog("%s\n", pht('Atomizing %s...', $file));91}9293$context['group'] = null;94foreach ($group_rules as $rule => $group) {95if (preg_match($rule, $file)) {96$context['group'] = $group;97break;98}99}100101$file_atoms = $file_atomizer->atomize($file, $data, $context);102$all_atoms[] = $file_atoms;103104if (count($file_atoms) !== 1) {105throw new Exception(106pht('Expected exactly one atom from file atomizer.'));107}108$file_atom = head($file_atoms);109110$atoms = $atomizer->atomize($file, $data, $context);111112foreach ($atoms as $atom) {113if (!$atom->hasParent()) {114$file_atom->addChild($atom);115}116}117118$all_atoms[] = $atoms;119}120121$all_atoms = array_mergev($all_atoms);122123$all_atoms = mpull($all_atoms, 'toDictionary');124$all_atoms = ipull($all_atoms, null, 'hash');125126if ($args->getArg('ugly')) {127$json = json_encode($all_atoms);128} else {129$json = id(new PhutilJSON())->encodeFormatted($all_atoms);130}131132$console->writeOut('%s', $json);133return 0;134}135136private function shouldAtomizeFile($file_name, $file_data) {137return strpos($file_data, '@'.'undivinable') === false;138}139140}141142143