diff --git a/src/applications/config/option/PhabricatorCoreConfigOptions.php b/src/applications/config/option/PhabricatorCoreConfigOptions.php index 77c48115a4..e8ccf5e093 100644 --- a/src/applications/config/option/PhabricatorCoreConfigOptions.php +++ b/src/applications/config/option/PhabricatorCoreConfigOptions.php @@ -1,335 +1,336 @@ deformat(pht(<<deformat(pht(<<newOption('phabricator.base-uri', 'string', null) ->setLocked(true) - ->setSummary(pht('URI where Phabricator is installed.')) + ->setSummary(pht('URI where this software is installed.')) ->setDescription( pht( - 'Set the URI where Phabricator is installed. Setting this '. + 'Set the URI where this software is installed. Setting this '. 'improves security by preventing cookies from being set on other '. 'domains, and allows daemons to send emails with links that have '. 'the correct domain.')) - ->addExample('http://phabricator.example.com/', pht('Valid Setting')), + ->addExample('http://devtools.example.com/', pht('Valid Setting')), $this->newOption('phabricator.production-uri', 'string', null) ->setSummary( pht('Primary install URI, for multi-environment installs.')) ->setDescription( pht( - 'If you have multiple Phabricator environments (like a '. + 'If you have multiple %s environments (like a '. 'development/staging environment for working on testing '. 'Phabricator, and a production environment for deploying it), '. 'set the production environment URI here so that emails and other '. 'durable URIs will always generate with links pointing at the '. 'production environment. If unset, defaults to `%s`. Most '. 'installs do not need to set this option.', + PlatformSymbols::getPlatformServerName(), 'phabricator.base-uri')) - ->addExample('http://phabricator.example.com/', pht('Valid Setting')), + ->addExample('http://devtools.example.com/', pht('Valid Setting')), $this->newOption('phabricator.allowed-uris', 'list', array()) ->setLocked(true) - ->setSummary(pht('Alternative URIs that can access Phabricator.')) + ->setSummary(pht('Alternative URIs that can access this service.')) ->setDescription( pht( "These alternative URIs will be able to access 'normal' pages ". - "on your Phabricator install. Other features such as OAuth ". + "on your this install. Other features such as OAuth ". "won't work. The major use case for this is moving installs ". "across domains.")) ->addExample( "http://phabricator2.example.com/\n". "http://phabricator3.example.com/", pht('Valid Setting')), $this->newOption('phabricator.timezone', 'string', null) ->setSummary( - pht('The timezone Phabricator should use.')) + pht('The timezone this software should use by default.')) ->setDescription($timezone_description) ->addExample('America/New_York', pht('US East (EDT)')) ->addExample('America/Chicago', pht('US Central (CDT)')) ->addExample('America/Boise', pht('US Mountain (MDT)')) ->addExample('America/Los_Angeles', pht('US West (PDT)')), $this->newOption('phabricator.cookie-prefix', 'string', null) ->setLocked(true) ->setSummary( pht( - 'Set a string Phabricator should use to prefix cookie names.')) + 'Set a string this software should use to prefix cookie names.')) ->setDescription( pht( 'Cookies set for x.com are also sent for y.x.com. Assuming '. - 'Phabricator instances are running on both domains, this will '. - 'create a collision preventing you from logging in.')) + 'instances are running on both domains, this will create a '. + 'collision preventing you from logging in.')) ->addExample('dev', pht('Prefix cookie with "%s"', 'dev')), $this->newOption('phabricator.show-prototypes', 'bool', false) ->setLocked(true) ->setBoolOptions( array( pht('Enable Prototypes'), pht('Disable Prototypes'), )) ->setSummary( pht( 'Install applications which are still under development.')) ->setDescription( pht( "IMPORTANT: The upstream does not provide support for prototype ". "applications.". "\n\n". - "Phabricator includes prototype applications which are in an ". + "This platform includes prototype applications which are in an ". "**early stage of development**. By default, prototype ". "applications are not installed, because they are often not yet ". "developed enough to be generally usable. You can enable ". - "this option to install them if you're developing Phabricator ". + "this option to install them if you're developing applications ". "or are interested in previewing upcoming features.". "\n\n". "To learn more about prototypes, see [[ %s | %s ]].". "\n\n". "After enabling prototypes, you can selectively uninstall them ". "(like normal applications).", $proto_doc_href, $proto_doc_name)), $this->newOption('phabricator.serious-business', 'bool', false) ->setBoolOptions( array( pht('Serious business'), pht('Shenanigans'), // That should be interesting to translate. :P )) ->setSummary( pht('Allows you to remove levity and jokes from the UI.')) ->setDescription( pht( - 'By default, Phabricator includes some flavor text in the UI, '. + 'By default, this software includes some flavor text in the UI, '. 'like a prompt to "Weigh In" rather than "Add Comment" in '. 'Maniphest. If you\'d prefer more traditional UI strings like '. '"Add Comment", you can set this flag to disable most of the '. 'extra flavor.')), $this->newOption( 'remarkup.ignored-object-names', 'string', // Q1, Q2, etc., are common abbreviations for "Quarter". // V1, V2, etc., are common abbreviations for "Version". // P1, P2, etc., are common abbreviations for "Priority". // M1 is a computer chip manufactured by Apple. // M2 (commonly spelled "M.2") is an expansion slot on motherboards. // M4 is a carbine. // M8 is a phonetic spelling of "mate", used in culturally significant // copypasta about navy seals. '/^(Q|V|M|P)\d$/') ->setSummary( pht('Text values that match this regex and are also object names '. 'will not be linked.')) ->setDescription( pht( - 'By default, Phabricator links object names in Remarkup fields '. + 'By default, this software links object names in Remarkup fields '. 'to the corresponding object. This regex can be used to modify '. 'this behavior; object names that match this regex will not be '. 'linked.')), $this->newOption('environment.append-paths', 'list', $paths) ->setSummary( pht( 'These paths get appended to your %s environment variable.', '$PATH')) ->setDescription( pht( - "Phabricator occasionally shells out to other binaries on the ". + "Thhi software sometimes executes other binaries on the ". "server. An example of this is the `%s` command, used to ". "syntax-highlight code written in languages other than PHP. By ". "default, it is assumed that these binaries are in the %s of the ". - "user running Phabricator (normally 'apache', 'httpd', or ". + "user running this software (normally 'apache', 'httpd', or ". "'nobody'). Here you can add extra directories to the %s ". "environment variable, for when these binaries are in ". "non-standard locations.\n\n". "Note that you can also put binaries in `%s` (for example, by ". "symlinking them).\n\n". "The current value of PATH after configuration is applied is:\n\n". " lang=text\n". " %s", 'pygmentize', '$PATH', '$PATH', - 'phabricator/support/bin/', + 'support/bin/', $path)) ->setLocked(true) ->addExample('/usr/local/bin', pht('Add One Path')) ->addExample("/usr/bin\n/usr/local/bin", pht('Add Multiple Paths')), $this->newOption('config.lock', 'set', array()) ->setLocked(true) ->setDescription(pht('Additional configuration options to lock.')), $this->newOption('config.hide', 'set', array()) ->setLocked(true) ->setDescription(pht('Additional configuration options to hide.')), $this->newOption('config.ignore-issues', 'set', array()) ->setLocked(true) ->setDescription(pht('Setup issues to ignore.')), $this->newOption('phabricator.env', 'string', null) ->setLocked(true) ->setDescription(pht('Internal.')), $this->newOption('test.value', 'wild', null) ->setLocked(true) ->setDescription(pht('Unit test value.')), $this->newOption('phabricator.uninstalled-applications', 'set', array()) ->setLocked(true) ->setLockedMessage(pht( 'Use the %s to manage installed applications.', phutil_tag( 'a', array( 'href' => $applications_app_href, ), pht('Applications application')))) ->setDescription( pht('Array containing list of uninstalled applications.')), $this->newOption('phabricator.application-settings', 'wild', array()) ->setLocked(true) ->setDescription( pht('Customized settings for Phabricator applications.')), $this->newOption('phabricator.cache-namespace', 'string', 'phabricator') ->setLocked(true) ->setDescription(pht('Cache namespace.')), $this->newOption('phabricator.silent', 'bool', false) ->setLocked(true) ->setBoolOptions( array( pht('Run Silently'), pht('Run Normally'), )) - ->setSummary(pht('Stop Phabricator from sending any email, etc.')) + ->setSummary(pht('Stop this software from sending any email, etc.')) ->setDescription($silent_description), ); } protected function didValidateOption( PhabricatorConfigOption $option, $value) { $key = $option->getKey(); if ($key == 'phabricator.base-uri' || $key == 'phabricator.production-uri') { $uri = new PhutilURI($value); $protocol = $uri->getProtocol(); if ($protocol !== 'http' && $protocol !== 'https') { throw new PhabricatorConfigValidationException( pht( 'Config option "%s" is invalid. The URI must start with '. '"%s" or "%s".', $key, 'http://', 'https://')); } $domain = $uri->getDomain(); if (strpos($domain, '.') === false) { throw new PhabricatorConfigValidationException( pht( 'Config option "%s" is invalid. The URI must contain a dot '. '("%s"), like "%s", not just a bare name like "%s". Some web '. 'browsers will not set cookies on domains with no TLD.', $key, '.', 'http://example.com/', 'http://example/')); } $path = $uri->getPath(); if ($path !== '' && $path !== '/') { throw new PhabricatorConfigValidationException( pht( "Config option '%s' is invalid. The URI must NOT have a path, ". - "e.g. '%s' is OK, but '%s' is not. Phabricator must be installed ". - "on an entire domain; it can not be installed on a path.", + "e.g. '%s' is OK, but '%s' is not. This software must be '. + 'installed on an entire domain; it can not be installed on a path.", $key, - 'http://phabricator.example.com/', - 'http://example.com/phabricator/')); + 'http://devtools.example.com/', + 'http://example.com/devtools/')); } } if ($key === 'phabricator.timezone') { $old = date_default_timezone_get(); $ok = @date_default_timezone_set($value); @date_default_timezone_set($old); if (!$ok) { throw new PhabricatorConfigValidationException( pht( 'Config option "%s" is invalid. The timezone identifier must '. 'be a valid timezone identifier recognized by PHP, like "%s".', $key, 'America/Los_Angeles')); } } } } diff --git a/src/applications/config/option/PhabricatorDeveloperConfigOptions.php b/src/applications/config/option/PhabricatorDeveloperConfigOptions.php index f4b8e8b157..cd09717bc7 100644 --- a/src/applications/config/option/PhabricatorDeveloperConfigOptions.php +++ b/src/applications/config/option/PhabricatorDeveloperConfigOptions.php @@ -1,157 +1,158 @@ newOption('darkconsole.enabled', 'bool', false) ->setBoolOptions( array( pht('Enable DarkConsole'), pht('Disable DarkConsole'), )) - ->setSummary(pht("Enable Phabricator's debugging console.")) + ->setSummary(pht('Enable the debugging console.')) ->setDescription( pht( "DarkConsole is a development and profiling tool built into ". - "Phabricator's web interface. You should leave it disabled unless ". - "you are developing or debugging Phabricator.\n\n". + "the web interface. You should leave it disabled unless ". + "you are developing or debugging %s.\n\n". "Once you activate DarkConsole for the install, **you need to ". "enable it for your account before it will actually appear on ". "pages.** You can do this in Settings > Developer Settings.\n\n". "DarkConsole exposes potentially sensitive data (like queries, ". "stack traces, and configuration) so you generally should not ". - "turn it on in production.")), + "turn it on in production.", + PlatformSymbols::getPlatformServerName())), $this->newOption('darkconsole.always-on', 'bool', false) ->setBoolOptions( array( pht('Always Activate DarkConsole'), pht('Require DarkConsole Activation'), )) ->setSummary(pht('Activate DarkConsole on every page.')) ->setDescription( pht( "This option allows you to enable DarkConsole on every page, ". "even for logged-out users. This is only really useful if you ". "need to debug something on a logged-out page. You should not ". "enable this option in production.\n\n". "You must enable DarkConsole by setting '%s' ". "before this option will have any effect.", 'darkconsole.enabled')), $this->newOption('debug.time-limit', 'int', null) ->setSummary( pht( 'Limit page execution time to debug hangs.')) ->setDescription( pht( "This option can help debug pages which are taking a very ". "long time (more than 30 seconds) to render.\n\n". "If a page is slow to render (but taking less than 30 seconds), ". "the best tools to use to figure out why it is slow are usually ". "the DarkConsole service call profiler and XHProf.\n\n". "However, if a request takes a very long time to return, some ". "components (like Apache, nginx, or PHP itself) may abort the ". "request before it finishes. This can prevent you from using ". "profiling tools to understand page performance in detail.\n\n". "In these cases, you can use this option to force the page to ". "abort after a smaller number of seconds (for example, 10), and ". "dump a useful stack trace. This can provide useful information ". "about why a page is hanging.\n\n". "To use this option, set it to a small number (like 10), and ". "reload a hanging page. The page should exit after 10 seconds ". "and give you a stack trace.\n\n". "You should turn this option off (set it to 0) when you are ". "done with it. Leaving it on creates a small amount of overhead ". "for all requests, even if they do not hit the time limit.")), $this->newOption('debug.stop-on-redirect', 'bool', false) ->setBoolOptions( array( pht('Stop Before HTTP Redirect'), pht('Use Normal HTTP Redirects'), )) ->setSummary( pht( 'Confirm before redirecting so DarkConsole can be examined.')) ->setDescription( pht( - 'Normally, Phabricator issues HTTP redirects after a successful '. + 'Normally, this software issues HTTP redirects after a successful '. 'POST. This can make it difficult to debug things which happen '. 'while processing the POST, because service and profiling '. 'information are lost. By setting this configuration option, '. - 'Phabricator will show a page instead of automatically '. + 'an interstitial page will be shown instead of automatically '. 'redirecting, allowing you to examine service and profiling '. 'information. It also makes the UX awful, so you should only '. 'enable it when debugging.')), $this->newOption('debug.profile-rate', 'int', 0) ->addExample(0, pht('No profiling')) ->addExample(1, pht('Profile every request (slow)')) ->addExample(1000, pht('Profile 0.1%% of all requests')) ->setSummary(pht('Automatically profile some percentage of pages.')) ->setDescription( pht( - "Normally, Phabricator profiles pages only when explicitly ". + "Normally, pages are profiled only when explicitly ". "requested via DarkConsole. However, it may be useful to profile ". "some pages automatically.\n\n". "Set this option to a positive integer N to profile 1 / N pages ". "automatically. For example, setting it to 1 will profile every ". "page, while setting it to 1000 will profile 1 page per 1000 ". "requests (i.e., 0.1%% of requests).\n\n". "Since profiling is slow and generates a lot of data, you should ". "set this to 0 in production (to disable it) or to a large number ". "(to collect a few samples, if you're interested in having some ". "data to look at eventually). In development, it may be useful to ". "set it to 1 in order to debug performance problems.\n\n". "NOTE: You must install XHProf for profiling to work.")), $this->newOption('debug.sample-rate', 'int', 1000) ->setLocked(true) ->addExample(0, pht('No performance sampling.')) ->addExample(1, pht('Sample every request (slow).')) ->addExample(1000, pht('Sample 0.1%% of requests.')) ->setSummary(pht('Automatically sample some fraction of requests.')) ->setDescription( pht( "The Multimeter application collects performance samples. You ". - "can use this data to help you understand what Phabricator is ". + "can use this data to help you understand what the software is ". "spending time and resources doing, and to identify problematic ". "access patterns.". "\n\n". "This option controls how frequently sampling activates. Set it ". "to some positive integer N to sample every 1 / N pages.". "\n\n". "For most installs, the default value (1 sample per 1000 pages) ". "should collect enough data to be useful without requiring much ". "storage or meaningfully impacting performance. If you're ". "investigating performance issues, you can adjust the rate ". "in order to collect more data.")), $this->newOption('phabricator.developer-mode', 'bool', false) ->setBoolOptions( array( pht('Enable developer mode'), pht('Disable developer mode'), )) ->setSummary(pht('Enable verbose error reporting and disk reads.')) ->setDescription( pht( 'This option enables verbose error reporting (stack traces, '. 'error callouts) and forces disk reads of static assets on '. 'every reload.')), ); } } diff --git a/src/applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php b/src/applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php index 0a3ea32e44..b4ecb4bdc1 100644 --- a/src/applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php +++ b/src/applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php @@ -1,42 +1,42 @@ newOption('load-libraries', 'list', array()) ->setLocked(true) ->setSummary(pht('Paths to additional phutil libraries to load.')) ->addExample('/srv/our-libs/sekrit-phutil', pht('Valid Setting')), $this->newOption('events.listeners', 'list', array()) ->setLocked(true) ->setSummary( pht('Listeners receive callbacks when interesting things occur.')) ->setDescription( pht( 'You can respond to various application events by installing '. 'listeners, which will receive callbacks when interesting things '. 'occur. Specify a list of classes which extend '. 'PhabricatorEventListener here.')) ->addExample('MyEventListener', pht('Valid Setting')), ); } } diff --git a/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php b/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php index 7e6978dfd8..cca8794055 100644 --- a/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php +++ b/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php @@ -1,309 +1,311 @@ deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<' - `real`: 'George Washington ' - `full`: 'gwashington (George Washington) ' The default is `full`. EODOC )); $mailers_description = $this->deformat(pht(<<deformat(pht(<<newOption('cluster.mailers', 'cluster.mailers', array()) ->setHidden(true) ->setDescription($mailers_description), $this->newOption('metamta.default-address', 'string', null) ->setLocked(true) ->setSummary(pht('Default address used when generating mail.')) ->setDescription($default_description), $this->newOption( 'metamta.one-mail-per-recipient', 'bool', true) ->setLocked(true) ->setBoolOptions( array( pht('Send Mail To Each Recipient'), pht('Send Mail To All Recipients'), )) ->setSummary( pht( - 'Controls whether Phabricator sends one email with multiple '. - 'recipients in the "To:" line, or multiple emails, each with a '. - 'single recipient in the "To:" line.')) + 'Controls whether email for multiple recipients is sent by '. + 'creating one message with everyone in the "To:" line, or '. + 'multiple messages that each have a single recipeint in the '. + '"To:" line.')) ->setDescription($one_mail_per_recipient_desc), $this->newOption('metamta.can-send-as-user', 'bool', false) ->setBoolOptions( array( pht('Send as User Taking Action'), - pht('Send as Phabricator'), + pht( + 'Send as %s', + PlatformSymbols::getPlatformServerName()), )) ->setSummary( pht( - 'Controls whether Phabricator sends email "From" users.')) + 'Controls whether email is sent "From" users.')) ->setDescription($send_as_user_desc), $this->newOption( 'metamta.reply-handler-domain', 'string', null) ->setLocked(true) ->setDescription(pht('Domain used for reply email addresses.')) - ->addExample('phabricator.example.com', ''), + ->addExample('devtools.example.com', ''), $this->newOption('metamta.recipients.show-hints', 'bool', true) ->setBoolOptions( array( pht('Show Recipient Hints'), pht('No Recipient Hints'), )) ->setSummary(pht('Show "To:" and "Cc:" footer hints in email.')) ->setDescription($recipient_hints_description), $this->newOption('metamta.email-preferences', 'bool', true) ->setBoolOptions( array( pht('Show Email Preferences Link'), pht('No Email Preferences Link'), )) ->setSummary(pht('Show email preferences link in email.')) ->setDescription($email_preferences_description), $this->newOption('metamta.public-replies', 'bool', false) ->setBoolOptions( array( pht('Use Public Replies (Less Secure)'), pht('Use Private Replies (More Secure)'), )) ->setSummary( pht( - 'Phabricator can use less-secure but mailing list friendly public '. - 'reply addresses.')) + 'Reply addresses can either be private (more secure) or '. + 'public (which works better with mailing lists).')) ->setDescription($public_replies_description), $this->newOption('metamta.single-reply-handler-prefix', 'string', null) ->setSummary( - pht('Allow Phabricator to use a single mailbox for all replies.')) + pht('Allow a single mailbox to be used for all replies.')) ->setDescription($single_description), $this->newOption('metamta.user-address-format', 'enum', 'full') ->setEnumOptions( array( 'short' => pht('Short'), 'real' => pht('Real'), 'full' => pht('Full'), )) - ->setSummary(pht('Control how Phabricator renders user names in mail.')) + ->setSummary(pht('Control how user names are rendered in mail.')) ->setDescription($address_description) ->addExample('gwashington ', 'short') ->addExample('George Washington ', 'real') ->addExample( 'gwashington (George Washington) ', 'full'), $this->newOption('metamta.email-body-limit', 'int', 524288) ->setDescription( pht( 'You can set a limit for the maximum byte size of outbound mail. '. 'Mail which is larger than this limit will be truncated before '. 'being sent. This can be useful if your MTA rejects mail which '. 'exceeds some limit (this is reasonably common). Specify a value '. 'in bytes.')) ->setSummary(pht('Global cap for size of generated emails (bytes).')) ->addExample(524288, pht('Truncate at 512KB')) ->addExample(1048576, pht('Truncate at 1MB')), ); } } diff --git a/src/applications/config/option/PhabricatorMySQLConfigOptions.php b/src/applications/config/option/PhabricatorMySQLConfigOptions.php index 97ae6af016..7b472cf379 100644 --- a/src/applications/config/option/PhabricatorMySQLConfigOptions.php +++ b/src/applications/config/option/PhabricatorMySQLConfigOptions.php @@ -1,57 +1,57 @@ newOption('mysql.host', 'string', 'localhost') ->setLocked(true) ->setDescription( pht('MySQL database hostname.')) ->addExample('localhost', pht('MySQL on this machine')) ->addExample('db.example.com:3300', pht('Nonstandard port')), $this->newOption('mysql.user', 'string', 'root') ->setLocked(true) ->setDescription( pht('MySQL username to use when connecting to the database.')), $this->newOption('mysql.pass', 'string', null) ->setHidden(true) ->setDescription( pht('MySQL password to use when connecting to the database.')), $this->newOption('storage.default-namespace', 'string', 'phabricator') ->setLocked(true) ->setSummary( - pht('The namespace that Phabricator databases should use.')) + pht('The namespace that databases should use.')) ->setDescription( pht( - "Phabricator puts databases in a namespace, which defaults to ". + "Databases are created in a namespace, which defaults to ". "'phabricator' -- for instance, the Differential database is ". "named 'phabricator_differential' by default. You can change ". "this namespace if you want. Normally, you should not do this ". - "unless you are developing Phabricator and using namespaces to ". + "unless you are developing extensions and using namespaces to ". "separate multiple sandbox datasets.")), $this->newOption('mysql.port', 'string', null) ->setLocked(true) ->setDescription( pht('MySQL port to use when connecting to the database.')), ); } } diff --git a/src/applications/config/option/PhabricatorSecurityConfigOptions.php b/src/applications/config/option/PhabricatorSecurityConfigOptions.php index 3438d3bd67..c57bd2ad87 100644 --- a/src/applications/config/option/PhabricatorSecurityConfigOptions.php +++ b/src/applications/config/option/PhabricatorSecurityConfigOptions.php @@ -1,339 +1,337 @@ deformat(pht(<<deformat(pht(<<newOption('security.alternate-file-domain', 'string', null) ->setLocked(true) ->setSummary(pht('Alternate domain to serve files from.')) ->setDescription( pht( - 'By default, Phabricator serves files from the same domain '. + 'By default, this software serves files from the same domain '. 'the application is served from. This is convenient, but '. 'presents a security risk.'. "\n\n". 'You should configure a CDN or alternate file domain to mitigate '. 'this risk. Configuring a CDN will also improve performance. See '. '[[ %s | %s ]] for instructions.', $doc_href, $doc_name)) ->addExample('https://files.phabcdn.net/', pht('Valid Setting')), $this->newOption( 'security.hmac-key', 'string', '[D\t~Y7eNmnQGJ;rnH6aF;m2!vJ8@v8C=Cs:aQS\.Qw') ->setHidden(true) ->setSummary( pht('Key for HMAC digests.')) ->setDescription( pht( 'Default key for HMAC digests where the key is not important '. '(i.e., the hash itself is secret). You can change this if you '. 'want (to any other string), but doing so will break existing '. 'sessions and CSRF tokens. This option is deprecated. Newer '. 'code automatically manages HMAC keys.')), $this->newOption('security.require-https', 'bool', false) ->setLocked(true) ->setSummary( pht('Force users to connect via HTTPS instead of HTTP.')) ->setDescription( pht( "If the web server responds to both HTTP and HTTPS requests but ". "you want users to connect with only HTTPS, you can set this ". - "to `true` to make Phabricator redirect HTTP requests to HTTPS.". + "to `true` to make this service redirect HTTP requests to HTTPS.". "\n\n". "Normally, you should just configure your server not to accept ". "HTTP traffic, but this setting may be useful if you originally ". "used HTTP and have now switched to HTTPS but don't want to ". "break old links, or if your webserver sits behind a load ". "balancer which terminates HTTPS connections and you can not ". "reasonably configure more granular behavior there.". "\n\n". - "IMPORTANT: Phabricator determines if a request is HTTPS or not ". - "by examining the PHP `%s` variable. If you run ". - "Apache/mod_php this will probably be set correctly for you ". - "automatically, but if you run Phabricator as CGI/FCGI (e.g., ". - "through nginx or lighttpd), you need to configure your web ". - "server so that it passes the value correctly based on the ". - "connection type.". + "IMPORTANT: A request is identified as HTTP or HTTPS by examining ". + "the PHP `%s` variable. If you run Apache/mod_php this will ". + "probably be set correctly for you automatically, but if you run ". + "as CGI/FCGI (e.g., through nginx or lighttpd), you need to ". + "configure your web server so that it passes the value correctly ". + "based on the connection type.". "\n\n". - "If you configure Phabricator in cluster mode, note that this ". + "If you configure clustering, note that this ". "setting is ignored by intracluster requests.", "\$_SERVER['HTTPS']")) ->setBoolOptions( array( pht('Force HTTPS'), pht('Allow HTTP'), )), $this->newOption('security.require-multi-factor-auth', 'bool', false) ->setLocked(true) ->setSummary( pht('Require all users to configure multi-factor authentication.')) ->setDescription($require_mfa_description) ->setBoolOptions( array( pht('Multi-Factor Required'), pht('Multi-Factor Optional'), )), $this->newOption( 'uri.allowed-protocols', 'set', array( 'http' => true, 'https' => true, 'mailto' => true, )) ->setSummary( pht( 'Determines which URI protocols are valid for links and '. 'redirects.')) ->setDescription( pht( 'When users write comments which have URIs, they will be '. 'automatically turned into clickable links if the URI protocol '. 'appears in this set.'. "\n\n". 'This set of allowed protocols is primarily intended to prevent '. 'security issues with "javascript:" and other potentially '. 'dangerous URI handlers.'. "\n\n". 'This set is also used to enforce valid redirect URIs. '. - 'Phabricator will refuse to issue a HTTP "Location" redirect to a '. - 'URI with a protocol not on this set.'. + 'This service will refuse to issue a HTTP "Location" redirect '. + 'to a URI with a protocol not on this set.'. "\n\n". 'Usually, "http" and "https" should be present in this set. If '. - 'you remove one or both protocols, some Phabricator features '. - 'which rely on links or redirects may not work.')) + 'you remove one or both protocols, some features which rely on '. + 'links or redirects may not work.')) ->addExample("http\nhttps", pht('Valid Setting')) ->setLocked(true), $this->newOption( 'uri.allowed-editor-protocols', 'set', array( 'http' => true, 'https' => true, // This handler is installed by Textmate. 'txmt' => true, // This handler is for MacVim. 'mvim' => true, // Unofficial handler for Vim. 'vim' => true, // Unofficial handler for Sublime. 'subl' => true, // Unofficial handler for Emacs. 'emacs' => true, // This isn't a standard handler installed by an application, but // is a reasonable name for a user-installed handler. 'editor' => true, // This handler is for Visual Studio Code. 'vscode' => true, // This is for IntelliJ IDEA. 'idea' => true, )) ->setSummary(pht('Whitelists editor protocols for "Open in Editor".')) ->setDescription( pht( 'Users can configure a URI pattern to open files in a text '. 'editor. The URI must use a protocol on this whitelist.')) ->setLocked(true), $this->newOption('remarkup.enable-embedded-youtube', 'bool', false) ->setBoolOptions( array( pht('Embed YouTube videos'), pht("Don't embed YouTube videos"), )) ->setSummary( pht('Determines whether or not YouTube videos get embedded.')) ->setDescription( pht( "If you enable this, linked YouTube videos will be embedded ". "inline. This has mild security implications (you'll leak ". "referrers to YouTube) and is pretty silly (but sort of ". "awesome).")), $this->newOption( 'security.outbound-blacklist', 'list', $default_address_blacklist) ->setLocked(true) ->setSummary( pht( 'Blacklist subnets to prevent user-initiated outbound '. 'requests.')) ->setDescription( pht( - 'Phabricator users can make requests to other services from '. - 'the Phabricator host in some circumstances (for example, by '. - 'creating a repository with a remote URL or having Phabricator '. - 'fetch an image from a remote server).'. + 'Users can make requests to other services from '. + 'service hosts in some circumstances (for example, by '. + 'creating a repository with a remote URL).'. "\n\n". 'This may represent a security vulnerability if services on '. 'the same subnet will accept commands or reveal private '. 'information over unauthenticated HTTP GET, based on the source '. 'IP address. In particular, all hosts in EC2 have access to '. 'such a service.'. "\n\n". - 'This option defines a list of netblocks which Phabricator '. - 'will decline to connect to. Generally, you should list all '. + 'This option defines a list of netblocks which requests will '. + 'never be issued to. Generally, you should list all '. 'private IP space here.')) ->addExample(array('0.0.0.0/0'), pht('No Outbound Requests')), $this->newOption('security.strict-transport-security', 'bool', false) ->setLocked(true) ->setBoolOptions( array( pht('Use HSTS'), pht('Do Not Use HSTS'), )) ->setSummary(pht('Enable HTTP Strict Transport Security (HSTS).')) ->setDescription( pht( 'HTTP Strict Transport Security (HSTS) sends a header which '. 'instructs browsers that the site should only be accessed '. 'over HTTPS, never HTTP. This defuses an attack where an '. 'adversary gains access to your network, then proxies requests '. 'through an unsecured link.'. "\n\n". 'Do not enable this option if you serve (or plan to ever serve) '. 'unsecured content over plain HTTP. It is very difficult to '. 'undo this change once users\' browsers have accepted the '. 'setting.')), $this->newOption('keyring', $keyring_type, array()) ->setHidden(true) ->setSummary(pht('Configure master encryption keys.')) ->setDescription($keyring_description), ); } protected function didValidateOption( PhabricatorConfigOption $option, $value) { $key = $option->getKey(); if ($key == 'security.alternate-file-domain') { $uri = new PhutilURI($value); $protocol = $uri->getProtocol(); if ($protocol !== 'http' && $protocol !== 'https') { throw new PhabricatorConfigValidationException( pht( "Config option '%s' is invalid. The URI must start with ". "'%s' or '%s'.", $key, 'http://', 'https://')); } $domain = $uri->getDomain(); if (strpos($domain, '.') === false) { throw new PhabricatorConfigValidationException( pht( "Config option '%s' is invalid. The URI must contain a dot ('.'), ". "like '%s', not just a bare name like '%s'. ". "Some web browsers will not set cookies on domains with no TLD.", $key, 'http://example.com/', 'http://example/')); } $path = $uri->getPath(); if ($path !== '' && $path !== '/') { throw new PhabricatorConfigValidationException( pht( "Config option '%s' is invalid. The URI must NOT have a path, ". - "e.g. '%s' is OK, but '%s' is not. Phabricator must be installed ". - "on an entire domain; it can not be installed on a path.", + "e.g. '%s' is OK, but '%s' is not. This software must be ". + "installed on an entire domain; it can not be installed on a path.", $key, - 'http://phabricator.example.com/', - 'http://example.com/phabricator/')); + 'http://devtools.example.com/', + 'http://example.com/devtools/')); } } } } diff --git a/src/applications/config/option/PhabricatorSyntaxHighlightingConfigOptions.php b/src/applications/config/option/PhabricatorSyntaxHighlightingConfigOptions.php index 27596f7f07..05303e2b96 100644 --- a/src/applications/config/option/PhabricatorSyntaxHighlightingConfigOptions.php +++ b/src/applications/config/option/PhabricatorSyntaxHighlightingConfigOptions.php @@ -1,155 +1,154 @@ newOption( 'syntax-highlighter.engine', 'class', 'PhutilDefaultSyntaxHighlighterEngine') ->setBaseClass('PhutilSyntaxHighlighterEngine') ->setSummary(pht('Default non-pygments syntax highlighter engine.')) ->setDescription( pht( - 'Phabricator can highlight PHP by default and use Pygments for '. - 'other languages if enabled. You can provide a custom '. - 'highlighter engine by extending class %s.', + 'You can provide a custom highlighter engine by extending '. + 'class %s.', 'PhutilSyntaxHighlighterEngine')), $this->newOption('pygments.enabled', 'bool', false) ->setSummary( - pht('Should Phabricator use Pygments to highlight code?')) + pht('Use Pygments to highlight code?')) ->setBoolOptions( array( pht('Use Pygments'), pht('Do Not Use Pygments'), )) ->setDescription( pht( - 'Phabricator supports syntax highlighting a few languages by '. + 'Syntax highlighting a supported for a few languages by '. 'default, but you can install Pygments (a third-party syntax '. 'highlighting tool) to provide support for many more languages.'. "\n\n". 'To install Pygments, visit '. '[[ http://pygments.org | pygments.org ]] and follow the '. 'download and install instructions.'. "\n\n". 'Once Pygments is installed, enable this option '. - '(`pygments.enabled`) to make Phabricator use Pygments when '. + '(`pygments.enabled`) to make use of Pygments when '. 'highlighting source code.'. "\n\n". 'After you install and enable Pygments, newly created source '. 'code (like diffs and pastes) should highlight correctly. '. - 'You may need to clear Phabricator\'s caches to get previously '. + 'You may need to clear caches to get previously '. 'existing source code to highlight. For instructions on '. 'managing caches, see [[ %s | Managing Caches ]].', $caches_href)), $this->newOption( 'pygments.dropdown-choices', 'wild', array( 'apacheconf' => 'Apache Configuration', 'bash' => 'Bash Scripting', 'brainfuck' => 'Brainf*ck', 'c' => 'C', 'coffee-script' => 'CoffeeScript', 'cpp' => 'C++', 'csharp' => 'C#', 'css' => 'CSS', 'd' => 'D', 'diff' => 'Diff', 'django' => 'Django Templating', 'docker' => 'Docker', 'erb' => 'Embedded Ruby/ERB', 'erlang' => 'Erlang', 'go' => 'Golang', 'groovy' => 'Groovy', 'haskell' => 'Haskell', 'html' => 'HTML', 'http' => 'HTTP', 'invisible' => 'Invisible', 'java' => 'Java', 'js' => 'Javascript', 'json' => 'JSON', 'make' => 'Makefile', 'mysql' => 'MySQL', 'nginx' => 'Nginx Configuration', 'objc' => 'Objective-C', 'perl' => 'Perl', 'php' => 'PHP', 'postgresql' => 'PostgreSQL', 'pot' => 'Gettext Catalog', 'puppet' => 'Puppet', 'python' => 'Python', 'rainbow' => 'Rainbow', 'remarkup' => 'Remarkup', 'rst' => 'reStructuredText', 'robotframework' => 'RobotFramework', 'ruby' => 'Ruby', 'sql' => 'SQL', 'tex' => 'LaTeX', 'text' => 'Plain Text', 'twig' => 'Twig', 'xml' => 'XML', 'yaml' => 'YAML', )) ->setSummary( pht('Set the language list which appears in dropdowns.')) ->setDescription( pht( 'In places that we display a dropdown to syntax-highlight code, '. 'this is where that list is defined.')), $this->newOption( 'syntax.filemap', 'custom:PhabricatorConfigRegexOptionType', array( '@\.arcconfig$@' => 'json', '@\.arclint$@' => 'json', '@\.divinerconfig$@' => 'json', )) ->setSummary( pht('Override what language files (based on filename) highlight as.')) ->setDescription( pht( 'This is an override list of regular expressions which allows '. 'you to choose what language files are highlighted as. If your '. 'projects have certain rules about filenames or use unusual or '. 'ambiguous language extensions, you can create a mapping here. '. 'This is an ordered dictionary of regular expressions which will '. 'be tested against the filename. They should map to either an '. 'explicit language as a string value, or a numeric index into '. 'the captured groups as an integer.')) ->addExample( '{"@\\\.xyz$@": "php"}', pht('Highlight %s as PHP.', '*.xyz')) ->addExample( '{"@/httpd\\\.conf@": "apacheconf"}', pht('Highlight httpd.conf as "apacheconf".')) ->addExample( '{"@\\\.([^.]+)\\\.bak$@": 1}', pht( "Treat all '*.x.bak' file as '.x'. NOTE: We map to capturing group ". "1 by specifying the mapping as '1'")), ); } } diff --git a/src/applications/config/option/PhabricatorUIConfigOptions.php b/src/applications/config/option/PhabricatorUIConfigOptions.php index 391ba7e123..6802149083 100644 --- a/src/applications/config/option/PhabricatorUIConfigOptions.php +++ b/src/applications/config/option/PhabricatorUIConfigOptions.php @@ -1,90 +1,91 @@ pht('Blindigo'), 'red' => pht('Red'), 'blue' => pht('Blue'), 'green' => pht('Green'), 'indigo' => pht('Indigo'), 'dark' => pht('Dark'), ); $example = <<newOption('ui.header-color', 'enum', 'blindigo') ->setDescription( - pht('Sets the default color scheme of Phabricator.')) + pht('Sets the default color scheme.')) ->setEnumOptions($options), $this->newOption('ui.logo', $logo_type, array()) ->setSummary( pht('Customize the logo and wordmark text in the header.')) ->setDescription( pht( "Customize the logo image and text which appears in the main ". "site header:\n\n". " - **Logo Image**: Upload a new 80 x 80px image to replace the ". - "Phabricator logo in the site header.\n\n". + "logo in the site header.\n\n". " - **Wordmark**: Choose new text to display next to the logo. ". - "By default, the header displays //Phabricator//.\n\n")), + "By default, the header displays //%s//.\n\n", + PlatformSymbols::getPlatformServerName())), $this->newOption('ui.favicons', 'wild', array()) ->setSummary(pht('Customize favicons.')) ->setDescription(pht('Customize favicons.')) ->setLocked(true), $this->newOption('ui.footer-items', $footer_type, array()) ->setSummary( pht( 'Allows you to add footer links on most pages.')) ->setDescription( pht( "Allows you to add a footer with links in it to most ". "pages. You might want to use these links to point at legal ". "information or an about page.\n\n". "Specify a list of dictionaries. Each dictionary describes ". "a footer item. These keys are supported:\n\n". " - `name` The name of the item.\n". " - `href` Optionally, the link target of the item. You can ". " omit this if you just want a piece of text, like a copyright ". " notice.")) ->addExample($example, pht('Basic Example')), ); } } diff --git a/src/applications/config/response/PhabricatorConfigResponse.php b/src/applications/config/response/PhabricatorConfigResponse.php index 588f60255f..3f9a9c86e9 100644 --- a/src/applications/config/response/PhabricatorConfigResponse.php +++ b/src/applications/config/response/PhabricatorConfigResponse.php @@ -1,51 +1,51 @@ view = $view; return $this; } public function getHTTPResponseCode() { return 500; } protected function getResources() { return array( 'css/application/config/config-template.css', 'css/application/config/setup-issue.css', ); } protected function getResponseTitle() { - return pht('Phabricator Setup Error'); + return pht('Setup Error'); } protected function getResponseBodyClass() { if (PhabricatorSetupCheck::isInFlight()) { return 'setup-fatal in-flight'; } else { return 'setup-fatal'; } } protected function getResponseBody() { $view = $this->view; if (PhabricatorSetupCheck::isInFlight()) { return $view->renderInFlight(); } else { return $view->render(); } } protected function buildPlainTextResponseString() { return pht( 'This install has a fatal setup error, access the web interface '. 'to view details and resolve it.'); } } diff --git a/src/applications/config/view/PhabricatorSetupIssueView.php b/src/applications/config/view/PhabricatorSetupIssueView.php index 74bdc2d522..003725d5fc 100644 --- a/src/applications/config/view/PhabricatorSetupIssueView.php +++ b/src/applications/config/view/PhabricatorSetupIssueView.php @@ -1,614 +1,614 @@ issue = $issue; return $this; } public function getIssue() { return $this->issue; } public function renderInFlight() { $issue = $this->getIssue(); return id(new PhabricatorInFlightErrorView()) ->setMessage($issue->getName()) ->render(); } public function render() { $issue = $this->getIssue(); $description = array(); $description[] = phutil_tag( 'div', array( 'class' => 'setup-issue-instructions', ), phutil_escape_html_newlines($issue->getMessage())); $configs = $issue->getPHPConfig(); if ($configs) { $description[] = $this->renderPHPConfig($configs, $issue); } $configs = $issue->getMySQLConfig(); if ($configs) { $description[] = $this->renderMySQLConfig($configs); } $configs = $issue->getPhabricatorConfig(); if ($configs) { $description[] = $this->renderPhabricatorConfig($configs); } $related_configs = $issue->getRelatedPhabricatorConfig(); if ($related_configs) { $description[] = $this->renderPhabricatorConfig($related_configs, $related = true); } $commands = $issue->getCommands(); if ($commands) { $run_these = pht('Run these %d command(s):', count($commands)); $description[] = phutil_tag( 'div', array( 'class' => 'setup-issue-config', ), array( phutil_tag('p', array(), $run_these), phutil_tag('pre', array(), phutil_implode_html("\n", $commands)), )); } $extensions = $issue->getPHPExtensions(); if ($extensions) { $install_these = pht( 'Install these %d PHP extension(s):', count($extensions)); $install_info = pht( 'You can usually install a PHP extension using %s or %s. Common '. 'package names are %s or %s. Try commands like these:', phutil_tag('tt', array(), 'apt-get'), phutil_tag('tt', array(), 'yum'), hsprintf('php-%s', pht('extname')), hsprintf('php5-%s', pht('extname'))); // TODO: We should do a better job of detecting how to install extensions // on the current system. $install_commands = hsprintf( "\$ sudo apt-get install php5-extname ". "# Debian / Ubuntu\n". "\$ sudo yum install php-extname ". "# Red Hat / Derivatives"); $fallback_info = pht( "If those commands don't work, try Google. The process of installing ". - "PHP extensions is not specific to Phabricator, and any instructions ". - "you can find for installing them on your system should work. On Mac ". - "OS X, you might want to try Homebrew."); + "PHP extensions is not specific to this software, and any ". + "instructions you can find for installing them on your system should ". + "work. On Mac OS X, you might want to try Homebrew."); $restart_info = pht( - 'After installing new PHP extensions, restart Phabricator '. + 'After installing new PHP extensions, restart everything '. 'for the changes to take effect. For help with restarting '. - 'Phabricator, see %s in the documentation.', + 'everything, see %s in the documentation.', $this->renderRestartLink()); $description[] = phutil_tag( 'div', array( 'class' => 'setup-issue-config', ), array( phutil_tag('p', array(), $install_these), phutil_tag('pre', array(), implode("\n", $extensions)), phutil_tag('p', array(), $install_info), phutil_tag('pre', array(), $install_commands), phutil_tag('p', array(), $fallback_info), phutil_tag('p', array(), $restart_info), )); } $related_links = $issue->getLinks(); if ($related_links) { $description[] = $this->renderRelatedLinks($related_links); } $actions = array(); if (!$issue->getIsFatal()) { if ($issue->getIsIgnored()) { $actions[] = javelin_tag( 'a', array( 'href' => '/config/unignore/'.$issue->getIssueKey().'/', 'sigil' => 'workflow', 'class' => 'button button-grey', ), pht('Unignore Setup Issue')); } else { $actions[] = javelin_tag( 'a', array( 'href' => '/config/ignore/'.$issue->getIssueKey().'/', 'sigil' => 'workflow', 'class' => 'button button-grey', ), pht('Ignore Setup Issue')); } $actions[] = javelin_tag( 'a', array( 'href' => '/config/issue/'.$issue->getIssueKey().'/', 'class' => 'button button-grey', ), pht('Reload Page')); } if ($actions) { $actions = phutil_tag( 'div', array( 'class' => 'setup-issue-actions', ), $actions); } if ($issue->getIsIgnored()) { $status = phutil_tag( 'div', array( 'class' => 'setup-issue-status', ), pht( 'This issue is currently ignored, and does not show a global '. 'warning.')); $next = null; } else { $status = null; $next = phutil_tag( 'div', array( 'class' => 'setup-issue-next', ), pht('To continue, resolve this problem and reload the page.')); } $name = phutil_tag( 'div', array( 'class' => 'setup-issue-name', ), $issue->getName()); $head = phutil_tag( 'div', array( 'class' => 'setup-issue-head', ), $name); $body = phutil_tag( 'div', array( 'class' => 'setup-issue-body', ), array( $status, $description, )); $tail = phutil_tag( 'div', array( 'class' => 'setup-issue-tail', ), $actions); $issue = phutil_tag( 'div', array( 'class' => 'setup-issue', ), array( $head, $body, $tail, )); $debug_info = phutil_tag( 'div', array( 'class' => 'setup-issue-debug', ), pht('Host: %s', php_uname('n'))); return phutil_tag( 'div', array( 'class' => 'setup-issue-shell', ), array( $issue, $next, $debug_info, )); } private function renderPhabricatorConfig(array $configs, $related = false) { $issue = $this->getIssue(); $table_info = phutil_tag( 'p', array(), pht( - 'The current Phabricator configuration has these %d value(s):', + 'The current configuration has these %d value(s):', count($configs))); $options = PhabricatorApplicationConfigOptions::loadAllOptions(); $hidden = array(); foreach ($options as $key => $option) { if ($option->getHidden()) { $hidden[$key] = true; } } $table = null; $dict = array(); foreach ($configs as $key) { if (isset($hidden[$key])) { $dict[$key] = null; } else { $dict[$key] = PhabricatorEnv::getUnrepairedEnvConfig($key); } } $table = $this->renderValueTable($dict, $hidden); if ($this->getIssue()->getIsFatal()) { $update_info = phutil_tag( 'p', array(), pht( 'To update these %d value(s), run these command(s) from the command '. 'line:', count($configs))); $update = array(); foreach ($configs as $key) { $update[] = hsprintf( - 'phabricator/ $ ./bin/config set %s value', + '$ ./bin/config set %s value', $key); } $update = phutil_tag('pre', array(), phutil_implode_html("\n", $update)); } else { $update = array(); foreach ($configs as $config) { if (idx($options, $config) && $options[$config]->getLocked()) { $name = pht('View "%s"', $config); } else { $name = pht('Edit "%s"', $config); } $link = phutil_tag( 'a', array( 'href' => '/config/edit/'.$config.'/?issue='.$issue->getIssueKey(), ), $name); $update[] = phutil_tag('li', array(), $link); } if ($update) { $update = phutil_tag('ul', array(), $update); if (!$related) { $update_info = phutil_tag( 'p', array(), pht('You can update these %d value(s) here:', count($configs))); } else { $update_info = phutil_tag( 'p', array(), pht('These %d configuration value(s) are related:', count($configs))); } } else { $update = null; $update_info = null; } } return phutil_tag( 'div', array( 'class' => 'setup-issue-config', ), array( $table_info, $table, $update_info, $update, )); } private function renderPHPConfig(array $configs, $issue) { $table_info = phutil_tag( 'p', array(), pht( 'The current PHP configuration has these %d value(s):', count($configs))); $dict = array(); foreach ($configs as $key) { $dict[$key] = $issue->getPHPConfigOriginalValue( $key, ini_get($key)); } $table = $this->renderValueTable($dict); ob_start(); phpinfo(); $phpinfo = ob_get_clean(); $rex = '@Loaded Configuration File\s*(.*?)@i'; $matches = null; $ini_loc = null; if (preg_match($rex, $phpinfo, $matches)) { $ini_loc = trim($matches[1]); } $rex = '@Additional \.ini files parsed\s*(.*?)@i'; $more_loc = array(); if (preg_match($rex, $phpinfo, $matches)) { $more_loc = trim($matches[1]); if ($more_loc == '(none)') { $more_loc = array(); } else { $more_loc = preg_split('/\s*,\s*/', $more_loc); } } $info = array(); if (!$ini_loc) { $info[] = phutil_tag( 'p', array(), pht( 'To update these %d value(s), edit your PHP configuration file.', count($configs))); } else { $info[] = phutil_tag( 'p', array(), pht( 'To update these %d value(s), edit your PHP configuration file, '. 'located here:', count($configs))); $info[] = phutil_tag( 'pre', array(), $ini_loc); } if ($more_loc) { $info[] = phutil_tag( 'p', array(), pht( 'PHP also loaded these %s configuration file(s):', phutil_count($more_loc))); $info[] = phutil_tag( 'pre', array(), implode("\n", $more_loc)); } $show_standard = false; $show_opcache = false; foreach ($configs as $key) { if (preg_match('/^opcache\./', $key)) { $show_opcache = true; } else { $show_standard = true; } } if ($show_standard) { $info[] = phutil_tag( 'p', array(), pht( 'You can find more information about PHP configuration values '. 'in the %s.', phutil_tag( 'a', array( 'href' => 'http://php.net/manual/ini.list.php', 'target' => '_blank', ), pht('PHP Documentation')))); } if ($show_opcache) { $info[] = phutil_tag( 'p', array(), pht( 'You can find more information about configuring OPcache in '. 'the %s.', phutil_tag( 'a', array( 'href' => 'http://php.net/manual/opcache.configuration.php', 'target' => '_blank', ), pht('PHP OPcache Documentation')))); } $info[] = phutil_tag( 'p', array(), pht( - 'After editing the PHP configuration, restart Phabricator for '. + 'After editing the PHP configuration, restart everything for '. 'the changes to take effect. For help with restarting '. - 'Phabricator, see %s in the documentation.', + 'everything, see %s in the documentation.', $this->renderRestartLink())); return phutil_tag( 'div', array( 'class' => 'setup-issue-config', ), array( $table_info, $table, $info, )); } private function renderMySQLConfig(array $config) { $values = array(); $issue = $this->getIssue(); $ref = $issue->getDatabaseRef(); if ($ref) { foreach ($config as $key) { $value = $ref->loadRawMySQLConfigValue($key); if ($value === null) { $value = phutil_tag( 'em', array(), pht('(Not Supported)')); } $values[$key] = $value; } } $table = $this->renderValueTable($values); $doc_href = PhabricatorEnv::getDoclink('User Guide: Amazon RDS'); $doc_link = phutil_tag( 'a', array( 'href' => $doc_href, 'target' => '_blank', ), pht('User Guide: Amazon RDS')); $info = array(); $info[] = phutil_tag( 'p', array(), pht( 'If you are using Amazon RDS, some of the instructions above may '. 'not apply to you. See %s for discussion of Amazon RDS.', $doc_link)); $table_info = phutil_tag( 'p', array(), pht( 'The current MySQL configuration has these %d value(s):', count($config))); return phutil_tag( 'div', array( 'class' => 'setup-issue-config', ), array( $table_info, $table, $info, )); } private function renderValueTable(array $dict, array $hidden = array()) { $rows = array(); foreach ($dict as $key => $value) { if (isset($hidden[$key])) { $value = phutil_tag('em', array(), 'hidden'); } else { $value = $this->renderValueForDisplay($value); } $cols = array( phutil_tag('th', array(), $key), phutil_tag('td', array(), $value), ); $rows[] = phutil_tag('tr', array(), $cols); } return phutil_tag('table', array(), $rows); } private function renderValueForDisplay($value) { if ($value === null) { return phutil_tag('em', array(), 'null'); } else if ($value === false) { return phutil_tag('em', array(), 'false'); } else if ($value === true) { return phutil_tag('em', array(), 'true'); } else if ($value === '') { return phutil_tag('em', array(), 'empty string'); } else if ($value instanceof PhutilSafeHTML) { return $value; } else { return PhabricatorConfigJSON::prettyPrintJSON($value); } } private function renderRelatedLinks(array $links) { $link_info = phutil_tag( 'p', array(), pht( '%d related link(s):', count($links))); $link_list = array(); foreach ($links as $link) { $link_tag = phutil_tag( 'a', array( 'target' => '_blank', 'href' => $link['href'], ), $link['name']); $link_item = phutil_tag('li', array(), $link_tag); $link_list[] = $link_item; } $link_list = phutil_tag('ul', array(), $link_list); return phutil_tag( 'div', array( 'class' => 'setup-issue-config', ), array( $link_info, $link_list, )); } private function renderRestartLink() { $doc_href = PhabricatorEnv::getDoclink('Restarting Phabricator'); return phutil_tag( 'a', array( 'href' => $doc_href, 'target' => '_blank', ), pht('Restarting Phabricator')); } }