Path: blob/master/src/applications/config/view/PhabricatorSetupIssueView.php
12256 views
<?php12final class PhabricatorSetupIssueView extends AphrontView {34private $issue;56public function setIssue(PhabricatorSetupIssue $issue) {7$this->issue = $issue;8return $this;9}1011public function getIssue() {12return $this->issue;13}1415public function renderInFlight() {16$issue = $this->getIssue();1718return id(new PhabricatorInFlightErrorView())19->setMessage($issue->getName())20->render();21}2223public function render() {24$issue = $this->getIssue();2526$description = array();27$description[] = phutil_tag(28'div',29array(30'class' => 'setup-issue-instructions',31),32phutil_escape_html_newlines($issue->getMessage()));3334$configs = $issue->getPHPConfig();35if ($configs) {36$description[] = $this->renderPHPConfig($configs, $issue);37}3839$configs = $issue->getMySQLConfig();40if ($configs) {41$description[] = $this->renderMySQLConfig($configs);42}4344$configs = $issue->getPhabricatorConfig();45if ($configs) {46$description[] = $this->renderPhabricatorConfig($configs);47}4849$related_configs = $issue->getRelatedPhabricatorConfig();50if ($related_configs) {51$description[] = $this->renderPhabricatorConfig($related_configs,52$related = true);53}5455$commands = $issue->getCommands();56if ($commands) {57$run_these = pht('Run these %d command(s):', count($commands));58$description[] = phutil_tag(59'div',60array(61'class' => 'setup-issue-config',62),63array(64phutil_tag('p', array(), $run_these),65phutil_tag('pre', array(), phutil_implode_html("\n", $commands)),66));67}6869$extensions = $issue->getPHPExtensions();70if ($extensions) {71$install_these = pht(72'Install these %d PHP extension(s):', count($extensions));7374$install_info = pht(75'You can usually install a PHP extension using %s or %s. Common '.76'package names are %s or %s. Try commands like these:',77phutil_tag('tt', array(), 'apt-get'),78phutil_tag('tt', array(), 'yum'),79hsprintf('<tt>php-<em>%s</em></tt>', pht('extname')),80hsprintf('<tt>php5-<em>%s</em></tt>', pht('extname')));8182// TODO: We should do a better job of detecting how to install extensions83// on the current system.84$install_commands = hsprintf(85"\$ sudo apt-get install php5-<em>extname</em> ".86"# Debian / Ubuntu\n".87"\$ sudo yum install php-<em>extname</em> ".88"# Red Hat / Derivatives");8990$fallback_info = pht(91"If those commands don't work, try Google. The process of installing ".92"PHP extensions is not specific to this software, and any ".93"instructions you can find for installing them on your system should ".94"work. On Mac OS X, you might want to try Homebrew.");9596$restart_info = pht(97'After installing new PHP extensions, <strong>restart everything '.98'for the changes to take effect</strong>. For help with restarting '.99'everything, see %s in the documentation.',100$this->renderRestartLink());101102$description[] = phutil_tag(103'div',104array(105'class' => 'setup-issue-config',106),107array(108phutil_tag('p', array(), $install_these),109phutil_tag('pre', array(), implode("\n", $extensions)),110phutil_tag('p', array(), $install_info),111phutil_tag('pre', array(), $install_commands),112phutil_tag('p', array(), $fallback_info),113phutil_tag('p', array(), $restart_info),114));115116}117118$related_links = $issue->getLinks();119if ($related_links) {120$description[] = $this->renderRelatedLinks($related_links);121}122123$actions = array();124if (!$issue->getIsFatal()) {125if ($issue->getIsIgnored()) {126$actions[] = javelin_tag(127'a',128array(129'href' => '/config/unignore/'.$issue->getIssueKey().'/',130'sigil' => 'workflow',131'class' => 'button button-grey',132),133pht('Unignore Setup Issue'));134} else {135$actions[] = javelin_tag(136'a',137array(138'href' => '/config/ignore/'.$issue->getIssueKey().'/',139'sigil' => 'workflow',140'class' => 'button button-grey',141),142pht('Ignore Setup Issue'));143}144145$actions[] = javelin_tag(146'a',147array(148'href' => '/config/issue/'.$issue->getIssueKey().'/',149'class' => 'button button-grey',150),151pht('Reload Page'));152}153154if ($actions) {155$actions = phutil_tag(156'div',157array(158'class' => 'setup-issue-actions',159),160$actions);161}162163if ($issue->getIsIgnored()) {164$status = phutil_tag(165'div',166array(167'class' => 'setup-issue-status',168),169pht(170'This issue is currently ignored, and does not show a global '.171'warning.'));172$next = null;173} else {174$status = null;175$next = phutil_tag(176'div',177array(178'class' => 'setup-issue-next',179),180pht('To continue, resolve this problem and reload the page.'));181}182183$name = phutil_tag(184'div',185array(186'class' => 'setup-issue-name',187),188$issue->getName());189190$head = phutil_tag(191'div',192array(193'class' => 'setup-issue-head',194),195$name);196197$body = phutil_tag(198'div',199array(200'class' => 'setup-issue-body',201),202array(203$status,204$description,205));206207$tail = phutil_tag(208'div',209array(210'class' => 'setup-issue-tail',211),212$actions);213214$issue = phutil_tag(215'div',216array(217'class' => 'setup-issue',218),219array(220$head,221$body,222$tail,223));224225$debug_info = phutil_tag(226'div',227array(228'class' => 'setup-issue-debug',229),230pht('Host: %s', php_uname('n')));231232return phutil_tag(233'div',234array(235'class' => 'setup-issue-shell',236),237array(238$issue,239$next,240$debug_info,241));242}243244private function renderPhabricatorConfig(array $configs, $related = false) {245$issue = $this->getIssue();246247$table_info = phutil_tag(248'p',249array(),250pht(251'The current configuration has these %d value(s):',252count($configs)));253254$options = PhabricatorApplicationConfigOptions::loadAllOptions();255$hidden = array();256foreach ($options as $key => $option) {257if ($option->getHidden()) {258$hidden[$key] = true;259}260}261262$table = null;263$dict = array();264foreach ($configs as $key) {265if (isset($hidden[$key])) {266$dict[$key] = null;267} else {268$dict[$key] = PhabricatorEnv::getUnrepairedEnvConfig($key);269}270}271272$table = $this->renderValueTable($dict, $hidden);273274if ($this->getIssue()->getIsFatal()) {275$update_info = phutil_tag(276'p',277array(),278pht(279'To update these %d value(s), run these command(s) from the command '.280'line:',281count($configs)));282283$update = array();284foreach ($configs as $key) {285$update[] = hsprintf(286'<tt>$</tt> ./bin/config set %s <em>value</em>',287$key);288}289$update = phutil_tag('pre', array(), phutil_implode_html("\n", $update));290} else {291$update = array();292foreach ($configs as $config) {293if (idx($options, $config) && $options[$config]->getLocked()) {294$name = pht('View "%s"', $config);295} else {296$name = pht('Edit "%s"', $config);297}298$link = phutil_tag(299'a',300array(301'href' => '/config/edit/'.$config.'/?issue='.$issue->getIssueKey(),302),303$name);304$update[] = phutil_tag('li', array(), $link);305}306if ($update) {307$update = phutil_tag('ul', array(), $update);308if (!$related) {309$update_info = phutil_tag(310'p',311array(),312pht('You can update these %d value(s) here:', count($configs)));313} else {314$update_info = phutil_tag(315'p',316array(),317pht('These %d configuration value(s) are related:', count($configs)));318}319} else {320$update = null;321$update_info = null;322}323}324325return phutil_tag(326'div',327array(328'class' => 'setup-issue-config',329),330array(331$table_info,332$table,333$update_info,334$update,335));336}337338private function renderPHPConfig(array $configs, $issue) {339$table_info = phutil_tag(340'p',341array(),342pht(343'The current PHP configuration has these %d value(s):',344count($configs)));345346$dict = array();347foreach ($configs as $key) {348$dict[$key] = $issue->getPHPConfigOriginalValue(349$key,350ini_get($key));351}352353$table = $this->renderValueTable($dict);354355ob_start();356phpinfo();357$phpinfo = ob_get_clean();358359360$rex = '@Loaded Configuration File\s*</td><td class="v">(.*?)</td>@i';361$matches = null;362363$ini_loc = null;364if (preg_match($rex, $phpinfo, $matches)) {365$ini_loc = trim($matches[1]);366}367368$rex = '@Additional \.ini files parsed\s*</td><td class="v">(.*?)</td>@i';369370$more_loc = array();371if (preg_match($rex, $phpinfo, $matches)) {372$more_loc = trim($matches[1]);373if ($more_loc == '(none)') {374$more_loc = array();375} else {376$more_loc = preg_split('/\s*,\s*/', $more_loc);377}378}379380$info = array();381if (!$ini_loc) {382$info[] = phutil_tag(383'p',384array(),385pht(386'To update these %d value(s), edit your PHP configuration file.',387count($configs)));388} else {389$info[] = phutil_tag(390'p',391array(),392pht(393'To update these %d value(s), edit your PHP configuration file, '.394'located here:',395count($configs)));396$info[] = phutil_tag(397'pre',398array(),399$ini_loc);400}401402if ($more_loc) {403$info[] = phutil_tag(404'p',405array(),406pht(407'PHP also loaded these %s configuration file(s):',408phutil_count($more_loc)));409$info[] = phutil_tag(410'pre',411array(),412implode("\n", $more_loc));413}414415$show_standard = false;416$show_opcache = false;417418foreach ($configs as $key) {419if (preg_match('/^opcache\./', $key)) {420$show_opcache = true;421} else {422$show_standard = true;423}424}425426if ($show_standard) {427$info[] = phutil_tag(428'p',429array(),430pht(431'You can find more information about PHP configuration values '.432'in the %s.',433phutil_tag(434'a',435array(436'href' => 'http://php.net/manual/ini.list.php',437'target' => '_blank',438),439pht('PHP Documentation'))));440}441442if ($show_opcache) {443$info[] = phutil_tag(444'p',445array(),446pht(447'You can find more information about configuring OPcache in '.448'the %s.',449phutil_tag(450'a',451array(452'href' => 'http://php.net/manual/opcache.configuration.php',453'target' => '_blank',454),455pht('PHP OPcache Documentation'))));456}457458$info[] = phutil_tag(459'p',460array(),461pht(462'After editing the PHP configuration, <strong>restart everything for '.463'the changes to take effect</strong>. For help with restarting '.464'everything, see %s in the documentation.',465$this->renderRestartLink()));466467return phutil_tag(468'div',469array(470'class' => 'setup-issue-config',471),472array(473$table_info,474$table,475$info,476));477}478479private function renderMySQLConfig(array $config) {480$values = array();481$issue = $this->getIssue();482$ref = $issue->getDatabaseRef();483if ($ref) {484foreach ($config as $key) {485$value = $ref->loadRawMySQLConfigValue($key);486if ($value === null) {487$value = phutil_tag(488'em',489array(),490pht('(Not Supported)'));491}492$values[$key] = $value;493}494}495496$table = $this->renderValueTable($values);497498$doc_href = PhabricatorEnv::getDoclink('User Guide: Amazon RDS');499$doc_link = phutil_tag(500'a',501array(502'href' => $doc_href,503'target' => '_blank',504),505pht('User Guide: Amazon RDS'));506507$info = array();508$info[] = phutil_tag(509'p',510array(),511pht(512'If you are using Amazon RDS, some of the instructions above may '.513'not apply to you. See %s for discussion of Amazon RDS.',514$doc_link));515516$table_info = phutil_tag(517'p',518array(),519pht(520'The current MySQL configuration has these %d value(s):',521count($config)));522523return phutil_tag(524'div',525array(526'class' => 'setup-issue-config',527),528array(529$table_info,530$table,531$info,532));533}534535private function renderValueTable(array $dict, array $hidden = array()) {536$rows = array();537foreach ($dict as $key => $value) {538if (isset($hidden[$key])) {539$value = phutil_tag('em', array(), 'hidden');540} else {541$value = $this->renderValueForDisplay($value);542}543544$cols = array(545phutil_tag('th', array(), $key),546phutil_tag('td', array(), $value),547);548$rows[] = phutil_tag('tr', array(), $cols);549}550return phutil_tag('table', array(), $rows);551}552553private function renderValueForDisplay($value) {554if ($value === null) {555return phutil_tag('em', array(), 'null');556} else if ($value === false) {557return phutil_tag('em', array(), 'false');558} else if ($value === true) {559return phutil_tag('em', array(), 'true');560} else if ($value === '') {561return phutil_tag('em', array(), 'empty string');562} else if ($value instanceof PhutilSafeHTML) {563return $value;564} else {565return PhabricatorConfigJSON::prettyPrintJSON($value);566}567}568569private function renderRelatedLinks(array $links) {570$link_info = phutil_tag(571'p',572array(),573pht(574'%d related link(s):',575count($links)));576577$link_list = array();578foreach ($links as $link) {579$link_tag = phutil_tag(580'a',581array(582'target' => '_blank',583'href' => $link['href'],584),585$link['name']);586$link_item = phutil_tag('li', array(), $link_tag);587$link_list[] = $link_item;588}589$link_list = phutil_tag('ul', array(), $link_list);590591return phutil_tag(592'div',593array(594'class' => 'setup-issue-config',595),596array(597$link_info,598$link_list,599));600}601602private function renderRestartLink() {603$doc_href = PhabricatorEnv::getDoclink('Restarting Phabricator');604return phutil_tag(605'a',606array(607'href' => $doc_href,608'target' => '_blank',609),610pht('Restarting Phabricator'));611}612613}614615616