public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $keys = $request->getStr('keys');
     try {
         $keys = phutil_json_decode($keys);
     } catch (PhutilJSONParserException $ex) {
         return new Aphront400Response();
     }
     // There have been at least two users asking for a keyboard shortcut to
     // close the dialog, so be explicit that escape works since it isn't
     // terribly discoverable.
     $keys[] = array('keys' => array('esc'), 'description' => pht('Close any dialog, including this one.'));
     $stroke_map = array('left' => "←", 'right' => "→", 'up' => "↑", 'down' => "↓", 'return' => "⏎", 'tab' => "⇥", 'delete' => "⌫");
     $rows = array();
     foreach ($keys as $shortcut) {
         $keystrokes = array();
         foreach ($shortcut['keys'] as $stroke) {
             $stroke = idx($stroke_map, $stroke, $stroke);
             $keystrokes[] = phutil_tag('kbd', array(), $stroke);
         }
         $keystrokes = phutil_implode_html(' or ', $keystrokes);
         $rows[] = phutil_tag('tr', array(), array(phutil_tag('th', array(), $keystrokes), phutil_tag('td', array(), $shortcut['description'])));
     }
     $table = phutil_tag('table', array('class' => 'keyboard-shortcut-help'), $rows);
     return $this->newDialog()->setTitle(pht('Keyboard Shortcuts'))->appendChild($table)->addCancelButton('#', pht('Close'));
 }
 public function processRequest()
 {
     $root = dirname(phutil_get_library_root('phabricator'));
     require_once $root . '/support/phame/libskin.php';
     $this->cssResources = array();
     $css = $this->getPath('css/');
     if (Filesystem::pathExists($css)) {
         foreach (Filesystem::listDirectory($css) as $path) {
             if (!preg_match('/.css$/', $path)) {
                 continue;
             }
             $this->cssResources[] = phutil_tag('link', array('rel' => 'stylesheet', 'type' => 'text/css', 'href' => $this->getResourceURI('css/' . $path)));
         }
     }
     $map = CelerityResourceMap::getNamedInstance('phabricator');
     $resource_symbol = 'syntax-highlighting-css';
     $resource_uri = $map->getURIForSymbol($resource_symbol);
     $this->cssResources[] = phutil_tag('link', array('rel' => 'stylesheet', 'type' => 'text/css', 'href' => PhabricatorEnv::getCDNURI($resource_uri)));
     $this->cssResources = phutil_implode_html("\n", $this->cssResources);
     $request = $this->getRequest();
     // Render page parts in order so the templates execute in order, if we're
     // using templates.
     $header = $this->renderHeader();
     $content = $this->renderContent($request);
     $footer = $this->renderFooter();
     if (!$content) {
         $content = $this->render404Page();
     }
     $content = array($header, $content, $footer);
     $response = new AphrontWebpageResponse();
     $response->setContent(phutil_implode_html("\n", $content));
     return $response;
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $inlines = $this->loadInlineComments();
     assert_instances_of($inlines, 'PhabricatorInlineCommentInterface');
     $engine = new PhabricatorMarkupEngine();
     $engine->setViewer($user);
     foreach ($inlines as $inline) {
         $engine->addObject($inline, PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY);
     }
     $engine->process();
     $phids = array($user->getPHID());
     $handles = $this->loadViewerHandles($phids);
     $views = array();
     foreach ($inlines as $inline) {
         $view = new DifferentialInlineCommentView();
         $view->setInlineComment($inline);
         $view->setMarkupEngine($engine);
         $view->setHandles($handles);
         $view->setEditable(false);
         $view->setPreview(true);
         $views[] = $view->render();
     }
     $views = phutil_implode_html("\n", $views);
     return id(new AphrontAjaxResponse())->setContent($views);
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $document = id(new PhrictionDocumentQuery())->setViewer($user)->withIDs(array($this->id))->needContent(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT, PhabricatorPolicyCapability::CAN_VIEW))->executeOne();
     if (!$document) {
         return new Aphront404Response();
     }
     $document_uri = PhrictionDocument::getSlugURI($document->getSlug());
     $e_text = null;
     if ($request->isFormPost()) {
         $xactions = array();
         $xactions[] = id(new PhrictionTransaction())->setTransactionType(PhrictionTransaction::TYPE_DELETE)->setNewValue(true);
         $editor = id(new PhrictionTransactionEditor())->setActor($user)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true);
         try {
             $editor->applyTransactions($document, $xactions);
             return id(new AphrontRedirectResponse())->setURI($document_uri);
         } catch (PhabricatorApplicationTransactionValidationException $ex) {
             $e_text = phutil_implode_html("\n", $ex->getErrorMessages());
         }
     }
     if ($e_text) {
         $dialog = id(new AphrontDialogView())->setUser($user)->setTitle(pht('Can Not Delete Document!'))->appendChild($e_text)->addCancelButton($document_uri);
     } else {
         $dialog = id(new AphrontDialogView())->setUser($user)->setTitle(pht('Delete Document?'))->appendChild(pht('Really delete this document? You can recover it later by ' . 'reverting to a previous version.'))->addSubmitButton(pht('Delete'))->addCancelButton($document_uri);
     }
     return id(new AphrontDialogResponse())->setDialog($dialog);
 }
 public function render()
 {
     if ($this->header !== null) {
         $header = phutil_tag('h1', array(), $this->header);
     } else {
         $header = null;
     }
     if ($this->caption !== null) {
         $caption = phutil_tag_div('aphront-panel-view-caption', $this->caption);
     } else {
         $caption = null;
     }
     $buttons = null;
     if ($this->buttons) {
         $buttons = phutil_tag_div('aphront-panel-view-buttons', phutil_implode_html(' ', $this->buttons));
     }
     $header_elements = phutil_tag_div('aphront-panel-header', array($buttons, $header, $caption));
     $table = phutil_implode_html('', $this->renderChildren());
     require_celerity_resource('aphront-panel-view-css');
     $classes = $this->classes;
     $classes[] = 'aphront-panel-view';
     if ($this->width) {
         $classes[] = 'aphront-panel-width-' . $this->width;
     }
     return phutil_tag('div', array('class' => implode(' ', $classes), 'id' => $this->id), array($header_elements, $table));
 }
 private function getRevisionMatchExplanation($revision_match_data, PhabricatorObjectHandle $obj_handle)
 {
     if (!$revision_match_data) {
         return pht('This commit was made before this feature was built and thus this ' . 'information is unavailable.');
     }
     $body_why = array();
     if ($revision_match_data['usedURI']) {
         return pht('We found a "%s" field with value "%s" in the commit message, ' . 'and the domain on the URI matches this install, so ' . 'we linked this commit to %s.', 'Differential Revision', $revision_match_data['foundURI'], phutil_tag('a', array('href' => $obj_handle->getURI()), $obj_handle->getName()));
     } else {
         if ($revision_match_data['foundURI']) {
             $body_why[] = pht('We found a "%s" field with value "%s" in the commit message, ' . 'but the domain on this URI did not match the configured ' . 'domain for this install, "%s", so we ignored it under ' . 'the assumption that it refers to some third-party revision.', 'Differential Revision', $revision_match_data['foundURI'], $revision_match_data['validDomain']);
         } else {
             $body_why[] = pht('We didn\'t find a "%s" field in the commit message.', 'Differential Revision');
         }
     }
     switch ($revision_match_data['matchHashType']) {
         case ArcanistDifferentialRevisionHash::HASH_GIT_TREE:
             $hash_info = true;
             $hash_type = 'tree';
             break;
         case ArcanistDifferentialRevisionHash::HASH_GIT_COMMIT:
         case ArcanistDifferentialRevisionHash::HASH_MERCURIAL_COMMIT:
             $hash_info = true;
             $hash_type = 'commit';
             break;
         default:
             $hash_info = false;
             break;
     }
     if ($hash_info) {
         $diff_link = phutil_tag('a', array('href' => $obj_handle->getURI()), $obj_handle->getName());
         $body_why = pht('This commit and the active diff of %s had the same %s hash ' . '(%s) so we linked this commit to %s.', $diff_link, $hash_type, $revision_match_data['matchHashValue'], $diff_link);
     }
     return phutil_implode_html("\n", $body_why);
 }
 protected function getTagContent()
 {
     require_celerity_resource('ponder-view-css');
     $answer = $this->answer;
     $viewer = $this->getUser();
     $status = $answer->getStatus();
     $author_phid = $answer->getAuthorPHID();
     $actions = $this->buildAnswerActions();
     $handle = $this->handle;
     $id = $answer->getID();
     if ($status == PonderAnswerStatus::ANSWER_STATUS_HIDDEN) {
         $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $answer, PhabricatorPolicyCapability::CAN_EDIT);
         $message = array();
         $message[] = phutil_tag('em', array(), pht('This answer has been hidden.'));
         if ($can_edit) {
             $message[] = phutil_tag('a', array('href' => "/ponder/answer/edit/{$id}/"), pht('Edit Answer'));
         }
         $message = phutil_implode_html(' ', $message);
         return id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_NODATA)->appendChild($message);
     }
     $action_button = id(new PHUIButtonView())->setTag('a')->setText(pht('Actions'))->setHref('#')->setIcon('fa-bars')->setDropdownMenu($actions);
     $header_name = phutil_tag('a', array('href' => $handle->getURI()), $handle->getName());
     $header = id(new PHUIHeaderView())->setUser($viewer)->setEpoch($answer->getDateModified())->setHeader($header_name)->addActionLink($action_button)->setImage($handle->getImageURI())->setImageURL($handle->getURI());
     $content = phutil_tag('div', array('class' => 'phabricator-remarkup'), PhabricatorMarkupEngine::renderOneObject($answer, $answer->getMarkupField(), $viewer));
     $anchor = id(new PhabricatorAnchorView())->setAnchorName("A{$id}");
     $content_id = celerity_generate_unique_node_id();
     $footer = id(new PonderFooterView())->setContentID($content_id)->setCount(count($this->transactions));
     $content = phutil_tag_div('ponder-answer-content', array($anchor, $content, $footer));
     $answer_view = id(new PHUIObjectBoxView())->setHeader($header)->setBackground(PHUIObjectBoxView::GREY)->addClass('ponder-answer')->appendChild($content);
     $comment_view = id(new PhabricatorApplicationTransactionCommentView())->setUser($viewer)->setObjectPHID($answer->getPHID())->setShowPreview(false)->setHeaderText(pht('Answer Comment'))->setAction("/ponder/answer/comment/{$id}/")->setSubmitButtonName(pht('Comment'));
     $hidden_view = phutil_tag('div', array('id' => $content_id, 'style' => 'display: none;'), array($this->timeline, $comment_view));
     return array($answer_view, $hidden_view);
 }
