1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-18 11:30:55 +01:00

Allow bulk edits to be made silently if you have CLI access

Summary:
Fixes T13042. This hooks up the new "silent" mode from D18882 and makes it actually work.

The UI (where we tell you to go run some command and then reload the page) is pretty clumsy, but should solve some problems for now and can be cleaned up eventually. The actual mechanics (timeline aggregation, Herald interaction,  etc.) are on firmer ground.

Test Plan:
  - Made a normal bulk edit, got mail and feed stories.
  - Made a silent bulk edit, no mail and no feed.
  - Saw "Silent Edit" marker in timeline for silent edits:

{F5386245}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13042

Differential Revision: https://secure.phabricator.com/D18883
This commit is contained in:
epriestley 2018-01-19 10:08:02 -08:00
parent 8b12fa6d6e
commit 3038d564a6
12 changed files with 165 additions and 5 deletions

1
bin/bulk Symbolic link
View file

@ -0,0 +1 @@
../scripts/setup/manage_bulk.php

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_worker.worker_bulkjob
ADD isSilent BOOL NOT NULL;

1
scripts/manage_bulk.php Symbolic link
View file

@ -0,0 +1 @@
../scripts/setup/manage_bulk.php

21
scripts/setup/manage_bulk.php Executable file
View file

@ -0,0 +1,21 @@
#!/usr/bin/env php
<?php
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
$args = new PhutilArgumentParser($argv);
$args->setTagline(pht('manage bulk jobs'));
$args->setSynopsis(<<<EOSYNOPSIS
**bulk** __command__ [__options__]
Manage and debug bulk jobs.
EOSYNOPSIS
);
$args->parseStandardArguments();
$workflows = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorBulkManagementWorkflow')
->execute();
$workflows[] = new PhutilHelpArgumentWorkflow();
$args->parseWorkflows($workflows);

View file

