Path: blob/master/src/view/layout/PhabricatorSourceCodeView.php
12241 views
<?php12final class PhabricatorSourceCodeView extends AphrontView {34private $lines;5private $uri;6private $highlights = array();7private $canClickHighlight = true;8private $truncatedFirstBytes = false;9private $truncatedFirstLines = false;10private $symbolMetadata;11private $blameMap;12private $coverage = array();1314public function setLines(array $lines) {15$this->lines = $lines;16return $this;17}1819public function setURI(PhutilURI $uri) {20$this->uri = $uri;21return $this;22}2324public function setHighlights(array $array) {25$this->highlights = array_fuse($array);26return $this;27}2829public function disableHighlightOnClick() {30$this->canClickHighlight = false;31return $this;32}3334public function setTruncatedFirstBytes($truncated_first_bytes) {35$this->truncatedFirstBytes = $truncated_first_bytes;36return $this;37}3839public function setTruncatedFirstLines($truncated_first_lines) {40$this->truncatedFirstLines = $truncated_first_lines;41return $this;42}4344public function setSymbolMetadata(array $symbol_metadata) {45$this->symbolMetadata = $symbol_metadata;46return $this;47}4849public function getSymbolMetadata() {50return $this->symbolMetadata;51}5253public function setBlameMap(array $map) {54$this->blameMap = $map;55return $this;56}5758public function getBlameMap() {59return $this->blameMap;60}6162public function setCoverage(array $coverage) {63$this->coverage = $coverage;64return $this;65}6667public function getCoverage() {68return $this->coverage;69}7071public function render() {72$blame_map = $this->getBlameMap();73$has_blame = ($blame_map !== null);7475require_celerity_resource('phabricator-source-code-view-css');76require_celerity_resource('syntax-highlighting-css');7778if ($this->canClickHighlight) {79Javelin::initBehavior('phabricator-line-linker');80}8182$line_number = 1;8384$rows = array();8586$lines = $this->lines;87if ($this->truncatedFirstLines) {88$lines[] = phutil_tag(89'span',90array(91'class' => 'c',92),93pht('...'));94} else if ($this->truncatedFirstBytes) {95$last_key = last_key($lines);96$lines[$last_key] = hsprintf(97'%s%s',98$lines[$last_key],99phutil_tag(100'span',101array(102'class' => 'c',103),104pht('...')));105}106107$base_uri = (string)$this->uri;108$wrote_anchor = false;109110$coverage = $this->getCoverage();111$coverage_count = count($coverage);112$coverage_data = ipull($coverage, 'data');113114// TODO: Modularize this properly, see T13125.115$coverage_map = array(116'C' => 'background: #66bbff;',117'U' => 'background: #dd8866;',118'N' => 'background: #ddeeff;',119'X' => 'background: #aa00aa;',120);121122foreach ($lines as $line) {123$row_attributes = array();124if (isset($this->highlights[$line_number])) {125$row_attributes['class'] = 'phabricator-source-highlight';126if (!$wrote_anchor) {127$row_attributes['id'] = 'phabricator-line-linker-anchor';128$wrote_anchor = true;129}130}131132if ($this->canClickHighlight) {133if ($base_uri) {134$line_href = $base_uri.'$'.$line_number;135} else {136$line_href = null;137}138139$tag_number = phutil_tag(140'a',141array(142'href' => $line_href,143'data-n' => $line_number,144));145} else {146$tag_number = phutil_tag(147'span',148array(),149$line_number);150}151152if ($has_blame) {153$lines = idx($blame_map, $line_number);154155if ($lines) {156$skip_blame = 'skip';157$info_blame = 'info';158} else {159$skip_blame = null;160$info_blame = null;161}162163$blame_cells = array(164phutil_tag(165'th',166array(167'class' => 'phabricator-source-blame-skip',168'data-blame' => $skip_blame,169)),170phutil_tag(171'th',172array(173'class' => 'phabricator-source-blame-info',174'data-blame' => $info_blame,175'data-blame-lines' => $lines,176)),177);178} else {179$blame_cells = null;180}181182$coverage_cells = array();183foreach ($coverage as $coverage_idx => $coverage_spec) {184if (isset($coverage_spec['data'][$line_number - 1])) {185$coverage_char = $coverage_spec['data'][$line_number - 1];186} else {187$coverage_char = null;188}189190$coverage_style = idx($coverage_map, $coverage_char, null);191192$coverage_cells[] = phutil_tag(193'th',194array(195'class' => 'phabricator-source-coverage',196'style' => $coverage_style,197'data-coverage' => $coverage_idx.'/'.$coverage_char,198));199}200201$rows[] = phutil_tag(202'tr',203$row_attributes,204array(205$blame_cells,206phutil_tag(207'th',208array(209'class' => 'phabricator-source-line',210),211$tag_number),212phutil_tag(213'td',214array(215'class' => 'phabricator-source-code',216),217$line),218$coverage_cells,219));220221$line_number++;222}223224$classes = array();225$classes[] = 'phabricator-source-code-view';226$classes[] = 'remarkup-code';227$classes[] = 'PhabricatorMonospaced';228229$symbol_metadata = $this->getSymbolMetadata();230231$sigils = array();232$sigils[] = 'phabricator-source';233$sigils[] = 'has-symbols';234235Javelin::initBehavior('repository-crossreference');236237return phutil_tag_div(238'phabricator-source-code-container',239javelin_tag(240'table',241array(242'class' => implode(' ', $classes),243'sigil' => implode(' ', $sigils),244'meta' => array(245'uri' => (string)$this->uri,246'symbols' => $symbol_metadata,247),248),249phutil_implode_html('', $rows)));250}251252}253254255