Remove product literal strings in "pht()", part 4
[phabricator.git] / src / applications / config / view / PhabricatorSetupIssueView.php
blob003725d5fcba92b18e03b5c83245147597a9fca3
1 <?php
3 final class PhabricatorSetupIssueView extends AphrontView {
5 private $issue;
7 public function setIssue(PhabricatorSetupIssue $issue) {
8 $this->issue = $issue;
9 return $this;
12 public function getIssue() {
13 return $this->issue;
16 public function renderInFlight() {
17 $issue = $this->getIssue();
19 return id(new PhabricatorInFlightErrorView())
20 ->setMessage($issue->getName())
21 ->render();
24 public function render() {
25 $issue = $this->getIssue();
27 $description = array();
28 $description[] = phutil_tag(
29 'div',
30 array(
31 'class' => 'setup-issue-instructions',
33 phutil_escape_html_newlines($issue->getMessage()));
35 $configs = $issue->getPHPConfig();
36 if ($configs) {
37 $description[] = $this->renderPHPConfig($configs, $issue);
40 $configs = $issue->getMySQLConfig();
41 if ($configs) {
42 $description[] = $this->renderMySQLConfig($configs);
45 $configs = $issue->getPhabricatorConfig();
46 if ($configs) {
47 $description[] = $this->renderPhabricatorConfig($configs);
50 $related_configs = $issue->getRelatedPhabricatorConfig();
51 if ($related_configs) {
52 $description[] = $this->renderPhabricatorConfig($related_configs,
53 $related = true);
56 $commands = $issue->getCommands();
57 if ($commands) {
58 $run_these = pht('Run these %d command(s):', count($commands));
59 $description[] = phutil_tag(
60 'div',
61 array(
62 'class' => 'setup-issue-config',
64 array(
65 phutil_tag('p', array(), $run_these),
66 phutil_tag('pre', array(), phutil_implode_html("\n", $commands)),
67 ));
70 $extensions = $issue->getPHPExtensions();
71 if ($extensions) {
72 $install_these = pht(
73 'Install these %d PHP extension(s):', count($extensions));
75 $install_info = pht(
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");
91 $fallback_info = pht(
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.");
97 $restart_info = pht(
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(
104 'div',
105 array(
106 'class' => 'setup-issue-config',
108 array(
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);
124 $actions = array();
125 if (!$issue->getIsFatal()) {
126 if ($issue->getIsIgnored()) {
127 $actions[] = javelin_tag(
128 'a',
129 array(
130 'href' => '/config/unignore/'.$issue->getIssueKey().'/',
131 'sigil' => 'workflow',
132 'class' => 'button button-grey',
134 pht('Unignore Setup Issue'));
135 } else {
136 $actions[] = javelin_tag(
137 'a',
138 array(
139 'href' => '/config/ignore/'.$issue->getIssueKey().'/',
140 'sigil' => 'workflow',
141 'class' => 'button button-grey',
143 pht('Ignore Setup Issue'));
146 $actions[] = javelin_tag(
147 'a',
148 array(
149 'href' => '/config/issue/'.$issue->getIssueKey().'/',
150 'class' => 'button button-grey',
152 pht('Reload Page'));
155 if ($actions) {
156 $actions = phutil_tag(
157 'div',
158 array(
159 'class' => 'setup-issue-actions',
161 $actions);
164 if ($issue->getIsIgnored()) {
165 $status = phutil_tag(
166 'div',
167 array(
168 'class' => 'setup-issue-status',
170 pht(
171 'This issue is currently ignored, and does not show a global '.
172 'warning.'));
173 $next = null;
174 } else {
175 $status = null;
176 $next = phutil_tag(
177 'div',
178 array(
179 'class' => 'setup-issue-next',
181 pht('To continue, resolve this problem and reload the page.'));
184 $name = phutil_tag(
185 'div',
186 array(
187 'class' => 'setup-issue-name',
189 $issue->getName());
191 $head = phutil_tag(
192 'div',
193 array(
194 'class' => 'setup-issue-head',
196 $name);
198 $body = phutil_tag(
199 'div',
200 array(
201 'class' => 'setup-issue-body',
203 array(
204 $status,
205 $description,
208 $tail = phutil_tag(
209 'div',
210 array(
211 'class' => 'setup-issue-tail',
213 $actions);
215 $issue = phutil_tag(
216 'div',
217 array(
218 'class' => 'setup-issue',
220 array(
221 $head,
222 $body,
223 $tail,
226 $debug_info = phutil_tag(
227 'div',
228 array(
229 'class' => 'setup-issue-debug',
231 pht('Host: %s', php_uname('n')));
233 return phutil_tag(
234 'div',
235 array(
236 'class' => 'setup-issue-shell',
238 array(
239 $issue,
240 $next,
241 $debug_info,
245 private function renderPhabricatorConfig(array $configs, $related = false) {
246 $issue = $this->getIssue();
248 $table_info = phutil_tag(
249 'p',
250 array(),
251 pht(
252 'The current configuration has these %d value(s):',
253 count($configs)));
255 $options = PhabricatorApplicationConfigOptions::loadAllOptions();
256 $hidden = array();
257 foreach ($options as $key => $option) {
258 if ($option->getHidden()) {
259 $hidden[$key] = true;
263 $table = null;
264 $dict = array();
265 foreach ($configs as $key) {
266 if (isset($hidden[$key])) {
267 $dict[$key] = null;
268 } else {
269 $dict[$key] = PhabricatorEnv::getUnrepairedEnvConfig($key);
273 $table = $this->renderValueTable($dict, $hidden);
275 if ($this->getIssue()->getIsFatal()) {
276 $update_info = phutil_tag(
277 'p',
278 array(),
279 pht(
280 'To update these %d value(s), run these command(s) from the command '.
281 'line:',
282 count($configs)));
284 $update = array();
285 foreach ($configs as $key) {
286 $update[] = hsprintf(
287 '<tt>$</tt> ./bin/config set %s <em>value</em>',
288 $key);
290 $update = phutil_tag('pre', array(), phutil_implode_html("\n", $update));
291 } else {
292 $update = array();
293 foreach ($configs as $config) {
294 if (idx($options, $config) && $options[$config]->getLocked()) {
295 $name = pht('View "%s"', $config);
296 } else {
297 $name = pht('Edit "%s"', $config);
299 $link = phutil_tag(
300 'a',
301 array(
302 'href' => '/config/edit/'.$config.'/?issue='.$issue->getIssueKey(),
304 $name);
305 $update[] = phutil_tag('li', array(), $link);
307 if ($update) {
308 $update = phutil_tag('ul', array(), $update);
309 if (!$related) {
310 $update_info = phutil_tag(
311 'p',
312 array(),
313 pht('You can update these %d value(s) here:', count($configs)));
314 } else {
315 $update_info = phutil_tag(
316 'p',
317 array(),
318 pht('These %d configuration value(s) are related:', count($configs)));
320 } else {
321 $update = null;
322 $update_info = null;
326 return phutil_tag(
327 'div',
328 array(
329 'class' => 'setup-issue-config',
331 array(
332 $table_info,
333 $table,
334 $update_info,
335 $update,
339 private function renderPHPConfig(array $configs, $issue) {
340 $table_info = phutil_tag(
341 'p',
342 array(),
343 pht(
344 'The current PHP configuration has these %d value(s):',
345 count($configs)));
347 $dict = array();
348 foreach ($configs as $key) {
349 $dict[$key] = $issue->getPHPConfigOriginalValue(
350 $key,
351 ini_get($key));
354 $table = $this->renderValueTable($dict);
356 ob_start();
357 phpinfo();
358 $phpinfo = ob_get_clean();
361 $rex = '@Loaded Configuration File\s*</td><td class="v">(.*?)</td>@i';
362 $matches = null;
364 $ini_loc = null;
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';
371 $more_loc = array();
372 if (preg_match($rex, $phpinfo, $matches)) {
373 $more_loc = trim($matches[1]);
374 if ($more_loc == '(none)') {
375 $more_loc = array();
376 } else {
377 $more_loc = preg_split('/\s*,\s*/', $more_loc);
381 $info = array();
382 if (!$ini_loc) {
383 $info[] = phutil_tag(
384 'p',
385 array(),
386 pht(
387 'To update these %d value(s), edit your PHP configuration file.',
388 count($configs)));
389 } else {
390 $info[] = phutil_tag(
391 'p',
392 array(),
393 pht(
394 'To update these %d value(s), edit your PHP configuration file, '.
395 'located here:',
396 count($configs)));
397 $info[] = phutil_tag(
398 'pre',
399 array(),
400 $ini_loc);
403 if ($more_loc) {
404 $info[] = phutil_tag(
405 'p',
406 array(),
407 pht(
408 'PHP also loaded these %s configuration file(s):',
409 phutil_count($more_loc)));
410 $info[] = phutil_tag(
411 'pre',
412 array(),
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;
422 } else {
423 $show_standard = true;
427 if ($show_standard) {
428 $info[] = phutil_tag(
429 'p',
430 array(),
431 pht(
432 'You can find more information about PHP configuration values '.
433 'in the %s.',
434 phutil_tag(
435 'a',
436 array(
437 'href' => 'http://php.net/manual/ini.list.php',
438 'target' => '_blank',
440 pht('PHP Documentation'))));
443 if ($show_opcache) {
444 $info[] = phutil_tag(
445 'p',
446 array(),
447 pht(
448 'You can find more information about configuring OPcache in '.
449 'the %s.',
450 phutil_tag(
451 'a',
452 array(
453 'href' => 'http://php.net/manual/opcache.configuration.php',
454 'target' => '_blank',
456 pht('PHP OPcache Documentation'))));
459 $info[] = phutil_tag(
460 'p',
461 array(),
462 pht(
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()));
468 return phutil_tag(
469 'div',
470 array(
471 'class' => 'setup-issue-config',
473 array(
474 $table_info,
475 $table,
476 $info,
480 private function renderMySQLConfig(array $config) {
481 $values = array();
482 $issue = $this->getIssue();
483 $ref = $issue->getDatabaseRef();
484 if ($ref) {
485 foreach ($config as $key) {
486 $value = $ref->loadRawMySQLConfigValue($key);
487 if ($value === null) {
488 $value = phutil_tag(
489 'em',
490 array(),
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(
501 'a',
502 array(
503 'href' => $doc_href,
504 'target' => '_blank',
506 pht('User Guide: Amazon RDS'));
508 $info = array();
509 $info[] = phutil_tag(
510 'p',
511 array(),
512 pht(
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.',
515 $doc_link));
517 $table_info = phutil_tag(
518 'p',
519 array(),
520 pht(
521 'The current MySQL configuration has these %d value(s):',
522 count($config)));
524 return phutil_tag(
525 'div',
526 array(
527 'class' => 'setup-issue-config',
529 array(
530 $table_info,
531 $table,
532 $info,
536 private function renderValueTable(array $dict, array $hidden = array()) {
537 $rows = array();
538 foreach ($dict as $key => $value) {
539 if (isset($hidden[$key])) {
540 $value = phutil_tag('em', array(), 'hidden');
541 } else {
542 $value = $this->renderValueForDisplay($value);
545 $cols = array(
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) {
564 return $value;
565 } else {
566 return PhabricatorConfigJSON::prettyPrintJSON($value);
570 private function renderRelatedLinks(array $links) {
571 $link_info = phutil_tag(
572 'p',
573 array(),
574 pht(
575 '%d related link(s):',
576 count($links)));
578 $link_list = array();
579 foreach ($links as $link) {
580 $link_tag = phutil_tag(
581 'a',
582 array(
583 'target' => '_blank',
584 'href' => $link['href'],
586 $link['name']);
587 $link_item = phutil_tag('li', array(), $link_tag);
588 $link_list[] = $link_item;
590 $link_list = phutil_tag('ul', array(), $link_list);
592 return phutil_tag(
593 'div',
594 array(
595 'class' => 'setup-issue-config',
597 array(
598 $link_info,
599 $link_list,
603 private function renderRestartLink() {
604 $doc_href = PhabricatorEnv::getDoclink('Restarting Phabricator');
605 return phutil_tag(
606 'a',
607 array(
608 'href' => $doc_href,
609 'target' => '_blank',
611 pht('Restarting Phabricator'));