Correct Aphlict websocket URI construction after PHP8 compatibility changes
[phabricator.git] / src / applications / repository / management / PhabricatorRepositoryManagementUnpublishWorkflow.php
blob418030864d76a3e74b59a8e4f75da7534228d93e
1 <?php
3 final class PhabricatorRepositoryManagementUnpublishWorkflow
4 extends PhabricatorRepositoryManagementWorkflow {
6 protected function didConstruct() {
7 $this
8 ->setName('unpublish')
9 ->setExamples(
10 '**unpublish** [__options__] __repository__')
11 ->setSynopsis(
12 pht(
13 'Unpublish all feed stories and notifications that a repository '.
14 'has generated. Keep expectations low; can not rewind time.'))
15 ->setArguments(
16 array(
17 array(
18 'name' => 'force',
19 'help' => pht('Do not prompt for confirmation.'),
21 array(
22 'name' => 'dry-run',
23 'help' => pht('Do not perform any writes.'),
25 array(
26 'name' => 'repositories',
27 'wildcard' => true,
29 ));
32 public function execute(PhutilArgumentParser $args) {
33 $viewer = $this->getViewer();
34 $is_force = $args->getArg('force');
35 $is_dry_run = $args->getArg('dry-run');
37 $repositories = $this->loadLocalRepositories($args, 'repositories');
38 if (count($repositories) !== 1) {
39 throw new PhutilArgumentUsageException(
40 pht('Specify exactly one repository to unpublish.'));
42 $repository = head($repositories);
44 if (!$is_force) {
45 echo tsprintf(
46 "%s\n",
47 pht(
48 'This script will unpublish all feed stories and notifications '.
49 'which a repository generated during import. This action can not '.
50 'be undone.'));
52 $prompt = pht(
53 'Permanently unpublish "%s"?',
54 $repository->getDisplayName());
55 if (!phutil_console_confirm($prompt)) {
56 throw new PhutilArgumentUsageException(
57 pht('User aborted workflow.'));
61 $commits = id(new DiffusionCommitQuery())
62 ->setViewer($viewer)
63 ->withRepositoryPHIDs(array($repository->getPHID()))
64 ->execute();
66 echo pht("Will unpublish %s commits.\n", count($commits));
68 foreach ($commits as $commit) {
69 $this->unpublishCommit($commit, $is_dry_run);
72 return 0;
75 private function unpublishCommit(
76 PhabricatorRepositoryCommit $commit,
77 $is_dry_run) {
78 $viewer = $this->getViewer();
80 echo tsprintf(
81 "%s\n",
82 pht(
83 'Unpublishing commit "%s".',
84 $commit->getMonogram()));
86 $stories = id(new PhabricatorFeedQuery())
87 ->setViewer($viewer)
88 ->withFilterPHIDs(array($commit->getPHID()))
89 ->execute();
91 if ($stories) {
92 echo tsprintf(
93 "%s\n",
94 pht(
95 'Found %s feed storie(s).',
96 count($stories)));
98 if (!$is_dry_run) {
99 $engine = new PhabricatorDestructionEngine();
100 foreach ($stories as $story) {
101 $story_data = $story->getStoryData();
102 $engine->destroyObject($story_data);
105 echo tsprintf(
106 "%s\n",
107 pht(
108 'Destroyed %s feed storie(s).',
109 count($stories)));
113 $edge_types = array(
114 PhabricatorObjectMentionsObjectEdgeType::EDGECONST => true,
115 DiffusionCommitHasTaskEdgeType::EDGECONST => true,
116 DiffusionCommitHasRevisionEdgeType::EDGECONST => true,
117 DiffusionCommitRevertsCommitEdgeType::EDGECONST => true,
120 $query = id(new PhabricatorEdgeQuery())
121 ->withSourcePHIDs(array($commit->getPHID()))
122 ->withEdgeTypes(array_keys($edge_types));
123 $edges = $query->execute();
125 foreach ($edges[$commit->getPHID()] as $type => $edge_list) {
126 foreach ($edge_list as $edge) {
127 $dst = $edge['dst'];
129 echo tsprintf(
130 "%s\n",
131 pht(
132 'Commit "%s" has edge of type "%s" to object "%s".',
133 $commit->getMonogram(),
134 $type,
135 $dst));
137 $object = id(new PhabricatorObjectQuery())
138 ->setViewer($viewer)
139 ->withPHIDs(array($dst))
140 ->executeOne();
141 if ($object) {
142 if ($object instanceof PhabricatorApplicationTransactionInterface) {
143 $this->unpublishEdgeTransaction(
144 $commit,
145 $type,
146 $object,
147 $is_dry_run);
154 private function unpublishEdgeTransaction(
155 $src,
156 $type,
157 PhabricatorApplicationTransactionInterface $dst,
158 $is_dry_run) {
159 $viewer = $this->getViewer();
161 $query = PhabricatorApplicationTransactionQuery::newQueryForObject($dst)
162 ->setViewer($viewer)
163 ->withObjectPHIDs(array($dst->getPHID()));
165 $xactions = id(clone $query)
166 ->withTransactionTypes(
167 array(
168 PhabricatorTransactions::TYPE_EDGE,
170 ->execute();
172 $type_obj = PhabricatorEdgeType::getByConstant($type);
173 $inverse_type = $type_obj->getInverseEdgeConstant();
175 $engine = new PhabricatorDestructionEngine();
176 foreach ($xactions as $xaction) {
177 $edge_type = $xaction->getMetadataValue('edge:type');
178 if ($edge_type != $inverse_type) {
179 // Some other type of edge was edited.
180 continue;
183 $record = PhabricatorEdgeChangeRecord::newFromTransaction($xaction);
184 $changed = $record->getChangedPHIDs();
185 if ($changed !== array($src->getPHID())) {
186 // Affected objects were not just the object we're unpublishing.
187 continue;
190 echo tsprintf(
191 "%s\n",
192 pht(
193 'Found edge transaction "%s" on object "%s" for type "%s".',
194 $xaction->getPHID(),
195 $dst->getPHID(),
196 $type));
198 if (!$is_dry_run) {
199 $engine->destroyObject($xaction);
201 echo tsprintf(
202 "%s\n",
203 pht(
204 'Destroyed transaction "%s" on object "%s".',
205 $xaction->getPHID(),
206 $dst->getPHID()));
210 if ($type === DiffusionCommitHasTaskEdgeType::EDGECONST) {
211 $xactions = id(clone $query)
212 ->withTransactionTypes(
213 array(
214 ManiphestTaskStatusTransaction::TRANSACTIONTYPE,
216 ->execute();
218 if ($xactions) {
219 foreach ($xactions as $xaction) {
220 $metadata = $xaction->getMetadata();
221 if (idx($metadata, 'commitPHID') === $src->getPHID()) {
222 echo tsprintf(
223 "%s\n",
224 pht(
225 'MANUAL Task "%s" was likely closed improperly by "%s".',
226 $dst->getMonogram(),
227 $src->getMonogram()));
233 if ($type === DiffusionCommitHasRevisionEdgeType::EDGECONST) {
234 $xactions = id(clone $query)
235 ->withTransactionTypes(
236 array(
237 DifferentialRevisionCloseTransaction::TRANSACTIONTYPE,
239 ->execute();
241 if ($xactions) {
242 foreach ($xactions as $xaction) {
243 $metadata = $xaction->getMetadata();
244 if (idx($metadata, 'commitPHID') === $src->getPHID()) {
245 echo tsprintf(
246 "%s\n",
247 pht(
248 'MANUAL Revision "%s" was likely closed improperly by "%s".',
249 $dst->getMonogram(),
250 $src->getMonogram()));
256 if (!$is_dry_run) {
257 id(new PhabricatorEdgeEditor())
258 ->removeEdge($src->getPHID(), $type, $dst->getPHID())
259 ->save();
260 echo tsprintf(
261 "%s\n",
262 pht(
263 'Destroyed edge of type "%s" between "%s" and "%s".',
264 $type,
265 $src->getPHID(),
266 $dst->getPHID()));