Beispiel #8
0
 public function render()
 {
     require_celerity_resource('phabricator-source-code-view-css');
     require_celerity_resource('syntax-highlighting-css');
     Javelin::initBehavior('phabricator-oncopy', array());
     $line_number = $this->start;
     $rows = array();
     foreach ($this->lines as $line) {
         $hit_limit = $this->limit && $line_number == $this->limit && count($this->lines) != $this->limit;
         if ($hit_limit) {
             $content_number = '';
             $content_line = phutil_tag('span', array('class' => 'c'), pht('...'));
         } else {
             $content_number = $line_number;
             $content_line = $line;
         }
         $row_attributes = array();
         if (isset($this->highlights[$line_number])) {
             $row_attributes['class'] = 'phabricator-source-highlight';
         }
         // TODO: Provide nice links.
         $th = phutil_tag('th', array('class' => 'phabricator-source-line', 'style' => 'background-color: #fff;'), $content_number);
         $td = phutil_tag('td', array('class' => 'phabricator-source-code'), $content_line);
         $rows[] = phutil_tag('tr', $row_attributes, array($th, $td));
         if ($hit_limit) {
             break;
         }
         $line_number++;
     }
     $classes = array();
     $classes[] = 'phabricator-source-code-view';
     $classes[] = 'remarkup-code';
     $classes[] = 'PhabricatorMonospaced';
     return phutil_tag('div', array('class' => 'phabricator-source-code-container', 'style' => 'background-color: black; color: white;'), phutil_tag('table', array('class' => implode(' ', $classes), 'style' => 'background-color: black'), phutil_implode_html('', $rows)));
 }
 public function renderPanel()
 {
     $data = $this->getData();
     $sections = array('Basics' => array('Machine' => php_uname('n')));
     // NOTE: This may not be present for some SAPIs, like php-fpm.
     if (!empty($data['Server']['SERVER_ADDR'])) {
         $addr = $data['Server']['SERVER_ADDR'];
         $sections['Basics']['Host'] = $addr;
         $sections['Basics']['Hostname'] = @gethostbyaddr($addr);
     }
     $sections = array_merge($sections, $data);
     $mask = array('HTTP_COOKIE' => true, 'HTTP_X_PHABRICATOR_CSRF' => true);
     $out = array();
     foreach ($sections as $header => $map) {
         $rows = array();
         foreach ($map as $key => $value) {
             if (isset($mask[$key])) {
                 $rows[] = array($key, phutil_tag('em', array(), '(Masked)'));
             } else {
                 $rows[] = array($key, is_array($value) ? json_encode($value) : $value);
             }
         }
         $table = new AphrontTableView($rows);
         $table->setHeaders(array($header, null));
         $table->setColumnClasses(array('header', 'wide wrap'));
         $out[] = $table->render();
     }
     return phutil_implode_html("\n", $out);
 }
 public function markupNavigation(array $matches)
 {
     if (!$this->isFlatText($matches[0])) {
         return $matches[0];
     }
     $elements = ltrim($matches[1], ", \n");
     $elements = explode('>', $elements);
     $defaults = array('name' => null, 'type' => 'link', 'href' => null, 'icon' => null);
     $sequence = array();
     $parser = new PhutilSimpleOptions();
     foreach ($elements as $element) {
         if (strpos($element, '=') === false) {
             $sequence[] = array('name' => trim($element)) + $defaults;
         } else {
             $sequence[] = $parser->parse($element) + $defaults;
         }
     }
     if ($this->getEngine()->isTextMode()) {
         return implode(' > ', ipull($sequence, 'name'));
     }
     static $icon_names;
     if (!$icon_names) {
         $icon_names = array_fuse(PHUIIconView::getIcons());
     }
     $out = array();
     foreach ($sequence as $item) {
         $item_name = $item['name'];
         $item_color = PHUITagView::COLOR_GREY;
         if ($item['type'] == 'instructions') {
             $item_name = phutil_tag('em', array(), $item_name);
             $item_color = PHUITagView::COLOR_INDIGO;
         }
         $tag = id(new PHUITagView())->setType(PHUITagView::TYPE_SHADE)->setShade($item_color)->setName($item_name);
         if ($item['icon']) {
             $icon_name = 'fa-' . $item['icon'];
             if (isset($icon_names[$icon_name])) {
                 $tag->setIcon($icon_name);
             }
         }
         if ($item['href'] !== null) {
             if (PhabricatorEnv::isValidRemoteURIForLink($item['href'])) {
                 $tag->setHref($item['href']);
                 $tag->setExternal(true);
             }
         }
         $out[] = $tag;
     }
     if ($this->getEngine()->isHTMLMailMode()) {
         $arrow_attr = array('style' => 'color: #92969D;');
         $nav_attr = array();
     } else {
         $arrow_attr = array('class' => 'remarkup-nav-sequence-arrow');
         $nav_attr = array('class' => 'remarkup-nav-sequence');
     }
     $joiner = phutil_tag('span', $arrow_attr, " → ");
     $out = phutil_implode_html($joiner, $out);
     $out = phutil_tag('span', $nav_attr, $out);
     return $this->getEngine()->storeText($out);
 }
 public function renderThreadsHTML()
 {
     $thread_html = array();
     foreach ($this->threads as $thread) {
         $thread_html[] = $this->renderSingleThread($thread);
     }
     return phutil_implode_html('', $thread_html);
 }
