diff --git a/src/applications/lipsum/generator/PhabricatorTestDataGenerator.php b/src/applications/lipsum/generator/PhabricatorTestDataGenerator.php index 731bb0ccac..077a2765b5 100644 --- a/src/applications/lipsum/generator/PhabricatorTestDataGenerator.php +++ b/src/applications/lipsum/generator/PhabricatorTestDataGenerator.php @@ -1,119 +1,119 @@ viewer = $viewer; return $this; } final public function getViewer() { return $this->viewer; } final public function getGeneratorKey() { return $this->getPhobjectClassConstant('GENERATORKEY', 64); } protected function loadRandomPHID($table) { $conn_r = $table->establishConnection('r'); $row = queryfx_one( $conn_r, 'SELECT phid FROM %T ORDER BY RAND() LIMIT 1', $table->getTableName()); if (!$row) { return null; } return $row['phid']; } protected function loadRandomUser() { $viewer = $this->getViewer(); $user_phid = $this->loadRandomPHID(new PhabricatorUser()); $user = null; if ($user_phid) { $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withPHIDs(array($user_phid)) + ->needUserSettings(true) ->executeOne(); } if (!$user) { throw new Exception( pht( 'Failed to load a random user. You may need to generate more '. 'test users first.')); } return $user; } protected function getLipsumContentSource() { return PhabricatorContentSource::newForSource( PhabricatorLipsumContentSource::SOURCECONST); } /** * Roll `n` dice with `d` sides each, then add `bonus` and return the sum. */ protected function roll($n, $d, $bonus = 0) { $sum = 0; for ($ii = 0; $ii < $n; $ii++) { $sum += mt_rand(1, $d); } $sum += $bonus; return $sum; } protected function newEmptyTransaction() { throw new PhutilMethodNotImplementedException(); } protected function newTransaction($type, $value, $metadata = array()) { $xaction = $this->newEmptyTransaction() ->setTransactionType($type) ->setNewValue($value); foreach ($metadata as $key => $value) { $xaction->setMetadataValue($key, $value); } return $xaction; } public function loadOneRandom($classname) { try { return newv($classname, array()) ->loadOneWhere('1 = 1 ORDER BY RAND() LIMIT 1'); } catch (PhutilMissingSymbolException $ex) { throw new PhutilMissingSymbolException( $classname, pht('class'), pht( 'Unable to load symbol %s: this class does not exist.', $classname)); } } public function loadPhabricatorUserPHID() { return $this->loadOneRandom('PhabricatorUser')->getPHID(); } public function loadPhabricatorUser() { return $this->loadOneRandom('PhabricatorUser'); } - } diff --git a/src/applications/lipsum/management/PhabricatorLipsumGenerateWorkflow.php b/src/applications/lipsum/management/PhabricatorLipsumGenerateWorkflow.php index 46ea9b6bae..24301640ed 100644 --- a/src/applications/lipsum/management/PhabricatorLipsumGenerateWorkflow.php +++ b/src/applications/lipsum/management/PhabricatorLipsumGenerateWorkflow.php @@ -1,196 +1,218 @@ setName('generate') ->setExamples('**generate**') ->setSynopsis(pht('Generate synthetic test objects.')) ->setArguments( array( + array( + 'name' => 'force', + 'short' => 'f', + 'help' => pht( + 'Generate objects without prompting for confirmation.'), + ), + array( + 'name' => 'quickly', + 'help' => pht( + 'Generate objects as quickly as possible.'), + ), array( 'name' => 'args', 'wildcard' => true, ), )); } public function execute(PhutilArgumentParser $args) { $config_key = 'phabricator.developer-mode'; if (!PhabricatorEnv::getEnvConfig($config_key)) { throw new PhutilArgumentUsageException( pht( 'lipsum is a development and testing tool and may only be run '. 'on installs in developer mode. Enable "%s" in your configuration '. 'to enable lipsum.', $config_key)); } $all_generators = id(new PhutilClassMapQuery()) ->setAncestorClass('PhabricatorTestDataGenerator') ->setUniqueMethod('getGeneratorKey') ->execute(); $argv = $args->getArg('args'); + $is_force = $args->getArg('force'); + $is_quickly = $args->getArg('quickly'); + $all = 'all'; if (isset($all_generators[$all])) { throw new Exception( pht( 'A lipsum generator is registered with key "%s". This key is '. 'reserved.', $all)); } if (!$argv) { ksort($all_generators); $names = array(); foreach ($all_generators as $generator) { $names[] = tsprintf( '%s (%s)', $generator->getGeneratorKey(), $generator->getGeneratorName()); } $list = id(new PhutilConsoleList()) ->setWrap(false) ->addItems($names); id(new PhutilConsoleBlock()) ->addParagraph( pht( 'Choose which type or types of test data you want to generate, '. 'or select "%s".', $all)) ->addList($list) ->draw(); return 0; } $generators = array(); foreach ($argv as $arg_original) { $arg = phutil_utf8_strtolower($arg_original); if ($arg == 'all') { $matches = $all_generators; } else { $matches = array(); foreach ($all_generators as $generator) { $name = phutil_utf8_strtolower($generator->getGeneratorKey()); // If there's an exact match, select just that generator. if ($arg == $name) { $matches = array($generator); break; } // If there's a partial match, match that generator but continue. if (strpos($name, $arg) !== false) { $matches[] = $generator; } } if (!$matches) { throw new PhutilArgumentUsageException( pht( 'Argument "%s" does not match the name of any generators.', $arg_original)); } if (count($matches) > 1) { throw new PhutilArgumentUsageException( pht( 'Argument "%s" is ambiguous, and matches multiple '. 'generators: %s.', $arg_original, implode(', ', mpull($matches, 'getGeneratorName')))); } } foreach ($matches as $match) { $generators[] = $match; } } $generators = mpull($generators, null, 'getGeneratorKey'); echo tsprintf( "** %s ** %s\n", pht('GENERATORS'), pht( 'Selected generators: %s.', implode(', ', mpull($generators, 'getGeneratorName')))); - echo tsprintf( - "** %s ** %s\n", - pht('WARNING'), - pht( - 'This command generates synthetic test data, including user '. - 'accounts. It is intended for use in development environments '. - 'so you can test features more easily. There is no easy way to '. - 'delete this data or undo the effects of this command. If you run '. - 'it in a production environment, it will pollute your data with '. - 'large amounts of meaningless garbage that you can not get rid of.')); - - $prompt = pht('Are you sure you want to generate piles of garbage?'); - if (!phutil_console_confirm($prompt, true)) { - return; + if (!$is_force) { + echo tsprintf( + "** %s ** %s\n", + pht('WARNING'), + pht( + 'This command generates synthetic test data, including user '. + 'accounts. It is intended for use in development environments so '. + 'you can test features more easily. There is no easy way to delete '. + 'this data or undo the effects of this command. If you run it in a '. + 'production environment, it will pollute your data with large '. + 'amounts of meaningless garbage that you can not get rid of.')); + + $prompt = pht('Are you sure you want to generate piles of garbage?'); + if (!phutil_console_confirm($prompt, true)) { + return; + } } echo tsprintf( "** %s ** %s\n", pht('LIPSUM'), pht( 'Generating synthetic test objects forever. '. 'Use ^C to stop when satisfied.')); - $this->generate($generators); + $this->generate($generators, $is_quickly); } - protected function generate(array $generators) { + protected function generate(array $generators, $is_quickly) { $viewer = $this->getViewer(); foreach ($generators as $generator) { $generator->setViewer($this->getViewer()); } while (true) { $generator = $generators[array_rand($generators)]; try { $object = $generator->generateObject(); } catch (Exception $ex) { echo tsprintf( "** %s ** %s\n", pht('OOPS'), pht( 'Generator ("%s") was unable to generate an object.', $generator->getGeneratorName())); echo tsprintf( "%B\n", $ex->getMessage()); continue; } - $object_phid = $object->getPHID(); + if (is_string($object)) { + $object_phid = $object; + } else { + $object_phid = $object->getPHID(); + } $handles = $viewer->loadHandles(array($object_phid)); echo tsprintf( "%s\n", pht( 'Generated "%s": %s', $handles[$object_phid]->getTypeName(), $handles[$object_phid]->getFullName())); - sleep(1); + if (!$is_quickly) { + sleep(1); + } } } }