public function restore($corpus) { if ($this->map) { $corpus = phutil_safe_html(str_replace(array_reverse(array_keys($this->map)), array_map('phutil_escape_html', array_reverse($this->map)), phutil_escape_html($corpus))); } return $corpus; }
protected function renderInput() { self::requireLib(); $uri = new PhutilURI(PhabricatorEnv::getEnvConfig('phabricator.base-uri')); $protocol = $uri->getProtocol(); $use_ssl = $protocol == 'https'; return phutil_safe_html(recaptcha_get_html(PhabricatorEnv::getEnvConfig('recaptcha.public-key'), $error = null, $use_ssl)); }
public function overwriteStoredText($token, $new_text) { if ($this->isTextMode()) { $new_text = phutil_safe_html($new_text); } $this->storage->overwrite($token, $new_text); return $this; }
public function renderExample() { $out = ''; $out .= $this->renderTestThings('AphrontProgressBarView', 13, 10); $out .= $this->renderTestThings('AphrontGlyphBarView', 13, 10); $out .= $this->renderWeirdOrderGlyphBars(); $out .= $this->renderAsciiStarBar(); return phutil_safe_html($out); }
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 restore($corpus, $text_mode = false) { if ($this->map) { if ($text_mode) { $corpus = str_replace(array_reverse(array_keys($this->map)), array_reverse($this->map), $corpus); } else { $corpus = phutil_safe_html(str_replace(array_reverse(array_keys($this->map)), array_map('phutil_escape_html', array_reverse($this->map)), phutil_escape_html($corpus))); } } return $corpus; }
private function renderTemplate($__template__, array $__scope__) { chdir($this->getPath()); ob_start(); if (Filesystem::pathExists($this->getPath($__template__))) { // Fool lint. $__evil__ = 'extract'; $__evil__($__scope__ + $this->getDefaultScope()); require $this->getPath($__template__); } return phutil_safe_html(ob_get_clean()); }
protected function didReceiveResult($result) { list($err, $stdout, $stderr) = $result; if (!$err && strlen($stdout)) { // Strip off fluff Pygments adds. $stdout = preg_replace('@^<div class="highlight"><pre>(.*)</pre></div>\\s*$@s', '\\1', $stdout); if ($this->scrub) { $stdout = preg_replace('/^.*\\n/', '', $stdout); } return phutil_safe_html($stdout); } throw new PhutilSyntaxHighlighterException($stderr, $err); }
public function getHighlightFuture($source) { $source = phutil_escape_html($source); // This highlighter isn't perfect but tries to do an okay job at getting // some of the basics at least. There's lots of room for improvement. $blocks = explode("\n\n", $source); foreach ($blocks as $key => $block) { if (preg_match('/^[^ ](?! )/m', $block)) { $blocks[$key] = $this->highlightBlock($block); } } $source = implode("\n\n", $blocks); $source = phutil_safe_html($source); return new ImmediateFuture($source); }
public static function applyIntralineDiff($str, $intra_stack) { $buf = ''; $p = $s = $e = 0; // position, start, end $highlight = $tag = $ent = false; $highlight_o = '<span class="bright">'; $highlight_c = '</span>'; $is_html = false; if ($str instanceof PhutilSafeHTML) { $is_html = true; $str = $str->getHTMLContent(); } $n = strlen($str); for ($i = 0; $i < $n; $i++) { if ($p == $e) { do { if (empty($intra_stack)) { $buf .= substr($str, $i); break 2; } $stack = array_shift($intra_stack); $s = $e; $e += $stack[1]; } while ($stack[0] == 0); } if (!$highlight && !$tag && !$ent && $p == $s) { $buf .= $highlight_o; $highlight = true; } if ($str[$i] == '<') { $tag = true; if ($highlight) { $buf .= $highlight_c; } } if (!$tag) { if ($str[$i] == '&') { $ent = true; } if ($ent && $str[$i] == ';') { $ent = false; } if (!$ent) { $p++; } } $buf .= $str[$i]; if ($tag && $str[$i] == '>') { $tag = false; if ($highlight) { $buf .= $highlight_o; } } if ($highlight && ($p == $e || $i == $n - 1)) { $buf .= $highlight_c; $highlight = false; } } if ($is_html) { return phutil_safe_html($buf); } return $buf; }
private function addTaskToTree($task) { $cdate = $this->getTaskCreatedDate($task); $date_created = phabricator_date($cdate, $this->viewer); $udate = $this->getTaskModifiedDate($task); $last_updated = phabricator_date($udate, $this->viewer); $status = $task->getStatus(); $owner_link = $this->setOwnerLink($this->handles, $task); $priority = $this->getPriority($task); $priority_name = $this->getPriorityName($task); $is_open = ManiphestTaskStatus::isOpenStatus($task->getStatus()); if ($this->blocker === true && $is_open === true) { $blockericon = $this->getIconforBlocker(); } else { $blockericon = ''; } if ($this->blocked === true && $is_open === true) { $blockedicon = $this->getIconforBlocked(); } else { $blockedicon = ''; } $output = array(); $output[] = array(phutil_safe_html(phutil_tag('a', array('href' => '/' . $task->getMonogram(), 'class' => $status !== 'open' ? 'phui-tag-core-closed' : ''), array($this->buildTaskLink($task), $blockericon, $blockedicon))), $cdate, $date_created, $udate, $last_updated, $owner_link, $priority, $priority_name, $this->points, $status); return $output; }
public final function renderChangesetTable($content) { $props = null; if ($this->shouldRenderPropertyChangeHeader()) { $props = $this->renderPropertyChangeHeader(); } $notice = null; if ($this->getIsTopLevel()) { $force = !$content && !$props; $notice = $this->renderChangeTypeHeader($force); } $result = $notice . $props . $content; // TODO: Let the user customize their tab width / display style. // TODO: We should possibly post-process "\r" as well. // TODO: Both these steps should happen earlier. $result = str_replace("\t", ' ', $result); return phutil_safe_html($result); }
private function loadContent(array $pastes) { $cache = new PhabricatorKeyValueDatabaseCache(); $cache = new PhutilKeyValueCacheProfiler($cache); $cache->setProfiler(PhutilServiceProfiler::getInstance()); $keys = array(); foreach ($pastes as $paste) { $keys[] = $this->getContentCacheKey($paste); } $caches = $cache->getKeys($keys); $results = array(); $need_raw = array(); foreach ($pastes as $key => $paste) { $key = $this->getContentCacheKey($paste); if (isset($caches[$key])) { $paste->attachContent(phutil_safe_html($caches[$key])); $results[$paste->getID()] = $paste; } else { $need_raw[$key] = $paste; } } if (!$need_raw) { return $results; } $write_data = array(); $need_raw = $this->loadRawContent($need_raw); foreach ($need_raw as $key => $paste) { $content = $this->buildContent($paste); $paste->attachContent($content); $write_data[$this->getContentCacheKey($paste)] = (string) $content; $results[$paste->getID()] = $paste; } $cache->setKeys($write_data); return $results; }
public function renderTextChange($range_start, $range_len, $rows) { $hunk_starts = $this->getHunkStartLines(); $context_not_available = null; if ($hunk_starts) { $context_not_available = javelin_tag('tr', array('sigil' => 'context-target'), phutil_tag('td', array('colspan' => 6, 'class' => 'show-more'), pht('Context not available.'))); } $html = array(); $old_lines = $this->getOldLines(); $new_lines = $this->getNewLines(); $gaps = $this->getGaps(); $reference = $this->getRenderingReference(); $left_id = $this->getOldChangesetID(); $right_id = $this->getNewChangesetID(); // "N" stands for 'new' and means the comment should attach to the new file // when stored, i.e. DifferentialInlineComment->setIsNewFile(). // "O" stands for 'old' and means the comment should attach to the old file. $left_char = $this->getOldAttachesToNewFile() ? 'N' : 'O'; $right_char = $this->getNewAttachesToNewFile() ? 'N' : 'O'; $changeset = $this->getChangeset(); $copy_lines = idx($changeset->getMetadata(), 'copy:lines', array()); $highlight_old = $this->getHighlightOld(); $highlight_new = $this->getHighlightNew(); $old_render = $this->getOldRender(); $new_render = $this->getNewRender(); $original_left = $this->getOriginalOld(); $original_right = $this->getOriginalNew(); $depths = $this->getDepths(); $mask = $this->getMask(); for ($ii = $range_start; $ii < $range_start + $range_len; $ii++) { if (empty($mask[$ii])) { // If we aren't going to show this line, we've just entered a gap. // Pop information about the next gap off the $gaps stack and render // an appropriate "Show more context" element. This branch eventually // increments $ii by the entire size of the gap and then continues // the loop. $gap = array_pop($gaps); $top = $gap[0]; $len = $gap[1]; $end = $top + $len - 20; $contents = array(); if ($len > 40) { $is_first_block = false; if ($ii == 0) { $is_first_block = true; } $contents[] = javelin_tag('a', array('href' => '#', 'mustcapture' => true, 'sigil' => 'show-more', 'meta' => array('ref' => $reference, 'range' => "{$top}-{$len}/{$top}-20")), $is_first_block ? pht('Show First 20 Lines') : pht("▲ Show 20 Lines")); } $contents[] = javelin_tag('a', array('href' => '#', 'mustcapture' => true, 'sigil' => 'show-more', 'meta' => array('type' => 'all', 'ref' => $reference, 'range' => "{$top}-{$len}/{$top}-{$len}")), pht('Show All %d Lines', $len)); $is_last_block = false; if ($ii + $len >= $rows) { $is_last_block = true; } if ($len > 40) { $contents[] = javelin_tag('a', array('href' => '#', 'mustcapture' => true, 'sigil' => 'show-more', 'meta' => array('ref' => $reference, 'range' => "{$top}-{$len}/{$end}-20")), $is_last_block ? pht('Show Last 20 Lines') : pht("▼ Show 20 Lines")); } $context = null; $context_line = null; if (!$is_last_block && $depths[$ii + $len]) { for ($l = $ii + $len - 1; $l >= $ii; $l--) { $line = $new_lines[$l]['text']; if ($depths[$l] < $depths[$ii + $len] && trim($line) != '') { $context = $new_render[$l]; $context_line = $new_lines[$l]['line']; break; } } } $container = javelin_tag('tr', array('sigil' => 'context-target'), array(phutil_tag('td', array('colspan' => 2, 'class' => 'show-more'), phutil_implode_html(" • ", $contents)), phutil_tag('th', array('class' => 'show-context-line'), $context_line ? (int) $context_line : null), phutil_tag('td', array('colspan' => 3, 'class' => 'show-context'), phutil_safe_html($context)))); $html[] = $container; $ii += $len - 1; continue; } $o_num = null; $o_classes = ''; $o_text = null; if (isset($old_lines[$ii])) { $o_num = $old_lines[$ii]['line']; $o_text = isset($old_render[$ii]) ? $old_render[$ii] : null; if ($old_lines[$ii]['type']) { if ($old_lines[$ii]['type'] == '\\') { $o_text = $old_lines[$ii]['text']; $o_class = 'comment'; } else { if ($original_left && !isset($highlight_old[$o_num])) { $o_class = 'old-rebase'; } else { if (empty($new_lines[$ii])) { $o_class = 'old old-full'; } else { $o_class = 'old'; } } } $o_classes = $o_class; } } $n_copy = hsprintf('<td class="copy" />'); $n_cov = null; $n_colspan = 2; $n_classes = ''; $n_num = null; $n_text = null; if (isset($new_lines[$ii])) { $n_num = $new_lines[$ii]['line']; $n_text = isset($new_render[$ii]) ? $new_render[$ii] : null; $coverage = $this->getCodeCoverage(); if ($coverage !== null) { if (empty($coverage[$n_num - 1])) { $cov_class = 'N'; } else { $cov_class = $coverage[$n_num - 1]; } $cov_class = 'cov-' . $cov_class; $n_cov = phutil_tag('td', array('class' => "cov {$cov_class}")); $n_colspan--; } if ($new_lines[$ii]['type']) { if ($new_lines[$ii]['type'] == '\\') { $n_text = $new_lines[$ii]['text']; $n_class = 'comment'; } else { if ($original_right && !isset($highlight_new[$n_num])) { $n_class = 'new-rebase'; } else { if (empty($old_lines[$ii])) { $n_class = 'new new-full'; } else { $n_class = 'new'; } } } $n_classes = $n_class; if ($new_lines[$ii]['type'] == '\\' || !isset($copy_lines[$n_num])) { $n_copy = phutil_tag('td', array('class' => "copy {$n_class}")); } else { list($orig_file, $orig_line, $orig_type) = $copy_lines[$n_num]; $title = ($orig_type == '-' ? 'Moved' : 'Copied') . ' from '; if ($orig_file == '') { $title .= "line {$orig_line}"; } else { $title .= basename($orig_file) . ":{$orig_line} in dir " . dirname('/' . $orig_file); } $class = $orig_type == '-' ? 'new-move' : 'new-copy'; $n_copy = javelin_tag('td', array('meta' => array('msg' => $title), 'class' => 'copy ' . $class), ''); } } } if (isset($hunk_starts[$o_num])) { $html[] = $context_not_available; } if ($o_num && $left_id) { $o_id = 'C' . $left_id . $left_char . 'L' . $o_num; } else { $o_id = null; } if ($n_num && $right_id) { $n_id = 'C' . $right_id . $right_char . 'L' . $n_num; } else { $n_id = null; } // NOTE: This is a unicode zero-width space, which we use as a hint when // intercepting 'copy' events to make sure sensible text ends up on the // clipboard. See the 'phabricator-oncopy' behavior. $zero_space = ""; // NOTE: The Javascript is sensitive to whitespace changes in this // block! $html[] = phutil_tag('tr', array(), array(phutil_tag('th', array('id' => $o_id), $o_num), phutil_tag('td', array('class' => $o_classes), $o_text), phutil_tag('th', array('id' => $n_id), $n_num), $n_copy, phutil_tag('td', array('class' => $n_classes, 'colspan' => $n_colspan), array(phutil_tag('span', array('class' => 'zwsp'), $zero_space), $n_text)), $n_cov)); if ($context_not_available && $ii == $rows - 1) { $html[] = $context_not_available; } $old_comments = $this->getOldComments(); $new_comments = $this->getNewComments(); if ($o_num && isset($old_comments[$o_num])) { foreach ($old_comments[$o_num] as $comment) { $comment_html = $this->renderInlineComment($comment, $on_right = false); $new = ''; if ($n_num && isset($new_comments[$n_num])) { foreach ($new_comments[$n_num] as $key => $new_comment) { if ($comment->isCompatible($new_comment)) { $new = $this->renderInlineComment($new_comment, $on_right = true); unset($new_comments[$n_num][$key]); } } } $html[] = phutil_tag('tr', array('class' => 'inline'), array(phutil_tag('th', array()), phutil_tag('td', array(), $comment_html), phutil_tag('th', array()), phutil_tag('td', array('colspan' => 3), $new))); } } if ($n_num && isset($new_comments[$n_num])) { foreach ($new_comments[$n_num] as $comment) { $comment_html = $this->renderInlineComment($comment, $on_right = true); $html[] = phutil_tag('tr', array('class' => 'inline'), array(phutil_tag('th', array()), phutil_tag('td', array()), phutil_tag('th', array()), phutil_tag('td', array('colspan' => 3), $comment_html))); } } } return $this->wrapChangeInTable(phutil_implode_html('', $html)); }
public function handleRequest(AphrontRequest $request) { $viewer = $request->getUser(); if ($viewer->isLoggedIn()) { // Kick the user home if they are already logged in. return id(new AphrontRedirectResponse())->setURI('/'); } if ($request->isAjax()) { return $this->processAjaxRequest(); } if ($request->isConduit()) { return $this->processConduitRequest(); } // If the user gets this far, they aren't logged in, so if they have a // user session token we can conclude that it's invalid: if it was valid, // they'd have been logged in above and never made it here. Try to clear // it and warn the user they may need to nuke their cookies. $session_token = $request->getCookie(PhabricatorCookies::COOKIE_SESSION); if (strlen($session_token)) { $kind = PhabricatorAuthSessionEngine::getSessionKindFromToken($session_token); switch ($kind) { case PhabricatorAuthSessionEngine::KIND_ANONYMOUS: // If this is an anonymous session. It's expected that they won't // be logged in, so we can just continue. break; default: // The session cookie is invalid, so clear it. $request->clearCookie(PhabricatorCookies::COOKIE_USERNAME); $request->clearCookie(PhabricatorCookies::COOKIE_SESSION); return $this->renderError(pht('Your login session is invalid. Try reloading the page and ' . 'logging in again. If that does not work, clear your browser ' . 'cookies.')); } } $providers = PhabricatorAuthProvider::getAllEnabledProviders(); foreach ($providers as $key => $provider) { if (!$provider->shouldAllowLogin()) { unset($providers[$key]); } } if (!$providers) { if ($this->isFirstTimeSetup()) { // If this is a fresh install, let the user register their admin // account. return id(new AphrontRedirectResponse())->setURI($this->getApplicationURI('/register/')); } return $this->renderError(pht('This Phabricator install is not configured with any enabled ' . 'authentication providers which can be used to log in. If you ' . 'have accidentally locked yourself out by disabling all providers, ' . 'you can use `%s` to recover access to an administrative account.', 'phabricator/bin/auth recover <username>')); } $next_uri = $request->getStr('next'); if (!strlen($next_uri)) { if ($this->getDelegatingController()) { // Only set a next URI from the request path if this controller was // delegated to, which happens when a user tries to view a page which // requires them to login. // If this controller handled the request directly, we're on the main // login page, and never want to redirect the user back here after they // login. $next_uri = (string) $this->getRequest()->getRequestURI(); } } if (!$request->isFormPost()) { if (strlen($next_uri)) { PhabricatorCookies::setNextURICookie($request, $next_uri); } PhabricatorCookies::setClientIDCookie($request); } if (!$request->getURIData('loggedout') && count($providers) == 1) { $auto_login_provider = head($providers); $auto_login_config = $auto_login_provider->getProviderConfig(); if ($auto_login_provider instanceof PhabricatorPhabricatorAuthProvider && $auto_login_config->getShouldAutoLogin()) { $auto_login_adapter = $provider->getAdapter(); $auto_login_adapter->setState($provider->getAuthCSRFCode($request)); return id(new AphrontRedirectResponse())->setIsExternal(true)->setURI($provider->getAdapter()->getAuthenticateURI()); } } $invite = $this->loadInvite(); $not_buttons = array(); $are_buttons = array(); $providers = msort($providers, 'getLoginOrder'); foreach ($providers as $provider) { if ($invite) { $form = $provider->buildInviteForm($this); } else { $form = $provider->buildLoginForm($this); } if ($provider->isLoginFormAButton()) { $are_buttons[] = $form; } else { $not_buttons[] = $form; } } $out = array(); $out[] = $not_buttons; if ($are_buttons) { require_celerity_resource('auth-css'); foreach ($are_buttons as $key => $button) { $are_buttons[$key] = phutil_tag('div', array('class' => 'phabricator-login-button mmb'), $button); } // If we only have one button, add a second pretend button so that we // always have two columns. This makes it easier to get the alignments // looking reasonable. if (count($are_buttons) == 1) { $are_buttons[] = null; } $button_columns = id(new AphrontMultiColumnView())->setFluidLayout(true); $are_buttons = array_chunk($are_buttons, ceil(count($are_buttons) / 2)); foreach ($are_buttons as $column) { $button_columns->addColumn($column); } $out[] = phutil_tag('div', array('class' => 'phabricator-login-buttons'), $button_columns); } $login_message = PhabricatorEnv::getEnvConfig('auth.login-message'); $login_message = phutil_safe_html($login_message); $invite_message = null; if ($invite) { $invite_message = $this->renderInviteHeader($invite); } $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Login')); $crumbs->setBorder(true); return $this->buildApplicationPage(array($crumbs, $login_message, $invite_message, $out), array('title' => pht('Login to Phabricator'))); }
public function addRawHTMLSection($html) { $this->htmlSections[] = phutil_safe_html($html); return $this; }
private function loadContent(array $pastes) { $cache = new PhabricatorKeyValueDatabaseCache(); $cache = new PhutilKeyValueCacheProfiler($cache); $cache->setProfiler(PhutilServiceProfiler::getInstance()); $keys = array(); foreach ($pastes as $paste) { $keys[] = $this->getContentCacheKey($paste); } $caches = $cache->getKeys($keys); $need_raw = array(); $have_cache = array(); foreach ($pastes as $paste) { $key = $this->getContentCacheKey($paste); if (isset($caches[$key])) { $paste->attachContent(phutil_safe_html($caches[$key])); $have_cache[$paste->getPHID()] = true; } else { $need_raw[$key] = $paste; } } if (!$need_raw) { return $pastes; } $write_data = array(); $have_raw = $this->loadRawContent($need_raw); $have_raw = mpull($have_raw, null, 'getPHID'); foreach ($pastes as $key => $paste) { $paste_phid = $paste->getPHID(); if (isset($have_cache[$paste_phid])) { continue; } if (empty($have_raw[$paste_phid])) { unset($pastes[$key]); continue; } $content = $this->buildContent($paste); $paste->attachContent($content); $write_data[$this->getContentCacheKey($paste)] = (string) $content; } if ($write_data) { $cache->setKeys($write_data); } return $pastes; }
public function translate($text) { if (isset($this->translations[$text])) { $translation = $this->translations[$text]; } else { $translation = $text; } $args = func_get_args(); while (is_array($translation)) { $arg = next($args); $translation = $this->chooseVariant($translation, $arg); if ($translation === null) { $pos = key($args); if (is_object($arg)) { $kind = get_class($arg); } else { $kind = gettype($arg); } return sprintf('[Invalid Translation!] The "%s" language data offers variant ' . 'translations for the plurality or gender of argument %s, but ' . 'the value for that argument is not an integer, PhutilNumber, or ' . 'PhutilPerson (it is a value of type "%s"). Raw input: <%s>.', $this->localeCode, $pos, $kind, $text); } } array_shift($args); foreach ($args as $k => $arg) { if ($arg instanceof PhutilNumber) { $args[$k] = $this->formatNumber($arg->getNumber(), $arg->getDecimals()); } } // Check if any arguments are PhutilSafeHTML. If they are, we will apply // any escaping necessary and output HTML. $is_html = false; foreach ($args as $arg) { if ($arg instanceof PhutilSafeHTML || $arg instanceof PhutilSafeHTMLProducerInterface) { $is_html = true; break; } } if ($is_html) { foreach ($args as $k => $arg) { $args[$k] = (string) phutil_escape_html($arg); } } $result = vsprintf($translation, $args); if ($result === false) { // If vsprintf() fails (often because the translated string references // too many parameters), show the bad template with a note instead of // returning an empty string. This makes it easier to figure out what // went wrong and fix it. $result = pht('[Invalid Translation!] %s', $translation); } if ($this->shouldPostProcess) { $result = $this->locale->didTranslateString($text, $translation, $args, $result); } if ($is_html) { $result = phutil_safe_html($result); } return $result; }
protected function replaceHTML($pattern, $callback, $text) { $this->replaceCallback = $callback; return phutil_safe_html(preg_replace_callback($pattern, array($this, 'replaceHTMLCallback'), phutil_escape_html($text))); }
/** * Check whether text is flat (contains no replacement tokens) or not. * * @param wild Ostensibly flat text. * @return bool True if the text is flat. */ protected function isFlatText($text) { $text = (string) hsprintf('%s', phutil_safe_html($text)); return strpos($text, PhutilRemarkupBlockStorage::MAGIC_BYTE) === false; }
private function addTaskToTree(&$output, $task, &$map, $handles, $depth = 0) { static $included = array(); // Get the owner object so we can render the owner username/link $owner = $handles[$task->getOwnerPHID()]; // If this task is already is this tree, this is a repeat. $repeat = isset($included[$task->getPHID()]); $depth_indent = ''; for ($i = 0; $i < $depth; $i++) { $depth_indent .= ' '; } // Build the row $output[] = array(phutil_safe_html($depth_indent . phutil_tag('a', array('href' => '/' . $task->getMonogram(), 'class' => $task->getStatus() !== 'open' ? 'phui-tag-core-closed' : ''), $task->getMonogram() . ': ' . $task->getTitle()) . ($repeat ? ' <em title="This task is a child of more than one task in this list. Children are only shown on ' . 'the first occurance">[Repeat]</em>' : '')), $task->getOwnerPHID() ? $owner->renderLink() : 'none assigned', $task->getStatus()); $included[$task->getPHID()] = $task->getPHID(); if (isset($map[$task->getPHID()]['children'])) { foreach ($map[$task->getPHID()]['children'] as $child) { $child = $this->tasks[$child]; $this->addTaskToTree($output, $child, $map, $handles, $depth + 1); } } }
public function renderTextChange($range_start, $range_len, $rows) { $hunk_starts = $this->getHunkStartLines(); $context_not_available = null; if ($hunk_starts) { $context_not_available = javelin_tag('tr', array('sigil' => 'context-target'), phutil_tag('td', array('colspan' => 6, 'class' => 'show-more'), pht('Context not available.'))); } $html = array(); $old_lines = $this->getOldLines(); $new_lines = $this->getNewLines(); $gaps = $this->getGaps(); $reference = $this->getRenderingReference(); list($left_prefix, $right_prefix) = $this->getLineIDPrefixes(); $changeset = $this->getChangeset(); $copy_lines = idx($changeset->getMetadata(), 'copy:lines', array()); $highlight_old = $this->getHighlightOld(); $highlight_new = $this->getHighlightNew(); $old_render = $this->getOldRender(); $new_render = $this->getNewRender(); $original_left = $this->getOriginalOld(); $original_right = $this->getOriginalNew(); $depths = $this->getDepths(); $mask = $this->getMask(); $hidden = new PHUIDiffRevealIconView(); /* Init extension */ $line_renderer = new DifferentialLineNumberRendered($changeset->getDisplayFilename(), $range_start, $range_len); for ($ii = $range_start; $ii < $range_start + $range_len; $ii++) { if (empty($mask[$ii])) { // If we aren't going to show this line, we've just entered a gap. // Pop information about the next gap off the $gaps stack and render // an appropriate "Show more context" element. This branch eventually // increments $ii by the entire size of the gap and then continues // the loop. $gap = array_pop($gaps); $top = $gap[0]; $len = $gap[1]; $contents = $this->renderShowContextLinks($top, $len, $rows); $is_last_block = false; if ($ii + $len >= $rows) { $is_last_block = true; } $context = null; $context_line = null; if (!$is_last_block && $depths[$ii + $len]) { for ($l = $ii + $len - 1; $l >= $ii; $l--) { $line = $new_lines[$l]['text']; if ($depths[$l] < $depths[$ii + $len] && trim($line) != '') { $context = $new_render[$l]; $context_line = $new_lines[$l]['line']; break; } } } $container = javelin_tag('tr', array('sigil' => 'context-target'), array(phutil_tag('td', array('colspan' => 2, 'class' => 'show-more'), $contents), phutil_tag('th', array('class' => 'show-context-line'), $context_line ? (int) $context_line : null), phutil_tag('td', array('colspan' => 3, 'class' => 'show-context'), phutil_safe_html($context)))); $html[] = $container; $ii += $len - 1; continue; } $o_num = null; $o_classes = ''; $o_text = null; if (isset($old_lines[$ii])) { $o_num = $old_lines[$ii]['line']; $o_text = isset($old_render[$ii]) ? $old_render[$ii] : null; if ($old_lines[$ii]['type']) { if ($old_lines[$ii]['type'] == '\\') { $o_text = $old_lines[$ii]['text']; $o_class = 'comment'; } else { if ($original_left && !isset($highlight_old[$o_num])) { $o_class = 'old-rebase'; } else { if (empty($new_lines[$ii])) { $o_class = 'old old-full'; } else { $o_class = 'old'; } } } $o_classes = $o_class; } } $n_copy = hsprintf('<td class="copy" />'); $n_cov = null; $n_colspan = 2; $n_classes = ''; $n_num = null; $n_text = null; if (isset($new_lines[$ii])) { $n_num = $new_lines[$ii]['line']; $n_text = isset($new_render[$ii]) ? $new_render[$ii] : null; $coverage = $this->getCodeCoverage(); if ($coverage !== null) { if (empty($coverage[$n_num - 1])) { $cov_class = 'N'; } else { $cov_class = $coverage[$n_num - 1]; } $cov_class = 'cov-' . $cov_class; $n_cov = phutil_tag('td', array('class' => "cov {$cov_class}")); $n_colspan--; } if ($new_lines[$ii]['type']) { if ($new_lines[$ii]['type'] == '\\') { $n_text = $new_lines[$ii]['text']; $n_class = 'comment'; } else { if ($original_right && !isset($highlight_new[$n_num])) { $n_class = 'new-rebase'; } else { if (empty($old_lines[$ii])) { $n_class = 'new new-full'; } else { $n_class = 'new'; } } } $n_classes = $n_class; if ($new_lines[$ii]['type'] == '\\' || !isset($copy_lines[$n_num])) { $n_copy = phutil_tag('td', array('class' => "copy {$n_class}")); } else { list($orig_file, $orig_line, $orig_type) = $copy_lines[$n_num]; $title = ($orig_type == '-' ? 'Moved' : 'Copied') . ' from '; if ($orig_file == '') { $title .= "line {$orig_line}"; } else { $title .= basename($orig_file) . ":{$orig_line} in dir " . dirname('/' . $orig_file); } $class = $orig_type == '-' ? 'new-move' : 'new-copy'; $n_copy = javelin_tag('td', array('meta' => array('msg' => $title), 'class' => 'copy ' . $class), ''); } } } if (isset($hunk_starts[$o_num])) { $html[] = $context_not_available; } if ($o_num && $left_prefix) { $o_id = $left_prefix . $o_num; } else { $o_id = null; } if ($n_num && $right_prefix) { $n_id = $right_prefix . $n_num; } else { $n_id = null; } $old_comments = $this->getOldComments(); $new_comments = $this->getNewComments(); $scaffolds = array(); $o_hidden = array(); $n_hidden = array(); if ($o_num && isset($old_comments[$o_num])) { foreach ($old_comments[$o_num] as $comment) { $inline = $this->buildInlineComment($comment, $on_right = false); $scaffold = $this->getRowScaffoldForInline($inline); if ($comment->isHidden()) { $o_hidden[] = $comment; } if ($n_num && isset($new_comments[$n_num])) { foreach ($new_comments[$n_num] as $key => $new_comment) { if ($comment->isCompatible($new_comment)) { $companion = $this->buildInlineComment($new_comment, $on_right = true); if ($new_comment->isHidden()) { $n_hidden = $new_comment; } $scaffold->addInlineView($companion); unset($new_comments[$n_num][$key]); break; } } } $scaffolds[] = $scaffold; } } if ($n_num && isset($new_comments[$n_num])) { foreach ($new_comments[$n_num] as $comment) { $inline = $this->buildInlineComment($comment, $on_right = true); if ($comment->isHidden()) { $n_hidden[] = $comment; } $scaffolds[] = $this->getRowScaffoldForInline($inline); } } if ($o_hidden) { $o_num = array($hidden, $o_num); } if ($n_hidden) { $n_num = array($hidden, $n_num); } // NOTE: This is a unicode zero-width space, which we use as a hint when // intercepting 'copy' events to make sure sensible text ends up on the // clipboard. See the 'phabricator-oncopy' behavior. $zero_space = ""; $line_num_rendered_o = $line_renderer->getLineTag($o_num); $line_num_rendered_n = $line_renderer->getLineTag($n_num); $html[] = phutil_tag('tr', array(), array(phutil_tag('th', array('id' => $o_id), $line_num_rendered_o), phutil_tag('td', array('class' => $o_classes), $o_text), phutil_tag('th', array('id' => $n_id), $line_num_rendered_n), $n_copy, phutil_tag('td', array('class' => $n_classes, 'colspan' => $n_colspan), array(phutil_tag('span', array('class' => 'zwsp'), $zero_space), $n_text)), $n_cov)); if ($context_not_available && $ii == $rows - 1) { $html[] = $context_not_available; } foreach ($scaffolds as $scaffold) { $html[] = $scaffold; } } return $this->wrapChangeInTable(phutil_implode_html('', $html)); }
private function buildDisplayRows(array $lines, array $blame_list, array $blame_commits, $show_color, $show_blame) { $request = $this->getRequest(); $viewer = $this->getViewer(); $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); $revision_map = array(); $revisions = array(); if ($blame_commits) { $commit_map = mpull($blame_commits, 'getCommitIdentifier', 'getPHID'); $revision_ids = id(new DifferentialRevision())->loadIDsByCommitPHIDs(array_keys($commit_map)); if ($revision_ids) { $revisions = id(new DifferentialRevisionQuery())->setViewer($viewer)->withIDs($revision_ids)->execute(); $revisions = mpull($revisions, null, 'getID'); } foreach ($revision_ids as $commit_phid => $revision_id) { $revision_map[$commit_map[$commit_phid]] = $revision_id; } } $phids = array(); foreach ($blame_commits as $commit) { $author_phid = $commit->getAuthorPHID(); if ($author_phid === null) { continue; } $phids[$author_phid] = $author_phid; } foreach ($revisions as $revision) { $author_phid = $revision->getAuthorPHID(); if ($author_phid === null) { continue; } $phids[$author_phid] = $author_phid; } $handles = $viewer->loadHandles($phids); $colors = array(); if ($blame_commits) { $epochs = array(); foreach ($blame_commits as $identifier => $commit) { $epochs[$identifier] = $commit->getEpoch(); } $epoch_list = array_filter($epochs); $epoch_list = array_unique($epoch_list); $epoch_list = array_values($epoch_list); $epoch_min = min($epoch_list); $epoch_max = max($epoch_list); $epoch_range = $epoch_max - $epoch_min + 1; foreach ($blame_commits as $identifier => $commit) { $epoch = $epochs[$identifier]; if (!$epoch) { $color = '#ffffdd'; // Warning color, missing data. } else { $color_ratio = ($epoch - $epoch_min) / $epoch_range; $color_value = 0xe6 * (1.0 - $color_ratio); $color = sprintf('#%02x%02x%02x', $color_value, 0xf6, $color_value); } $colors[$identifier] = $color; } } $display = array(); $last_identifier = null; $last_color = null; foreach ($lines as $line_index => $line) { $color = '#f6f6f6'; $duplicate = false; if (isset($blame_list[$line_index])) { $identifier = $blame_list[$line_index]; if (isset($colors[$identifier])) { $color = $colors[$identifier]; } if ($identifier === $last_identifier) { $duplicate = true; } else { $last_identifier = $identifier; } } $display[$line_index] = array('data' => $line, 'target' => false, 'highlighted' => false, 'color' => $color, 'duplicate' => $duplicate); } $line_arr = array(); $line_str = $drequest->getLine(); $ranges = explode(',', $line_str); foreach ($ranges as $range) { if (strpos($range, '-') !== false) { list($min, $max) = explode('-', $range, 2); $line_arr[] = array('min' => min($min, $max), 'max' => max($min, $max)); } else { if (strlen($range)) { $line_arr[] = array('min' => $range, 'max' => $range); } } } // Mark the first highlighted line as the target line. if ($line_arr) { $target_line = $line_arr[0]['min']; if (isset($display[$target_line - 1])) { $display[$target_line - 1]['target'] = true; } } // Mark all other highlighted lines as highlighted. foreach ($line_arr as $range) { for ($ii = $range['min']; $ii <= $range['max']; $ii++) { if (isset($display[$ii - 1])) { $display[$ii - 1]['highlighted'] = true; } } } $engine = null; $inlines = array(); if ($this->getRequest()->getStr('lint') !== null && $this->lintMessages) { $engine = new PhabricatorMarkupEngine(); $engine->setViewer($viewer); foreach ($this->lintMessages as $message) { $inline = id(new PhabricatorAuditInlineComment())->setSyntheticAuthor(ArcanistLintSeverity::getStringForSeverity($message['severity']) . ' ' . $message['code'] . ' (' . $message['name'] . ')')->setLineNumber($message['line'])->setContent($message['description']); $inlines[$message['line']][] = $inline; $engine->addObject($inline, PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY); } $engine->process(); require_celerity_resource('differential-changeset-view-css'); } $rows = $this->renderInlines(idx($inlines, 0, array()), $show_blame, (bool) $this->coverage, $engine); // NOTE: We're doing this manually because rendering is otherwise // dominated by URI generation for very large files. $line_base = (string) $drequest->generateURI(array('action' => 'browse', 'stable' => true)); require_celerity_resource('aphront-tooltip-css'); Javelin::initBehavior('phabricator-oncopy'); Javelin::initBehavior('phabricator-tooltips'); Javelin::initBehavior('phabricator-line-linker'); // Render these once, since they tend to get repeated many times in large // blame outputs. $commit_links = $this->renderCommitLinks($blame_commits, $handles); $revision_links = $this->renderRevisionLinks($revisions, $handles); $skip_text = pht('Skip Past This Commit'); foreach ($display as $line_index => $line) { $row = array(); $line_number = $line_index + 1; $line_href = $line_base . '$' . $line_number; if (isset($blame_list[$line_index])) { $identifier = $blame_list[$line_index]; } else { $identifier = null; } $revision_link = null; $commit_link = null; $before_link = null; $style = 'background: ' . $line['color'] . ';'; if ($identifier && !$line['duplicate']) { if (isset($commit_links[$identifier])) { $commit_link = $commit_links[$identifier]; } if (isset($revision_map[$identifier])) { $revision_id = $revision_map[$identifier]; if (isset($revision_links[$revision_id])) { $revision_link = $revision_links[$revision_id]; } } $skip_href = $line_href . '?before=' . $identifier . '&view=blame'; $before_link = javelin_tag('a', array('href' => $skip_href, 'sigil' => 'has-tooltip', 'meta' => array('tip' => $skip_text, 'align' => 'E', 'size' => 300)), "«"); } $row[] = phutil_tag('th', array('class' => 'diffusion-blame-link'), $before_link); $object_links = array(); $object_links[] = $commit_link; if ($revision_link) { $object_links[] = phutil_tag('span', array(), '/'); $object_links[] = $revision_link; } $row[] = phutil_tag('th', array('class' => 'diffusion-rev-link'), $object_links); $line_link = phutil_tag('a', array('href' => $line_href, 'style' => $style), $line_number); $row[] = javelin_tag('th', array('class' => 'diffusion-line-link', 'sigil' => 'phabricator-source-line', 'style' => $style), $line_link); if ($line['target']) { Javelin::initBehavior('diffusion-jump-to', array('target' => 'scroll_target')); $anchor_text = phutil_tag('a', array('id' => 'scroll_target'), ''); } else { $anchor_text = null; } $row[] = phutil_tag('td', array(), array($anchor_text, "", phutil_safe_html(str_replace("\t", ' ', $line['data'])))); if ($this->coverage) { require_celerity_resource('differential-changeset-view-css'); $cov_index = $line_index; if (isset($this->coverage[$cov_index])) { $cov_class = $this->coverage[$cov_index]; } else { $cov_class = 'N'; } $row[] = phutil_tag('td', array('class' => 'cov cov-' . $cov_class), ''); } $rows[] = phutil_tag('tr', array('class' => $line['highlighted'] ? 'phabricator-source-highlight' : null), $row); $cur_inlines = $this->renderInlines(idx($inlines, $line_number, array()), $show_blame, $this->coverage, $engine); foreach ($cur_inlines as $cur_inline) { $rows[] = $cur_inline; } } return $rows; }
private function buildWelcomePanel() { $panel = new PHUIObjectBoxView(); $panel->setHeaderText(pht('Welcome')); $panel->appendChild(phutil_safe_html(PhabricatorEnv::getEnvConfig('welcome.html'))); return $panel; }
public function translate($text) { $translation = idx($this->translations, $text, $text); $args = func_get_args(); while (is_array($translation)) { $translation = $this->chooseVariant($translation, next($args)); } array_shift($args); foreach ($args as $k => $arg) { if ($arg instanceof PhutilNumber) { $args[$k] = $this->formatNumber($arg->getNumber(), $arg->getDecimals()); } } // Check if any arguments are PhutilSafeHTML. If they are, we will apply // any escaping necessary and output HTML. $is_html = false; foreach ($args as $arg) { if ($arg instanceof PhutilSafeHTML) { $is_html = true; break; } } if ($is_html) { foreach ($args as $k => $arg) { $args[$k] = (string) phutil_escape_html($arg); } } $result = vsprintf($translation, $args); if ($result === false) { // If vsprintf() fails (often because the translated string references // too many parameters), show the bad template with a note instead of // returning an empty string. This makes it easier to figure out what // went wrong and fix it. $result = pht('[Invalid Translation!] %s', $translation); } if ($this->shouldPostProcess) { $result = $this->locale->didTranslateString($text, $translation, $args, $result); } if ($is_html) { $result = phutil_safe_html($result); } return $result; }
private function buildWelcomePanel() { $panel = new AphrontPanelView(); $panel->appendChild(phutil_safe_html(PhabricatorEnv::getEnvConfig('welcome.html'))); $panel->setNoBackground(); return $panel; }
public static function renderInlineScript($data) { if (stripos($data, '</script>') !== false) { throw new Exception(pht('Literal %s is not allowed inside inline script.', '</script>')); } if (strpos($data, '<!') !== false) { throw new Exception(pht('Literal %s is not allowed inside inline script.', '<!')); } // We don't use <![CDATA[ ]]> because it is ignored by HTML parsers. We // would need to send the document with XHTML content type. return phutil_tag('script', array('type' => 'text/javascript'), phutil_safe_html($data)); }
private function buildDisplayRows(array $text_list, array $rev_list, array $blame_dict, $needs_blame, DiffusionRequest $drequest, $show_blame, $show_color) { $handles = array(); if ($blame_dict) { $epoch_list = ipull(ifilter($blame_dict, 'epoch'), 'epoch'); $epoch_min = min($epoch_list); $epoch_max = max($epoch_list); $epoch_range = $epoch_max - $epoch_min + 1; $author_phids = ipull(ifilter($blame_dict, 'authorPHID'), 'authorPHID'); $handles = $this->loadViewerHandles($author_phids); } $line_arr = array(); $line_str = $drequest->getLine(); $ranges = explode(',', $line_str); foreach ($ranges as $range) { if (strpos($range, '-') !== false) { list($min, $max) = explode('-', $range, 2); $line_arr[] = array('min' => min($min, $max), 'max' => max($min, $max)); } else { if (strlen($range)) { $line_arr[] = array('min' => $range, 'max' => $range); } } } $display = array(); $line_number = 1; $last_rev = null; $color = null; foreach ($text_list as $k => $line) { $display_line = array('epoch' => null, 'commit' => null, 'author' => null, 'target' => null, 'highlighted' => null, 'line' => $line_number, 'data' => $line); if ($show_blame) { // If the line's rev is same as the line above, show empty content // with same color; otherwise generate blame info. The newer a change // is, the more saturated the color. $rev = idx($rev_list, $k, $last_rev); if ($last_rev == $rev) { $display_line['color'] = $color; } else { $blame = $blame_dict[$rev]; if (!isset($blame['epoch'])) { $color = '#ffd'; // Render as warning. } else { $color_ratio = ($blame['epoch'] - $epoch_min) / $epoch_range; $color_value = 0xe6 * (1.0 - $color_ratio); $color = sprintf('#%02x%02x%02x', $color_value, 0xf6, $color_value); } $display_line['epoch'] = idx($blame, 'epoch'); $display_line['color'] = $color; $display_line['commit'] = $rev; $author_phid = idx($blame, 'authorPHID'); if ($author_phid && $handles[$author_phid]) { $author_link = $handles[$author_phid]->renderLink(); } else { $author_link = $blame['author']; } $display_line['author'] = $author_link; $last_rev = $rev; } } if ($line_arr) { if ($line_number == $line_arr[0]['min']) { $display_line['target'] = true; } foreach ($line_arr as $range) { if ($line_number >= $range['min'] && $line_number <= $range['max']) { $display_line['highlighted'] = true; } } } $display[] = $display_line; ++$line_number; } $request = $this->getRequest(); $viewer = $request->getUser(); $commits = array_filter(ipull($display, 'commit')); if ($commits) { $commits = id(new DiffusionCommitQuery())->setViewer($viewer)->withRepository($drequest->getRepository())->withIdentifiers($commits)->execute(); $commits = mpull($commits, null, 'getCommitIdentifier'); } $revision_ids = id(new DifferentialRevision())->loadIDsByCommitPHIDs(mpull($commits, 'getPHID')); $revisions = array(); if ($revision_ids) { $revisions = id(new DifferentialRevisionQuery())->setViewer($viewer)->withIDs($revision_ids)->execute(); } $phids = array(); foreach ($commits as $commit) { if ($commit->getAuthorPHID()) { $phids[] = $commit->getAuthorPHID(); } } foreach ($revisions as $revision) { if ($revision->getAuthorPHID()) { $phids[] = $revision->getAuthorPHID(); } } $handles = $this->loadViewerHandles($phids); Javelin::initBehavior('phabricator-oncopy', array()); $engine = null; $inlines = array(); if ($this->getRequest()->getStr('lint') !== null && $this->lintMessages) { $engine = new PhabricatorMarkupEngine(); $engine->setViewer($viewer); foreach ($this->lintMessages as $message) { $inline = id(new PhabricatorAuditInlineComment())->setSyntheticAuthor(ArcanistLintSeverity::getStringForSeverity($message['severity']) . ' ' . $message['code'] . ' (' . $message['name'] . ')')->setLineNumber($message['line'])->setContent($message['description']); $inlines[$message['line']][] = $inline; $engine->addObject($inline, PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY); } $engine->process(); require_celerity_resource('differential-changeset-view-css'); } $rows = $this->renderInlines(idx($inlines, 0, array()), $show_blame, (bool) $this->coverage, $engine); foreach ($display as $line) { $line_href = $drequest->generateURI(array('action' => 'browse', 'line' => $line['line'], 'stable' => true)); $blame = array(); $style = null; if (array_key_exists('color', $line)) { if ($line['color']) { $style = 'background: ' . $line['color'] . ';'; } $before_link = null; $commit_link = null; $revision_link = null; if (idx($line, 'commit')) { $commit = $line['commit']; if (idx($commits, $commit)) { $tooltip = $this->renderCommitTooltip($commits[$commit], $handles, $line['author']); } else { $tooltip = null; } Javelin::initBehavior('phabricator-tooltips', array()); require_celerity_resource('aphront-tooltip-css'); $commit_link = javelin_tag('a', array('href' => $drequest->generateURI(array('action' => 'commit', 'commit' => $line['commit'])), 'sigil' => 'has-tooltip', 'meta' => array('tip' => $tooltip, 'align' => 'E', 'size' => 600)), id(new PhutilUTF8StringTruncator())->setMaximumGlyphs(9)->setTerminator('')->truncateString($line['commit'])); $revision_id = null; if (idx($commits, $commit)) { $revision_id = idx($revision_ids, $commits[$commit]->getPHID()); } if ($revision_id) { $revision = idx($revisions, $revision_id); if ($revision) { $tooltip = $this->renderRevisionTooltip($revision, $handles); $revision_link = javelin_tag('a', array('href' => '/D' . $revision->getID(), 'sigil' => 'has-tooltip', 'meta' => array('tip' => $tooltip, 'align' => 'E', 'size' => 600)), 'D' . $revision->getID()); } } $uri = $line_href->alter('before', $commit); $before_link = javelin_tag('a', array('href' => $uri->setQueryParam('view', 'blame'), 'sigil' => 'has-tooltip', 'meta' => array('tip' => pht('Skip Past This Commit'), 'align' => 'E', 'size' => 300)), "«"); } $blame[] = phutil_tag('th', array('class' => 'diffusion-blame-link'), $before_link); $object_links = array(); $object_links[] = $commit_link; if ($revision_link) { $object_links[] = phutil_tag('span', array(), '/'); $object_links[] = $revision_link; } $blame[] = phutil_tag('th', array('class' => 'diffusion-rev-link'), $object_links); } $line_link = phutil_tag('a', array('href' => $line_href, 'style' => $style), $line['line']); $blame[] = javelin_tag('th', array('class' => 'diffusion-line-link', 'sigil' => 'phabricator-source-line', 'style' => $style), $line_link); Javelin::initBehavior('phabricator-line-linker'); if ($line['target']) { Javelin::initBehavior('diffusion-jump-to', array('target' => 'scroll_target')); $anchor_text = phutil_tag('a', array('id' => 'scroll_target'), ''); } else { $anchor_text = null; } $blame[] = phutil_tag('td', array(), array($anchor_text, "", phutil_safe_html(str_replace("\t", ' ', $line['data'])))); if ($this->coverage) { require_celerity_resource('differential-changeset-view-css'); $cov_index = $line['line'] - 1; if (isset($this->coverage[$cov_index])) { $cov_class = $this->coverage[$cov_index]; } else { $cov_class = 'N'; } $blame[] = phutil_tag('td', array('class' => 'cov cov-' . $cov_class), ''); } $rows[] = phutil_tag('tr', array('class' => $line['highlighted'] ? 'phabricator-source-highlight' : null), $blame); $cur_inlines = $this->renderInlines(idx($inlines, $line['line'], array()), $show_blame, $this->coverage, $engine); foreach ($cur_inlines as $cur_inline) { $rows[] = $cur_inline; } } return $rows; }
protected function getHead() { $monospaced = PhabricatorEnv::getEnvConfig('style.monospace'); $monospaced_win = PhabricatorEnv::getEnvConfig('style.monospace.windows'); $request = $this->getRequest(); if ($request) { $user = $request->getUser(); if ($user) { $pref = $user->loadPreferences()->getPreference(PhabricatorUserPreferences::PREFERENCE_MONOSPACED); $monospaced = nonempty($pref, $monospaced); $monospaced_win = nonempty($pref, $monospaced_win); } } $response = CelerityAPI::getStaticResourceResponse(); return hsprintf('%s<style type="text/css">' . '.PhabricatorMonospaced, ' . '.phabricator-remarkup .remarkup-code-block { font: %s; } ' . '.platform-windows .PhabricatorMonospaced, ' . '.platform-windows .phabricator-remarkup ' . '.remarkup-code-block { font: %s; }' . '</style>%s', parent::getHead(), phutil_safe_html($monospaced), phutil_safe_html($monospaced_win), $response->renderSingleResource('javelin-magical-init', 'phabricator')); }