[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * This is a standard Phabricator page with menus, Javelin, DarkConsole, and 5 * basic styles. 6 * 7 */ 8 final class PhabricatorStandardPageView extends PhabricatorBarePageView { 9 10 private $baseURI; 11 private $applicationName; 12 private $glyph; 13 private $menuContent; 14 private $showChrome = true; 15 private $disableConsole; 16 private $pageObjects = array(); 17 private $applicationMenu; 18 private $showFooter = true; 19 20 public function setShowFooter($show_footer) { 21 $this->showFooter = $show_footer; 22 return $this; 23 } 24 25 public function getShowFooter() { 26 return $this->showFooter; 27 } 28 29 public function setApplicationMenu(PHUIListView $application_menu) { 30 $this->applicationMenu = $application_menu; 31 return $this; 32 } 33 34 public function getApplicationMenu() { 35 return $this->applicationMenu; 36 } 37 38 public function setApplicationName($application_name) { 39 $this->applicationName = $application_name; 40 return $this; 41 } 42 43 public function setDisableConsole($disable) { 44 $this->disableConsole = $disable; 45 return $this; 46 } 47 48 public function getApplicationName() { 49 return $this->applicationName; 50 } 51 52 public function setBaseURI($base_uri) { 53 $this->baseURI = $base_uri; 54 return $this; 55 } 56 57 public function getBaseURI() { 58 return $this->baseURI; 59 } 60 61 public function setShowChrome($show_chrome) { 62 $this->showChrome = $show_chrome; 63 return $this; 64 } 65 66 public function getShowChrome() { 67 return $this->showChrome; 68 } 69 70 public function appendPageObjects(array $objs) { 71 foreach ($objs as $obj) { 72 $this->pageObjects[] = $obj; 73 } 74 } 75 76 public function getTitle() { 77 $use_glyph = true; 78 79 $request = $this->getRequest(); 80 if ($request) { 81 $user = $request->getUser(); 82 if ($user && $user->loadPreferences()->getPreference( 83 PhabricatorUserPreferences::PREFERENCE_TITLES) !== 'glyph') { 84 $use_glyph = false; 85 } 86 } 87 88 $title = parent::getTitle(); 89 90 $prefix = null; 91 if ($use_glyph) { 92 $prefix = $this->getGlyph(); 93 } else { 94 $application_name = $this->getApplicationName(); 95 if (strlen($application_name)) { 96 $prefix = '['.$application_name.']'; 97 } 98 } 99 100 if (strlen($prefix)) { 101 $title = $prefix.' '.$title; 102 } 103 104 return $title; 105 } 106 107 108 protected function willRenderPage() { 109 parent::willRenderPage(); 110 111 if (!$this->getRequest()) { 112 throw new Exception( 113 pht( 114 'You must set the Request to render a PhabricatorStandardPageView.')); 115 } 116 117 $console = $this->getConsole(); 118 119 require_celerity_resource('phabricator-core-css'); 120 require_celerity_resource('phabricator-zindex-css'); 121 require_celerity_resource('phui-button-css'); 122 require_celerity_resource('phui-spacing-css'); 123 require_celerity_resource('phui-form-css'); 124 require_celerity_resource('sprite-gradient-css'); 125 require_celerity_resource('phabricator-standard-page-view'); 126 127 Javelin::initBehavior('workflow', array()); 128 129 $request = $this->getRequest(); 130 $user = null; 131 if ($request) { 132 $user = $request->getUser(); 133 } 134 135 if ($user) { 136 $default_img_uri = 137 celerity_get_resource_uri( 138 'rsrc/image/icon/fatcow/document_black.png'); 139 $download_form = phabricator_form( 140 $user, 141 array( 142 'action' => '#', 143 'method' => 'POST', 144 'class' => 'lightbox-download-form', 145 'sigil' => 'download', 146 ), 147 phutil_tag( 148 'button', 149 array(), 150 pht('Download'))); 151 152 Javelin::initBehavior( 153 'lightbox-attachments', 154 array( 155 'defaultImageUri' => $default_img_uri, 156 'downloadForm' => $download_form, 157 )); 158 } 159 160 Javelin::initBehavior('aphront-form-disable-on-submit'); 161 Javelin::initBehavior('toggle-class', array()); 162 Javelin::initBehavior('konami', array()); 163 Javelin::initBehavior('history-install'); 164 Javelin::initBehavior('phabricator-gesture'); 165 166 $current_token = null; 167 if ($user) { 168 $current_token = $user->getCSRFToken(); 169 } 170 171 Javelin::initBehavior( 172 'refresh-csrf', 173 array( 174 'tokenName' => AphrontRequest::getCSRFTokenName(), 175 'header' => AphrontRequest::getCSRFHeaderName(), 176 'current' => $current_token, 177 )); 178 179 Javelin::initBehavior('device'); 180 181 if ($user->hasSession()) { 182 $hisec = ($user->getSession()->getHighSecurityUntil() - time()); 183 if ($hisec > 0) { 184 $remaining_time = phutil_format_relative_time($hisec); 185 Javelin::initBehavior( 186 'high-security-warning', 187 array( 188 'uri' => '/auth/session/downgrade/', 189 'message' => pht( 190 'Your session is in high security mode. When you '. 191 'finish using it, click here to leave.', 192 $remaining_time), 193 )); 194 } 195 } 196 197 if ($console) { 198 require_celerity_resource('aphront-dark-console-css'); 199 200 $headers = array(); 201 if (DarkConsoleXHProfPluginAPI::isProfilerStarted()) { 202 $headers[DarkConsoleXHProfPluginAPI::getProfilerHeader()] = 'page'; 203 } 204 if (DarkConsoleServicesPlugin::isQueryAnalyzerRequested()) { 205 $headers[DarkConsoleServicesPlugin::getQueryAnalyzerHeader()] = true; 206 } 207 208 Javelin::initBehavior( 209 'dark-console', 210 array( 211 // NOTE: We use a generic label here to prevent input reflection 212 // and mitigate compression attacks like BREACH. See discussion in 213 // T3684. 214 'uri' => pht('Main Request'), 215 'selected' => $user ? $user->getConsoleTab() : null, 216 'visible' => $user ? (int)$user->getConsoleVisible() : true, 217 'headers' => $headers, 218 )); 219 220 // Change this to initBehavior when there is some behavior to initialize 221 require_celerity_resource('javelin-behavior-error-log'); 222 } 223 224 if ($user) { 225 $viewer = $user; 226 } else { 227 $viewer = new PhabricatorUser(); 228 } 229 230 $menu = id(new PhabricatorMainMenuView()) 231 ->setUser($viewer); 232 233 if ($this->getController()) { 234 $menu->setController($this->getController()); 235 } 236 237 if ($this->getApplicationMenu()) { 238 $menu->setApplicationMenu($this->getApplicationMenu()); 239 } 240 241 $this->menuContent = $menu->render(); 242 } 243 244 245 protected function getHead() { 246 $monospaced = PhabricatorEnv::getEnvConfig('style.monospace'); 247 $monospaced_win = PhabricatorEnv::getEnvConfig('style.monospace.windows'); 248 249 $request = $this->getRequest(); 250 if ($request) { 251 $user = $request->getUser(); 252 if ($user) { 253 $pref = $user->loadPreferences()->getPreference( 254 PhabricatorUserPreferences::PREFERENCE_MONOSPACED); 255 $monospaced = nonempty($pref, $monospaced); 256 $monospaced_win = nonempty($pref, $monospaced_win); 257 } 258 } 259 260 $response = CelerityAPI::getStaticResourceResponse(); 261 262 return hsprintf( 263 '%s<style type="text/css">'. 264 '.PhabricatorMonospaced, '. 265 '.phabricator-remarkup .remarkup-code-block '. 266 '.remarkup-code { font: %s; } '. 267 '.platform-windows .PhabricatorMonospaced, '. 268 '.platform-windows .phabricator-remarkup '. 269 '.remarkup-code-block .remarkup-code { font: %s; }'. 270 '</style>%s', 271 parent::getHead(), 272 phutil_safe_html($monospaced), 273 phutil_safe_html($monospaced_win), 274 $response->renderSingleResource('javelin-magical-init', 'phabricator')); 275 } 276 277 public function setGlyph($glyph) { 278 $this->glyph = $glyph; 279 return $this; 280 } 281 282 public function getGlyph() { 283 return $this->glyph; 284 } 285 286 protected function willSendResponse($response) { 287 $request = $this->getRequest(); 288 $response = parent::willSendResponse($response); 289 290 $console = $request->getApplicationConfiguration()->getConsole(); 291 292 if ($console) { 293 $response = PhutilSafeHTML::applyFunction( 294 'str_replace', 295 hsprintf('<darkconsole />'), 296 $console->render($request), 297 $response); 298 } 299 300 return $response; 301 } 302 303 protected function getBody() { 304 $console = $this->getConsole(); 305 306 $user = null; 307 $request = $this->getRequest(); 308 if ($request) { 309 $user = $request->getUser(); 310 } 311 312 $header_chrome = null; 313 if ($this->getShowChrome()) { 314 $header_chrome = $this->menuContent; 315 } 316 317 $developer_warning = null; 318 if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode') && 319 DarkConsoleErrorLogPluginAPI::getErrors()) { 320 $developer_warning = phutil_tag_div( 321 'aphront-developer-error-callout', 322 pht( 323 'This page raised PHP errors. Find them in DarkConsole '. 324 'or the error log.')); 325 } 326 327 // Render the "you have unresolved setup issues..." warning. 328 $setup_warning = null; 329 if ($user && $user->getIsAdmin()) { 330 $open = PhabricatorSetupCheck::getOpenSetupIssueCount(); 331 if ($open) { 332 $setup_warning = phutil_tag_div( 333 'setup-warning-callout', 334 phutil_tag( 335 'a', 336 array( 337 'href' => '/config/issue/', 338 ), 339 pht('You have %d unresolved setup issue(s)...', $open))); 340 } 341 } 342 343 return phutil_tag( 344 'div', 345 array( 346 'id' => 'base-page', 347 'class' => 'phabricator-standard-page', 348 ), 349 array( 350 $developer_warning, 351 $setup_warning, 352 $header_chrome, 353 phutil_tag_div('phabricator-standard-page-body', array( 354 ($console ? hsprintf('<darkconsole />') : null), 355 parent::getBody(), 356 $this->renderFooter(), 357 )), 358 )); 359 } 360 361 protected function getTail() { 362 $request = $this->getRequest(); 363 $user = $request->getUser(); 364 365 $tail = array( 366 parent::getTail(), 367 ); 368 369 $response = CelerityAPI::getStaticResourceResponse(); 370 371 if (PhabricatorEnv::getEnvConfig('notification.enabled')) { 372 if ($user && $user->isLoggedIn()) { 373 374 $aphlict_object_id = celerity_generate_unique_node_id(); 375 $aphlict_container_id = celerity_generate_unique_node_id(); 376 377 $client_uri = PhabricatorEnv::getEnvConfig('notification.client-uri'); 378 $client_uri = new PhutilURI($client_uri); 379 if ($client_uri->getDomain() == 'localhost') { 380 $this_host = $this->getRequest()->getHost(); 381 $this_host = new PhutilURI('http://'.$this_host.'/'); 382 $client_uri->setDomain($this_host->getDomain()); 383 } 384 385 $map = CelerityResourceMap::getNamedInstance('phabricator'); 386 $swf_uri = $response->getURI($map, 'rsrc/swf/aphlict.swf', true); 387 388 $enable_debug = PhabricatorEnv::getEnvConfig('notification.debug'); 389 390 $subscriptions = $this->pageObjects; 391 if ($user) { 392 $subscriptions[] = $user->getPHID(); 393 } 394 395 Javelin::initBehavior( 396 'aphlict-listen', 397 array( 398 'id' => $aphlict_object_id, 399 'containerID' => $aphlict_container_id, 400 'server' => $client_uri->getDomain(), 401 'port' => $client_uri->getPort(), 402 'debug' => $enable_debug, 403 'swfURI' => $swf_uri, 404 'pageObjects' => array_fill_keys($this->pageObjects, true), 405 'subscriptions' => $subscriptions, 406 )); 407 408 $tail[] = phutil_tag( 409 'div', 410 array( 411 'id' => $aphlict_container_id, 412 'style' => 413 'position: absolute; width: 0; height: 0; overflow: hidden;', 414 ), 415 ''); 416 } 417 } 418 419 $tail[] = $response->renderHTMLFooter(); 420 421 return $tail; 422 } 423 424 protected function getBodyClasses() { 425 $classes = array(); 426 427 if (!$this->getShowChrome()) { 428 $classes[] = 'phabricator-chromeless-page'; 429 } 430 431 $agent = AphrontRequest::getHTTPHeader('User-Agent'); 432 433 // Try to guess the device resolution based on UA strings to avoid a flash 434 // of incorrectly-styled content. 435 $device_guess = 'device-desktop'; 436 if (preg_match('@iPhone|iPod|(Android.*Chrome/[.0-9]* Mobile)@', $agent)) { 437 $device_guess = 'device-phone device'; 438 } else if (preg_match('@iPad|(Android.*Chrome/)@', $agent)) { 439 $device_guess = 'device-tablet device'; 440 } 441 442 $classes[] = $device_guess; 443 444 if (preg_match('@Windows@', $agent)) { 445 $classes[] = 'platform-windows'; 446 } else if (preg_match('@Macintosh@', $agent)) { 447 $classes[] = 'platform-mac'; 448 } else if (preg_match('@X11@', $agent)) { 449 $classes[] = 'platform-linux'; 450 } 451 452 if ($this->getRequest()->getStr('__print__')) { 453 $classes[] = 'printable'; 454 } 455 456 if ($this->getRequest()->getStr('__aural__')) { 457 $classes[] = 'audible'; 458 } 459 460 return implode(' ', $classes); 461 } 462 463 private function getConsole() { 464 if ($this->disableConsole) { 465 return null; 466 } 467 return $this->getRequest()->getApplicationConfiguration()->getConsole(); 468 } 469 470 private function renderFooter() { 471 if (!$this->getShowChrome()) { 472 return null; 473 } 474 475 if (!$this->getShowFooter()) { 476 return null; 477 } 478 479 $items = PhabricatorEnv::getEnvConfig('ui.footer-items'); 480 if (!$items) { 481 return null; 482 } 483 484 $foot = array(); 485 foreach ($items as $item) { 486 $name = idx($item, 'name', pht('Unnamed Footer Item')); 487 488 $href = idx($item, 'href'); 489 if (!PhabricatorEnv::isValidWebResource($href)) { 490 $href = null; 491 } 492 493 if ($href !== null) { 494 $tag = 'a'; 495 } else { 496 $tag = 'span'; 497 } 498 499 $foot[] = phutil_tag( 500 $tag, 501 array( 502 'href' => $href, 503 ), 504 $name); 505 } 506 $foot = phutil_implode_html(" \xC2\xB7 ", $foot); 507 508 return phutil_tag( 509 'div', 510 array( 511 'class' => 'phabricator-standard-page-footer grouped', 512 ), 513 $foot); 514 } 515 516 }
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 |