3 final class PhabricatorSetupIssueView
extends AphrontView
{
7 public function setIssue(PhabricatorSetupIssue
$issue) {
12 public function getIssue() {
16 public function renderInFlight() {
17 $issue = $this->getIssue();
19 return id(new PhabricatorInFlightErrorView())
20 ->setMessage($issue->getName())
24 public function render() {
25 $issue = $this->getIssue();
27 $description = array();
28 $description[] = phutil_tag(
31 'class' => 'setup-issue-instructions',
33 phutil_escape_html_newlines($issue->getMessage()));
35 $configs = $issue->getPHPConfig();
37 $description[] = $this->renderPHPConfig($configs, $issue);
40 $configs = $issue->getMySQLConfig();
42 $description[] = $this->renderMySQLConfig($configs);
45 $configs = $issue->getPhabricatorConfig();
47 $description[] = $this->renderPhabricatorConfig($configs);
50 $related_configs = $issue->getRelatedPhabricatorConfig();
51 if ($related_configs) {
52 $description[] = $this->renderPhabricatorConfig($related_configs,
56 $commands = $issue->getCommands();
58 $run_these = pht('Run these %d command(s):', count($commands));
59 $description[] = phutil_tag(
62 'class' => 'setup-issue-config',
65 phutil_tag('p', array(), $run_these),
66 phutil_tag('pre', array(), phutil_implode_html("\n", $commands)),
70 $extensions = $issue->getPHPExtensions();
73 'Install these %d PHP extension(s):', count($extensions));
76 'You can usually install a PHP extension using %s or %s. Common '.
77 'package names are %s or %s. Try commands like these:',
78 phutil_tag('tt', array(), 'apt-get'),
79 phutil_tag('tt', array(), 'yum'),
80 hsprintf('<tt>php-<em>%s</em></tt>', pht('extname')),
81 hsprintf('<tt>php5-<em>%s</em></tt>', pht('extname')));
83 // TODO: We should do a better job of detecting how to install extensions
84 // on the current system.
85 $install_commands = hsprintf(
86 "\$ sudo apt-get install php5-<em>extname</em> ".
87 "# Debian / Ubuntu\n".
88 "\$ sudo yum install php-<em>extname</em> ".
89 "# Red Hat / Derivatives");
92 "If those commands don't work, try Google. The process of installing ".
93 "PHP extensions is not specific to this software, and any ".
94 "instructions you can find for installing them on your system should ".
95 "work. On Mac OS X, you might want to try Homebrew.");
98 'After installing new PHP extensions, <strong>restart everything '.
99 'for the changes to take effect</strong>. For help with restarting '.
100 'everything, see %s in the documentation.',
101 $this->renderRestartLink());
103 $description[] = phutil_tag(
106 'class' => 'setup-issue-config',
109 phutil_tag('p', array(), $install_these),
110 phutil_tag('pre', array(), implode("\n", $extensions)),
111 phutil_tag('p', array(), $install_info),
112 phutil_tag('pre', array(), $install_commands),
113 phutil_tag('p', array(), $fallback_info),
114 phutil_tag('p', array(), $restart_info),
119 $related_links = $issue->getLinks();
120 if ($related_links) {
121 $description[] = $this->renderRelatedLinks($related_links);
125 if (!$issue->getIsFatal()) {
126 if ($issue->getIsIgnored()) {
127 $actions[] = javelin_tag(
130 'href' => '/config/unignore/'.$issue->getIssueKey().'/',
131 'sigil' => 'workflow',
132 'class' => 'button button-grey',
134 pht('Unignore Setup Issue'));
136 $actions[] = javelin_tag(
139 'href' => '/config/ignore/'.$issue->getIssueKey().'/',
140 'sigil' => 'workflow',
141 'class' => 'button button-grey',
143 pht('Ignore Setup Issue'));
146 $actions[] = javelin_tag(
149 'href' => '/config/issue/'.$issue->getIssueKey().'/',
150 'class' => 'button button-grey',
156 $actions = phutil_tag(
159 'class' => 'setup-issue-actions',
164 if ($issue->getIsIgnored()) {
165 $status = phutil_tag(
168 'class' => 'setup-issue-status',
171 'This issue is currently ignored, and does not show a global '.
179 'class' => 'setup-issue-next',
181 pht('To continue, resolve this problem and reload the page.'));
187 'class' => 'setup-issue-name',
194 'class' => 'setup-issue-head',
201 'class' => 'setup-issue-body',
211 'class' => 'setup-issue-tail',
218 'class' => 'setup-issue',
226 $debug_info = phutil_tag(
229 'class' => 'setup-issue-debug',
231 pht('Host: %s', php_uname('n')));
236 'class' => 'setup-issue-shell',
245 private function renderPhabricatorConfig(array $configs, $related = false) {
246 $issue = $this->getIssue();
248 $table_info = phutil_tag(
252 'The current configuration has these %d value(s):',
255 $options = PhabricatorApplicationConfigOptions
::loadAllOptions();
257 foreach ($options as $key => $option) {
258 if ($option->getHidden()) {
259 $hidden[$key] = true;
265 foreach ($configs as $key) {
266 if (isset($hidden[$key])) {
269 $dict[$key] = PhabricatorEnv
::getUnrepairedEnvConfig($key);
273 $table = $this->renderValueTable($dict, $hidden);
275 if ($this->getIssue()->getIsFatal()) {
276 $update_info = phutil_tag(
280 'To update these %d value(s), run these command(s) from the command '.
285 foreach ($configs as $key) {
286 $update[] = hsprintf(
287 '<tt>$</tt> ./bin/config set %s <em>value</em>',
290 $update = phutil_tag('pre', array(), phutil_implode_html("\n", $update));
293 foreach ($configs as $config) {
294 if (idx($options, $config) && $options[$config]->getLocked()) {
295 $name = pht('View "%s"', $config);
297 $name = pht('Edit "%s"', $config);
302 'href' => '/config/edit/'.$config.'/?issue='.$issue->getIssueKey(),
305 $update[] = phutil_tag('li', array(), $link);
308 $update = phutil_tag('ul', array(), $update);
310 $update_info = phutil_tag(
313 pht('You can update these %d value(s) here:', count($configs)));
315 $update_info = phutil_tag(
318 pht('These %d configuration value(s) are related:', count($configs)));
329 'class' => 'setup-issue-config',
339 private function renderPHPConfig(array $configs, $issue) {
340 $table_info = phutil_tag(
344 'The current PHP configuration has these %d value(s):',
348 foreach ($configs as $key) {
349 $dict[$key] = $issue->getPHPConfigOriginalValue(
354 $table = $this->renderValueTable($dict);
358 $phpinfo = ob_get_clean();
361 $rex = '@Loaded Configuration File\s*</td><td class="v">(.*?)</td>@i';
365 if (preg_match($rex, $phpinfo, $matches)) {
366 $ini_loc = trim($matches[1]);
369 $rex = '@Additional \.ini files parsed\s*</td><td class="v">(.*?)</td>@i';
372 if (preg_match($rex, $phpinfo, $matches)) {
373 $more_loc = trim($matches[1]);
374 if ($more_loc == '(none)') {
377 $more_loc = preg_split('/\s*,\s*/', $more_loc);
383 $info[] = phutil_tag(
387 'To update these %d value(s), edit your PHP configuration file.',
390 $info[] = phutil_tag(
394 'To update these %d value(s), edit your PHP configuration file, '.
397 $info[] = phutil_tag(
404 $info[] = phutil_tag(
408 'PHP also loaded these %s configuration file(s):',
409 phutil_count($more_loc)));
410 $info[] = phutil_tag(
413 implode("\n", $more_loc));
416 $show_standard = false;
417 $show_opcache = false;
419 foreach ($configs as $key) {
420 if (preg_match('/^opcache\./', $key)) {
421 $show_opcache = true;
423 $show_standard = true;
427 if ($show_standard) {
428 $info[] = phutil_tag(
432 'You can find more information about PHP configuration values '.
437 'href' => 'http://php.net/manual/ini.list.php',
438 'target' => '_blank',
440 pht('PHP Documentation'))));
444 $info[] = phutil_tag(
448 'You can find more information about configuring OPcache in '.
453 'href' => 'http://php.net/manual/opcache.configuration.php',
454 'target' => '_blank',
456 pht('PHP OPcache Documentation'))));
459 $info[] = phutil_tag(
463 'After editing the PHP configuration, <strong>restart everything for '.
464 'the changes to take effect</strong>. For help with restarting '.
465 'everything, see %s in the documentation.',
466 $this->renderRestartLink()));
471 'class' => 'setup-issue-config',
480 private function renderMySQLConfig(array $config) {
482 $issue = $this->getIssue();
483 $ref = $issue->getDatabaseRef();
485 foreach ($config as $key) {
486 $value = $ref->loadRawMySQLConfigValue($key);
487 if ($value === null) {
491 pht('(Not Supported)'));
493 $values[$key] = $value;
497 $table = $this->renderValueTable($values);
499 $doc_href = PhabricatorEnv
::getDoclink('User Guide: Amazon RDS');
500 $doc_link = phutil_tag(
504 'target' => '_blank',
506 pht('User Guide: Amazon RDS'));
509 $info[] = phutil_tag(
513 'If you are using Amazon RDS, some of the instructions above may '.
514 'not apply to you. See %s for discussion of Amazon RDS.',
517 $table_info = phutil_tag(
521 'The current MySQL configuration has these %d value(s):',
527 'class' => 'setup-issue-config',
536 private function renderValueTable(array $dict, array $hidden = array()) {
538 foreach ($dict as $key => $value) {
539 if (isset($hidden[$key])) {
540 $value = phutil_tag('em', array(), 'hidden');
542 $value = $this->renderValueForDisplay($value);
546 phutil_tag('th', array(), $key),
547 phutil_tag('td', array(), $value),
549 $rows[] = phutil_tag('tr', array(), $cols);
551 return phutil_tag('table', array(), $rows);
554 private function renderValueForDisplay($value) {
555 if ($value === null) {
556 return phutil_tag('em', array(), 'null');
557 } else if ($value === false) {
558 return phutil_tag('em', array(), 'false');
559 } else if ($value === true) {
560 return phutil_tag('em', array(), 'true');
561 } else if ($value === '') {
562 return phutil_tag('em', array(), 'empty string');
563 } else if ($value instanceof PhutilSafeHTML
) {
566 return PhabricatorConfigJSON
::prettyPrintJSON($value);
570 private function renderRelatedLinks(array $links) {
571 $link_info = phutil_tag(
575 '%d related link(s):',
578 $link_list = array();
579 foreach ($links as $link) {
580 $link_tag = phutil_tag(
583 'target' => '_blank',
584 'href' => $link['href'],
587 $link_item = phutil_tag('li', array(), $link_tag);
588 $link_list[] = $link_item;
590 $link_list = phutil_tag('ul', array(), $link_list);
595 'class' => 'setup-issue-config',
603 private function renderRestartLink() {
604 $doc_href = PhabricatorEnv
::getDoclink('Restarting Phabricator');
609 'target' => '_blank',
611 pht('Restarting Phabricator'));