@ -2206,6 +2206,8 @@ phutil_register_library_map(array(
'PhabricatorBulkContentSource' => 'infrastructure/daemon/contentsource/PhabricatorBulkContentSource.php', 'PhabricatorBulkContentSource' => 'infrastructure/daemon/contentsource/PhabricatorBulkContentSource.php',
'PhabricatorBulkEditGroup' => 'applications/transactions/bulk/PhabricatorBulkEditGroup.php', 'PhabricatorBulkEditGroup' => 'applications/transactions/bulk/PhabricatorBulkEditGroup.php',
'PhabricatorBulkEngine' => 'applications/transactions/bulk/PhabricatorBulkEngine.php', 'PhabricatorBulkEngine' => 'applications/transactions/bulk/PhabricatorBulkEngine.php',
'PhabricatorBulkManagementMakeSilentWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementMakeSilentWorkflow.php',
'PhabricatorBulkManagementWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementWorkflow.php',
'PhabricatorCacheDAO' => 'applications/cache/storage/PhabricatorCacheDAO.php', 'PhabricatorCacheDAO' => 'applications/cache/storage/PhabricatorCacheDAO.php',
'PhabricatorCacheEngine' => 'applications/system/engine/PhabricatorCacheEngine.php', 'PhabricatorCacheEngine' => 'applications/system/engine/PhabricatorCacheEngine.php',
'PhabricatorCacheEngineExtension' => 'applications/system/engine/PhabricatorCacheEngineExtension.php', 'PhabricatorCacheEngineExtension' => 'applications/system/engine/PhabricatorCacheEngineExtension.php',
@ -7504,6 +7506,8 @@ phutil_register_library_map(array(
'PhabricatorBulkContentSource' => 'PhabricatorContentSource', 'PhabricatorBulkContentSource' => 'PhabricatorContentSource',
'PhabricatorBulkEditGroup' => 'Phobject', 'PhabricatorBulkEditGroup' => 'Phobject',
'PhabricatorBulkEngine' => 'Phobject', 'PhabricatorBulkEngine' => 'Phobject',
'PhabricatorBulkManagementMakeSilentWorkflow' => 'PhabricatorBulkManagementWorkflow',
'PhabricatorBulkManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorCacheDAO' => 'PhabricatorLiskDAO', 'PhabricatorCacheDAO' => 'PhabricatorLiskDAO',
'PhabricatorCacheEngine' => 'Phobject', 'PhabricatorCacheEngine' => 'Phobject',
'PhabricatorCacheEngineExtension' => 'Phobject', 'PhabricatorCacheEngineExtension' => 'Phobject',

View file

@ -49,13 +49,22 @@ final class PhabricatorDaemonBulkJobMonitorController
return id(new AphrontRedirectResponse()) return id(new AphrontRedirectResponse())
->setURI($job->getMonitorURI()); ->setURI($job->getMonitorURI());
} else { } else {
return $this->newDialog() $dialog = $this->newDialog()
->setTitle(pht('Confirm Bulk Job')) ->setTitle(pht('Confirm Bulk Job'));
->appendParagraph($job->getDescriptionForConfirm())
$confirm = $job->getDescriptionForConfirm();
$confirm = (array)$confirm;
foreach ($confirm as $paragraph) {
$dialog->appendParagraph($paragraph);
}
$dialog
->appendParagraph( ->appendParagraph(
pht('Start work on this bulk job?')) pht('Start work on this bulk job?'))
->addCancelButton($job->getManageURI(), pht('Details')) ->addCancelButton($job->getManageURI(), pht('Details'))
->addSubmitButton(pht('Start Work')); ->addSubmitButton(pht('Start Work'));
return $dialog;
} }
} else { } else {
return $this->newDialog() return $this->newDialog()

View file

@ -12,10 +12,36 @@ final class PhabricatorEditEngineBulkJobType
} }
public function getDescriptionForConfirm(PhabricatorWorkerBulkJob $job) { public function getDescriptionForConfirm(PhabricatorWorkerBulkJob $job) {
return pht( $parts = array();
$parts[] = pht(
'You are about to apply a bulk edit which will affect '. 'You are about to apply a bulk edit which will affect '.
'%s object(s).', '%s object(s).',
new PhutilNumber($job->getSize())); new PhutilNumber($job->getSize()));
if ($job->getIsSilent()) {
$parts[] = pht(
'If you start work now, this edit will be applied silently: it will '.
'not send mail or publish notifications.');
} else {
$parts[] = pht(
'If you start work now, this edit will send mail and publish '.
'notifications normally.');
$parts[] = pht('To silence this edit, run this command:');
$command = csprintf(
'phabricator/ $ ./bin/bulk make-silent --id %R',
$job->getID());
$command = (string)$command;
$parts[] = phutil_tag('tt', array(), $command);
$parts[] = pht(
'After running this command, reload this page to see the new setting.');
}
return $parts;
} }
public function getJobSize(PhabricatorWorkerBulkJob $job) { public function getJobSize(PhabricatorWorkerBulkJob $job) {
@ -56,12 +82,14 @@ final class PhabricatorEditEngineBulkJobType
$raw_xactions = $job->getParameter('xactions'); $raw_xactions = $job->getParameter('xactions');
$xactions = $this->buildTransactions($object, $raw_xactions); $xactions = $this->buildTransactions($object, $raw_xactions);
$is_silent = $job->getIsSilent();
$editor = $object->getApplicationTransactionEditor() $editor = $object->getApplicationTransactionEditor()
->setActor($actor) ->setActor($actor)
->setContentSource($job->newContentSource()) ->setContentSource($job->newContentSource())
->setContinueOnNoEffect(true) ->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true) ->setContinueOnMissingFields(true)
->setIsSilent($is_silent)
->applyTransactions($object, $xactions); ->applyTransactions($object, $xactions);
} }

View file

