[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class AphrontTableView extends AphrontView { 4 5 protected $data; 6 protected $headers; 7 protected $shortHeaders; 8 protected $rowClasses = array(); 9 protected $columnClasses = array(); 10 protected $cellClasses = array(); 11 protected $zebraStripes = true; 12 protected $noDataString; 13 protected $className; 14 protected $columnVisibility = array(); 15 private $deviceVisibility = array(); 16 17 protected $sortURI; 18 protected $sortParam; 19 protected $sortSelected; 20 protected $sortReverse; 21 protected $sortValues; 22 private $deviceReadyTable; 23 24 public function __construct(array $data) { 25 $this->data = $data; 26 } 27 28 public function setHeaders(array $headers) { 29 $this->headers = $headers; 30 return $this; 31 } 32 33 public function setColumnClasses(array $column_classes) { 34 $this->columnClasses = $column_classes; 35 return $this; 36 } 37 38 public function setRowClasses(array $row_classes) { 39 $this->rowClasses = $row_classes; 40 return $this; 41 } 42 43 public function setCellClasses(array $cell_classes) { 44 $this->cellClasses = $cell_classes; 45 return $this; 46 } 47 48 public function setNoDataString($no_data_string) { 49 $this->noDataString = $no_data_string; 50 return $this; 51 } 52 53 public function setClassName($class_name) { 54 $this->className = $class_name; 55 return $this; 56 } 57 58 public function setZebraStripes($zebra_stripes) { 59 $this->zebraStripes = $zebra_stripes; 60 return $this; 61 } 62 63 public function setColumnVisibility(array $visibility) { 64 $this->columnVisibility = $visibility; 65 return $this; 66 } 67 68 public function setDeviceVisibility(array $device_visibility) { 69 $this->deviceVisibility = $device_visibility; 70 return $this; 71 } 72 73 public function setDeviceReadyTable($ready) { 74 $this->deviceReadyTable = $ready; 75 return $this; 76 } 77 78 public function setShortHeaders(array $short_headers) { 79 $this->shortHeaders = $short_headers; 80 return $this; 81 } 82 83 /** 84 * Parse a sorting parameter: 85 * 86 * list($sort, $reverse) = AphrontTableView::parseSortParam($sort_param); 87 * 88 * @param string Sort request parameter. 89 * @return pair Sort value, sort direction. 90 */ 91 public static function parseSort($sort) { 92 return array(ltrim($sort, '-'), preg_match('/^-/', $sort)); 93 } 94 95 public function makeSortable( 96 PhutilURI $base_uri, 97 $param, 98 $selected, 99 $reverse, 100 array $sort_values) { 101 102 $this->sortURI = $base_uri; 103 $this->sortParam = $param; 104 $this->sortSelected = $selected; 105 $this->sortReverse = $reverse; 106 $this->sortValues = array_values($sort_values); 107 108 return $this; 109 } 110 111 public function render() { 112 require_celerity_resource('aphront-table-view-css'); 113 114 $table = array(); 115 116 $col_classes = array(); 117 foreach ($this->columnClasses as $key => $class) { 118 if (strlen($class)) { 119 $col_classes[] = $class; 120 } else { 121 $col_classes[] = null; 122 } 123 } 124 125 $visibility = array_values($this->columnVisibility); 126 $device_visibility = array_values($this->deviceVisibility); 127 $headers = $this->headers; 128 $short_headers = $this->shortHeaders; 129 $sort_values = $this->sortValues; 130 if ($headers) { 131 while (count($headers) > count($visibility)) { 132 $visibility[] = true; 133 } 134 while (count($headers) > count($device_visibility)) { 135 $device_visibility[] = true; 136 } 137 while (count($headers) > count($short_headers)) { 138 $short_headers[] = null; 139 } 140 while (count($headers) > count($sort_values)) { 141 $sort_values[] = null; 142 } 143 144 $tr = array(); 145 foreach ($headers as $col_num => $header) { 146 if (!$visibility[$col_num]) { 147 continue; 148 } 149 150 $classes = array(); 151 152 if (!empty($col_classes[$col_num])) { 153 $classes[] = $col_classes[$col_num]; 154 } 155 156 if (empty($device_visibility[$col_num])) { 157 $classes[] = 'aphront-table-view-nodevice'; 158 } 159 160 if ($sort_values[$col_num] !== null) { 161 $classes[] = 'aphront-table-view-sortable'; 162 163 $sort_value = $sort_values[$col_num]; 164 $sort_glyph_class = 'aphront-table-down-sort'; 165 if ($sort_value == $this->sortSelected) { 166 if ($this->sortReverse) { 167 $sort_glyph_class = 'aphront-table-up-sort'; 168 } else if (!$this->sortReverse) { 169 $sort_value = '-'.$sort_value; 170 } 171 $classes[] = 'aphront-table-view-sortable-selected'; 172 } 173 174 $sort_glyph = phutil_tag( 175 'span', 176 array( 177 'class' => $sort_glyph_class, 178 ), 179 ''); 180 181 $header = phutil_tag( 182 'a', 183 array( 184 'href' => $this->sortURI->alter($this->sortParam, $sort_value), 185 'class' => 'aphront-table-view-sort-link', 186 ), 187 array( 188 $header, 189 ' ', 190 $sort_glyph, 191 )); 192 } 193 194 if ($classes) { 195 $class = implode(' ', $classes); 196 } else { 197 $class = null; 198 } 199 200 if ($short_headers[$col_num] !== null) { 201 $header_nodevice = phutil_tag( 202 'span', 203 array( 204 'class' => 'aphront-table-view-nodevice', 205 ), 206 $header); 207 $header_device = phutil_tag( 208 'span', 209 array( 210 'class' => 'aphront-table-view-device', 211 ), 212 $short_headers[$col_num]); 213 214 $header = hsprintf('%s %s', $header_nodevice, $header_device); 215 } 216 217 $tr[] = phutil_tag('th', array('class' => $class), $header); 218 } 219 $table[] = phutil_tag('tr', array(), $tr); 220 } 221 222 foreach ($col_classes as $key => $value) { 223 224 if (($sort_values[$key] !== null) && 225 ($sort_values[$key] == $this->sortSelected)) { 226 $value = trim($value.' sorted-column'); 227 } 228 229 if ($value !== null) { 230 $col_classes[$key] = $value; 231 } 232 } 233 234 $data = $this->data; 235 if ($data) { 236 $row_num = 0; 237 foreach ($data as $row) { 238 while (count($row) > count($col_classes)) { 239 $col_classes[] = null; 240 } 241 while (count($row) > count($visibility)) { 242 $visibility[] = true; 243 } 244 $tr = array(); 245 // NOTE: Use of a separate column counter is to allow this to work 246 // correctly if the row data has string or non-sequential keys. 247 $col_num = 0; 248 foreach ($row as $value) { 249 if (!$visibility[$col_num]) { 250 ++$col_num; 251 continue; 252 } 253 $class = $col_classes[$col_num]; 254 if (empty($device_visibility[$col_num])) { 255 $class = trim($class.' aphront-table-view-nodevice'); 256 } 257 if (!empty($this->cellClasses[$row_num][$col_num])) { 258 $class = trim($class.' '.$this->cellClasses[$row_num][$col_num]); 259 } 260 $tr[] = phutil_tag('td', array('class' => $class), $value); 261 ++$col_num; 262 } 263 264 $class = idx($this->rowClasses, $row_num); 265 if ($this->zebraStripes && ($row_num % 2)) { 266 if ($class !== null) { 267 $class = 'alt alt-'.$class; 268 } else { 269 $class = 'alt'; 270 } 271 } 272 273 $table[] = phutil_tag('tr', array('class' => $class), $tr); 274 ++$row_num; 275 } 276 } else { 277 $colspan = max(count(array_filter($visibility)), 1); 278 $table[] = phutil_tag( 279 'tr', 280 array('class' => 'no-data'), 281 phutil_tag( 282 'td', 283 array('colspan' => $colspan), 284 coalesce($this->noDataString, pht('No data available.')))); 285 } 286 287 $table_class = 'aphront-table-view'; 288 if ($this->className !== null) { 289 $table_class .= ' '.$this->className; 290 } 291 if ($this->deviceReadyTable) { 292 $table_class .= ' aphront-table-view-device-ready'; 293 } 294 295 $html = phutil_tag('table', array('class' => $table_class), $table); 296 return phutil_tag_div('aphront-table-wrap', $html); 297 } 298 299 public static function renderSingleDisplayLine($line) { 300 301 // TODO: Is there a cleaner way to do this? We use a relative div with 302 // overflow hidden to provide the bounds, and an absolute span with 303 // white-space: pre to prevent wrapping. We need to append a character 304 // ( -- nonbreaking space) afterward to give the bounds div height 305 // (alternatively, we could hard-code the line height). This is gross but 306 // it's not clear that there's a better appraoch. 307 308 return phutil_tag( 309 'div', 310 array( 311 'class' => 'single-display-line-bounds', 312 ), 313 array( 314 phutil_tag( 315 'span', 316 array( 317 'class' => 'single-display-line-content', 318 ), 319 $line), 320 "\xC2\xA0", 321 )); 322 } 323 324 325 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |