diff --git a/src/aphront/response/AphrontRedirectResponse.php b/src/aphront/response/AphrontRedirectResponse.php
index b01cc3644d..4ee21fb4ee 100644
--- a/src/aphront/response/AphrontRedirectResponse.php
+++ b/src/aphront/response/AphrontRedirectResponse.php
@@ -1,66 +1,68 @@
uri = $uri;
return $this;
}
public function getURI() {
return (string)$this->uri;
}
public function shouldStopForDebugging() {
return PhabricatorEnv::getEnvConfig('debug.stop-on-redirect');
}
public function getHeaders() {
$headers = array();
if (!$this->shouldStopForDebugging()) {
$headers[] = array('Location', $this->uri);
}
$headers = array_merge(parent::getHeaders(), $headers);
return $headers;
}
public function buildResponseString() {
if ($this->shouldStopForDebugging()) {
$view = new PhabricatorStandardPageView();
$view->setRequest($this->getRequest());
$view->setApplicationName('Debug');
$view->setTitle('Stopped on Redirect');
$error = new AphrontErrorView();
$error->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
$error->setTitle('Stopped on Redirect');
+ $error->appendChild(phutil_tag('p', array(), pht(
+ 'You were stopped here because %s is set in your configuration.',
+ phutil_tag('tt', array(), 'debug.stop-on-redirect'))));
+
$link = phutil_tag(
'a',
array(
'href' => $this->getURI(),
),
- 'Continue to: '.$this->getURI());
+ $this->getURI());
- $error->appendChild(hsprintf(
- '
You were stopped here because debug.stop-on-redirect '.
- 'is set in your configuration.
'.
- '%s
',
- $link));
+ $error->appendChild(phutil_tag('p', array(), pht(
+ 'Continue to: %s',
+ $link)));
$view->appendChild($error);
return $view->render();
}
return '';
}
}
diff --git a/src/infrastructure/celerity/CelerityStaticResourceResponse.php b/src/infrastructure/celerity/CelerityStaticResourceResponse.php
index ccde0280e2..069be5cd85 100644
--- a/src/infrastructure/celerity/CelerityStaticResourceResponse.php
+++ b/src/infrastructure/celerity/CelerityStaticResourceResponse.php
@@ -1,262 +1,263 @@
metadataBlock = (int)$_REQUEST['__metablock__'];
}
}
public function addMetadata($metadata) {
$id = count($this->metadata);
$this->metadata[$id] = $metadata;
return $this->metadataBlock.'_'.$id;
}
public function getMetadataBlock() {
return $this->metadataBlock;
}
/**
* Register a behavior for initialization. NOTE: if $config is empty,
* a behavior will execute only once even if it is initialized multiple times.
* If $config is nonempty, the behavior will be invoked once for each config.
*/
public function initBehavior($behavior, array $config = array()) {
$this->requireResource('javelin-behavior-'.$behavior);
if (empty($this->behaviors[$behavior])) {
$this->behaviors[$behavior] = array();
}
if ($config) {
$this->behaviors[$behavior][] = $config;
}
return $this;
}
public function requireResource($symbol) {
$this->symbols[$symbol] = true;
$this->needsResolve = true;
return $this;
}
private function resolveResources() {
if ($this->needsResolve) {
$map = CelerityResourceMap::getInstance();
$this->resolved = $map->resolveResources(array_keys($this->symbols));
$this->packaged = $map->packageResources($this->resolved);
$this->needsResolve = false;
}
return $this;
}
public function renderSingleResource($symbol) {
$map = CelerityResourceMap::getInstance();
$resolved = $map->resolveResources(array($symbol));
$packaged = $map->packageResources($resolved);
return $this->renderPackagedResources($packaged);
}
public function renderResourcesOfType($type) {
$this->resolveResources();
$resources = array();
foreach ($this->packaged as $resource) {
if ($resource['type'] == $type) {
$resources[] = $resource;
}
}
return $this->renderPackagedResources($resources);
}
private function renderPackagedResources(array $resources) {
$output = array();
foreach ($resources as $resource) {
if (isset($this->hasRendered[$resource['uri']])) {
continue;
}
$this->hasRendered[$resource['uri']] = true;
$output[] = $this->renderResource($resource);
$output[] = "\n";
}
return phutil_implode_html('', $output);
}
private function renderResource(array $resource) {
$uri = $this->getURI($resource);
switch ($resource['type']) {
case 'css':
return phutil_tag(
'link',
array(
'rel' => 'stylesheet',
'type' => 'text/css',
'href' => $uri,
));
case 'js':
return phutil_tag(
'script',
array(
'type' => 'text/javascript',
'src' => $uri,
),
'');
}
throw new Exception("Unable to render resource.");
}
public function renderHTMLFooter() {
$data = array();
if ($this->metadata) {
$json_metadata = AphrontResponse::encodeJSONForHTTPResponse(
$this->metadata);
$this->metadata = array();
} else {
$json_metadata = '{}';
}
// Even if there is no metadata on the page, Javelin uses the mergeData()
// call to start dispatching the event queue.
$data[] = 'JX.Stratcom.mergeData('.$this->metadataBlock.', '.
$json_metadata.');';
$onload = array();
if ($this->behaviors) {
$behaviors = $this->behaviors;
$this->behaviors = array();
$higher_priority_names = array(
'refresh-csrf',
'aphront-basic-tokenizer',
'dark-console',
'history-install',
);
$higher_priority_behaviors = array_select_keys(
$behaviors,
$higher_priority_names);
foreach ($higher_priority_names as $name) {
unset($behaviors[$name]);
}
$behavior_groups = array(
$higher_priority_behaviors,
$behaviors);
foreach ($behavior_groups as $group) {
if (!$group) {
continue;
}
$group_json = AphrontResponse::encodeJSONForHTTPResponse(
$group);
$onload[] = 'JX.initBehaviors('.$group_json.')';
}
}
if ($onload) {
foreach ($onload as $func) {
$data[] = 'JX.onload(function(){'.$func.'});';
}
}
if ($data) {
$data = implode("\n", $data);
return self::renderInlineScript($data);
} else {
return '';
}
}
public static function renderInlineScript($data) {
if (stripos($data, '') !== false) {
throw new Exception(
'Literal is not allowed inside inline script.');
}
if (strpos($data, ' because it is ignored by HTML parsers. We
- // would need to send the document with XHTML content type.
- '',
+ // We don't use 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));
}
public function buildAjaxResponse($payload, $error = null) {
$response = array(
'error' => $error,
'payload' => $payload,
);
if ($this->metadata) {
$response['javelin_metadata'] = $this->metadata;
$this->metadata = array();
}
if ($this->behaviors) {
$response['javelin_behaviors'] = $this->behaviors;
$this->behaviors = array();
}
$this->resolveResources();
$resources = array();
foreach ($this->packaged as $resource) {
$resources[] = $this->getURI($resource);
}
if ($resources) {
$response['javelin_resources'] = $resources;
}
return $response;
}
private function getURI($resource) {
$uri = $resource['uri'];
// In developer mode, we dump file modification times into the URI. When a
// page is reloaded in the browser, any resources brought in by Ajax calls
// do not trigger revalidation, so without this it's very difficult to get
// changes to Ajaxed-in CSS to work (you must clear your cache or rerun
// the map script). In production, we can assume the map script gets run
// after changes, and safely skip this.
if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode')) {
$root = dirname(phutil_get_library_root('phabricator')).'/webroot';
if (isset($resource['disk'])) {
$mtime = (int)filemtime($root.$resource['disk']);
} else {
$mtime = 0;
foreach ($resource['symbols'] as $symbol) {
$map = CelerityResourceMap::getInstance();
$symbol_info = $map->lookupSymbolInformation($symbol);
$mtime = max($mtime, (int)filemtime($root.$symbol_info['disk']));
}
}
$uri = preg_replace('@^/res/@', '/res/'.$mtime.'T/', $uri);
}
return PhabricatorEnv::getCDNURI($uri);
}
}
diff --git a/src/infrastructure/diff/PhabricatorInlineCommentController.php b/src/infrastructure/diff/PhabricatorInlineCommentController.php
index 3a8ad2f1ad..77b3bfe19e 100644
--- a/src/infrastructure/diff/PhabricatorInlineCommentController.php
+++ b/src/infrastructure/diff/PhabricatorInlineCommentController.php
@@ -1,247 +1,248 @@
commentID;
}
public function getOperation() {
return $this->operation;
}
public function getCommentText() {
return $this->commentText;
}
public function getLineLength() {
return $this->lineLength;
}
public function getLineNumber() {
return $this->lineNumber;
}
public function getIsOnRight() {
return $this->isOnRight;
}
public function getChangesetID() {
return $this->changesetID;
}
public function getIsNewFile() {
return $this->isNewFile;
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$this->readRequestParameters();
switch ($this->getOperation()) {
case 'delete':
$inline = $this->loadCommentForEdit($this->getCommentID());
if ($request->isFormPost()) {
$inline->delete();
return $this->buildEmptyResponse();
}
$dialog = new AphrontDialogView();
$dialog->setUser($user);
$dialog->setSubmitURI($request->getRequestURI());
$dialog->setTitle('Really delete this comment?');
$dialog->addHiddenInput('id', $this->getCommentID());
$dialog->addHiddenInput('op', 'delete');
- $dialog->appendChild(hsprintf('Delete this inline comment?
'));
+ $dialog->appendChild(
+ phutil_tag('p', array(), pht('Delete this inline comment?')));
$dialog->addCancelButton('#');
$dialog->addSubmitButton('Delete');
return id(new AphrontDialogResponse())->setDialog($dialog);
case 'edit':
$inline = $this->loadCommentForEdit($this->getCommentID());
$text = $this->getCommentText();
if ($request->isFormPost()) {
if (strlen($text)) {
$inline->setContent($text);
$inline->save();
return $this->buildRenderedCommentResponse(
$inline,
$this->getIsOnRight());
} else {
$inline->delete();
return $this->buildEmptyResponse();
}
}
$edit_dialog = $this->buildEditDialog();
$edit_dialog->setTitle('Edit Inline Comment');
$edit_dialog->addHiddenInput('id', $this->getCommentID());
$edit_dialog->addHiddenInput('op', 'edit');
$edit_dialog->appendChild(
$this->renderTextArea(
nonempty($text, $inline->getContent())));
return id(new AphrontAjaxResponse())
->setContent($edit_dialog->render());
case 'create':
$text = $this->getCommentText();
if (!$request->isFormPost() || !strlen($text)) {
return $this->buildEmptyResponse();
}
$inline = $this->createComment()
->setChangesetID($this->getChangesetID())
->setAuthorPHID($user->getPHID())
->setLineNumber($this->getLineNumber())
->setLineLength($this->getLineLength())
->setIsNewFile($this->getIsNewFile())
->setContent($text)
->save();
return $this->buildRenderedCommentResponse(
$inline,
$this->getIsOnRight());
case 'reply':
default:
$edit_dialog = $this->buildEditDialog();
if ($this->getOperation() == 'reply') {
$inline = $this->loadComment($this->getCommentID());
$edit_dialog->setTitle('Reply to Inline Comment');
$changeset = $inline->getChangesetID();
$is_new = $inline->getIsNewFile();
$number = $inline->getLineNumber();
$length = $inline->getLineLength();
} else {
$edit_dialog->setTitle('New Inline Comment');
$changeset = $this->getChangesetID();
$is_new = $this->getIsNewFile();
$number = $this->getLineNumber();
$length = $this->getLineLength();
}
$edit_dialog->addHiddenInput('op', 'create');
$edit_dialog->addHiddenInput('changeset', $changeset);
$edit_dialog->addHiddenInput('is_new', $is_new);
$edit_dialog->addHiddenInput('number', $number);
$edit_dialog->addHiddenInput('length', $length);
$text_area = $this->renderTextArea($this->getCommentText());
$edit_dialog->appendChild($text_area);
return id(new AphrontAjaxResponse())
->setContent($edit_dialog->render());
}
}
private function readRequestParameters() {
$request = $this->getRequest();
// NOTE: This isn't necessarily a DifferentialChangeset ID, just an
// application identifier for the changeset. In Diffusion, it's a Path ID.
$this->changesetID = $request->getInt('changeset');
$this->isNewFile = $request->getBool('is_new');
$this->isOnRight = $request->getBool('on_right');
$this->lineNumber = $request->getInt('number');
$this->lineLength = $request->getInt('length');
$this->commentText = $request->getStr('text');
$this->commentID = $request->getInt('id');
$this->operation = $request->getStr('op');
}
private function buildEditDialog() {
$request = $this->getRequest();
$user = $request->getUser();
$edit_dialog = new DifferentialInlineCommentEditView();
$edit_dialog->setUser($user);
$edit_dialog->setSubmitURI($request->getRequestURI());
$edit_dialog->setOnRight($this->getIsOnRight());
$edit_dialog->setNumber($this->getLineNumber());
$edit_dialog->setLength($this->getLineLength());
return $edit_dialog;
}
private function buildEmptyResponse() {
return id(new AphrontAjaxResponse())
->setContent(
array(
'markup' => '',
));
}
private function buildRenderedCommentResponse(
PhabricatorInlineCommentInterface $inline,
$on_right) {
$request = $this->getRequest();
$user = $request->getUser();
$engine = new PhabricatorMarkupEngine();
$engine->setViewer($user);
$engine->addObject(
$inline,
PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY);
$engine->process();
$phids = array($user->getPHID());
$handles = $this->loadViewerHandles($phids);
$view = new DifferentialInlineCommentView();
$view->setInlineComment($inline);
$view->setOnRight($on_right);
$view->setBuildScaffolding(true);
$view->setMarkupEngine($engine);
$view->setHandles($handles);
$view->setEditable(true);
return id(new AphrontAjaxResponse())
->setContent(
array(
'inlineCommentID' => $inline->getID(),
'markup' => $view->render(),
));
}
private function renderTextArea($text) {
return javelin_tag(
'textarea',
array(
'class' => 'differential-inline-comment-edit-textarea',
'sigil' => 'differential-inline-comment-edit-textarea',
'name' => 'text',
),
$text);
}
}
diff --git a/src/infrastructure/diff/view/PhabricatorInlineSummaryView.php b/src/infrastructure/diff/view/PhabricatorInlineSummaryView.php
index f8686ebba0..9e05640b61 100644
--- a/src/infrastructure/diff/view/PhabricatorInlineSummaryView.php
+++ b/src/infrastructure/diff/view/PhabricatorInlineSummaryView.php
@@ -1,113 +1,107 @@
groups[$name])) {
$this->groups[$name] = $items;
} else {
$this->groups[$name] = array_merge($this->groups[$name], $items);
}
return $this;
}
public function render() {
require_celerity_resource('inline-comment-summary-css');
return hsprintf('%s%s', $this->renderHeader(), $this->renderTable());
}
private function renderHeader() {
- return phutil_tag(
- 'div',
- array(
- 'class' => 'phabricator-inline-summary',
- ),
- 'Inline Comments');
+ return phutil_tag_div('phabricator-inline-summary', pht('Inline Comments'));
}
private function renderTable() {
$rows = array();
foreach ($this->groups as $group => $items) {
$has_where = false;
foreach ($items as $item) {
if (!empty($item['where'])) {
$has_where = true;
break;
}
}
- $rows[] = hsprintf('%s ', $group);
+ $rows[] = phutil_tag(
+ 'tr',
+ array(),
+ phutil_tag('th', array('colspan' => 3), $group));
foreach ($items as $item) {
$items = isort($items, 'line');
$line = $item['line'];
$length = $item['length'];
if ($length) {
$lines = $line."\xE2\x80\x93".($line + $length);
} else {
$lines = $line;
}
if (isset($item['href'])) {
$href = $item['href'];
$target = '_blank';
$tail = " \xE2\x86\x97";
} else {
$href = '#inline-'.$item['id'];
$target = null;
$tail = null;
}
if ($href) {
$lines = phutil_tag(
'a',
array(
'href' => $href,
'target' => $target,
'class' => 'num',
),
array(
$lines,
$tail,
));
}
$where = idx($item, 'where');
$colspan = ($has_where ? null : 2);
- $rows[] = hsprintf(
- ''.
- '%s '.
- '%s'.
- '%s'.
- ' ',
- $lines,
- ($has_where
- ? hsprintf('%s ', $where)
- : null),
- phutil_tag(
- 'td',
- array(
- 'class' => 'inline-summary-content',
- 'colspan' => $colspan,
- ),
- hsprintf(
- '',
- $item['content'])));
+ $rows[] = phutil_tag(
+ 'tr',
+ array(),
+ array(
+ phutil_tag('td', array('class' => 'inline-line-number'), $lines),
+ ($has_where
+ ? phutil_tag('td', array('class' => 'inline-which-diff'), $where)
+ : null),
+ phutil_tag(
+ 'td',
+ array(
+ 'class' => 'inline-summary-content',
+ 'colspan' => $colspan,
+ ),
+ phutil_tag_div('phabricator-remarkup', $item['content']))));
}
}
return phutil_tag(
'table',
array(
'class' => 'phabricator-inline-summary-table',
),
phutil_implode_html("\n", $rows));
}
}
diff --git a/src/infrastructure/markup/rule/PhabricatorRemarkupRuleYoutube.php b/src/infrastructure/markup/rule/PhabricatorRemarkupRuleYoutube.php
index 6ea88db6ca..ba3b0c92dc 100644
--- a/src/infrastructure/markup/rule/PhabricatorRemarkupRuleYoutube.php
+++ b/src/infrastructure/markup/rule/PhabricatorRemarkupRuleYoutube.php
@@ -1,48 +1,48 @@
uri = new PhutilURI($text);
if ($this->uri->getDomain() &&
preg_match('/(^|\.)youtube\.com$/', $this->uri->getDomain()) &&
idx($this->uri->getQueryParams(), 'v')) {
return $this->markupYoutubeLink();
}
return $text;
}
public function markupYoutubeLink() {
$v = idx($this->uri->getQueryParams(), 'v');
if ($this->getEngine()->isTextMode()) {
return $this->getEngine()->storeText('http://youtu.be/'.$v);
}
$youtube_src = 'https://www.youtube.com/embed/'.$v;
- $iframe = hsprintf(
- '%s
',
+ $iframe = phutil_tag_div(
+ 'embedded-youtube-video',
phutil_tag(
'iframe',
array(
'width' => '650',
'height' => '400',
'style' => 'margin: 1em auto; border: 0px;',
'src' => $youtube_src,
'frameborder' => 0,
),
''));
return $this->getEngine()->storeText($iframe);
}
}
diff --git a/src/view/control/AphrontTableView.php b/src/view/control/AphrontTableView.php
index ede387b65a..17fca10d5a 100644
--- a/src/view/control/AphrontTableView.php
+++ b/src/view/control/AphrontTableView.php
@@ -1,320 +1,323 @@
data = $data;
}
public function setHeaders(array $headers) {
$this->headers = $headers;
return $this;
}
public function setColumnClasses(array $column_classes) {
$this->columnClasses = $column_classes;
return $this;
}
public function setRowClasses(array $row_classes) {
$this->rowClasses = $row_classes;
return $this;
}
public function setCellClasses(array $cell_classes) {
$this->cellClasses = $cell_classes;
return $this;
}
public function setNoDataString($no_data_string) {
$this->noDataString = $no_data_string;
return $this;
}
public function setClassName($class_name) {
$this->className = $class_name;
return $this;
}
public function setZebraStripes($zebra_stripes) {
$this->zebraStripes = $zebra_stripes;
return $this;
}
public function setColumnVisibility(array $visibility) {
$this->columnVisibility = $visibility;
return $this;
}
public function setDeviceVisibility(array $device_visibility) {
$this->deviceVisibility = $device_visibility;
return $this;
}
public function setDeviceReadyTable($ready) {
$this->deviceReadyTable = $ready;
return $this;
}
public function setShortHeaders(array $short_headers) {
$this->shortHeaders = $short_headers;
return $this;
}
/**
* Parse a sorting parameter:
*
* list($sort, $reverse) = AphrontTableView::parseSortParam($sort_param);
*
* @param string Sort request parameter.
* @return pair Sort value, sort direction.
*/
public static function parseSort($sort) {
return array(ltrim($sort, '-'), preg_match('/^-/', $sort));
}
public function makeSortable(
PhutilURI $base_uri,
$param,
$selected,
$reverse,
array $sort_values) {
$this->sortURI = $base_uri;
$this->sortParam = $param;
$this->sortSelected = $selected;
$this->sortReverse = $reverse;
$this->sortValues = array_values($sort_values);
return $this;
}
public function render() {
require_celerity_resource('aphront-table-view-css');
$table = array();
$col_classes = array();
foreach ($this->columnClasses as $key => $class) {
if (strlen($class)) {
$col_classes[] = $class;
} else {
$col_classes[] = null;
}
}
$visibility = array_values($this->columnVisibility);
$device_visibility = array_values($this->deviceVisibility);
$headers = $this->headers;
$short_headers = $this->shortHeaders;
$sort_values = $this->sortValues;
if ($headers) {
while (count($headers) > count($visibility)) {
$visibility[] = true;
}
while (count($headers) > count($device_visibility)) {
$device_visibility[] = true;
}
while (count($headers) > count($short_headers)) {
$short_headers[] = null;
}
while (count($headers) > count($sort_values)) {
$sort_values[] = null;
}
$tr = array();
foreach ($headers as $col_num => $header) {
if (!$visibility[$col_num]) {
continue;
}
$classes = array();
if (!empty($col_classes[$col_num])) {
$classes[] = $col_classes[$col_num];
}
if (empty($device_visiblity[$col_num])) {
$classes[] = 'aphront-table-nodevice';
}
if ($sort_values[$col_num] !== null) {
$classes[] = 'aphront-table-view-sortable';
$sort_value = $sort_values[$col_num];
$sort_glyph_class = 'aphront-table-down-sort';
if ($sort_value == $this->sortSelected) {
if ($this->sortReverse) {
$sort_glyph_class = 'aphront-table-up-sort';
} else if (!$this->sortReverse) {
$sort_value = '-'.$sort_value;
}
$classes[] = 'aphront-table-view-sortable-selected';
}
$sort_glyph = phutil_tag(
'span',
array(
'class' => $sort_glyph_class,
),
'');
$header = phutil_tag(
'a',
array(
'href' => $this->sortURI->alter($this->sortParam, $sort_value),
'class' => 'aphront-table-view-sort-link',
),
array(
$header,
' ',
$sort_glyph,
));
}
if ($classes) {
$class = implode(' ', $classes);
} else {
$class = null;
}
if ($short_headers[$col_num] !== null) {
$header_nodevice = phutil_tag(
'span',
array(
'class' => 'aphront-table-view-nodevice',
),
$header);
$header_device = phutil_tag(
'span',
array(
'class' => 'aphront-table-view-device',
),
$short_headers[$col_num]);
$header = hsprintf('%s %s', $header_nodevice, $header_device);
}
$tr[] = phutil_tag('th', array('class' => $class), $header);
}
$table[] = phutil_tag('tr', array(), $tr);
}
foreach ($col_classes as $key => $value) {
if (($sort_values[$key] !== null) &&
($sort_values[$key] == $this->sortSelected)) {
$value = trim($value.' sorted-column');
}
if ($value !== null) {
$col_classes[$key] = $value;
}
}
$data = $this->data;
if ($data) {
$row_num = 0;
foreach ($data as $row) {
while (count($row) > count($col_classes)) {
$col_classes[] = null;
}
while (count($row) > count($visibility)) {
$visibility[] = true;
}
$tr = array();
// NOTE: Use of a separate column counter is to allow this to work
// correctly if the row data has string or non-sequential keys.
$col_num = 0;
foreach ($row as $value) {
if (!$visibility[$col_num]) {
++$col_num;
continue;
}
$class = $col_classes[$col_num];
if (!empty($this->cellClasses[$row_num][$col_num])) {
$class = trim($class.' '.$this->cellClasses[$row_num][$col_num]);
}
$tr[] = phutil_tag('td', array('class' => $class), $value);
++$col_num;
}
$class = idx($this->rowClasses, $row_num);
if ($this->zebraStripes && ($row_num % 2)) {
if ($class !== null) {
$class = 'alt alt-'.$class;
} else {
$class = 'alt';
}
}
$table[] = phutil_tag('tr', array('class' => $class), $tr);
++$row_num;
}
} else {
$colspan = max(count(array_filter($visibility)), 1);
- $table[] = hsprintf(
- '%s ',
- $colspan,
- coalesce($this->noDataString, pht('No data available.')));
+ $table[] = phutil_tag(
+ 'tr',
+ array('class' => 'no-data'),
+ phutil_tag(
+ 'td',
+ array('colspan' => $colspan),
+ coalesce($this->noDataString, pht('No data available.'))));
}
$table_class = 'aphront-table-view';
if ($this->className !== null) {
$table_class .= ' '.$this->className;
}
if ($this->deviceReadyTable) {
$table_class .= ' aphront-table-view-device-ready';
}
$html = phutil_tag('table', array('class' => $table_class), $table);
- return hsprintf('%s
', $html);
+ return phutil_tag_div('aphront-table-wrap', $html);
}
public static function renderSingleDisplayLine($line) {
// TODO: Is there a cleaner way to do this? We use a relative div with
// overflow hidden to provide the bounds, and an absolute span with
// white-space: pre to prevent wrapping. We need to append a character
// ( -- nonbreaking space) afterward to give the bounds div height
// (alternatively, we could hard-code the line height). This is gross but
// it's not clear that there's a better appraoch.
return phutil_tag(
'div',
array(
'class' => 'single-display-line-bounds',
),
array(
phutil_tag(
'span',
array(
'class' => 'single-display-line-content',
),
$line),
"\xC2\xA0",
));
}
}
diff --git a/src/view/control/PhabricatorObjectSelectorDialog.php b/src/view/control/PhabricatorObjectSelectorDialog.php
index 0d98861dff..f6e107a99c 100644
--- a/src/view/control/PhabricatorObjectSelectorDialog.php
+++ b/src/view/control/PhabricatorObjectSelectorDialog.php
@@ -1,199 +1,194 @@
user = $user;
return $this;
}
public function setFilters(array $filters) {
$this->filters = $filters;
return $this;
}
public function setSelectedFilter($selected_filter) {
$this->selectedFilter = $selected_filter;
return $this;
}
public function setExcluded($excluded_phid) {
$this->excluded = $excluded_phid;
return $this;
}
public function setHandles(array $handles) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$this->handles = $handles;
return $this;
}
public function setCancelURI($cancel_uri) {
$this->cancelURI = $cancel_uri;
return $this;
}
public function setSubmitURI($submit_uri) {
$this->submitURI = $submit_uri;
return $this;
}
public function setSearchURI($search_uri) {
$this->searchURI = $search_uri;
return $this;
}
public function setTitle($title) {
$this->title = $title;
return $this;
}
public function setHeader($header) {
$this->header = $header;
return $this;
}
public function setButtonText($button_text) {
$this->buttonText = $button_text;
return $this;
}
public function setInstructions($instructions) {
$this->instructions = $instructions;
return $this;
}
public function buildDialog() {
$user = $this->user;
$filter_id = celerity_generate_unique_node_id();
$query_id = celerity_generate_unique_node_id();
$results_id = celerity_generate_unique_node_id();
$current_id = celerity_generate_unique_node_id();
$search_id = celerity_generate_unique_node_id();
$form_id = celerity_generate_unique_node_id();
require_celerity_resource('phabricator-object-selector-css');
$options = array();
foreach ($this->filters as $key => $label) {
$options[] = phutil_tag(
'option',
array(
'value' => $key,
'selected' => ($key == $this->selectedFilter)
? 'selected'
: null,
),
$label);
}
$instructions = null;
if ($this->instructions) {
$instructions = phutil_tag(
'p',
array('class' => 'phabricator-object-selector-instructions'),
$this->instructions);
}
$search_box = phabricator_form(
$user,
array(
'method' => 'POST',
'action' => $this->submitURI,
'id' => $search_id,
),
- hsprintf(
- '',
- phutil_tag(
- 'select',
- array('id' => $filter_id),
- $options),
- phutil_tag(
- 'input',
- array(
- 'id' => $query_id,
- 'type' => 'text'))));
+ phutil_tag(
+ 'table',
+ array('class' => 'phabricator-object-selector-search'),
+ phutil_tag('tr', array(), array(
+ phutil_tag(
+ 'td',
+ array('class' => 'phabricator-object-selector-search-filter'),
+ phutil_tag('select', array('id' => $filter_id), $options)),
+ phutil_tag(
+ 'td',
+ array('class' => 'phabricator-object-selector-search-text'),
+ phutil_tag('input', array('id' => $query_id, 'type' => 'text'))),
+ ))));
$result_box = phutil_tag(
'div',
array(
'class' => 'phabricator-object-selector-results',
'id' => $results_id,
),
'');
- $attached_box = hsprintf(
- ''.
- '
'.
- ''.
- '
'.
- '%s'.
- '
'.
- '
',
- $this->header,
- $current_id,
- $instructions);
+ $attached_box = phutil_tag_div(
+ 'phabricator-object-selector-current',
+ phutil_tag_div(
+ 'phabricator-object-selector-currently-attached',
+ array(
+ phutil_tag_div('phabricator-object-selector-header', $this->header),
+ phutil_tag('div', array('id' => $current_id)),
+ $instructions,
+ )));
$dialog = new AphrontDialogView();
$dialog
->setUser($this->user)
->setTitle($this->title)
->setClass('phabricator-object-selector-dialog')
->appendChild($search_box)
->appendChild($result_box)
->appendChild($attached_box)
->setRenderDialogAsDiv()
->setFormID($form_id)
->addSubmitButton($this->buttonText);
if ($this->cancelURI) {
$dialog->addCancelButton($this->cancelURI);
}
$handle_views = array();
foreach ($this->handles as $handle) {
$phid = $handle->getPHID();
$view = new PhabricatorHandleObjectSelectorDataView($handle);
$handle_views[$phid] = $view->renderData();
}
$dialog->addHiddenInput('phids', implode(';', array_keys($this->handles)));
Javelin::initBehavior(
'phabricator-object-selector',
array(
'filter' => $filter_id,
'query' => $query_id,
'search' => $search_id,
'results' => $results_id,
'current' => $current_id,
'form' => $form_id,
'exclude' => $this->excluded,
'uri' => $this->searchURI,
'handles' => $handle_views,
));
return $dialog;
}
}
diff --git a/src/view/form/control/AphrontFormCheckboxControl.php b/src/view/form/control/AphrontFormCheckboxControl.php
index 4d452c448e..6e575fd533 100644
--- a/src/view/form/control/AphrontFormCheckboxControl.php
+++ b/src/view/form/control/AphrontFormCheckboxControl.php
@@ -1,52 +1,52 @@
boxes[] = array(
'name' => $name,
'value' => $value,
'label' => $label,
'checked' => $checked,
);
return $this;
}
protected function getCustomControlClass() {
return 'aphront-form-control-checkbox';
}
protected function renderInput() {
$rows = array();
foreach ($this->boxes as $box) {
$id = celerity_generate_unique_node_id();
$checkbox = phutil_tag(
'input',
array(
'id' => $id,
'type' => 'checkbox',
'name' => $box['name'],
'value' => $box['value'],
'checked' => $box['checked'] ? 'checked' : null,
'disabled' => $this->getDisabled() ? 'disabled' : null,
));
$label = phutil_tag(
'label',
array(
'for' => $id,
),
$box['label']);
- $rows[] = hsprintf(
- '%s %s ',
- $checkbox,
- $label);
+ $rows[] = phutil_tag('tr', array(), array(
+ phutil_tag('td', array(), $checkbox),
+ phutil_tag('th', array(), $label)
+ ));
}
return phutil_tag(
'table',
array('class' => 'aphront-form-control-checkbox-layout'),
$rows);
}
}
diff --git a/src/view/form/control/AphrontFormRadioButtonControl.php b/src/view/form/control/AphrontFormRadioButtonControl.php
index 589968af13..5764275151 100644
--- a/src/view/form/control/AphrontFormRadioButtonControl.php
+++ b/src/view/form/control/AphrontFormRadioButtonControl.php
@@ -1,71 +1,71 @@
buttons[] = array(
'value' => $value,
'label' => $label,
'caption' => $caption,
'class' => $class,
'disabled' => $disabled,
);
return $this;
}
protected function getCustomControlClass() {
return 'aphront-form-control-radio';
}
protected function renderInput() {
$rows = array();
foreach ($this->buttons as $button) {
$id = celerity_generate_unique_node_id();
$radio = phutil_tag(
'input',
array(
'id' => $id,
'type' => 'radio',
'name' => $this->getName(),
'value' => $button['value'],
'checked' => ($button['value'] == $this->getValue())
? 'checked'
: null,
'disabled' => ($this->getDisabled() || $button['disabled'])
? 'disabled'
: null,
));
$label = phutil_tag(
'label',
array(
'for' => $id,
'class' => $button['class'],
),
$button['label']);
if ($button['caption']) {
- $label = hsprintf(
- '%s%s
',
+ $label = array(
$label,
- $button['caption']);
+ phutil_tag_div('aphront-form-radio-caption', $button['caption']),
+ );
}
- $rows[] = hsprintf(
- '%s %s ',
- $radio,
- $label);
+ $rows[] = phutil_tag('tr', array(), array(
+ phutil_tag('td', array(), $radio),
+ phutil_tag('th', array(), $label),
+ ));
}
return phutil_tag(
'table',
array('class' => 'aphront-form-control-radio-layout'),
$rows);
}
}
diff --git a/src/view/layout/AphrontContextBarView.php b/src/view/layout/AphrontContextBarView.php
index 07c640fbb5..2d5a6d3637 100644
--- a/src/view/layout/AphrontContextBarView.php
+++ b/src/view/layout/AphrontContextBarView.php
@@ -1,30 +1,29 @@
buttons[] = $button;
return $this;
}
public function render() {
$view = new AphrontNullView();
$view->appendChild($this->buttons);
require_celerity_resource('aphront-contextbar-view-css');
- return hsprintf(
- '',
- $view->render(),
- $this->renderChildren());
+ return phutil_tag_div(
+ 'aphront-contextbar-view',
+ array(
+ phutil_tag_div('aphront-contextbar-core', array(
+ phutil_tag_div('aphront-contextbar-buttons', $view->render()),
+ phutil_tag_div('aphront-contextbar-content', $this->renderChildren()),
+ )),
+ phutil_tag('div', array('style' => 'clear: both;')),
+ ));
}
}
diff --git a/src/view/layout/AphrontPanelView.php b/src/view/layout/AphrontPanelView.php
index 0ae35ef0df..066d538de6 100644
--- a/src/view/layout/AphrontPanelView.php
+++ b/src/view/layout/AphrontPanelView.php
@@ -1,111 +1,106 @@
addButton(
phutil_tag(
'a',
array(
'href' => $href,
'class' => 'button green',
),
$create_button));
return $this;
}
public function addClass($class) {
$this->classes[] = $class;
return $this;
}
public function addButton($button) {
$this->buttons[] = $button;
return $this;
}
public function setHeader($header) {
$this->header = $header;
return $this;
}
public function setWidth($width) {
$this->width = $width;
return $this;
}
public function setID($id) {
$this->id = $id;
return $this;
}
public function setCaption($caption) {
$this->caption = $caption;
return $this;
}
public function setNoBackground() {
$this->classes[] = 'aphront-panel-plain';
return $this;
}
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',
- array('class' => 'aphront-panel-view-caption'),
- $this->caption);
+ $caption = phutil_tag_div('aphront-panel-view-caption', $this->caption);
} else {
$caption = null;
}
$buttons = null;
if ($this->buttons) {
- $buttons = hsprintf(
- '%s
',
+ $buttons = phutil_tag_div(
+ 'aphront-panel-view-buttons',
phutil_implode_html(" ", $this->buttons));
}
- $header_elements = hsprintf(
- '',
- $buttons,
- $header,
- $caption);
+ $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));
}
}
diff --git a/src/view/layout/PhabricatorSourceCodeView.php b/src/view/layout/PhabricatorSourceCodeView.php
index b8396b78b2..7c2b64d660 100644
--- a/src/view/layout/PhabricatorSourceCodeView.php
+++ b/src/view/layout/PhabricatorSourceCodeView.php
@@ -1,133 +1,130 @@
limit = $limit;
return $this;
}
public function setLines(array $lines) {
$this->lines = $lines;
return $this;
}
public function setURI(PhutilURI $uri) {
$this->uri = $uri;
return $this;
}
public function setHighlights(array $array) {
$this->highlights = array_fuse($array);
return $this;
}
public function disableHighlightOnClick() {
$this->canClickHighlight = false;
return $this;
}
public function render() {
require_celerity_resource('phabricator-source-code-view-css');
require_celerity_resource('syntax-highlighting-css');
Javelin::initBehavior('phabricator-oncopy', array());
if ($this->canClickHighlight) {
Javelin::initBehavior('phabricator-line-linker');
}
$line_number = 1;
$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 = hsprintf("\xE2\x80\x8B%s", $line);
}
$row_attributes = array();
if (isset($this->highlights[$line_number])) {
$row_attributes['class'] = 'phabricator-source-highlight';
}
if ($this->canClickHighlight) {
$line_uri = $this->uri . "$" . $line_number;
$line_href = (string) new PhutilURI($line_uri);
$tag_number = javelin_tag(
'a',
array(
'href' => $line_href
),
$line_number);
} else {
$tag_number = javelin_tag(
'span',
array(),
$line_number);
}
$rows[] = phutil_tag(
'tr',
$row_attributes,
array(
javelin_tag(
'th',
array(
'class' => 'phabricator-source-line',
'sigil' => 'phabricator-source-line'
),
$tag_number),
phutil_tag(
'td',
array(
'class' => 'phabricator-source-code'
),
$content_line)));
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',
- ),
+ return phutil_tag_div(
+ 'phabricator-source-code-container',
javelin_tag(
'table',
array(
'class' => implode(' ', $classes),
'sigil' => 'phabricator-source'
),
phutil_implode_html('', $rows)));
}
}
diff --git a/src/view/layout/PhabricatorTransactionView.php b/src/view/layout/PhabricatorTransactionView.php
index 7ceb3023bc..f87a1f3df9 100644
--- a/src/view/layout/PhabricatorTransactionView.php
+++ b/src/view/layout/PhabricatorTransactionView.php
@@ -1,148 +1,146 @@
imageURI = $uri;
return $this;
}
public function setActions(array $actions) {
$this->actions = $actions;
return $this;
}
public function setEpoch($epoch) {
$this->epoch = $epoch;
return $this;
}
public function setContentSource(PhabricatorContentSource $source) {
$this->contentSource = $source;
return $this;
}
public function setAnchor($anchor_name, $anchor_text) {
$this->anchorName = $anchor_name;
$this->anchorText = $anchor_text;
return $this;
}
public function addClass($class) {
$this->classes[] = $class;
return $this;
}
public function setIsPreview($preview) {
$this->isPreview = $preview;
return $this;
}
public function render() {
if (!$this->user) {
throw new Exception(pht("Call setUser() before render()!"));
}
require_celerity_resource('phabricator-transaction-view-css');
$info = $this->renderTransactionInfo();
$actions = $this->renderTransactionActions();
$style = $this->renderTransactionStyle();
$content = $this->renderTransactionContent();
$classes = implode(' ', $this->classes);
$transaction_id = $this->anchorName ? 'anchor-'.$this->anchorName : null;
+ $header = phutil_tag_div(
+ 'phabricator-transaction-header',
+ array($info, $actions));
+
return phutil_tag(
'div',
array(
'class' => 'phabricator-transaction-view',
'id' => $transaction_id,
'style' => $style,
),
- hsprintf(
- ''.
- ''.
- '%s'.
- '
',
- $classes,
- $info,
- $actions,
- $content));
+ phutil_tag_div(
+ 'phabricator-transaction-detail '.$classes,
+ array($header, $content)));
}
private function renderTransactionInfo() {
$info = array();
if ($this->contentSource) {
$content_source = new PhabricatorContentSourceView();
$content_source->setContentSource($this->contentSource);
$content_source->setUser($this->user);
$source = $content_source->render();
if ($source) {
$info[] = $source;
}
}
if ($this->isPreview) {
$info[] = 'PREVIEW';
} else if ($this->epoch) {
$info[] = phabricator_datetime($this->epoch, $this->user);
}
if ($this->anchorName) {
Javelin::initBehavior('phabricator-watch-anchor');
$anchor = id(new PhabricatorAnchorView())
->setAnchorName($this->anchorName)
->render();
$info[] = hsprintf(
'%s%s',
$anchor,
phutil_tag(
'a',
array('href' => '#'.$this->anchorName),
$this->anchorText));
}
$info = phutil_implode_html(" \xC2\xB7 ", $info);
- return hsprintf(
- '%s ',
+ return phutil_tag(
+ 'span',
+ array('class' => 'phabricator-transaction-info'),
$info);
}
private function renderTransactionActions() {
return $this->actions;
}
private function renderTransactionStyle() {
if ($this->imageURI) {
return 'background-image: url('.$this->imageURI.');';
} else {
return null;
}
}
private function renderTransactionContent() {
if (!$this->hasChildren()) {
return null;
}
- return phutil_tag(
- 'div',
- array('class' => 'phabricator-transaction-content'),
+ return phutil_tag_div(
+ 'phabricator-transaction-content',
$this->renderChildren());
}
}
diff --git a/src/view/page/AphrontRequestFailureView.php b/src/view/page/AphrontRequestFailureView.php
index 1965340dd5..5910b4468f 100644
--- a/src/view/page/AphrontRequestFailureView.php
+++ b/src/view/page/AphrontRequestFailureView.php
@@ -1,27 +1,27 @@
header = $header;
return $this;
}
final public function render() {
require_celerity_resource('aphront-request-failure-view-css');
- return hsprintf(
- ''.
- '
'.
- '
%s '.
- ''.
- '
%s
'.
- '
',
- $this->header,
+ $head = phutil_tag_div(
+ 'aphront-request-failure-head',
+ phutil_tag('h1', array(), $this->header));
+
+ $body = phutil_tag_div(
+ 'aphront-request-failure-body',
$this->renderChildren());
+
+ return phutil_tag_div('aphront-request-failure-view', array($head, $body));
}
}
diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php
index affcc3bd88..f01d2ccd92 100644
--- a/src/view/page/PhabricatorStandardPageView.php
+++ b/src/view/page/PhabricatorStandardPageView.php
@@ -1,441 +1,435 @@
applicationMenu = $application_menu;
return $this;
}
public function getApplicationMenu() {
return $this->applicationMenu;
}
public function setApplicationName($application_name) {
$this->applicationName = $application_name;
return $this;
}
public function setDisableConsole($disable) {
$this->disableConsole = $disable;
return $this;
}
public function getApplicationName() {
return $this->applicationName;
}
public function setBaseURI($base_uri) {
$this->baseURI = $base_uri;
return $this;
}
public function getBaseURI() {
return $this->baseURI;
}
public function setShowChrome($show_chrome) {
$this->showChrome = $show_chrome;
return $this;
}
public function getShowChrome() {
return $this->showChrome;
}
public function setSearchDefaultScope($search_default_scope) {
$this->searchDefaultScope = $search_default_scope;
return $this;
}
public function getSearchDefaultScope() {
return $this->searchDefaultScope;
}
public function appendPageObjects(array $objs) {
foreach ($objs as $obj) {
$this->pageObjects[] = $obj;
}
}
public function getTitle() {
$use_glyph = true;
$request = $this->getRequest();
if ($request) {
$user = $request->getUser();
if ($user && $user->loadPreferences()->getPreference(
PhabricatorUserPreferences::PREFERENCE_TITLES) !== 'glyph') {
$use_glyph = false;
}
}
$title = parent::getTitle();
$prefix = null;
if ($use_glyph) {
$prefix = $this->getGlyph();
} else {
$application_name = $this->getApplicationName();
if (strlen($application_name)) {
$prefix = '['.$application_name.']';
}
}
if (strlen($prefix)) {
$title = $prefix.' '.$title;
}
return $title;
}
protected function willRenderPage() {
parent::willRenderPage();
if (!$this->getRequest()) {
throw new Exception(
pht(
"You must set the Request to render a PhabricatorStandardPageView."));
}
$console = $this->getConsole();
require_celerity_resource('phabricator-core-css');
require_celerity_resource('phabricator-zindex-css');
require_celerity_resource('phui-button-css');
require_celerity_resource('phui-spacing-css');
require_celerity_resource('phui-form-css');
require_celerity_resource('sprite-gradient-css');
require_celerity_resource('phabricator-standard-page-view');
Javelin::initBehavior('workflow', array());
$request = $this->getRequest();
$user = null;
if ($request) {
$user = $request->getUser();
}
if ($user) {
$default_img_uri =
PhabricatorEnv::getCDNURI(
'/rsrc/image/icon/fatcow/document_black.png');
$download_form = phabricator_form(
$user,
array(
'action' => '#',
'method' => 'POST',
'class' => 'lightbox-download-form',
'sigil' => 'download',
),
phutil_tag(
'button',
array(),
pht('Download')));
Javelin::initBehavior(
'lightbox-attachments',
array(
'defaultImageUri' => $default_img_uri,
'downloadForm' => $download_form,
));
}
Javelin::initBehavior('aphront-form-disable-on-submit');
Javelin::initBehavior('toggle-class', array());
Javelin::initBehavior('konami', array());
Javelin::initBehavior('history-install');
Javelin::initBehavior('phabricator-gesture');
$current_token = null;
if ($user) {
$current_token = $user->getCSRFToken();
}
Javelin::initBehavior(
'refresh-csrf',
array(
'tokenName' => AphrontRequest::getCSRFTokenName(),
'header' => AphrontRequest::getCSRFHeaderName(),
'current' => $current_token,
));
Javelin::initBehavior('device');
if ($console) {
require_celerity_resource('aphront-dark-console-css');
$headers = array();
if (DarkConsoleXHProfPluginAPI::isProfilerStarted()) {
$headers[DarkConsoleXHProfPluginAPI::getProfilerHeader()] = 'page';
}
Javelin::initBehavior(
'dark-console',
array(
// NOTE: We use a generic label here to prevent input reflection
// and mitigate compression attacks like BREACH. See discussion in
// T3684.
'uri' => pht('Main Request'),
'selected' => $user ? $user->getConsoleTab() : null,
'visible' => $user ? (int)$user->getConsoleVisible() : true,
'headers' => $headers,
));
// Change this to initBehavior when there is some behavior to initialize
require_celerity_resource('javelin-behavior-error-log');
}
if ($user) {
$viewer = $user;
} else {
$viewer = new PhabricatorUser();
}
$menu = id(new PhabricatorMainMenuView())
->setUser($viewer)
->setDefaultSearchScope($this->getSearchDefaultScope());
if ($this->getController()) {
$menu->setController($this->getController());
}
if ($this->getApplicationMenu()) {
$menu->setApplicationMenu($this->getApplicationMenu());
}
$this->menuContent = $menu->render();
}
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%s',
parent::getHead(),
phutil_safe_html($monospaced),
phutil_safe_html($monospaced_win),
$response->renderSingleResource('javelin-magical-init'));
}
public function setGlyph($glyph) {
$this->glyph = $glyph;
return $this;
}
public function getGlyph() {
return $this->glyph;
}
protected function willSendResponse($response) {
$request = $this->getRequest();
$response = parent::willSendResponse($response);
$console = $request->getApplicationConfiguration()->getConsole();
if ($console) {
$response = PhutilSafeHTML::applyFunction(
'str_replace',
hsprintf(' '),
$console->render($request),
$response);
}
return $response;
}
protected function getBody() {
$console = $this->getConsole();
$user = null;
$request = $this->getRequest();
if ($request) {
$user = $request->getUser();
}
$header_chrome = null;
if ($this->getShowChrome()) {
$header_chrome = $this->menuContent;
}
$developer_warning = null;
if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode') &&
DarkConsoleErrorLogPluginAPI::getErrors()) {
- $developer_warning = phutil_tag(
- 'div',
- array(
- 'class' => 'aphront-developer-error-callout',
- ),
+ $developer_warning = phutil_tag_div(
+ 'aphront-developer-error-callout',
pht(
'This page raised PHP errors. Find them in DarkConsole '.
'or the error log.'));
}
// Render the "you have unresolved setup issues..." warning.
$setup_warning = null;
if ($user && $user->getIsAdmin()) {
$open = PhabricatorSetupCheck::getOpenSetupIssueCount();
if ($open) {
- $setup_warning = phutil_tag(
- 'div',
- array(
- 'class' => 'setup-warning-callout',
- ),
+ $setup_warning = phutil_tag_div(
+ 'setup-warning-callout',
phutil_tag(
'a',
array(
'href' => '/config/issue/',
),
pht('You have %d unresolved setup issue(s)...', $open)));
}
}
return
phutil_tag(
'div',
array(
'id' => 'base-page',
'class' => 'phabricator-standard-page',
),
- hsprintf(
- '%s%s%s'.
- '',
- $developer_warning,
- $setup_warning,
- $header_chrome,
- ($console ? hsprintf(' ') : null),
- parent::getBody()));
+ array(
+ $developer_warning,
+ $setup_warning,
+ $header_chrome,
+ phutil_tag_div('phabricator-standard-page-body', array(
+ ($console ? hsprintf(' ') : null),
+ parent::getBody(),
+ phutil_tag('div', array('style' => 'clear: both;')),
+ )),
+ ));
}
protected function getTail() {
$request = $this->getRequest();
$user = $request->getUser();
$container = null;
if ($user && $user->isLoggedIn()) {
$aphlict_object_id = celerity_generate_unique_node_id();
$aphlict_container_id = celerity_generate_unique_node_id();
$client_uri = PhabricatorEnv::getEnvConfig('notification.client-uri');
$client_uri = new PhutilURI($client_uri);
if ($client_uri->getDomain() == 'localhost') {
$this_host = $this->getRequest()->getHost();
$this_host = new PhutilURI('http://'.$this_host.'/');
$client_uri->setDomain($this_host->getDomain());
}
$enable_debug = PhabricatorEnv::getEnvConfig('notification.debug');
Javelin::initBehavior(
'aphlict-listen',
array(
'id' => $aphlict_object_id,
'containerID' => $aphlict_container_id,
'server' => $client_uri->getDomain(),
'port' => $client_uri->getPort(),
'debug' => $enable_debug,
'pageObjects' => array_fill_keys($this->pageObjects, true),
));
$container = phutil_tag(
'div',
array(
'id' => $aphlict_container_id,
'style' =>
'position: absolute; width: 0; height: 0; overflow: hidden;',
),
'');
}
$response = CelerityAPI::getStaticResourceResponse();
$tail = array(
parent::getTail(),
$container,
$response->renderHTMLFooter(),
);
return phutil_implode_html("\n", $tail);
}
protected function getBodyClasses() {
$classes = array();
if (!$this->getShowChrome()) {
$classes[] = 'phabricator-chromeless-page';
}
$agent = AphrontRequest::getHTTPHeader('User-Agent');
// Try to guess the device resolution based on UA strings to avoid a flash
// of incorrectly-styled content.
$device_guess = 'device-desktop';
if (preg_match('@iPhone|iPod|(Android.*Chrome/[.0-9]* Mobile)@', $agent)) {
$device_guess = 'device-phone device';
} else if (preg_match('@iPad|(Android.*Chrome/)@', $agent)) {
$device_guess = 'device-tablet device';
}
$classes[] = $device_guess;
if (preg_match('@Windows@', $agent)) {
$classes[] = 'platform-windows';
} else if (preg_match('@Macintosh@', $agent)) {
$classes[] = 'platform-mac';
} else if (preg_match('@X11@', $agent)) {
$classes[] = 'platform-linux';
}
if ($this->getRequest()->getStr('__print__')) {
$classes[] = 'printable';
}
return implode(' ', $classes);
}
private function getConsole() {
if ($this->disableConsole) {
return null;
}
return $this->getRequest()->getApplicationConfiguration()->getConsole();
}
}
diff --git a/src/view/page/menu/PhabricatorMainMenuSearchView.php b/src/view/page/menu/PhabricatorMainMenuSearchView.php
index 1f416a1f94..4d2cd11045 100644
--- a/src/view/page/menu/PhabricatorMainMenuSearchView.php
+++ b/src/view/page/menu/PhabricatorMainMenuSearchView.php
@@ -1,80 +1,79 @@
scope = $scope;
return $this;
}
public function getID() {
if (!$this->id) {
$this->id = celerity_generate_unique_node_id();
}
return $this->id;
}
public function render() {
$user = $this->user;
$target_id = celerity_generate_unique_node_id();
$search_id = $this->getID();
$input = phutil_tag(
'input',
array(
'type' => 'text',
'name' => 'query',
'id' => $search_id,
'autocomplete' => 'off',
));
$scope = $this->scope;
$target = javelin_tag(
'div',
array(
'id' => $target_id,
'class' => 'phabricator-main-menu-search-target',
),
'');
Javelin::initBehavior(
'phabricator-search-typeahead',
array(
'id' => $target_id,
'input' => $search_id,
'src' => '/typeahead/common/mainsearch/',
'limit' => 10,
'placeholder' => PhabricatorSearchScope::getScopePlaceholder($scope),
));
$scope_input = phutil_tag(
'input',
array(
'type' => 'hidden',
'name' => 'scope',
'value' => $scope,
));
$form = phabricator_form(
$user,
array(
'action' => '/search/',
'method' => 'POST',
),
- hsprintf(
- ''.
- '%sSearch %s%s'.
- '
',
+ phutil_tag_div('phabricator-main-menu-search-container', array(
$input,
+ phutil_tag('button', array(), pht('Search')),
$scope_input,
- $target));
+ $target,
+ )));
return $form;
}
}
diff --git a/src/view/widget/bars/AphrontProgressBarView.php b/src/view/widget/bars/AphrontProgressBarView.php
index 4584c08c8f..ef63cd0ccd 100644
--- a/src/view/widget/bars/AphrontProgressBarView.php
+++ b/src/view/widget/bars/AphrontProgressBarView.php
@@ -1,60 +1,57 @@
value = $value;
return $this;
}
public function setMax($max) {
$this->max = $max;
return $this;
}
public function setAlt($text) {
$this->alt = $text;
return $this;
}
protected function getRatio() {
return min($this->value, $this->max) / $this->max;
}
public function render() {
require_celerity_resource('aphront-bars');
$ratio = $this->getRatio();
$width = self::WIDTH * $ratio;
$color = $this->getColor();
- return phutil_tag(
- 'div',
- array(
- 'class' => "aphront-bar progress color-{$color}",
- ),
+ return phutil_tag_div(
+ "aphront-bar progress color-{$color}",
array(
phutil_tag(
'div',
array('title' => $this->alt),
phutil_tag(
'div',
- array('style' => hsprintf("width: %dpx;", $width)),
+ array('style' => "width: {$width}px;"),
'')),
phutil_tag(
'span',
array(),
$this->getCaption())));
}
}
diff --git a/src/view/widget/hovercard/PhabricatorHovercardView.php b/src/view/widget/hovercard/PhabricatorHovercardView.php
index 7b68046bb1..1db3af0a4b 100644
--- a/src/view/widget/hovercard/PhabricatorHovercardView.php
+++ b/src/view/widget/hovercard/PhabricatorHovercardView.php
@@ -1,186 +1,161 @@
handle = $handle;
return $this;
}
public function setTitle($title) {
$this->title = $title;
return $this;
}
public function setDetail($detail) {
$this->detail = $detail;
return $this;
}
public function addField($label, $value) {
$this->fields[] = array(
'label' => $label,
'value' => $value,
);
return $this;
}
public function addAction($label, $uri, $workflow = false) {
$this->actions[] = array(
'label' => $label,
'uri' => $uri,
'workflow' => $workflow,
);
return $this;
}
public function addTag(PhabricatorTagView $tag) {
$this->tags[] = $tag;
return $this;
}
public function setColor($color) {
$this->color = $color;
return $this;
}
public function render() {
if (!$this->handle) {
throw new Exception("Call setObjectHandle() before calling render()!");
}
$handle = $this->handle;
require_celerity_resource("phabricator-hovercard-view-css");
$title = pht("%s: %s",
$handle->getTypeName(),
$this->title ? $this->title : $handle->getName());
$header = new PhabricatorActionHeaderView();
$header->setHeaderColor($this->color);
$header->setHeaderTitle($title);
if ($this->tags) {
foreach ($this->tags as $tag) {
$header->setTag($tag);
}
}
$body = array();
if ($this->detail) {
$body_title = $this->detail;
} else {
// Fallback for object handles
$body_title = $handle->getFullName();
}
- $body[] = phutil_tag(
- 'div',
- array(
- 'class' => 'phabricator-hovercard-body-header'
- ),
- $body_title);
+ $body[] = phutil_tag_div('phabricator-hovercard-body-header', $body_title);
foreach ($this->fields as $field) {
- $item = hsprintf('%s: %s ',
- $field['label'], $field['value']);
- $body[] = phutil_tag(
- 'div',
- array(
- 'class' => 'phabricator-hovercard-body-item'
- ),
- $item);
+ $item = array(
+ phutil_tag('strong', array(), $field['label']),
+ ' ',
+ phutil_tag('span', array(), $field['value']),
+ );
+ $body[] = phutil_tag_div('phabricator-hovercard-body-item', $item);
}
if ($handle->getImageURI()) {
// Probably a user, we don't need to assume something else
// "Prepend" the image by appending $body
$body = phutil_tag(
'div',
array(
'class' => 'profile-header-picture-frame',
'style' => 'background-image: url('.$handle->getImageURI().');',
),
'')
->appendHTML($body);
}
$buttons = array();
foreach ($this->actions as $action) {
$options = array(
'class' => 'button grey',
'href' => $action['uri'],
);
if ($action['workflow']) {
$options['sigil'] = 'workflow';
$buttons[] = javelin_tag(
'a',
$options,
$action['label']);
} else {
$buttons[] = phutil_tag(
'a',
$options,
$action['label']);
}
}
$tail = null;
if ($buttons) {
- $tail = phutil_tag('div',
- array('class' => 'phabricator-hovercard-tail'),
- $buttons);
+ $tail = phutil_tag_div('phabricator-hovercard-tail', $buttons);
}
// Assemble container
// TODO: Add color support
- $content = hsprintf(
- '%s%s%s',
- phutil_tag('div',
- array(
- 'class' => 'phabricator-hovercard-head'
- ),
- $header),
- phutil_tag('div',
- array(
- 'class' => 'phabricator-hovercard-body'
- ),
- $body),
- $tail);
-
- $hovercard = phutil_tag("div",
+ $hovercard = phutil_tag_div(
+ 'phabricator-hovercard-container',
array(
- "class" => "phabricator-hovercard-container",
- ),
- $content);
+ phutil_tag_div('phabricator-hovercard-head', $header),
+ phutil_tag_div('phabricator-hovercard-body', $body),
+ $tail,
+ ));
// Wrap for thick border
// and later the tip at the bottom
- return phutil_tag('div',
- array(
- 'class' => 'phabricator-hovercard-wrapper',
- ),
- $hovercard);
+ return phutil_tag_div('phabricator-hovercard-wrapper', $hovercard);
}
}