Beispiel #12
0
/**
 * Implodes selected handles from a pool of handles. Useful if you load handles
 * for various phids, but only render a few of them at a time.
 *
 * @return PhutilSafeHTML
 */
function implode_selected_handle_links($glue, array $handles, array $phids)
{
    $items = array();
    foreach ($phids as $phid) {
        $items[] = $handles[$phid]->renderLink();
    }
    return phutil_implode_html($glue, $items);
}
 private function buildClusterNotificationStatus()
 {
     $viewer = $this->getViewer();
     $servers = PhabricatorNotificationServerRef::newRefs();
     Javelin::initBehavior('phabricator-tooltips');
     $rows = array();
     foreach ($servers as $server) {
         if ($server->isAdminServer()) {
             $type_icon = 'fa-database sky';
             $type_tip = pht('Admin Server');
         } else {
             $type_icon = 'fa-bell sky';
             $type_tip = pht('Client Server');
         }
         $type_icon = id(new PHUIIconView())->setIcon($type_icon)->addSigil('has-tooltip')->setMetadata(array('tip' => $type_tip));
         $messages = array();
         $details = array();
         if ($server->isAdminServer()) {
             try {
                 $details = $server->loadServerStatus();
                 $status_icon = 'fa-exchange green';
                 $status_label = pht('Version %s', idx($details, 'version'));
             } catch (Exception $ex) {
                 $status_icon = 'fa-times red';
                 $status_label = pht('Connection Error');
                 $messages[] = $ex->getMessage();
             }
         } else {
             try {
                 $server->testClient();
                 $status_icon = 'fa-exchange green';
                 $status_label = pht('Connected');
             } catch (Exception $ex) {
                 $status_icon = 'fa-times red';
                 $status_label = pht('Connection Error');
                 $messages[] = $ex->getMessage();
             }
         }
         if ($details) {
             $uptime = idx($details, 'uptime');
             $uptime = $uptime / 1000;
             $uptime = phutil_format_relative_time_detailed($uptime);
             $clients = pht('%s Active / %s Total', new PhutilNumber(idx($details, 'clients.active')), new PhutilNumber(idx($details, 'clients.total')));
             $stats = pht('%s In / %s Out', new PhutilNumber(idx($details, 'messages.in')), new PhutilNumber(idx($details, 'messages.out')));
         } else {
             $uptime = null;
             $clients = null;
             $stats = null;
         }
         $status_view = array(id(new PHUIIconView())->setIcon($status_icon), ' ', $status_label);
         $messages = phutil_implode_html(phutil_tag('br'), $messages);
         $rows[] = array($type_icon, $server->getProtocol(), $server->getHost(), $server->getPort(), $status_view, $uptime, $clients, $stats, $messages);
     }
     $table = id(new AphrontTableView($rows))->setNoDataString(pht('No notification servers are configured.'))->setHeaders(array(null, pht('Proto'), pht('Host'), pht('Port'), pht('Status'), pht('Uptime'), pht('Clients'), pht('Messages'), null))->setColumnClasses(array(null, null, null, null, null, null, null, null, 'wide'));
     $doc_href = PhabricatorEnv::getDoclink('Cluster: Notifications');
     $header = id(new PHUIHeaderView())->setHeader(pht('Cluster Notification Status'))->addActionLink(id(new PHUIButtonView())->setIcon('fa-book')->setHref($doc_href)->setTag('a')->setText(pht('Documentation')));
     return id(new PHUIObjectBoxView())->setHeader($header)->setTable($table);
 }
 public function markupText($text, $children)
 {
     $text = preg_replace('/%%%\\s*$/', '', substr($text, 3));
     if ($this->getEngine()->isTextMode()) {
         return $text;
     }
     $text = phutil_split_lines($text, $retain_endings = true);
     return phutil_implode_html(phutil_tag('br', array()), $text);
 }
 public function renderPropertyViewValue(array $handles)
 {
     $value = $this->getFieldValue();
     if (!$value) {
         return null;
     }
     $handles = mpull($handles, 'renderLink');
     $handles = phutil_implode_html(', ', $handles);
     return $handles;
 }
 private function buildResources()
 {
     $css = array('application/config/config-template.css', 'application/config/setup-issue.css');
     $webroot = dirname(phutil_get_library_root('phabricator')) . '/webroot/';
     $resources = array();
     foreach ($css as $path) {
         $resources[] = phutil_tag('style', array('type' => 'text/css'), phutil_safe_html(Filesystem::readFile($webroot . '/rsrc/css/' . $path)));
     }
     return phutil_implode_html("\n", $resources);
 }
 private function buildResources()
 {
     $paths = $this->getResources();
     $webroot = dirname(phutil_get_library_root('phabricator')) . '/webroot/';
     $resources = array();
     foreach ($paths as $path) {
         $resources[] = phutil_tag('style', array('type' => 'text/css'), phutil_safe_html(Filesystem::readFile($webroot . '/rsrc/' . $path)));
     }
     return phutil_implode_html("\n", $resources);
 }
 public function markupKeystrokes(array $matches)
 {
     if (!$this->isFlatText($matches[0])) {
         return $matches[0];
     }
     $keys = explode(' ', $matches[1]);
     foreach ($keys as $k => $v) {
         $v = trim($v, " \n");
         $v = preg_replace('/\\\\(.)/', '\\1', $v);
         if (!strlen($v)) {
             unset($keys[$k]);
             continue;
         }
         $keys[$k] = $v;
     }
     $special = array(array('name' => pht('Command'), 'symbol' => "⌘", 'aliases' => array('cmd', 'command')), array('name' => pht('Option'), 'symbol' => "⌥", 'aliases' => array('opt', 'option')), array('name' => pht('Shift'), 'symbol' => "⇧", 'aliases' => array('shift')), array('name' => pht('Escape'), 'symbol' => "⎋", 'aliases' => array('esc', 'escape')), array('name' => pht('Up'), 'symbol' => "↑", 'heavy' => "⬆", 'aliases' => array('up', 'arrow-up', 'up-arrow', 'north')), array('name' => pht('Tab'), 'symbol' => "⇥", 'aliases' => array('tab')), array('name' => pht('Right'), 'symbol' => "→", 'heavy' => "➡", 'aliases' => array('right', 'right-arrow', 'arrow-right', 'east')), array('name' => pht('Left'), 'symbol' => "←", 'heavy' => "⬅", 'aliases' => array('left', 'left-arrow', 'arrow-left', 'west')), array('name' => pht('Down'), 'symbol' => "↓", 'heavy' => "⬇", 'aliases' => array('down', 'down-arrow', 'arrow-down', 'south')), array('name' => pht('Up Right'), 'symbol' => "↗", 'heavy' => "⬈", 'aliases' => array('up-right', 'upright', 'up-right-arrow', 'upright-arrow', 'arrow-up-right', 'arrow-upright', 'northeast', 'north-east')), array('name' => pht('Down Right'), 'symbol' => "↘", 'heavy' => "⬊", 'aliases' => array('down-right', 'downright', 'down-right-arrow', 'downright-arrow', 'arrow-down-right', 'arrow-downright', 'southeast', 'south-east')), array('name' => pht('Down Left'), 'symbol' => "↙", 'heavy' => "⬋", 'aliases' => array('down-left', 'downleft', 'down-left-arrow', 'downleft-arrow', 'arrow-down-left', 'arrow-downleft', 'southwest', 'south-west')), array('name' => pht('Up Left'), 'symbol' => "↖", 'heavy' => "⬉", 'aliases' => array('up-left', 'upleft', 'up-left-arrow', 'upleft-arrow', 'arrow-up-left', 'arrow-upleft', 'northwest', 'north-west')));
     $map = array();
     foreach ($special as $spec) {
         foreach ($spec['aliases'] as $alias) {
             $map[$alias] = $spec;
         }
     }
     $is_text = $this->getEngine()->isTextMode();
     $is_html_mail = $this->getEngine()->isHTMLMailMode();
     if ($is_html_mail) {
         $key_style = array('display: inline-block;', 'min-width: 1em;', 'padding: 4px 5px 5px;', 'font-weight: normal;', 'font-size: 0.8rem;', 'text-align: center;', 'text-decoration: none;', 'line-height: 0.6rem;', 'border-radius: 3px;', 'box-shadow: inset 0 -1px 0 rgba(71, 87, 120, 0.08);', 'user-select: none;', 'background: #f7f7f7;', 'border: 1px solid #C7CCD9;');
         $key_style = implode(' ', $key_style);
         $join_style = array('padding: 0 4px;', 'color: #92969D;');
         $join_style = implode(' ', $join_style);
     } else {
         $key_style = null;
         $join_style = null;
     }
     $parts = array();
     foreach ($keys as $k => $v) {
         $normal = phutil_utf8_strtolower($v);
         if (isset($map[$normal])) {
             $spec = $map[$normal];
         } else {
             $spec = array('name' => null, 'symbol' => $v);
         }
         if ($is_text) {
             $parts[] = '[' . $spec['symbol'] . ']';
         } else {
             $parts[] = phutil_tag('kbd', array('title' => $spec['name'], 'style' => $key_style), $spec['symbol']);
         }
     }
     if ($is_text) {
         $parts = implode(' + ', $parts);
     } else {
         $glue = phutil_tag('span', array('class' => 'kbd-join', 'style' => $join_style), '+');
         $parts = phutil_implode_html($glue, $parts);
     }
     return $this->getEngine()->storeText($parts);
 }
 public function render()
 {
     $id = celerity_generate_unique_node_id();
     $placeholder = phutil_tag('span', array('id' => $id));
     require_celerity_resource($this->getCelerityResource());
     $render_context = self::peekRenderContext();
     self::pushRenderContext($id);
     Javelin::initBehavior('view-placeholder', array('id' => $id, 'view' => $this->getName(), 'params' => $this->getParameters(), 'children' => phutil_implode_html('', $this->renderChildren()), 'trigger_id' => $render_context));
     self::popRenderContext();
     return $placeholder;
 }
 public function renderConditionValue(PhabricatorUser $viewer, $value)
 {
     $change_map = PhabricatorRepositoryPushLog::getHeraldChangeFlagConditionOptions();
     foreach ($value as $index => $val) {
         $name = idx($change_map, $val);
         if ($name) {
             $value[$index] = $name;
         }
     }
     return phutil_implode_html(', ', $value);
 }
 protected function executeChecks()
 {
     $master = PhabricatorDatabaseRef::getMasterDatabaseRef();
     if (!$master) {
         // If we're implicitly in read-only mode during disaster recovery,
         // don't bother with these setup checks.
         return;
     }
     $conn_raw = $master->newManagementConnection();
     try {
         queryfx($conn_raw, 'SELECT 1');
         $database_exception = null;
     } catch (AphrontInvalidCredentialsQueryException $ex) {
         $database_exception = $ex;
     } catch (AphrontConnectionQueryException $ex) {
         $database_exception = $ex;
     }
     if ($database_exception) {
         $issue = PhabricatorSetupIssue::newDatabaseConnectionIssue($database_exception);
         $this->addIssue($issue);
         return;
     }
     $engines = queryfx_all($conn_raw, 'SHOW ENGINES');
     $engines = ipull($engines, 'Support', 'Engine');
     $innodb = idx($engines, 'InnoDB');
     if ($innodb != 'YES' && $innodb != 'DEFAULT') {
         $message = pht("The 'InnoDB' engine is not available in MySQL. Enable InnoDB in " . "your MySQL configuration." . "\n\n" . "(If you aleady created tables, MySQL incorrectly used some other " . "engine to create them. You need to convert them or drop and " . "reinitialize them.)");
         $this->newIssue('mysql.innodb')->setName(pht('MySQL InnoDB Engine Not Available'))->setMessage($message)->setIsFatal(true);
         return;
     }
     $namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace');
     $databases = queryfx_all($conn_raw, 'SHOW DATABASES');
     $databases = ipull($databases, 'Database', 'Database');
     if (empty($databases[$namespace . '_meta_data'])) {
         $message = pht("Run the storage upgrade script to setup Phabricator's database " . "schema.");
         $this->newIssue('storage.upgrade')->setName(pht('Setup MySQL Schema'))->setMessage($message)->setIsFatal(true)->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade'));
     } else {
         $conn_meta = $master->newApplicationConnection($namespace . '_meta_data');
         $applied = queryfx_all($conn_meta, 'SELECT patch FROM patch_status');
         $applied = ipull($applied, 'patch', 'patch');
         $all = PhabricatorSQLPatchList::buildAllPatches();
         $diff = array_diff_key($all, $applied);
         if ($diff) {
             $this->newIssue('storage.patch')->setName(pht('Upgrade MySQL Schema'))->setMessage(pht("Run the storage upgrade script to upgrade Phabricator's " . "database schema. Missing patches:<br />%s<br />", phutil_implode_html(phutil_tag('br'), array_keys($diff))))->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade'));
         }
     }
     $host = PhabricatorEnv::getEnvConfig('mysql.host');
     $matches = null;
     if (preg_match('/^([^:]+):(\\d+)$/', $host, $matches)) {
         $host = $matches[1];
         $port = $matches[2];
         $this->newIssue('storage.mysql.hostport')->setName(pht('Deprecated mysql.host Format'))->setSummary(pht('Move port information from `%s` to `%s` in your config.', 'mysql.host', 'mysql.port'))->setMessage(pht('Your `%s` configuration contains a port number, but this usage ' . 'is deprecated. Instead, put the port number in `%s`.', 'mysql.host', 'mysql.port'))->addPhabricatorConfig('mysql.host')->addPhabricatorConfig('mysql.port')->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/config set mysql.host %s', $host))->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/config set mysql.port %s', $port));
     }
 }
 private function renderWeirdOrderGlyphBars()
 {
     $views = array();
     $indices = array(1, 3, 7, 4, 2, 8, 9, 5, 10, 6);
     $max = count($indices);
     foreach ($indices as $index) {
         $views[] = id(new AphrontGlyphBarView())->setValue($index)->setMax($max)->setNumGlyphs(5)->setCaption("Lol score is {$index}/{$max}")->setGlyph(hsprintf('%s', 'LOL!'))->setBackgroundGlyph(hsprintf('%s', '____'))->render();
         $views[] = hsprintf('<div style="clear:both;"></div>');
     }
     return $this->wrap('Glyph bars in weird order', phutil_implode_html('', $views));
 }
 public function markupText($text)
 {
     $lines = array();
     foreach (explode("\n", $text) as $line) {
         $lines[] = $this->applyRules(preg_replace('/^>\\s*/', '', $line));
     }
     if ($this->getEngine()->isTextMode()) {
         return '> ' . implode("\n> ", $lines);
     }
     return hsprintf('<blockquote><p>%s</p></blockquote>', phutil_implode_html(phutil_tag('br'), $lines));
 }
 public function renderPropertyViewValue(array $handles)
 {
     $xobjs = $this->loadDoorkeeperExternalObjects($this->getValue());
     if (!$xobjs) {
         return null;
     }
     $links = array();
     foreach ($xobjs as $xobj) {
         $links[] = id(new DoorkeeperTagView())->setExternalObject($xobj);
     }
     return phutil_implode_html(phutil_tag('br'), $links);
 }
 public function renderTextChange($range_start, $range_len, $rows)
 {
     $primitives = $this->buildPrimitives($range_start, $range_len);
     $out = array();
     foreach ($primitives as $p) {
         $type = $p['type'];
         switch ($type) {
             case 'old':
             case 'new':
                 $out[] = hsprintf('<tr>');
                 if ($type == 'old') {
                     if ($p['htype']) {
                         $class = 'left old';
                     } else {
                         $class = 'left';
                     }
                     $out[] = phutil_tag('th', array(), $p['line']);
                     $out[] = phutil_tag('th', array());
                     $out[] = phutil_tag('td', array('class' => $class), $p['render']);
                 } else {
                     if ($type == 'new') {
                         if ($p['htype']) {
                             $class = 'right new';
                             $out[] = phutil_tag('th', array());
                         } else {
                             $class = 'right';
                             $out[] = phutil_tag('th', array(), $p['oline']);
                         }
                         $out[] = phutil_tag('th', array(), $p['line']);
                         $out[] = phutil_tag('td', array('class' => $class), $p['render']);
                     }
                 }
                 $out[] = hsprintf('</tr>');
                 break;
             case 'inline':
                 $out[] = hsprintf('<tr><th /><th />');
                 $out[] = hsprintf('<td>');
                 $inline = $this->buildInlineComment($p['comment'], $p['right']);
                 $inline->setBuildScaffolding(false);
                 $out[] = $inline->render();
                 $out[] = hsprintf('</td></tr>');
                 break;
             default:
                 $out[] = hsprintf('<tr><th /><th /><td>%s</td></tr>', $type);
                 break;
         }
     }
     if ($out) {
         return $this->wrapChangeInTable(phutil_implode_html('', $out));
     }
     return null;
 }
 protected function getTagContent()
 {
     $items = array();
     foreach ($this->handleList as $handle) {
         $items[] = $handle->renderLink();
     }
     if ($this->getAsInline()) {
         $items = phutil_implode_html(', ', $items);
     } else {
         $items = phutil_implode_html(phutil_tag('br'), $items);
     }
     return $items;
 }
 private function handlePropertyEvent($event)
 {
     $user = $event->getUser();
     $object = $event->getValue('object');
     if (!$object || !$object->getPHID()) {
         // No object, or the object has no PHID yet..
         return;
     }
     if (!$object instanceof PhabricatorProjectInterface) {
         // This object doesn't have projects.
         return;
     }
     $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
     if ($project_phids) {
         $project_phids = array_reverse($project_phids);
         $handles = id(new PhabricatorHandleQuery())->setViewer($user)->withPHIDs($project_phids)->execute();
     } else {
         $handles = array();
     }
     // If this object can appear on boards, build the workboard annotations.
     // Some day, this might be a generic interface. For now, only tasks can
     // appear on boards.
     $can_appear_on_boards = $object instanceof ManiphestTask;
     $annotations = array();
     if ($handles && $can_appear_on_boards) {
         $engine = id(new PhabricatorBoardLayoutEngine())->setViewer($user)->setBoardPHIDs($project_phids)->setObjectPHIDs(array($object->getPHID()))->executeLayout();
         // TDOO: Generalize this UI and move it out of Maniphest.
         require_celerity_resource('maniphest-task-summary-css');
         foreach ($project_phids as $project_phid) {
             $handle = $handles[$project_phid];
             $columns = $engine->getObjectColumns($project_phid, $object->getPHID());
             $annotation = array();
             foreach ($columns as $column) {
                 $project_id = $column->getProject()->getID();
                 $column_name = pht('(%s)', $column->getDisplayName());
                 $column_link = phutil_tag('a', array('href' => "/project/board/{$project_id}/", 'class' => 'maniphest-board-link'), $column_name);
                 $annotation[] = $column_link;
             }
             if ($annotation) {
                 $annotations[$project_phid] = array(' ', phutil_implode_html(', ', $annotation));
             }
         }
     }
     if ($handles) {
         $list = id(new PHUIHandleTagListView())->setHandles($handles)->setAnnotations($annotations)->setShowHovercards(true);
     } else {
         $list = phutil_tag('em', array(), pht('None'));
     }
     $view = $event->getValue('view');
     $view->addProperty(pht('Projects'), $list);
 }
 protected function executeChecks()
 {
     $conf = PhabricatorEnv::newObjectFromConfig('mysql.configuration-provider');
     $conn_user = $conf->getUser();
     $conn_pass = $conf->getPassword();
     $conn_host = $conf->getHost();
     $conn_port = $conf->getPort();
     ini_set('mysql.connect_timeout', 2);
     $config = array('user' => $conn_user, 'pass' => $conn_pass, 'host' => $conn_host, 'port' => $conn_port, 'database' => null);
     $conn_raw = PhabricatorEnv::newObjectFromConfig('mysql.implementation', array($config));
     try {
         queryfx($conn_raw, 'SELECT 1');
     } catch (AphrontConnectionQueryException $ex) {
         $message = pht("Unable to connect to MySQL!\n\n" . "%s\n\n" . "Make sure Phabricator and MySQL are correctly configured.", $ex->getMessage());
         $this->newIssue('mysql.connect')->setName(pht('Can Not Connect to MySQL'))->setMessage($message)->setIsFatal(true)->addRelatedPhabricatorConfig('mysql.host')->addRelatedPhabricatorConfig('mysql.port')->addRelatedPhabricatorConfig('mysql.user')->addRelatedPhabricatorConfig('mysql.pass');
         return;
     }
     $engines = queryfx_all($conn_raw, 'SHOW ENGINES');
     $engines = ipull($engines, 'Support', 'Engine');
     $innodb = idx($engines, 'InnoDB');
     if ($innodb != 'YES' && $innodb != 'DEFAULT') {
         $message = pht("The 'InnoDB' engine is not available in MySQL. Enable InnoDB in " . "your MySQL configuration." . "\n\n" . "(If you aleady created tables, MySQL incorrectly used some other " . "engine to create them. You need to convert them or drop and " . "reinitialize them.)");
         $this->newIssue('mysql.innodb')->setName(pht('MySQL InnoDB Engine Not Available'))->setMessage($message)->setIsFatal(true);
         return;
     }
     $namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace');
     $databases = queryfx_all($conn_raw, 'SHOW DATABASES');
     $databases = ipull($databases, 'Database', 'Database');
     if (empty($databases[$namespace . '_meta_data'])) {
         $message = pht("Run the storage upgrade script to setup Phabricator's database " . "schema.");
         $this->newIssue('storage.upgrade')->setName(pht('Setup MySQL Schema'))->setMessage($message)->setIsFatal(true)->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade'));
     } else {
         $config['database'] = $namespace . '_meta_data';
         $conn_meta = PhabricatorEnv::newObjectFromConfig('mysql.implementation', array($config));
         $applied = queryfx_all($conn_meta, 'SELECT patch FROM patch_status');
         $applied = ipull($applied, 'patch', 'patch');
         $all = PhabricatorSQLPatchList::buildAllPatches();
         $diff = array_diff_key($all, $applied);
         if ($diff) {
             $this->newIssue('storage.patch')->setName(pht('Upgrade MySQL Schema'))->setMessage(pht("Run the storage upgrade script to upgrade Phabricator's " . "database schema. Missing patches:<br />%s<br />", phutil_implode_html(phutil_tag('br'), array_keys($diff))))->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade'));
         }
     }
     $host = PhabricatorEnv::getEnvConfig('mysql.host');
     $matches = null;
     if (preg_match('/^([^:]+):(\\d+)$/', $host, $matches)) {
         $host = $matches[1];
         $port = $matches[2];
         $this->newIssue('storage.mysql.hostport')->setName(pht('Deprecated mysql.host Format'))->setSummary(pht('Move port information from `%s` to `%s` in your config.', 'mysql.host', 'mysql.port'))->setMessage(pht('Your `%s` configuration contains a port number, but this usage ' . 'is deprecated. Instead, put the port number in `%s`.', 'mysql.host', 'mysql.port'))->addPhabricatorConfig('mysql.host')->addPhabricatorConfig('mysql.port')->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/config set mysql.host %s', $host))->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/config set mysql.port %s', $port));
     }
 }
 public function renderThreadsHTML()
 {
     $thread_html = array();
     if ($this->scrollUpParticipant->getID()) {
         $thread_html[] = $this->getScrollMenuItem($this->scrollUpParticipant, 'up');
     }
     foreach ($this->threads as $thread) {
         $thread_html[] = $this->renderSingleThread($thread);
     }
     if ($this->scrollDownParticipant->getID()) {
         $thread_html[] = $this->getScrollMenuItem($this->scrollDownParticipant, 'down');
     }
     return phutil_implode_html('', $thread_html);
 }
 public function markupText($text, $children)
 {
     $text = rtrim($text);
     $text = phutil_split_lines($text, $retain_endings = true);
     foreach ($text as $key => $line) {
         $line = preg_replace('/^\\s*%%%/', '', $line);
         $line = preg_replace('/%%%(\\s*)\\z/', '\\1', $line);
         $text[$key] = $line;
     }
     if ($this->getEngine()->isTextMode()) {
         return implode('', $text);
     }
     return phutil_tag('p', array('class' => 'remarkup-literal'), phutil_implode_html(phutil_tag('br', array()), $text));
 }