@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhabricatorDaemonBulkJobMonitorController
4 extends PhabricatorDaemonBulkJobController {
5
6 public function handleRequest(AphrontRequest $request) {
7 $viewer = $this->getViewer();
8
9 $job = id(new PhabricatorWorkerBulkJobQuery())
10 ->setViewer($viewer)
11 ->withIDs(array($request->getURIData('id')))
12 ->executeOne();
13 if (!$job) {
14 return new Aphront404Response();
15 }
16
17 // If the user clicks "Continue" on a completed job, take them back to
18 // whatever application sent them here.
19 if ($request->getStr('done')) {
20 if ($request->isFormPost()) {
21 $done_uri = $job->getDoneURI();
22 return id(new AphrontRedirectResponse())->setURI($done_uri);
23 }
24 }
25
26 $title = pht('Bulk Job %d', $job->getID());
27
28 if ($job->getStatus() == PhabricatorWorkerBulkJob::STATUS_CONFIRM) {
29 $can_edit = PhabricatorPolicyFilter::hasCapability(
30 $viewer,
31 $job,
32 PhabricatorPolicyCapability::CAN_EDIT);
33
34 if ($can_edit) {
35 if ($request->isFormPost()) {
36 $type_status = PhabricatorWorkerBulkJobTransaction::TYPE_STATUS;
37
38 $xactions = array();
39 $xactions[] = id(new PhabricatorWorkerBulkJobTransaction())
40 ->setTransactionType($type_status)
41 ->setNewValue(PhabricatorWorkerBulkJob::STATUS_WAITING);
42
43 $editor = id(new PhabricatorWorkerBulkJobEditor())
44 ->setActor($viewer)
45 ->setContentSourceFromRequest($request)
46 ->setContinueOnMissingFields(true)
47 ->applyTransactions($job, $xactions);
48
49 return id(new AphrontRedirectResponse())
50 ->setURI($job->getMonitorURI());
51 } else {
52 $dialog = $this->newDialog()
53 ->setTitle(pht('Confirm Bulk Job'));
54
55 $confirm = $job->getDescriptionForConfirm();
56 $confirm = (array)$confirm;
57 foreach ($confirm as $paragraph) {
58 $dialog->appendParagraph($paragraph);
59 }
60
61 $dialog
62 ->appendParagraph(
63 pht('Start work on this bulk job?'))
64 ->addCancelButton($job->getManageURI(), pht('Details'))
65 ->addSubmitButton(pht('Start Work'));
66
67 return $dialog;
68 }
69 } else {
70 return $this->newDialog()
71 ->setTitle(pht('Waiting For Confirmation'))
72 ->appendParagraph(
73 pht(
74 'This job is waiting for confirmation before work begins.'))
75 ->addCancelButton($job->getManageURI(), pht('Details'));
76 }
77 }
78
79
80 $dialog = $this->newDialog()
81 ->setTitle(pht('%s: %s', $title, $job->getStatusName()))
82 ->addCancelButton($job->getManageURI(), pht('Details'));
83
84 switch ($job->getStatus()) {
85 case PhabricatorWorkerBulkJob::STATUS_WAITING:
86 $dialog->appendParagraph(
87 pht('This job is waiting for tasks to be queued.'));
88 break;
89 case PhabricatorWorkerBulkJob::STATUS_RUNNING:
90 $dialog->appendParagraph(
91 pht('This job is running.'));
92 break;
93 case PhabricatorWorkerBulkJob::STATUS_COMPLETE:
94 $dialog->appendParagraph(
95 pht('This job is complete.'));
96 break;
97 }
98
99 $counts = $job->loadTaskStatusCounts();
100 if ($counts) {
101 $dialog->appendParagraph($this->renderProgress($counts));
102 }
103
104 switch ($job->getStatus()) {
105 case PhabricatorWorkerBulkJob::STATUS_COMPLETE:
106 $dialog->addHiddenInput('done', true);
107 $dialog->addSubmitButton(pht('Continue'));
108 break;
109 default:
110 Javelin::initBehavior('bulk-job-reload');
111 break;
112 }
113
114 return $dialog;
115 }
116
117 private function renderProgress(array $counts) {
118 $this->requireResource('bulk-job-css');
119
120 $states = array(
121 PhabricatorWorkerBulkTask::STATUS_DONE => array(
122 'class' => 'bulk-job-progress-slice-green',
123 ),
124 PhabricatorWorkerBulkTask::STATUS_RUNNING => array(
125 'class' => 'bulk-job-progress-slice-blue',
126 ),
127 PhabricatorWorkerBulkTask::STATUS_WAITING => array(
128 'class' => 'bulk-job-progress-slice-empty',
129 ),
130 PhabricatorWorkerBulkTask::STATUS_FAIL => array(
131 'class' => 'bulk-job-progress-slice-red',
132 ),
133 );
134
135 $total = array_sum($counts);
136 $offset = 0;
137 $bars = array();
138 foreach ($states as $state => $spec) {
139 $size = idx($counts, $state, 0);
140 if (!$size) {
141 continue;
142 }
143
144 $classes = array();
145 $classes[] = 'bulk-job-progress-slice';
146 $classes[] = $spec['class'];
147
148 $width = ($size / $total);
149 $bars[] = phutil_tag(
150 'div',
151 array(
152 'class' => implode(' ', $classes),
153 'style' =>
154 'left: '.sprintf('%.2f%%', 100 * $offset).'; '.
155 'width: '.sprintf('%.2f%%', 100 * $width).';',
156 ),
157 '');
158
159 $offset += $width;
160 }
161
162 return phutil_tag(
163 'div',
164 array(
165 'class' => 'bulk-job-progress-bar',
166 ),
167 $bars);
168 }
169
170}