Page MenuHomePhabricator

D19806.diff
No OneTemporary

D19806.diff

diff --git a/bin/herald b/bin/herald
new file mode 120000
--- /dev/null
+++ b/bin/herald
@@ -0,0 +1 @@
+../scripts/setup/manage_herald.php
\ No newline at end of file
diff --git a/scripts/setup/manage_herald.php b/scripts/setup/manage_herald.php
new file mode 100755
--- /dev/null
+++ b/scripts/setup/manage_herald.php
@@ -0,0 +1,21 @@
+#!/usr/bin/env php
+<?php
+
+$root = dirname(dirname(dirname(__FILE__)));
+require_once $root.'/scripts/init/init-script.php';
+
+$args = new PhutilArgumentParser($argv);
+$args->setTagline(pht('manage Herald'));
+$args->setSynopsis(<<<EOSYNOPSIS
+**herald** __command__ [__options__]
+ Manage and debug Herald.
+
+EOSYNOPSIS
+ );
+$args->parseStandardArguments();
+
+$workflows = id(new PhutilClassMapQuery())
+ ->setAncestorClass('HeraldManagementWorkflow')
+ ->execute();
+$workflows[] = new PhutilHelpArgumentWorkflow();
+$args->parseWorkflows($workflows);
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1488,6 +1488,7 @@
'HeraldInvalidConditionException' => 'applications/herald/engine/exception/HeraldInvalidConditionException.php',
'HeraldMailableState' => 'applications/herald/state/HeraldMailableState.php',
'HeraldManageGlobalRulesCapability' => 'applications/herald/capability/HeraldManageGlobalRulesCapability.php',
+ 'HeraldManagementWorkflow' => 'applications/herald/management/HeraldManagementWorkflow.php',
'HeraldManiphestTaskAdapter' => 'applications/maniphest/herald/HeraldManiphestTaskAdapter.php',
'HeraldNewController' => 'applications/herald/controller/HeraldNewController.php',
'HeraldNewObjectField' => 'applications/herald/field/HeraldNewObjectField.php',
@@ -1537,6 +1538,7 @@
'HeraldSupportActionGroup' => 'applications/herald/action/HeraldSupportActionGroup.php',
'HeraldSupportFieldGroup' => 'applications/herald/field/HeraldSupportFieldGroup.php',
'HeraldTestConsoleController' => 'applications/herald/controller/HeraldTestConsoleController.php',
+ 'HeraldTestManagementWorkflow' => 'applications/herald/management/HeraldTestManagementWorkflow.php',
'HeraldTextFieldValue' => 'applications/herald/value/HeraldTextFieldValue.php',
'HeraldTokenizerFieldValue' => 'applications/herald/value/HeraldTokenizerFieldValue.php',
'HeraldTransactionQuery' => 'applications/herald/query/HeraldTransactionQuery.php',
@@ -6975,6 +6977,7 @@
'HeraldInvalidConditionException' => 'Exception',
'HeraldMailableState' => 'HeraldState',
'HeraldManageGlobalRulesCapability' => 'PhabricatorPolicyCapability',
+ 'HeraldManagementWorkflow' => 'PhabricatorManagementWorkflow',
'HeraldManiphestTaskAdapter' => 'HeraldAdapter',
'HeraldNewController' => 'HeraldController',
'HeraldNewObjectField' => 'HeraldField',
@@ -7031,6 +7034,7 @@
'HeraldSupportActionGroup' => 'HeraldActionGroup',
'HeraldSupportFieldGroup' => 'HeraldFieldGroup',
'HeraldTestConsoleController' => 'HeraldController',
+ 'HeraldTestManagementWorkflow' => 'HeraldManagementWorkflow',
'HeraldTextFieldValue' => 'HeraldFieldValue',
'HeraldTokenizerFieldValue' => 'HeraldFieldValue',
'HeraldTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
diff --git a/src/applications/herald/management/HeraldManagementWorkflow.php b/src/applications/herald/management/HeraldManagementWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/herald/management/HeraldManagementWorkflow.php
@@ -0,0 +1,4 @@
+<?php
+
+abstract class HeraldManagementWorkflow
+ extends PhabricatorManagementWorkflow {}
diff --git a/src/applications/herald/management/HeraldTestManagementWorkflow.php b/src/applications/herald/management/HeraldTestManagementWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/herald/management/HeraldTestManagementWorkflow.php
@@ -0,0 +1,139 @@
+<?php
+
+final class HeraldTestManagementWorkflow
+ extends HeraldManagementWorkflow {
+
+ protected function didConstruct() {
+ $this
+ ->setName('test')
+ ->setExamples('**test** --object __object__ --type __type__')
+ ->setSynopsis(
+ pht(
+ 'Test content rules for an object. Executes a dry run, like the '.
+ 'web UI test console.'))
+ ->setArguments(
+ array(
+ array(
+ 'name' => 'object',
+ 'param' => 'object',
+ 'help' => pht('Run rules on this object.'),
+ ),
+ array(
+ 'name' => 'type',
+ 'param' => 'type',
+ 'help' => pht('Run rules for this content type.'),
+ ),
+ ));
+ }
+
+ public function execute(PhutilArgumentParser $args) {
+ $viewer = $this->getViewer();
+
+ $object_name = $args->getArg('object');
+ if (!strlen($object_name)) {
+ throw new PhutilArgumentUsageException(
+ pht('Specify an object to test rules for with "--object".'));
+ }
+
+ $objects = id(new PhabricatorObjectQuery())
+ ->setViewer($viewer)
+ ->withNames(array($object_name))
+ ->execute();
+ if (!$objects) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Unable to load specified object ("%s").',
+ $object_name));
+ }
+ $object = head($objects);
+
+ $adapters = HeraldAdapter::getAllAdapters();
+
+ $can_select = array();
+ $display_adapters = array();
+ foreach ($adapters as $key => $adapter) {
+ if (!$adapter->isTestAdapterForObject($object)) {
+ continue;
+ }
+
+ if (!$adapter->isAvailableToUser($viewer)) {
+ continue;
+ }
+
+ $display_adapters[$key] = $adapter;
+
+ if ($adapter->canCreateTestAdapterForObject($object)) {
+ $can_select[$key] = $adapter;
+ }
+ }
+
+
+ $content_type = $args->getArg('type');
+ if (!strlen($content_type)) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Specify a content type to run rules for. For this object, valid '.
+ 'content types are: %s.',
+ implode(', ', array_keys($can_select))));
+ }
+
+ if (!isset($can_select[$content_type])) {
+ if (!isset($display_adapters[$content_type])) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Specify a content type to run rules for. The specified content '.
+ 'type ("%s") is not valid. For this object, valid content types '.
+ 'are: %s.',
+ $content_type,
+ implode(', ', array_keys($can_select))));
+ } else {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'The specified content type ("%s") does not support dry runs. '.
+ 'Choose a testable content type. For this object, valid content '.
+ 'types are: %s.',
+ $content_type,
+ implode(', ', array_keys($can_select))));
+ }
+ }
+
+ $adapter = $can_select[$content_type]->newTestAdapter(
+ $viewer,
+ $object);
+
+ $content_source = $this->newContentSource();
+
+ $adapter
+ ->setContentSource($content_source)
+ ->setIsNewObject(false)
+ ->setViewer($viewer);
+
+ $rules = id(new HeraldRuleQuery())
+ ->setViewer($viewer)
+ ->withContentTypes(array($adapter->getAdapterContentType()))
+ ->withDisabled(false)
+ ->needConditionsAndActions(true)
+ ->needAppliedToPHIDs(array($object->getPHID()))
+ ->needValidateAuthors(true)
+ ->execute();
+
+ $engine = id(new HeraldEngine())
+ ->setDryRun(true);
+
+ $effects = $engine->applyRules($rules, $adapter);
+ $engine->applyEffects($effects, $adapter, $rules);
+
+ $xscript = $engine->getTranscript();
+
+ $uri = '/herald/transcript/'.$xscript->getID().'/';
+ $uri = PhabricatorEnv::getProductionURI($uri);
+
+ echo tsprintf(
+ "%s\n\n __%s__\n\n",
+ pht('Test run complete. Transcript:'),
+ $uri);
+
+ return 0;
+ }
+
+}
diff --git a/src/applications/herald/query/HeraldTranscriptQuery.php b/src/applications/herald/query/HeraldTranscriptQuery.php
--- a/src/applications/herald/query/HeraldTranscriptQuery.php
+++ b/src/applications/herald/query/HeraldTranscriptQuery.php
@@ -30,36 +30,35 @@
protected function loadPage() {
$transcript = new HeraldTranscript();
- $conn_r = $transcript->establishConnection('r');
+ $conn = $transcript->establishConnection('r');
// NOTE: Transcripts include a potentially enormous amount of serialized
// data, so we're loading only some of the fields here if the caller asked
// for partial records.
if ($this->needPartialRecords) {
- $fields = implode(
- ', ',
- array(
- 'id',
- 'phid',
- 'objectPHID',
- 'time',
- 'duration',
- 'dryRun',
- 'host',
- ));
+ $fields = array(
+ 'id',
+ 'phid',
+ 'objectPHID',
+ 'time',
+ 'duration',
+ 'dryRun',
+ 'host',
+ );
+ $fields = qsprintf($conn, '%LC', $fields);
} else {
- $fields = '*';
+ $fields = qsprintf($conn, '*');
}
$rows = queryfx_all(
- $conn_r,
+ $conn,
'SELECT %Q FROM %T t %Q %Q %Q',
$fields,
$transcript->getTableName(),
- $this->buildWhereClause($conn_r),
- $this->buildOrderClause($conn_r),
- $this->buildLimitClause($conn_r));
+ $this->buildWhereClause($conn),
+ $this->buildOrderClause($conn),
+ $this->buildLimitClause($conn));
$transcripts = $transcript->loadAllFromArray($rows);

File Metadata

Mime Type
text/plain
Expires
Thu, Jan 23, 12:48 AM (19 h, 26 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7031550
Default Alt Text
D19806.diff (9 KB)

Event Timeline