Select the types of activity you want to include in your feed.
@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
···11+<?php
22+33+abstract class DifferentialHarbormasterField
44+ extends DifferentialCustomField {
55+66+ abstract protected function getDiffPropertyKeys();
77+ abstract protected function loadHarbormasterTargetMessages(
88+ array $target_phids);
99+ abstract protected function getLegacyProperty();
1010+ abstract protected function newModernMessage(array $message);
1111+ abstract protected function renderHarbormasterStatus(
1212+ DifferentialDiff $diff,
1313+ array $messages);
1414+ abstract protected function newHarbormasterMessageView(array $messages);
1515+1616+ public function renderDiffPropertyViewValue(DifferentialDiff $diff) {
1717+ // TODO: This load is slightly inefficient, but most of this is moving
1818+ // to Harbormaster and this simplifies the transition. Eat 1-2 extra
1919+ // queries for now.
2020+ $keys = $this->getDiffPropertyKeys();
2121+2222+ $properties = id(new DifferentialDiffProperty())->loadAllWhere(
2323+ 'diffID = %d AND name IN (%Ls)',
2424+ $diff->getID(),
2525+ $keys);
2626+ $properties = mpull($properties, 'getData', 'getName');
2727+2828+ foreach ($keys as $key) {
2929+ $diff->attachProperty($key, idx($properties, $key));
3030+ }
3131+3232+ $messages = array();
3333+3434+ $buildable = $diff->getBuildable();
3535+ if ($buildable) {
3636+ $target_phids = array();
3737+ foreach ($buildable->getBuilds() as $build) {
3838+ foreach ($build->getBuildTargets() as $target) {
3939+ $target_phids[] = $target->getPHID();
4040+ }
4141+ }
4242+4343+ if ($target_phids) {
4444+ $messages = $this->loadHarbormasterTargetMessages($target_phids);
4545+ }
4646+ }
4747+4848+ if (!$messages) {
4949+ // No Harbormaster messages, so look for legacy messages and make them
5050+ // look like modern messages.
5151+ $legacy_messages = $diff->getProperty($this->getLegacyProperty());
5252+ if ($legacy_messages) {
5353+ // Show the top 100 legacy lint messages. Previously, we showed some
5454+ // by default and let the user toggle the rest. With modern messages,
5555+ // we can send the user to the Harbormaster detail page. Just show
5656+ // "a lot" of messages in legacy cases to try to strike a balance
5757+ // between implementation simplicitly and compatibility.
5858+ $legacy_messages = array_slice($legacy_messages, 0, 100);
5959+6060+ foreach ($legacy_messages as $message) {
6161+ try {
6262+ $modern = $this->newModernMessage($message);
6363+ $messages[] = $modern;
6464+ } catch (Exception $ex) {
6565+ // Ignore any poorly formatted messages.
6666+ }
6767+ }
6868+ }
6969+ }
7070+7171+ $status = $this->renderHarbormasterStatus($diff, $messages);
7272+7373+ if ($messages) {
7474+ $path_map = mpull($diff->loadChangesets(), 'getID', 'getFilename');
7575+ foreach ($path_map as $path => $id) {
7676+ $href = '#C'.$id.'NL';
7777+7878+ // TODO: When the diff is not the right-hand-size diff, we should
7979+ // ideally adjust this URI to be absolute.
8080+8181+ $path_map[$path] = $href;
8282+ }
8383+8484+ $view = $this->newHarbormasterMessageView($messages);
8585+ if ($view) {
8686+ $view->setPathURIMap($path_map);
8787+ }
8888+ } else {
8989+ $view = null;
9090+ }
9191+9292+ if ($view) {
9393+ $view = phutil_tag(
9494+ 'div',
9595+ array(
9696+ 'class' => 'differential-harbormaster-table-view',
9797+ ),
9898+ $view);
9999+ }
100100+101101+ return array(
102102+ $status,
103103+ $view,
104104+ );
105105+ }
106106+107107+}
···11+<?php
22+33+abstract class PhabricatorWorkerBulkJobType extends Phobject {
44+55+ abstract public function getJobName(PhabricatorWorkerBulkJob $job);
66+ abstract public function getBulkJobTypeKey();
77+ abstract public function getJobSize(PhabricatorWorkerBulkJob $job);
88+ abstract public function getDescriptionForConfirm(
99+ PhabricatorWorkerBulkJob $job);
1010+1111+ abstract public function createTasks(PhabricatorWorkerBulkJob $job);
1212+ abstract public function runTask(
1313+ PhabricatorUser $actor,
1414+ PhabricatorWorkerBulkJob $job,
1515+ PhabricatorWorkerBulkTask $task);
1616+1717+ public function getDoneURI(PhabricatorWorkerBulkJob $job) {
1818+ return $job->getManageURI();
1919+ }
2020+2121+ final public static function getAllJobTypes() {
2222+ return id(new PhutilClassMapQuery())
2323+ ->setAncestorClass(__CLASS__)
2424+ ->setUniqueMethod('getBulkJobTypeKey')
2525+ ->execute();
2626+ }
2727+2828+}
···11+<?php
22+33+final class PhabricatorWorkerBulkJobTransactionQuery
44+ extends PhabricatorApplicationTransactionQuery {
55+66+ public function getTemplateApplicationTransaction() {
77+ return new PhabricatorWorkerBulkJobTransaction();
88+ }
99+1010+}
···11+/**
22+ * @provides javelin-behavior-bulk-job-reload
33+ * @requires javelin-behavior
44+ * javelin-uri
55+ */
66+77+JX.behavior('bulk-job-reload', function() {
88+99+ // TODO: It would be nice to have a pretty Ajax progress bar here, but just
1010+ // reload the page for now.
1111+1212+ function reload() {
1313+ JX.$U().go();
1414+ }
1515+1616+ setTimeout(reload, 1000);
1717+1818+});