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

at recaptime-dev/main 624 lines 16 kB view raw
1<?php 2 3final class PhabricatorSetupIssueView extends AphrontView { 4 5 private $issue; 6 7 public function setIssue(PhabricatorSetupIssue $issue) { 8 $this->issue = $issue; 9 return $this; 10 } 11 12 public function getIssue() { 13 return $this->issue; 14 } 15 16 public function renderInFlight() { 17 $issue = $this->getIssue(); 18 19 return id(new PhabricatorInFlightErrorView()) 20 ->setMessage($issue->getName()) 21 ->render(); 22 } 23 24 public function render() { 25 $issue = $this->getIssue(); 26 27 $description = array(); 28 $description[] = phutil_tag( 29 'div', 30 array( 31 'class' => 'setup-issue-instructions', 32 ), 33 phutil_escape_html_newlines($issue->getMessage())); 34 35 $configs = $issue->getPHPConfig(); 36 if ($configs) { 37 $description[] = $this->renderPHPConfig($configs, $issue); 38 } 39 40 $configs = $issue->getMySQLConfig(); 41 if ($configs) { 42 $description[] = $this->renderMySQLConfig($configs); 43 } 44 45 $configs = $issue->getPhabricatorConfig(); 46 if ($configs) { 47 $description[] = $this->renderPhabricatorConfig($configs); 48 } 49 50 $related_configs = $issue->getRelatedPhabricatorConfig(); 51 if ($related_configs) { 52 $description[] = $this->renderPhabricatorConfig($related_configs, 53 $related = true); 54 } 55 56 $commands = $issue->getCommands(); 57 58 $or = null; 59 if ($configs && $commands) { 60 $or = pht('Or:'); 61 } 62 63 if ($commands) { 64 $run_these = pht('Run these %d command(s):', count($commands)); 65 $description[] = phutil_tag( 66 'div', 67 array( 68 'class' => 'setup-issue-config', 69 ), 70 array( 71 phutil_tag('p', array(), $or), 72 phutil_tag('p', array(), $run_these), 73 phutil_tag('pre', array(), phutil_implode_html("\n", $commands)), 74 )); 75 } 76 77 $extensions = $issue->getPHPExtensions(); 78 if ($extensions) { 79 $install_these = pht( 80 'Install these %d PHP extension(s):', count($extensions)); 81 82 $install_info = pht( 83 'You can usually install a PHP extension using %s, %s, or %s. A '. 84 'common package name is %s. Try commands like these:', 85 phutil_tag('kbd', array(), 'apt-get'), 86 phutil_tag('kbd', array(), 'dnf'), 87 phutil_tag('kbd', array(), 'yum'), 88 hsprintf('<kbd>php-<em>%s</em></kbd>', pht('extname'))); 89 90 // TODO: We should do a better job of detecting how to install extensions 91 // on the current system. 92 $install_commands = hsprintf( 93 "<samp>$</samp><kbd>sudo apt-get install php-<em>extname</em></kbd> ". 94 "# Debian / Ubuntu\n". 95 "<samp>$</samp><kbd>sudo dnf install php-<em>extname</em></kbd> ". 96 "# Red Hat / Derivatives\n". 97 "<samp>$</samp><kbd>sudo yum install php-<em>extname</em></kbd> ". 98 "# Older Red Hat versions"); 99 100 $fallback_info = pht( 101 "If those commands don't work, try Google. The process of installing ". 102 "PHP extensions is not specific to this software, and any ". 103 "instructions you can find for installing them on your system should ". 104 "work. On Mac OS X, you might want to try Homebrew."); 105 106 $restart_info = pht( 107 'After installing new PHP extensions, <strong>restart everything '. 108 'for the changes to take effect</strong>. For help with restarting '. 109 'everything, see %s in the documentation.', 110 $this->renderRestartLink()); 111 112 $description[] = phutil_tag( 113 'div', 114 array( 115 'class' => 'setup-issue-config', 116 ), 117 array( 118 phutil_tag('p', array(), $install_these), 119 phutil_tag('pre', array(), implode("\n", $extensions)), 120 phutil_tag('p', array(), $install_info), 121 phutil_tag('pre', array(), $install_commands), 122 phutil_tag('p', array(), $fallback_info), 123 phutil_tag('p', array(), $restart_info), 124 )); 125 126 } 127 128 $related_links = $issue->getLinks(); 129 if ($related_links) { 130 $description[] = $this->renderRelatedLinks($related_links); 131 } 132 133 $actions = array(); 134 if (!$issue->getIsFatal()) { 135 if ($issue->getIsIgnored()) { 136 $actions[] = javelin_tag( 137 'a', 138 array( 139 'href' => '/config/unignore/'.$issue->getIssueKey().'/', 140 'sigil' => 'workflow', 141 'class' => 'button button-grey', 142 ), 143 pht('Unignore Setup Issue')); 144 } else { 145 $actions[] = javelin_tag( 146 'a', 147 array( 148 'href' => '/config/ignore/'.$issue->getIssueKey().'/', 149 'sigil' => 'workflow', 150 'class' => 'button button-grey', 151 ), 152 pht('Ignore Setup Issue')); 153 } 154 155 $actions[] = javelin_tag( 156 'a', 157 array( 158 'href' => '/config/issue/'.$issue->getIssueKey().'/', 159 'class' => 'button button-grey', 160 ), 161 pht('Reload Page')); 162 } 163 164 if ($actions) { 165 $actions = phutil_tag( 166 'div', 167 array( 168 'class' => 'setup-issue-actions', 169 ), 170 $actions); 171 } 172 173 if ($issue->getIsIgnored()) { 174 $status = phutil_tag( 175 'div', 176 array( 177 'class' => 'setup-issue-status', 178 ), 179 pht( 180 'This issue is currently ignored, and does not show a global '. 181 'warning.')); 182 $next = null; 183 } else { 184 $status = null; 185 $next = phutil_tag( 186 'div', 187 array( 188 'class' => 'setup-issue-next', 189 ), 190 pht('To continue, resolve this problem and reload the page.')); 191 } 192 193 $name = phutil_tag( 194 'div', 195 array( 196 'class' => 'setup-issue-name', 197 ), 198 $issue->getName()); 199 200 $head = phutil_tag( 201 'div', 202 array( 203 'class' => 'setup-issue-head', 204 ), 205 $name); 206 207 $body = phutil_tag( 208 'div', 209 array( 210 'class' => 'setup-issue-body', 211 ), 212 array( 213 $status, 214 $description, 215 )); 216 217 $tail = phutil_tag( 218 'div', 219 array( 220 'class' => 'setup-issue-tail', 221 ), 222 $actions); 223 224 $issue = phutil_tag( 225 'div', 226 array( 227 'class' => 'setup-issue', 228 ), 229 array( 230 $head, 231 $body, 232 $tail, 233 )); 234 235 $debug_info = phutil_tag( 236 'div', 237 array( 238 'class' => 'setup-issue-debug', 239 ), 240 pht('Host: %s', php_uname('n'))); 241 242 return phutil_tag( 243 'div', 244 array( 245 'class' => 'setup-issue-shell', 246 ), 247 array( 248 $issue, 249 $next, 250 $debug_info, 251 )); 252 } 253 254 private function renderPhabricatorConfig(array $configs, $related = false) { 255 $issue = $this->getIssue(); 256 257 $table_info = phutil_tag( 258 'p', 259 array(), 260 pht( 261 'The current configuration has these %d value(s):', 262 count($configs))); 263 264 $options = PhabricatorApplicationConfigOptions::loadAllOptions(); 265 $hidden = array(); 266 foreach ($options as $key => $option) { 267 if ($option->getHidden()) { 268 $hidden[$key] = true; 269 } 270 } 271 272 $table = null; 273 $dict = array(); 274 foreach ($configs as $key) { 275 if (isset($hidden[$key])) { 276 $dict[$key] = null; 277 } else { 278 $dict[$key] = PhabricatorEnv::getUnrepairedEnvConfig($key); 279 } 280 } 281 282 $table = $this->renderValueTable($dict, $hidden); 283 284 if ($this->getIssue()->getIsFatal()) { 285 $update_info = phutil_tag( 286 'p', 287 array(), 288 pht( 289 'To update these %d value(s), run these command(s) from the command '. 290 'line:', 291 count($configs))); 292 293 $update = array(); 294 foreach ($configs as $key) { 295 $update[] = hsprintf( 296 '<samp>%s $</samp><kbd>./bin/config set %s <em>value</em></kbd>', 297 PlatformSymbols::getPlatformServerPath(), 298 $key); 299 } 300 $update = phutil_tag('pre', array(), phutil_implode_html("\n", $update)); 301 } else { 302 $update = array(); 303 foreach ($configs as $config) { 304 if (idx($options, $config) && $options[$config]->getLocked()) { 305 $name = pht('View "%s"', $config); 306 } else { 307 $name = pht('Edit "%s"', $config); 308 } 309 $link = phutil_tag( 310 'a', 311 array( 312 'href' => '/config/edit/'.$config.'/?issue='.$issue->getIssueKey(), 313 ), 314 $name); 315 $update[] = phutil_tag('li', array(), $link); 316 } 317 if ($update) { 318 $update = phutil_tag('ul', array(), $update); 319 if (!$related) { 320 $update_info = phutil_tag( 321 'p', 322 array(), 323 pht('You can update these %d value(s) here:', count($configs))); 324 } else { 325 $update_info = phutil_tag( 326 'p', 327 array(), 328 pht('These %d configuration value(s) are related:', count($configs))); 329 } 330 } else { 331 $update = null; 332 $update_info = null; 333 } 334 } 335 336 return phutil_tag( 337 'div', 338 array( 339 'class' => 'setup-issue-config', 340 ), 341 array( 342 $table_info, 343 $table, 344 $update_info, 345 $update, 346 )); 347 } 348 349 private function renderPHPConfig(array $configs, $issue) { 350 $table_info = phutil_tag( 351 'p', 352 array(), 353 pht( 354 'The current PHP configuration has these %d value(s):', 355 count($configs))); 356 357 $dict = array(); 358 foreach ($configs as $key) { 359 $dict[$key] = $issue->getPHPConfigOriginalValue( 360 $key, 361 ini_get($key)); 362 } 363 364 $table = $this->renderValueTable($dict); 365 366 ob_start(); 367 phpinfo(); 368 $phpinfo = ob_get_clean(); 369 370 371 $rex = '@Loaded Configuration File\s*</td><td class="v">(.*?)</td>@i'; 372 $matches = null; 373 374 $ini_loc = null; 375 if ($phpinfo && preg_match($rex, $phpinfo, $matches)) { 376 $ini_loc = trim($matches[1]); 377 } 378 379 $rex = '@Additional \.ini files parsed\s*</td><td class="v">(.*?)</td>@i'; 380 381 $more_loc = array(); 382 if ($phpinfo && preg_match($rex, $phpinfo, $matches)) { 383 $more_loc = trim($matches[1]); 384 if ($more_loc == '(none)') { 385 $more_loc = array(); 386 } else { 387 $more_loc = preg_split('/\s*,\s*/', $more_loc); 388 } 389 } 390 391 $info = array(); 392 if (!$ini_loc) { 393 $info[] = phutil_tag( 394 'p', 395 array(), 396 pht( 397 'To update these %d value(s), edit your PHP configuration file.', 398 count($configs))); 399 } else { 400 $info[] = phutil_tag( 401 'p', 402 array(), 403 pht( 404 'To update these %d value(s), edit your PHP configuration file, '. 405 'located here:', 406 count($configs))); 407 $info[] = phutil_tag( 408 'pre', 409 array(), 410 $ini_loc); 411 } 412 413 if ($more_loc) { 414 $info[] = phutil_tag( 415 'p', 416 array(), 417 pht( 418 'PHP also loaded these %s configuration file(s):', 419 phutil_count($more_loc))); 420 $info[] = phutil_tag( 421 'pre', 422 array(), 423 implode("\n", $more_loc)); 424 } 425 426 $show_standard = false; 427 $show_opcache = false; 428 429 foreach ($configs as $key) { 430 if (preg_match('/^opcache\./', $key)) { 431 $show_opcache = true; 432 } else { 433 $show_standard = true; 434 } 435 } 436 437 if ($show_standard) { 438 $info[] = phutil_tag( 439 'p', 440 array(), 441 pht( 442 'You can find more information about PHP configuration values '. 443 'in the %s.', 444 phutil_tag( 445 'a', 446 array( 447 'href' => 'https://www.php.net/manual/ini.list.php', 448 'target' => '_blank', 449 ), 450 pht('PHP Documentation')))); 451 } 452 453 if ($show_opcache) { 454 $info[] = phutil_tag( 455 'p', 456 array(), 457 pht( 458 'You can find more information about configuring OPcache in '. 459 'the %s.', 460 phutil_tag( 461 'a', 462 array( 463 'href' => 'https://www.php.net/manual/opcache.configuration.php', 464 'target' => '_blank', 465 ), 466 pht('PHP OPcache Documentation')))); 467 } 468 469 $info[] = phutil_tag( 470 'p', 471 array(), 472 pht( 473 'After editing the PHP configuration, <strong>restart everything for '. 474 'the changes to take effect</strong>. For help with restarting '. 475 'everything, see %s in the documentation.', 476 $this->renderRestartLink())); 477 478 return phutil_tag( 479 'div', 480 array( 481 'class' => 'setup-issue-config', 482 ), 483 array( 484 $table_info, 485 $table, 486 $info, 487 )); 488 } 489 490 private function renderMySQLConfig(array $config) { 491 $values = array(); 492 $issue = $this->getIssue(); 493 $ref = $issue->getDatabaseRef(); 494 if ($ref) { 495 foreach ($config as $key) { 496 $value = $ref->loadRawMySQLConfigValue($key); 497 if ($value === null) { 498 $value = phutil_tag( 499 'em', 500 array(), 501 pht('(Not Supported)')); 502 } 503 $values[$key] = $value; 504 } 505 } 506 507 $table = $this->renderValueTable($values); 508 509 $doc_href = PhabricatorEnv::getDoclink('User Guide: Amazon RDS'); 510 $doc_link = phutil_tag( 511 'a', 512 array( 513 'href' => $doc_href, 514 'target' => '_blank', 515 ), 516 pht('User Guide: Amazon RDS')); 517 518 $info = array(); 519 $info[] = phutil_tag( 520 'p', 521 array(), 522 pht( 523 'If you are using Amazon RDS, some of the instructions above may '. 524 'not apply to you. See %s for discussion of Amazon RDS.', 525 $doc_link)); 526 527 $table_info = phutil_tag( 528 'p', 529 array(), 530 pht( 531 'The current MySQL configuration has these %d value(s):', 532 count($config))); 533 534 return phutil_tag( 535 'div', 536 array( 537 'class' => 'setup-issue-config', 538 ), 539 array( 540 $table_info, 541 $table, 542 $info, 543 )); 544 } 545 546 private function renderValueTable(array $dict, array $hidden = array()) { 547 $rows = array(); 548 foreach ($dict as $key => $value) { 549 if (isset($hidden[$key])) { 550 $value = phutil_tag('em', array(), 'hidden'); 551 } else { 552 $value = $this->renderValueForDisplay($value); 553 } 554 555 $cols = array( 556 phutil_tag('th', array(), $key), 557 phutil_tag('td', array(), $value), 558 ); 559 $rows[] = phutil_tag('tr', array(), $cols); 560 } 561 return phutil_tag('table', array(), $rows); 562 } 563 564 private function renderValueForDisplay($value) { 565 if ($value === null) { 566 return phutil_tag('em', array(), 'null'); 567 } else if ($value === false) { 568 return phutil_tag('em', array(), 'false'); 569 } else if ($value === true) { 570 return phutil_tag('em', array(), 'true'); 571 } else if ($value === '') { 572 return phutil_tag('em', array(), 'empty string'); 573 } else if ($value instanceof PhutilSafeHTML) { 574 return $value; 575 } else { 576 return PhabricatorConfigJSON::prettyPrintJSON($value); 577 } 578 } 579 580 private function renderRelatedLinks(array $links) { 581 $link_info = phutil_tag( 582 'p', 583 array(), 584 pht( 585 '%d related link(s):', 586 count($links))); 587 588 $link_list = array(); 589 foreach ($links as $link) { 590 $link_tag = phutil_tag( 591 'a', 592 array( 593 'target' => '_blank', 594 'href' => $link['href'], 595 ), 596 $link['name']); 597 $link_item = phutil_tag('li', array(), $link_tag); 598 $link_list[] = $link_item; 599 } 600 $link_list = phutil_tag('ul', array(), $link_list); 601 602 return phutil_tag( 603 'div', 604 array( 605 'class' => 'setup-issue-config', 606 ), 607 array( 608 $link_info, 609 $link_list, 610 )); 611 } 612 613 private function renderRestartLink() { 614 $doc_href = PhabricatorEnv::getDoclink('Restarting Phorge'); 615 return phutil_tag( 616 'a', 617 array( 618 'href' => $doc_href, 619 'target' => '_blank', 620 ), 621 pht('Restarting')); 622 } 623 624}