@ -0,0 +1,72 @@
<?php
final class PhabricatorBulkManagementMakeSilentWorkflow
extends PhabricatorBulkManagementWorkflow {
protected function didConstruct() {
$this
->setName('make-silent')
->setExamples('**make-silent** [options]')
->setSynopsis(
pht('Configure a bulk job to execute silently.'))
->setArguments(
array(
array(
'name' => 'id',
'param' => 'id',
'help' => pht(
'Configure bulk job __id__ to run silently (without sending '.
'mail or publishing notifications).'),
),
));
}
public function execute(PhutilArgumentParser $args) {
$viewer = $this->getViewer();
$id = $args->getArg('id');
if (!$id) {
throw new PhutilArgumentUsageException(
pht('Use "--id" to choose a bulk job to make silent.'));
}
$job = id(new PhabricatorWorkerBulkJobQuery())
->setViewer($viewer)
->withIDs(array($id))
->executeOne();
if (!$job) {
throw new PhutilArgumentUsageException(
pht(
'Unable to load bulk job with ID "%s".',
$id));
}
if ($job->getIsSilent()) {
echo tsprintf(
"%s\n",
pht('This job is already configured to run silently.'));
return 0;
}
if ($job->getStatus() !== PhabricatorWorkerBulkJob::STATUS_CONFIRM) {
throw new PhutilArgumentUsageException(
pht(
'Work has already started on job "%s". Jobs can not be '.
'reconfigured after they have been started.',
$id));
}
$job
->setIsSilent(true)
->save();
echo tsprintf(
"%s\n",
pht(
'Configured job "%s" to run silently.',
$id));
return 0;
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class PhabricatorBulkManagementWorkflow
extends PhabricatorManagementWorkflow {}

View file

@ -21,6 +21,7 @@ final class PhabricatorWorkerBulkJob
protected $status; protected $status;
protected $parameters = array(); protected $parameters = array();
protected $size; protected $size;
protected $isSilent;
private $jobImplementation = self::ATTACHABLE; private $jobImplementation = self::ATTACHABLE;
@ -34,6 +35,7 @@ final class PhabricatorWorkerBulkJob
'jobTypeKey' => 'text32', 'jobTypeKey' => 'text32',
'status' => 'text32', 'status' => 'text32',
'size' => 'uint32', 'size' => 'uint32',
'isSilent' => 'bool',
), ),
self::CONFIG_KEY_SCHEMA => array( self::CONFIG_KEY_SCHEMA => array(
'key_type' => array( 'key_type' => array(
@ -58,7 +60,8 @@ final class PhabricatorWorkerBulkJob
->setAuthorPHID($actor->getPHID()) ->setAuthorPHID($actor->getPHID())
->setJobTypeKey($type->getBulkJobTypeKey()) ->setJobTypeKey($type->getBulkJobTypeKey())
->setParameters($parameters) ->setParameters($parameters)
->attachJobImplementation($type); ->attachJobImplementation($type)
->setIsSilent(0);
$job->setSize($job->computeSize()); $job->setSize($job->computeSize());

View file

@ -1639,6 +1639,13 @@ final class PhabricatorUSEnglishTranslation
), ),
), ),
'You are about to apply a bulk edit which will affect '.
'%s object(s).' => array(
'You are about to apply a bulk edit to a single object.',
'You are about to apply a bulk edit which will affect '.
'%s objects.',
),
); );
} }

View file

@ -584,6 +584,14 @@ final class PHUITimelineEventView extends AphrontView {
} }
$extra[] = $date; $extra[] = $date;
} }
// If this edit was applied silently, give user a hint that they should
// not expect to have received any mail or notifications.
if ($this->getIsSilent()) {
$extra[] = id(new PHUIIconView())
->setIcon('fa-bell-slash', 'red')
->setTooltip(pht('Silent Edit'));
}
} }
$extra = javelin_tag( $extra = javelin_tag(