@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
fork

Configure Feed

Select the types of activity you want to include in your feed.

When Phabricator is in read-only mode, explain why

Summary:
Ref T4571. Allows users to click the "read-only mode" notification to get more information about why an install is in read-only mode.

Installs can be in this mode for several reasons (explicit administrative action, no masters defined, no masters reachable), and it's useful to be able to tell the difference.

Test Plan: {F1212930}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T4571

Differential Revision: https://secure.phabricator.com/D15671

+103 -14
+8 -8
resources/celerity/map.php
··· 8 8 return array( 9 9 'names' => array( 10 10 'core.pkg.css' => '35e4a99a', 11 - 'core.pkg.js' => '8a616602', 11 + 'core.pkg.js' => '08b41036', 12 12 'darkconsole.pkg.js' => 'e7393ebb', 13 13 'differential.pkg.css' => '7ba78475', 14 14 'differential.pkg.js' => 'd0cd0df6', ··· 494 494 'rsrc/js/core/behavior-oncopy.js' => '2926fff2', 495 495 'rsrc/js/core/behavior-phabricator-nav.js' => '56a1ca03', 496 496 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '340c8eff', 497 - 'rsrc/js/core/behavior-read-only-warning.js' => 'f8ea359c', 497 + 'rsrc/js/core/behavior-read-only-warning.js' => 'ba158207', 498 498 'rsrc/js/core/behavior-refresh-csrf.js' => 'ab2f381b', 499 499 'rsrc/js/core/behavior-remarkup-preview.js' => '4b700e9e', 500 500 'rsrc/js/core/behavior-reorder-applications.js' => '76b9fc3e', ··· 667 667 'javelin-behavior-project-boards' => '14a1faae', 668 668 'javelin-behavior-project-create' => '065227cc', 669 669 'javelin-behavior-quicksand-blacklist' => '7927a7d3', 670 - 'javelin-behavior-read-only-warning' => 'f8ea359c', 670 + 'javelin-behavior-read-only-warning' => 'ba158207', 671 671 'javelin-behavior-recurring-edit' => '5f1c4d5f', 672 672 'javelin-behavior-refresh-csrf' => 'ab2f381b', 673 673 'javelin-behavior-releeph-preview-branch' => 'b2b4fbaf', ··· 1783 1783 'javelin-json', 1784 1784 'phabricator-draggable-list', 1785 1785 ), 1786 + 'ba158207' => array( 1787 + 'javelin-behavior', 1788 + 'javelin-uri', 1789 + 'phabricator-notification', 1790 + ), 1786 1791 'bae58312' => array( 1787 1792 'javelin-install', 1788 1793 'javelin-workboard-card', ··· 2110 2115 'javelin-mask', 2111 2116 'javelin-util', 2112 2117 'phabricator-busy', 2113 - ), 2114 - 'f8ea359c' => array( 2115 - 'javelin-behavior', 2116 - 'javelin-uri', 2117 - 'phabricator-notification', 2118 2118 ), 2119 2119 'fa0f4fc2' => array( 2120 2120 'javelin-behavior',
+2
src/__phutil_library_map__.php
··· 3425 3425 'PhabricatorSystemDAO' => 'applications/system/storage/PhabricatorSystemDAO.php', 3426 3426 'PhabricatorSystemDestructionGarbageCollector' => 'applications/system/garbagecollector/PhabricatorSystemDestructionGarbageCollector.php', 3427 3427 'PhabricatorSystemDestructionLog' => 'applications/system/storage/PhabricatorSystemDestructionLog.php', 3428 + 'PhabricatorSystemReadOnlyController' => 'applications/system/controller/PhabricatorSystemReadOnlyController.php', 3428 3429 'PhabricatorSystemRemoveDestroyWorkflow' => 'applications/system/management/PhabricatorSystemRemoveDestroyWorkflow.php', 3429 3430 'PhabricatorSystemRemoveLogWorkflow' => 'applications/system/management/PhabricatorSystemRemoveLogWorkflow.php', 3430 3431 'PhabricatorSystemRemoveWorkflow' => 'applications/system/management/PhabricatorSystemRemoveWorkflow.php', ··· 8076 8077 'PhabricatorSystemDAO' => 'PhabricatorLiskDAO', 8077 8078 'PhabricatorSystemDestructionGarbageCollector' => 'PhabricatorGarbageCollector', 8078 8079 'PhabricatorSystemDestructionLog' => 'PhabricatorSystemDAO', 8080 + 'PhabricatorSystemReadOnlyController' => 'PhabricatorController', 8079 8081 'PhabricatorSystemRemoveDestroyWorkflow' => 'PhabricatorSystemRemoveWorkflow', 8080 8082 'PhabricatorSystemRemoveLogWorkflow' => 'PhabricatorSystemRemoveWorkflow', 8081 8083 'PhabricatorSystemRemoveWorkflow' => 'PhabricatorManagementWorkflow',
+3
src/applications/system/application/PhabricatorSystemApplication.php
··· 23 23 'encoding/' => 'PhabricatorSystemSelectEncodingController', 24 24 'highlight/' => 'PhabricatorSystemSelectHighlightController', 25 25 ), 26 + '/readonly/' => array( 27 + '(?P<reason>[^/]+)/' => 'PhabricatorSystemReadOnlyController', 28 + ), 26 29 ); 27 30 } 28 31
+50
src/applications/system/controller/PhabricatorSystemReadOnlyController.php
··· 1 + <?php 2 + 3 + final class PhabricatorSystemReadOnlyController 4 + extends PhabricatorController { 5 + 6 + public function shouldRequireLogin() { 7 + return false; 8 + } 9 + 10 + public function handleRequest(AphrontRequest $request) { 11 + $reason = $request->getURIData('reason'); 12 + 13 + $body = array(); 14 + switch ($reason) { 15 + case PhabricatorEnv::READONLY_CONFIG: 16 + $title = pht('Administrative Read-Only Mode'); 17 + $body[] = pht( 18 + 'An administrator has placed Phabricator into read-only mode.'); 19 + $body[] = pht( 20 + 'This mode may be used to perform temporary maintenance, test '. 21 + 'configuration, or archive an installation permanently.'); 22 + $body[] = pht( 23 + 'Read-only mode was enabled by the explicit action of a human '. 24 + 'administrator, so you can get more information about why it '. 25 + 'has been turned on by rolling your chair away from your desk and '. 26 + 'yelling "Hey! Why is Phabricator in read-only mode??!" using '. 27 + 'your very loudest outside voice.'); 28 + $button = pht('Wait Patiently'); 29 + break; 30 + default: 31 + return new Aphront404Response(); 32 + } 33 + 34 + $body[] = pht( 35 + 'In read-only mode you can read existing information, but you will not '. 36 + 'be able to edit information or create new information until this mode '. 37 + 'is disabled.'); 38 + 39 + $dialog = $this->newDialog() 40 + ->setTitle($title) 41 + ->setWidth(AphrontDialogView::WIDTH_FORM) 42 + ->addCancelButton('/', $button); 43 + 44 + foreach ($body as $paragraph) { 45 + $dialog->appendParagraph($paragraph); 46 + } 47 + 48 + return $dialog; 49 + } 50 + }
+27 -1
src/infrastructure/env/PhabricatorEnv.php
··· 57 57 private static $cache; 58 58 private static $localeCode; 59 59 private static $readOnly; 60 + private static $readOnlyReason; 61 + 62 + const READONLY_CONFIG = 'config'; 60 63 61 64 /** 62 65 * @phutil-external-symbol class PhabricatorStartup ··· 447 450 return self::getEnvConfig('cluster.read-only'); 448 451 } 449 452 450 - public static function setReadOnly($read_only) { 453 + public static function setReadOnly($read_only, $reason) { 451 454 self::$readOnly = $read_only; 455 + self::$readOnlyReason = $reason; 456 + } 457 + 458 + public static function getReadOnlyMessage() { 459 + return pht('Phabricator is currently in read-only mode.'); 460 + } 461 + 462 + public static function getReadOnlyURI() { 463 + return urisprintf( 464 + '/readonly/%s/', 465 + self::getReadOnlyReason()); 466 + } 467 + 468 + public static function getReadOnlyReason() { 469 + if (!self::isReadOnly()) { 470 + return null; 471 + } 472 + 473 + if (self::$readOnlyReason !== null) { 474 + return self::$readOnlyReason; 475 + } 476 + 477 + return self::READONLY_CONFIG; 452 478 } 453 479 454 480
+1 -1
src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php
··· 52 52 53 53 if (PhabricatorEnv::isReadOnly()) { 54 54 if ($this->isForce()) { 55 - PhabricatorEnv::setReadOnly(false); 55 + PhabricatorEnv::setReadOnly(false, null); 56 56 } else { 57 57 throw new PhutilArgumentUsageException( 58 58 pht(
+2 -1
src/view/page/PhabricatorStandardPageView.php
··· 276 276 Javelin::initBehavior( 277 277 'read-only-warning', 278 278 array( 279 - 'message' => pht('Phabricator is currently in read-only mode.'), 279 + 'message' => PhabricatorEnv::getReadOnlyMessage(), 280 + 'uri' => PhabricatorEnv::getReadOnlyURI(), 280 281 )); 281 282 } 282 283
+10 -3
webroot/rsrc/js/core/behavior-read-only-warning.js
··· 7 7 8 8 JX.behavior('read-only-warning', function(config) { 9 9 10 - new JX.Notification() 10 + var n = new JX.Notification() 11 11 .setContent(config.message) 12 12 .setDuration(0) 13 - .alterClassName('jx-notification-read-only', true) 14 - .show(); 13 + .alterClassName('jx-notification-read-only', true); 14 + 15 + n.listen( 16 + 'activate', 17 + function() { 18 + JX.$U(config.uri).go(); 19 + }); 20 + 21 + n.show(); 15 22 16 23 });