Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/config/controller/PhabricatorConfigEditController.php b/src/applications/config/controller/PhabricatorConfigEditController.php
index c0b5dcab9f..5983bbc1ae 100644
--- a/src/applications/config/controller/PhabricatorConfigEditController.php
+++ b/src/applications/config/controller/PhabricatorConfigEditController.php
@@ -1,503 +1,503 @@
<?php
final class PhabricatorConfigEditController
extends PhabricatorConfigController {
private $key;
public function willProcessRequest(array $data) {
$this->key = $data['key'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
if (empty($options[$this->key])) {
// This may be a dead config entry, which existed in the past but no
// longer exists. Allow it to be edited so it can be reviewed and
// deleted.
$option = id(new PhabricatorConfigOption())
->setKey($this->key)
->setType('wild')
->setDefault(null)
->setDescription(
pht(
"This configuration option is unknown. It may be misspelled, ".
"or have existed in a previous version of Phabricator."));
$group = null;
$group_uri = $this->getApplicationURI();
} else {
$option = $options[$this->key];
$group = $option->getGroup();
$group_uri = $this->getApplicationURI('group/'.$group->getKey().'/');
}
$issue = $request->getStr('issue');
if ($issue) {
// If the user came here from an open setup issue, send them back.
$done_uri = $this->getApplicationURI('issue/'.$issue.'/');
} else {
$done_uri = $group_uri;
}
// Check if the config key is already stored in the database.
// Grab the value if it is.
$config_entry = id(new PhabricatorConfigEntry())
->loadOneWhere(
'configKey = %s AND namespace = %s',
$this->key,
'default');
if (!$config_entry) {
$config_entry = id(new PhabricatorConfigEntry())
->setConfigKey($this->key)
->setNamespace('default')
->setIsDeleted(true);
}
$e_value = null;
$errors = array();
if ($request->isFormPost() && !$option->getLocked()) {
$result = $this->readRequest(
$option,
$request);
list($e_value, $value_errors, $display_value, $xaction) = $result;
$errors = array_merge($errors, $value_errors);
if (!$errors) {
$editor = id(new PhabricatorConfigEditor())
->setActor($user)
->setContinueOnNoEffect(true)
->setContentSource(
PhabricatorContentSource::newForSource(
PhabricatorContentSource::SOURCE_WEB,
array(
'ip' => $request->getRemoteAddr(),
)));
try {
$editor->applyTransactions($config_entry, array($xaction));
return id(new AphrontRedirectResponse())->setURI($done_uri);
} catch (PhabricatorConfigValidationException $ex) {
$e_value = pht('Invalid');
$errors[] = $ex->getMessage();
}
}
} else {
$display_value = $this->getDisplayValue($option, $config_entry);
}
$form = new AphrontFormView();
$form->setFlexible(true);
$error_view = null;
if ($errors) {
$error_view = id(new AphrontErrorView())
->setTitle(pht('You broke everything!'))
->setErrors($errors);
} else if ($option->getHidden()) {
$msg = pht(
"This configuration is hidden and can not be edited or viewed from ".
"the web interface.");
$error_view = id(new AphrontErrorView())
->setTitle(pht('Configuration Hidden'))
->setSeverity(AphrontErrorView::SEVERITY_WARNING)
->appendChild('<p>'.phutil_escape_html($msg).'</p>');
} else if ($option->getLocked()) {
$msg = pht(
"This configuration is locked and can not be edited from the web ".
"interface.");
$error_view = id(new AphrontErrorView())
->setTitle(pht('Configuration Locked'))
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
->appendChild('<p>'.phutil_escape_html($msg).'</p>');
}
if ($option->getHidden()) {
$control = null;
} else {
$control = $this->renderControl(
$option,
$display_value,
$e_value);
}
$engine = new PhabricatorMarkupEngine();
$engine->addObject($option, 'description');
$engine->process();
$description = phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup',
),
- $engine->getOutput($option, 'description'));
+ phutil_safe_html($engine->getOutput($option, 'description')));
$form
->setUser($user)
->addHiddenInput('issue', $request->getStr('issue'))
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Description'))
->setValue($description))
->appendChild($control);
$submit_control = id(new AphrontFormSubmitControl())
->addCancelButton($done_uri);
if (!$option->getLocked()) {
$submit_control->setValue(pht('Save Config Entry'));
}
$form->appendChild($submit_control);
$examples = $this->renderExamples($option);
if ($examples) {
$form->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Examples'))
->setValue($examples));
}
if (!$option->getHidden()) {
$form->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Default'))
->setValue($this->renderDefaults($option)));
}
$title = pht('Edit %s', $this->key);
$short = pht('Edit');
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('Config'))
->setHref($this->getApplicationURI()));
if ($group) {
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($group->getName())
->setHref($group_uri));
}
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($this->key)
->setHref('/config/edit/'.$this->key));
$xactions = id(new PhabricatorConfigTransactionQuery())
->withObjectPHIDs(array($config_entry->getPHID()))
->setViewer($user)
->execute();
$xaction_view = id(new PhabricatorApplicationTransactionView())
->setUser($user)
->setTransactions($xactions);
return $this->buildApplicationPage(
array(
$crumbs,
id(new PhabricatorHeaderView())->setHeader($title),
$error_view,
$form,
$xaction_view,
),
array(
'title' => $title,
'device' => true,
));
}
private function readRequest(
PhabricatorConfigOption $option,
AphrontRequest $request) {
$xaction = new PhabricatorConfigTransaction();
$xaction->setTransactionType(PhabricatorConfigTransaction::TYPE_EDIT);
$e_value = null;
$errors = array();
$value = $request->getStr('value');
if (!strlen($value)) {
$value = null;
$xaction->setNewValue(
array(
'deleted' => true,
'value' => null,
));
return array($e_value, $errors, $value, $xaction);
}
$type = $option->getType();
$set_value = null;
switch ($type) {
case 'int':
if (preg_match('/^-?[0-9]+$/', trim($value))) {
$set_value = (int)$value;
} else {
$e_value = pht('Invalid');
$errors[] = pht('Value must be an integer.');
}
break;
case 'string':
case 'enum':
$set_value = (string)$value;
break;
case 'list<string>':
$set_value = $request->getStrList('value');
break;
case 'set':
$set_value = array_fill_keys($request->getStrList('value'), true);
break;
case 'bool':
switch ($value) {
case 'true':
$set_value = true;
break;
case 'false':
$set_value = false;
break;
default:
$e_value = pht('Invalid');
$errors[] = pht('Value must be boolean, "true" or "false".');
break;
}
break;
case 'class':
if (!class_exists($value)) {
$e_value = pht('Invalid');
$errors[] = pht('Class does not exist.');
} else {
$base = $option->getBaseClass();
if (!is_subclass_of($value, $base)) {
$e_value = pht('Invalid');
$errors[] = pht('Class is not of valid type.');
} else {
$set_value = $value;
}
}
break;
default:
$json = json_decode($value, true);
if ($json === null && strtolower($value) != 'null') {
$e_value = pht('Invalid');
$errors[] = pht(
'The given value must be valid JSON. This means, among '.
'other things, that you must wrap strings in double-quotes.');
} else {
$set_value = $json;
}
break;
}
if (!$errors) {
$xaction->setNewValue(
array(
'deleted' => false,
'value' => $set_value,
));
} else {
$xaction = null;
}
return array($e_value, $errors, $value, $xaction);
}
private function getDisplayValue(
PhabricatorConfigOption $option,
PhabricatorConfigEntry $entry) {
if ($entry->getIsDeleted()) {
return null;
}
$type = $option->getType();
$value = $entry->getValue();
switch ($type) {
case 'int':
case 'string':
case 'enum':
return $value;
case 'bool':
return $value ? 'true' : 'false';
case 'list<string>':
return implode("\n", nonempty($value, array()));
case 'set':
return implode("\n", nonempty(array_keys($value), array()));
default:
return PhabricatorConfigJSON::prettyPrintJSON($value);
}
}
private function renderControl(
PhabricatorConfigOption $option,
$display_value,
$e_value) {
$type = $option->getType();
switch ($type) {
case 'int':
case 'string':
$control = id(new AphrontFormTextControl());
break;
case 'bool':
$control = id(new AphrontFormSelectControl())
->setOptions(
array(
'' => pht('(Use Default)'),
'true' => idx($option->getBoolOptions(), 0),
'false' => idx($option->getBoolOptions(), 1),
));
break;
case 'enum':
$options = array_mergev(
array(
array('' => pht('(Use Default)')),
$option->getEnumOptions(),
));
$control = id(new AphrontFormSelectControl())
->setOptions($options);
break;
case 'class':
$symbols = id(new PhutilSymbolLoader())
->setType('class')
->setAncestorClass($option->getBaseClass())
->setConcreteOnly(true)
->selectSymbolsWithoutLoading();
$names = ipull($symbols, 'name', 'name');
asort($names);
$names = array(
'' => pht('(Use Default)'),
) + $names;
$control = id(new AphrontFormSelectControl())
->setOptions($names);
break;
case 'list<string>':
case 'set':
$control = id(new AphrontFormTextAreaControl())
->setCaption(pht('Separate values with newlines or commas.'));
break;
default:
$control = id(new AphrontFormTextAreaControl())
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
->setCustomClass('PhabricatorMonospaced')
->setCaption(pht('Enter value in JSON.'));
break;
}
$control
->setLabel('Value')
->setError($e_value)
->setValue($display_value)
->setName('value');
if ($option->getLocked()) {
$control->setDisabled(true);
}
return $control;
}
private function renderExamples(PhabricatorConfigOption $option) {
$examples = $option->getExamples();
if (!$examples) {
return null;
}
$table = array();
$table[] = '<tr class="column-labels">';
$table[] = '<th>'.pht('Example').'</th>';
$table[] = '<th>'.pht('Value').'</th>';
$table[] = '</tr>';
foreach ($examples as $example) {
list($value, $description) = $example;
if ($value === null) {
$value = '<em>'.pht('(empty)').'</em>';
} else {
$value = nl2br(phutil_escape_html($value));
}
$table[] = '<tr>';
$table[] = '<th>'.phutil_escape_html($description).'</th>';
$table[] = '<td>'.$value.'</td>';
$table[] = '</tr>';
}
require_celerity_resource('config-options-css');
return phutil_tag(
'table',
array(
'class' => 'config-option-table',
),
new PhutilSafeHTML(implode("\n", $table)));
}
private function renderDefaults(PhabricatorConfigOption $option) {
$stack = PhabricatorEnv::getConfigSourceStack();
$stack = $stack->getStack();
/*
TODO: Once DatabaseSource lands, do this:
foreach ($stack as $key => $source) {
unset($stack[$key]);
if ($source instanceof PhabricatorConfigDatabaseSource) {
break;
}
}
*/
$table = array();
$table[] = '<tr class="column-labels">';
$table[] = '<th>'.pht('Source').'</th>';
$table[] = '<th>'.pht('Value').'</th>';
$table[] = '</tr>';
foreach ($stack as $key => $source) {
$value = $source->getKeys(
array(
$option->getKey(),
));
if (!array_key_exists($option->getKey(), $value)) {
$value = '<em>'.pht('(empty)').'</em>';
} else {
$value = PhabricatorConfigJSON::prettyPrintJSON(
$value[$option->getKey()]);
}
$table[] = '<tr>';
$table[] = '<th>'.phutil_escape_html($source->getName()).'</th>';
$table[] = '<td>'.$value.'</td>';
$table[] = '</tr>';
}
require_celerity_resource('config-options-css');
return phutil_tag(
'table',
array(
'class' => 'config-option-table',
),
new PhutilSafeHTML(implode("\n", $table)));
}
}
diff --git a/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php b/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php
index 337dd9a625..20c2920e6e 100644
--- a/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php
+++ b/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php
@@ -1,426 +1,426 @@
<?php
final class DifferentialChangesetTwoUpRenderer
extends DifferentialChangesetHTMLRenderer {
public function isOneUpRenderer() {
return false;
}
public function renderTextChange(
$range_start,
$range_len,
$rows) {
$hunk_starts = $this->getHunkStartLines();
$context_not_available = null;
if ($hunk_starts) {
$context_not_available = javelin_render_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_render_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("\xE2\x96\xB2 Show 20 Lines"));
}
$contents[] = javelin_render_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_render_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("\xE2\x96\xBC 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_render_tag(
'tr',
array(
'sigil' => 'context-target',
),
'<td colspan="2" class="show-more">'.
implode(' &bull; ', $contents).
'</td>'.
'<th class="show-context-line">'.$context_line.'</td>'.
'<td colspan="3" class="show-context">'.$context.'</td>');
$html[] = $container;
$ii += ($len - 1);
continue;
}
$o_num = null;
$o_classes = 'left';
$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_classes .= ' comment';
} else if ($original_left && !isset($highlight_old[$o_num])) {
$o_classes .= ' old-rebase';
} else if (empty($new_lines[$ii])) {
$o_classes .= ' old old-full';
} else {
$o_classes .= ' old';
}
}
}
$n_copy = '<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 = '<td class="cov '.$cov_class.'"></td>';
$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 = '<td class="copy '.$n_class.'"></td>';
} 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_render_tag(
'td',
array(
'meta' => array(
'msg' => $title,
),
'class' => 'copy '.$class,
),
'');
}
}
}
$n_classes .= ' right'.$n_colspan;
if (isset($hunk_starts[$o_num])) {
$html[] = $context_not_available;
}
if ($o_num && $left_id) {
$o_id = ' id="C'.$left_id.$left_char.'L'.$o_num.'"';
} else {
$o_id = null;
}
if ($n_num && $right_id) {
$n_id = ' id="C'.$right_id.$right_char.'L'.$n_num.'"';
} else {
$n_id = null;
}
// NOTE: The Javascript is sensitive to whitespace changes in this
// block!
$html[] =
'<tr>'.
'<th'.$o_id.'>'.$o_num.'</th>'.
'<td class="'.$o_classes.'">'.$o_text.'</td>'.
'<th'.$n_id.'>'.$n_num.'</th>'.
$n_copy.
// 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.
'<td class="'.$n_classes.'" colspan="'.$n_colspan.'">'.
"\xE2\x80\x8B".$n_text.
'</td>'.
$n_cov.
'</tr>';
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[] =
'<tr class="inline">'.
'<th />'.
'<td class="left">'.$comment_html.'</td>'.
'<th />'.
'<td colspan="3" class="right3">'.$new.'</td>'.
'</tr>';
}
}
if ($n_num && isset($new_comments[$n_num])) {
foreach ($new_comments[$n_num] as $comment) {
$comment_html = $this->renderInlineComment($comment,
$on_right = true);
$html[] =
'<tr class="inline">'.
'<th />'.
'<td class="left" />'.
'<th />'.
'<td colspan="3" class="right3">'.$comment_html.'</td>'.
'</tr>';
}
}
}
return $this->wrapChangeInTable(implode('', $html));
}
public function renderFileChange($old_file = null,
$new_file = null,
$id = 0,
$vs = 0) {
$old = null;
if ($old_file) {
- $old = phutil_render_tag(
+ $old = phutil_tag(
'div',
array(
'class' => 'differential-image-stage'
),
phutil_tag(
'img',
array(
'src' => $old_file->getBestURI(),
)
)
);
}
$new = null;
if ($new_file) {
- $new = phutil_render_tag(
+ $new = phutil_tag(
'div',
array(
'class' => 'differential-image-stage'
),
phutil_tag(
'img',
array(
'src' => $new_file->getBestURI(),
)
)
);
}
$html_old = array();
$html_new = array();
foreach ($this->getOldComments() as $on_line => $comment_group) {
foreach ($comment_group as $comment) {
$comment_html = $this->renderInlineComment($comment, $on_right = false);
$html_old[] =
'<tr class="inline">'.
'<th />'.
'<td class="left">'.$comment_html.'</td>'.
'<th />'.
'<td class="right3" colspan="3" />'.
'</tr>';
}
}
foreach ($this->getNewComments() as $lin_line => $comment_group) {
foreach ($comment_group as $comment) {
$comment_html = $this->renderInlineComment($comment, $on_right = true);
$html_new[] =
'<tr class="inline">'.
'<th />'.
'<td class="left" />'.
'<th />'.
'<td class="right3" colspan="3">'.$comment_html.'</td>'.
'</tr>';
}
}
if (!$old) {
$th_old = '<th></th>';
} else {
$th_old = '<th id="C'.$vs.'OL1">1</th>';
}
if (!$new) {
$th_new = '<th></th>';
} else {
$th_new = '<th id="C'.$id.'NL1">1</th>';
}
$output =
'<tr class="differential-image-diff">'.
$th_old.
'<td class="left differential-old-image">'.$old.'</td>'.
$th_new.
'<td class="right3 differential-new-image" colspan="3">'.
$new.
'</td>'.
'</tr>'.
implode('', $html_old).
implode('', $html_new);
$output = $this->wrapChangeInTable($output);
return $this->renderChangesetTable($output);
}
}
diff --git a/src/applications/phame/controller/post/PhamePostPublishController.php b/src/applications/phame/controller/post/PhamePostPublishController.php
index 0a04ec542e..2a456fe394 100644
--- a/src/applications/phame/controller/post/PhamePostPublishController.php
+++ b/src/applications/phame/controller/post/PhamePostPublishController.php
@@ -1,87 +1,87 @@
<?php
/**
* @group phame
*/
final class PhamePostPublishController extends PhameController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$post = id(new PhamePostQuery())
->setViewer($user)
->withIDs(array($this->id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$post) {
return new Aphront404Response();
}
$view_uri = $this->getApplicationURI('/post/view/'.$post->getID().'/');
if ($request->isFormPost()) {
$post->setVisibility(PhamePost::VISIBILITY_PUBLISHED);
$post->setDatePublished(time());
$post->save();
return id(new AphrontRedirectResponse())->setURI($view_uri);
}
$header = id(new PhabricatorHeaderView())
->setHeader('Preview Post');
$form = id(new AphrontFormView())
->setUser($user)
->setFlexible(true)
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Publish Post'))
->addCancelButton($view_uri));
$frame = $this->renderPreviewFrame($post);
$nav = $this->renderSideNavFilterView(null);
$nav->appendChild(
array(
$header,
$form,
$frame,
));
return $this->buildApplicationPage(
$nav,
array(
'title' => pht('Preview Post'),
'device' => true,
));
}
private function renderPreviewFrame(PhamePost $post) {
// TODO: Clean up this CSS.
- return phutil_render_tag(
+ return phutil_tag(
'div',
array(
'style' => 'text-align: center; padding: 1em;',
),
phutil_tag(
'iframe',
array(
'style' => 'width: 100%; height: 600px; '.
'border: 1px solid #303030; background: #303030;',
'src' => $this->getApplicationURI('/post/framed/'.$post->getID().'/'),
),
''));
}
}
diff --git a/src/applications/phame/view/PhamePostView.php b/src/applications/phame/view/PhamePostView.php
index 582e32ccf7..533d4402a5 100644
--- a/src/applications/phame/view/PhamePostView.php
+++ b/src/applications/phame/view/PhamePostView.php
@@ -1,242 +1,242 @@
<?php
/**
* @group phame
*/
final class PhamePostView extends AphrontView {
private $post;
private $author;
private $body;
private $skin;
private $summary;
public function setSkin(PhameBlogSkin $skin) {
$this->skin = $skin;
return $this;
}
public function getSkin() {
return $this->skin;
}
public function setAuthor(PhabricatorObjectHandle $author) {
$this->author = $author;
return $this;
}
public function getAuthor() {
return $this->author;
}
public function setPost(PhamePost $post) {
$this->post = $post;
return $this;
}
public function getPost() {
return $this->post;
}
public function setBody($body) {
$this->body = $body;
return $this;
}
public function getBody() {
return $this->body;
}
public function setSummary($summary) {
$this->summary = $summary;
return $this;
}
public function getSummary() {
return $this->summary;
}
public function renderTitle() {
$href = $this->getSkin()->getURI('post/'.$this->getPost()->getPhameTitle());
- return phutil_render_tag(
+ return phutil_tag(
'h2',
array(
'class' => 'phame-post-title',
),
phutil_tag(
'a',
array(
'href' => $href,
),
$this->getPost()->getTitle()));
}
public function renderDatePublished() {
return phutil_tag(
'div',
array(
'class' => 'phame-post-date',
),
pht(
'Published on %s by %s',
phabricator_datetime(
$this->getPost()->getDatePublished(),
$this->getUser()),
$this->getAuthor()->getName()));
}
public function renderBody() {
return phutil_render_tag(
'div',
array(
'class' => 'phame-post-body',
),
$this->getBody());
}
public function renderSummary() {
return phutil_render_tag(
'div',
array(
'class' => 'phame-post-body',
),
$this->getSummary());
}
public function renderComments() {
$post = $this->getPost();
switch ($post->getCommentsWidget()) {
case 'facebook':
$comments = $this->renderFacebookComments();
break;
case 'disqus':
$comments = $this->renderDisqusComments();
break;
case 'none':
default:
$comments = null;
break;
}
return $comments;
}
public function render() {
return phutil_tag(
'div',
array(
'class' => 'phame-post',
),
array(
$this->renderTitle(),
$this->renderDatePublished(),
$this->renderBody(),
$this->renderComments(),
));
}
public function renderWithSummary() {
return phutil_tag(
'div',
array(
'class' => 'phame-post',
),
array(
$this->renderTitle(),
$this->renderDatePublished(),
$this->renderSummary(),
));
}
private function renderFacebookComments() {
$fb_id = PhabricatorEnv::getEnvConfig('facebook.application-id');
if (!$fb_id) {
return null;
}
$fb_root = phutil_tag('div',
array(
'id' => 'fb-root',
),
''
);
$c_uri = '//connect.facebook.net/en_US/all.js#xfbml=1&appId='.$fb_id;
$fb_js = jsprintf(
'<script>(function(d, s, id) {'.
' var js, fjs = d.getElementsByTagName(s)[0];'.
' if (d.getElementById(id)) return;'.
' js = d.createElement(s); js.id = id;'.
' js.src = %s;'.
' fjs.parentNode.insertBefore(js, fjs);'.
'}(document, \'script\', \'facebook-jssdk\'));</script>',
$c_uri
);
$uri = $this->getSkin()->getURI('post/'.$this->getPost()->getPhameTitle());
$fb_comments = phutil_tag('div',
array(
'class' => 'fb-comments',
'data-href' => $uri,
'data-num-posts' => 5,
),
''
);
return phutil_render_tag(
'div',
array(
'class' => 'phame-comments-facebook',
),
$fb_root.
$fb_js.
$fb_comments);
}
private function renderDisqusComments() {
$disqus_shortname = PhabricatorEnv::getEnvConfig('disqus.shortname');
if (!$disqus_shortname) {
return null;
}
$post = $this->getPost();
$disqus_thread = phutil_tag('div',
array(
'id' => 'disqus_thread'
)
);
// protip - try some var disqus_developer = 1; action to test locally
$disqus_js = jsprintf(
'<script>'.
' var disqus_shortname = "phabricator";'.
' var disqus_identifier = %s;'.
' var disqus_url = %s;'.
' var disqus_title = %s;'.
'(function() {'.
' var dsq = document.createElement("script");'.
' dsq.type = "text/javascript";'.
' dsq.async = true;'.
' dsq.src = "http://" + disqus_shortname + ".disqus.com/embed.js";'.
'(document.getElementsByTagName("head")[0] ||'.
' document.getElementsByTagName("body")[0]).appendChild(dsq);'.
'})(); </script>',
$post->getPHID(),
$this->getSkin()->getURI('post/'.$this->getPost()->getPhameTitle()),
$post->getTitle()
);
return phutil_render_tag(
'div',
array(
'class' => 'phame-comments-disqus',
),
$disqus_thread.
$disqus_js);
}
}
diff --git a/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php b/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php
index b1e15f43e1..531ddaba61 100644
--- a/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php
+++ b/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php
@@ -1,456 +1,456 @@
<?php
/**
* @group slowvote
*/
final class PhabricatorSlowvotePollController
extends PhabricatorSlowvoteController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$viewer_phid = $user->getPHID();
$poll = id(new PhabricatorSlowvotePoll())->load($this->id);
if (!$poll) {
return new Aphront404Response();
}
$options = id(new PhabricatorSlowvoteOption())->loadAllWhere(
'pollID = %d',
$poll->getID());
$choices = id(new PhabricatorSlowvoteChoice())->loadAllWhere(
'pollID = %d',
$poll->getID());
$comments = id(new PhabricatorSlowvoteComment())->loadAllWhere(
'pollID = %d',
$poll->getID());
$choices_by_option = mgroup($choices, 'getOptionID');
$comments_by_user = mpull($comments, null, 'getAuthorPHID');
$choices_by_user = mgroup($choices, 'getAuthorPHID');
$viewer_choices = idx($choices_by_user, $viewer_phid, array());
$viewer_comment = idx($comments_by_user, $viewer_phid, null);
$comment_text = null;
if ($viewer_comment) {
$comment_text = $viewer_comment->getCommentText();
}
if ($request->isFormPost()) {
$comment = idx($comments_by_user, $viewer_phid, null);
if ($comment) {
$comment->delete();
}
$comment_text = $request->getStr('comments');
if (strlen($comment_text)) {
id(new PhabricatorSlowvoteComment())
->setAuthorPHID($viewer_phid)
->setPollID($poll->getID())
->setCommentText($comment_text)
->save();
}
$votes = $request->getArr('vote');
switch ($poll->getMethod()) {
case PhabricatorSlowvotePoll::METHOD_PLURALITY:
// Enforce only one vote.
$votes = array_slice($votes, 0, 1);
break;
case PhabricatorSlowvotePoll::METHOD_APPROVAL:
// No filtering.
break;
default:
throw new Exception("Unknown poll method!");
}
foreach ($viewer_choices as $viewer_choice) {
$viewer_choice->delete();
}
foreach ($votes as $vote) {
id(new PhabricatorSlowvoteChoice())
->setAuthorPHID($viewer_phid)
->setPollID($poll->getID())
->setOptionID($vote)
->save();
}
return id(new AphrontRedirectResponse())->setURI('/V'.$poll->getID());
}
require_celerity_resource('phabricator-slowvote-css');
$phids = array_merge(
mpull($choices, 'getAuthorPHID'),
mpull($comments, 'getAuthorPHID'),
array(
$poll->getAuthorPHID(),
));
$query = new PhabricatorObjectHandleData($phids);
$handles = $query->loadHandles();
$objects = $query->loadObjects();
if ($poll->getShuffle()) {
shuffle($options);
}
$option_markup = array();
foreach ($options as $option) {
$option_markup[] = $this->renderPollOption(
$poll,
$viewer_choices,
$option);
}
$option_markup = implode("\n", $option_markup);
$comments_by_option = array();
switch ($poll->getMethod()) {
case PhabricatorSlowvotePoll::METHOD_PLURALITY:
$choice_ids = array();
foreach ($choices_by_user as $user_phid => $user_choices) {
$choice_ids[$user_phid] = head($user_choices)->getOptionID();
}
foreach ($comments as $comment) {
$choice = idx($choice_ids, $comment->getAuthorPHID());
if ($choice) {
$comments_by_option[$choice][] = $comment;
}
}
break;
case PhabricatorSlowvotePoll::METHOD_APPROVAL:
// All comments are grouped in approval voting.
break;
default:
throw new Exception("Unknown poll method!");
}
$result_markup = $this->renderResultMarkup(
$poll,
$options,
$choices,
$comments,
$viewer_choices,
$choices_by_option,
$comments_by_option,
$handles,
$objects);
if ($viewer_choices) {
$instructions =
'Your vote has been recorded... but there is still ample time to '.
'rethink your position. Have you thoroughly considered all possible '.
'eventualities?';
} else {
$instructions =
'This is a weighty matter indeed. Consider your choices with the '.
'greatest of care.';
}
$form = id(new AphrontFormView())
->setUser($user)
->appendChild(
'<p class="aphront-form-instructions">'.$instructions.'</p>')
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel('Vote')
->setValue($option_markup))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Comments')
->setHeight(AphrontFormTextAreaControl::HEIGHT_SHORT)
->setName('comments')
->setValue($comment_text))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Cautiously Engage in Deliberations'));
$panel = new AphrontPanelView();
$panel->setHeader(phutil_escape_html($poll->getQuestion()));
$panel->setWidth(AphrontPanelView::WIDTH_WIDE);
$panel->appendChild($form);
$panel->appendChild('<br /><br />');
$panel->appendChild($result_markup);
return $this->buildStandardPageResponse(
$panel,
array(
'title' => 'V'.$poll->getID().' '.$poll->getQuestion(),
));
}
private function renderComments(array $comments, array $handles) {
assert_instances_of($comments, 'PhabricatorSlowvoteComment');
assert_instances_of($handles, 'PhabricatorObjectHandle');
$viewer = $this->getRequest()->getUser();
$engine = PhabricatorMarkupEngine::newSlowvoteMarkupEngine();
$comment_markup = array();
foreach ($comments as $comment) {
$handle = $handles[$comment->getAuthorPHID()];
$markup = $engine->markupText($comment->getCommentText());
require_celerity_resource('phabricator-remarkup-css');
$comment_markup[] =
'<tr>'.
'<th>'.
$handle->renderLink().
'<div class="phabricator-slowvote-datestamp">'.
phabricator_datetime($comment->getDateCreated(), $viewer).
'</div>'.
'<td>'.
'<div class="phabricator-remarkup">'.
$markup.
'</div>'.
'</td>'.
'</tr>';
}
if ($comment_markup) {
$comment_markup = phutil_tag(
'table',
array(
'class' => 'phabricator-slowvote-comments',
),
new PhutilSafeHTML(implode("\n", $comment_markup)));
} else {
$comment_markup = null;
}
return $comment_markup;
}
private function renderPollOption(
PhabricatorSlowvotePoll $poll,
array $viewer_choices,
PhabricatorSlowvoteOption $option) {
assert_instances_of($viewer_choices, 'PhabricatorSlowvoteChoice');
$id = $option->getID();
switch ($poll->getMethod()) {
case PhabricatorSlowvotePoll::METHOD_PLURALITY:
// Render a radio button.
$selected_option = head($viewer_choices);
if ($selected_option) {
$selected = $selected_option->getOptionID();
} else {
$selected = null;
}
if ($selected == $id) {
$checked = "checked";
} else {
$checked = null;
}
$input = phutil_tag(
'input',
array(
'type' => 'radio',
'name' => 'vote[]',
'value' => $id,
'checked' => $checked,
));
break;
case PhabricatorSlowvotePoll::METHOD_APPROVAL:
// Render a check box.
$checked = null;
foreach ($viewer_choices as $choice) {
if ($choice->getOptionID() == $id) {
$checked = 'checked';
break;
}
}
$input = phutil_tag(
'input',
array(
'type' => 'checkbox',
'name' => 'vote[]',
'checked' => $checked,
'value' => $id,
));
break;
default:
throw new Exception("Unknown poll method!");
}
if ($checked) {
$checked_class = 'phabricator-slowvote-checked';
} else {
$checked_class = null;
}
return phutil_tag(
'label',
array(
'class' => 'phabricator-slowvote-label '.$checked_class,
),
array($input, $option->getName()));
}
private function renderVoteCount(
PhabricatorSlowvotePoll $poll,
array $choices,
array $chosen) {
assert_instances_of($choices, 'PhabricatorSlowvoteChoice');
assert_instances_of($chosen, 'PhabricatorSlowvoteChoice');
switch ($poll->getMethod()) {
case PhabricatorSlowvotePoll::METHOD_PLURALITY:
$out_of_total = count($choices);
break;
case PhabricatorSlowvotePoll::METHOD_APPROVAL:
// Count unique respondents for approval votes.
$out_of_total = count(mpull($choices, null, 'getAuthorPHID'));
break;
default:
throw new Exception("Unknown poll method!");
}
return sprintf(
'%d / %d (%d%%)',
number_format(count($chosen)),
number_format($out_of_total),
$out_of_total
? round(100 * count($chosen) / $out_of_total)
: 0);
}
private function renderResultMarkup(
PhabricatorSlowvotePoll $poll,
array $options,
array $choices,
array $comments,
array $viewer_choices,
array $choices_by_option,
array $comments_by_option,
array $handles,
array $objects) {
assert_instances_of($options, 'PhabricatorSlowvoteOption');
assert_instances_of($choices, 'PhabricatorSlowvoteChoice');
assert_instances_of($comments, 'PhabricatorSlowvoteComment');
assert_instances_of($viewer_choices, 'PhabricatorSlowvoteChoice');
assert_instances_of($handles, 'PhabricatorObjectHandle');
assert_instances_of($objects, 'PhabricatorLiskDAO');
$viewer_phid = $this->getRequest()->getUser()->getPHID();
$can_see_responses = false;
$need_vote = false;
switch ($poll->getResponseVisibility()) {
case PhabricatorSlowvotePoll::RESPONSES_VISIBLE:
$can_see_responses = true;
break;
case PhabricatorSlowvotePoll::RESPONSES_VOTERS:
$can_see_responses = (bool)$viewer_choices;
$need_vote = true;
break;
case PhabricatorSlowvotePoll::RESPONSES_OWNER:
$can_see_responses = ($viewer_phid == $poll->getAuthorPHID());
break;
}
$result_markup = id(new AphrontFormLayoutView())
->appendChild('<h1>Ongoing Deliberation</h1>');
if (!$can_see_responses) {
if ($need_vote) {
$reason = "You must vote to see the results.";
} else {
$reason = "The results are not public.";
}
$result_markup
->appendChild(
'<p class="aphront-form-instructions"><em>'.$reason.'</em></p>');
return $result_markup;
}
foreach ($options as $option) {
$id = $option->getID();
$chosen = idx($choices_by_option, $id, array());
$users = array_select_keys($handles, mpull($chosen, 'getAuthorPHID'));
if ($users) {
$user_markup = array();
foreach ($users as $handle) {
$object = idx($objects, $handle->getPHID());
if (!$object) {
continue;
}
$profile_image = $handle->getImageURI();
- $user_markup[] = phutil_render_tag(
+ $user_markup[] = phutil_tag(
'a',
array(
'href' => $handle->getURI(),
'class' => 'phabricator-slowvote-facepile',
),
phutil_tag(
'img',
array(
'src' => $profile_image,
)));
}
$user_markup = implode('', $user_markup);
} else {
$user_markup = 'This option has failed to appeal to anyone.';
}
$comment_markup = $this->renderComments(
idx($comments_by_option, $id, array()),
$handles);
$vote_count = $this->renderVoteCount(
$poll,
$choices,
$chosen);
$result_markup->appendChild(
'<div>'.
'<div class="phabricator-slowvote-count">'.
$vote_count.
'</div>'.
'<h1>'.phutil_escape_html($option->getName()).'</h1>'.
'<hr class="phabricator-slowvote-hr" />'.
$user_markup.
'<div style="clear: both;">'.
'<hr class="phabricator-slowvote-hr" />'.
$comment_markup.
'</div>');
}
if ($poll->getMethod() == PhabricatorSlowvotePoll::METHOD_APPROVAL &&
$comments) {
$comment_markup = $this->renderComments(
$comments,
$handles);
$result_markup->appendChild(
'<h1>Motions Proposed for Consideration</h1>');
$result_markup->appendChild($comment_markup);
}
return $result_markup;
}
}
diff --git a/src/view/layout/PhabricatorHeaderView.php b/src/view/layout/PhabricatorHeaderView.php
index 60a9e0655e..7d8a6e5109 100644
--- a/src/view/layout/PhabricatorHeaderView.php
+++ b/src/view/layout/PhabricatorHeaderView.php
@@ -1,64 +1,64 @@
<?php
final class PhabricatorHeaderView extends AphrontView {
private $objectName;
private $header;
private $tags = array();
public function setHeader($header) {
$this->header = $header;
return $this;
}
public function setObjectName($object_name) {
$this->objectName = $object_name;
return $this;
}
public function addTag(PhabricatorTagView $tag) {
$this->tags[] = $tag;
return $this;
}
public function render() {
require_celerity_resource('phabricator-header-view-css');
$header = array($this->header);
if ($this->objectName) {
array_unshift(
$header,
phutil_tag(
'a',
array(
'href' => '/'.$this->objectName,
),
$this->objectName),
' ');
}
if ($this->tags) {
$header[] = phutil_render_tag(
'span',
array(
'class' => 'phabricator-header-tags',
),
self::renderSingleView($this->tags));
}
- return phutil_render_tag(
+ return phutil_tag(
'div',
array(
'class' => 'phabricator-header-shell',
),
phutil_tag(
'h1',
array(
'class' => 'phabricator-header-view',
),
$header));
}
}
diff --git a/src/view/layout/PhabricatorPinboardItemView.php b/src/view/layout/PhabricatorPinboardItemView.php
index ed8b2e2998..76cf5104ba 100644
--- a/src/view/layout/PhabricatorPinboardItemView.php
+++ b/src/view/layout/PhabricatorPinboardItemView.php
@@ -1,77 +1,77 @@
<?php
final class PhabricatorPinboardItemView extends AphrontView {
private $imageURI;
private $uri;
private $header;
private $imageWidth;
private $imageHeight;
public function setHeader($header) {
$this->header = $header;
return $this;
}
public function setURI($uri) {
$this->uri = $uri;
return $this;
}
public function setImageURI($image_uri) {
$this->imageURI = $image_uri;
return $this;
}
public function setImageSize($x, $y) {
$this->imageWidth = $x;
$this->imageHeight = $y;
return $this;
}
public function render() {
$header = null;
if ($this->header) {
$header = hsprintf('<a href="%s">%s</a>', $this->uri, $this->header);
$header = phutil_tag(
'div',
array(
'class' => 'phabricator-pinboard-item-header',
),
$header);
}
- $image = phutil_render_tag(
+ $image = phutil_tag(
'a',
array(
'href' => $this->uri,
'class' => 'phabricator-pinboard-item-image-link',
),
phutil_tag(
'img',
array(
'src' => $this->imageURI,
'width' => $this->imageWidth,
'height' => $this->imageHeight,
)));
$content = $this->renderChildren();
if ($content) {
$content = phutil_render_tag(
'div',
array(
'class' => 'phabricator-pinboard-item-content',
),
$content);
}
return phutil_tag(
'div',
array(
'class' => 'phabricator-pinboard-item-view',
),
array($header, $image, $content));
}
}
diff --git a/src/view/layout/PhabricatorSourceCodeView.php b/src/view/layout/PhabricatorSourceCodeView.php
index 49768fc1f8..790ea663d3 100644
--- a/src/view/layout/PhabricatorSourceCodeView.php
+++ b/src/view/layout/PhabricatorSourceCodeView.php
@@ -1,82 +1,82 @@
<?php
final class PhabricatorSourceCodeView extends AphrontView {
private $lines;
private $limit;
public function setLimit($limit) {
$this->limit = $limit;
return $this;
}
public function setLines(array $lines) {
$this->lines = $lines;
return $this;
}
public function render() {
require_celerity_resource('phabricator-source-code-view-css');
require_celerity_resource('syntax-highlighting-css');
Javelin::initBehavior('phabricator-oncopy', array());
$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 = phutil_escape_html($line_number);
$content_line = "\xE2\x80\x8B".$line;
}
// TODO: Provide nice links.
$rows[] =
'<tr>'.
'<th class="phabricator-source-line">'.
$content_number.
'</th>'.
'<td class="phabricator-source-code">'.
$content_line.
'</td>'.
'</tr>';
if ($hit_limit) {
break;
}
$line_number++;
}
$classes = array();
$classes[] = 'phabricator-source-code-view';
$classes[] = 'remarkup-code';
$classes[] = 'PhabricatorMonospaced';
- return phutil_render_tag(
+ return phutil_tag(
'div',
array(
'class' => 'phabricator-source-code-container',
),
- phutil_render_tag(
+ phutil_tag(
'table',
array(
'class' => implode(' ', $classes),
),
- implode('', $rows)));
+ new PhutilSafeHTML(implode('', $rows))));
}
}
diff --git a/src/view/layout/PhabricatorTimelineEventView.php b/src/view/layout/PhabricatorTimelineEventView.php
index 4359a5c9c0..63f7af3cdc 100644
--- a/src/view/layout/PhabricatorTimelineEventView.php
+++ b/src/view/layout/PhabricatorTimelineEventView.php
@@ -1,300 +1,300 @@
<?php
final class PhabricatorTimelineEventView extends AphrontView {
private $userHandle;
private $title;
private $icon;
private $color;
private $classes = array();
private $contentSource;
private $dateCreated;
private $anchor;
private $isEditable;
private $isEdited;
private $transactionPHID;
private $isPreview;
public function setTransactionPHID($transaction_phid) {
$this->transactionPHID = $transaction_phid;
return $this;
}
public function getTransactionPHID() {
return $this->transactionPHID;
}
public function setIsEdited($is_edited) {
$this->isEdited = $is_edited;
return $this;
}
public function getIsEdited() {
return $this->isEdited;
}
public function setIsPreview($is_preview) {
$this->isPreview = $is_preview;
return $this;
}
public function getIsPreview() {
return $this->isPreview;
}
public function setIsEditable($is_editable) {
$this->isEditable = $is_editable;
return $this;
}
public function getIsEditable() {
return $this->isEditable;
}
public function setDateCreated($date_created) {
$this->dateCreated = $date_created;
return $this;
}
public function getDateCreated() {
return $this->dateCreated;
}
public function setContentSource(PhabricatorContentSource $content_source) {
$this->contentSource = $content_source;
return $this;
}
public function getContentSource() {
return $this->contentSource;
}
public function setUserHandle(PhabricatorObjectHandle $handle) {
$this->userHandle = $handle;
return $this;
}
public function setAnchor($anchor) {
$this->anchor = $anchor;
return $this;
}
public function setTitle($title) {
$this->title = $title;
return $this;
}
public function addClass($class) {
$this->classes[] = $class;
return $this;
}
public function setIcon($icon) {
$this->icon = $icon;
return $this;
}
public function setColor($color) {
$this->color = $color;
return $this;
}
public function render() {
$content = $this->renderChildren();
$title = $this->title;
if (($title === null) && !strlen($content)) {
$title = '';
}
$extra = $this->renderExtra();
if ($title !== null || $extra !== null) {
$title_classes = array();
$title_classes[] = 'phabricator-timeline-title';
$icon = null;
if ($this->icon) {
$title_classes[] = 'phabricator-timeline-title-with-icon';
- $icon = phutil_render_tag(
+ $icon = phutil_tag(
'span',
array(
'class' => 'phabricator-timeline-icon-fill',
),
phutil_tag(
'span',
array(
'class' => 'phabricator-timeline-icon sprite-icon '.
'action-'.$this->icon.'-white',
),
''));
}
$title = phutil_render_tag(
'div',
array(
'class' => implode(' ', $title_classes),
),
$title.$extra);
$title = $icon.$title;
}
$wedge = phutil_tag(
'div',
array(
'class' => 'phabricator-timeline-wedge phabricator-timeline-border',
),
'');
$image_uri = $this->userHandle->getImageURI();
$image = phutil_tag(
'div',
array(
'style' => 'background-image: url('.$image_uri.')',
'class' => 'phabricator-timeline-image',
),
'');
$content_classes = array();
$content_classes[] = 'phabricator-timeline-content';
$classes = array();
$classes[] = 'phabricator-timeline-event-view';
$classes[] = 'phabricator-timeline-border';
if ($content) {
$classes[] = 'phabricator-timeline-major-event';
$content = phutil_render_tag(
'div',
array(
'class' => implode(' ', $content_classes),
),
phutil_render_tag(
'div',
array(
'class' => 'phabricator-timeline-inner-content',
),
$title.
phutil_render_tag(
'div',
array(
'class' => 'phabricator-timeline-core-content',
),
$content)));
$content = $image.$wedge.$content;
} else {
$classes[] = 'phabricator-timeline-minor-event';
$content = phutil_render_tag(
'div',
array(
'class' => implode(' ', $content_classes),
),
$image.$wedge.$title);
}
$outer_classes = $this->classes;
$outer_classes[] = 'phabricator-timeline-shell';
if ($this->color) {
$outer_classes[] = 'phabricator-timeline-'.$this->color;
}
$sigil = null;
$meta = null;
if ($this->getTransactionPHID()) {
$sigil = 'transaction';
$meta = array(
'phid' => $this->getTransactionPHID(),
'anchor' => $this->anchor,
);
}
return javelin_render_tag(
'div',
array(
'class' => implode(' ', $outer_classes),
'id' => $this->anchor ? 'anchor-'.$this->anchor : null,
'sigil' => $sigil,
'meta' => $meta,
),
phutil_render_tag(
'div',
array(
'class' => implode(' ', $classes),
),
$content));
}
private function renderExtra() {
$extra = array();
if ($this->getIsPreview()) {
$extra[] = pht('PREVIEW');
} else {
$xaction_phid = $this->getTransactionPHID();
if ($this->getIsEdited()) {
$extra[] = javelin_render_tag(
'a',
array(
'href' => '/transactions/history/'.$xaction_phid.'/',
'sigil' => 'workflow',
),
pht('Edited'));
}
if ($this->getIsEditable()) {
$extra[] = javelin_render_tag(
'a',
array(
'href' => '/transactions/edit/'.$xaction_phid.'/',
'sigil' => 'workflow transaction-edit',
),
pht('Edit'));
}
$source = $this->getContentSource();
if ($source) {
$extra[] = id(new PhabricatorContentSourceView())
->setContentSource($source)
->setUser($this->getUser())
->render();
}
if ($this->getDateCreated()) {
$date = phabricator_datetime(
$this->getDateCreated(),
$this->getUser());
if ($this->anchor) {
Javelin::initBehavior('phabricator-watch-anchor');
$anchor = id(new PhabricatorAnchorView())
->setAnchorName($this->anchor)
->render();
$date = $anchor.phutil_tag(
'a',
array(
'href' => '#'.$this->anchor,
),
$date);
}
$extra[] = $date;
}
}
$extra = implode(' &middot; ', $extra);
if ($extra) {
$extra = phutil_render_tag(
'span',
array(
'class' => 'phabricator-timeline-extra',
),
$extra);
}
return $extra;
}
}
diff --git a/src/view/page/menu/PhabricatorMainMenuView.php b/src/view/page/menu/PhabricatorMainMenuView.php
index a8ada196e7..e833a6f828 100644
--- a/src/view/page/menu/PhabricatorMainMenuView.php
+++ b/src/view/page/menu/PhabricatorMainMenuView.php
@@ -1,370 +1,370 @@
<?php
final class PhabricatorMainMenuView extends AphrontView {
private $defaultSearchScope;
private $controller;
private $applicationMenu;
public function setApplicationMenu(PhabricatorMenuView $application_menu) {
$this->applicationMenu = $application_menu;
return $this;
}
public function getApplicationMenu() {
return $this->applicationMenu;
}
public function setController(PhabricatorController $controller) {
$this->controller = $controller;
return $this;
}
public function getController() {
return $this->controller;
}
public function setDefaultSearchScope($default_search_scope) {
$this->defaultSearchScope = $default_search_scope;
return $this;
}
public function getDefaultSearchScope() {
return $this->defaultSearchScope;
}
public function render() {
$user = $this->user;
require_celerity_resource('phabricator-main-menu-view');
$header_id = celerity_generate_unique_node_id();
$menus = array();
$alerts = array();
if ($user->isLoggedIn()) {
list($menu, $dropdown) = $this->renderNotificationMenu();
$alerts[] = $menu;
$menus[] = $dropdown;
}
$phabricator_menu = $this->renderPhabricatorMenu();
if ($alerts) {
$alerts = phutil_render_tag(
'div',
array(
'class' => 'phabricator-main-menu-alerts',
),
self::renderSingleView($alerts));
}
$application_menu = $this->getApplicationMenu();
if ($application_menu) {
$application_menu->addClass('phabricator-dark-menu');
$application_menu->addClass('phabricator-application-menu');
}
return phutil_render_tag(
'div',
array(
'class' => 'phabricator-main-menu',
'id' => $header_id,
),
self::renderSingleView(
array(
$this->renderPhabricatorMenuButton($header_id),
$application_menu
? $this->renderApplicationMenuButton($header_id)
: null,
$this->renderPhabricatorLogo(),
$alerts,
$phabricator_menu,
$application_menu,
))).
self::renderSingleView($menus);
}
private function renderSearch() {
$user = $this->user;
$result = null;
$keyboard_config = array(
'helpURI' => '/help/keyboardshortcut/',
);
if ($user->isLoggedIn()) {
$search = new PhabricatorMainMenuSearchView();
$search->setUser($user);
$search->setScope($this->getDefaultSearchScope());
$result = $search;
$pref_shortcut = PhabricatorUserPreferences::PREFERENCE_SEARCH_SHORTCUT;
if ($user->loadPreferences()->getPreference($pref_shortcut, true)) {
$keyboard_config['searchID'] = $search->getID();
}
}
Javelin::initBehavior('phabricator-keyboard-shortcuts', $keyboard_config);
if ($result) {
$result = id(new PhabricatorMenuItemView())
->addClass('phabricator-main-menu-search')
->appendChild($result);
}
return $result;
}
private function renderPhabricatorMenuButton($header_id) {
return javelin_render_tag(
'a',
array(
'class' => 'phabricator-main-menu-expand-button '.
'phabricator-expand-core-menu',
'sigil' => 'jx-toggle-class',
'meta' => array(
'map' => array(
$header_id => 'phabricator-core-menu-expanded',
),
),
),
phutil_tag(
'span',
array(
'class' => 'phabricator-menu-button-icon sprite-menu menu-icon-eye',
),
''));
}
public function renderApplicationMenuButton($header_id) {
return javelin_render_tag(
'a',
array(
'class' => 'phabricator-main-menu-expand-button '.
'phabricator-expand-application-menu',
'sigil' => 'jx-toggle-class',
'meta' => array(
'map' => array(
$header_id => 'phabricator-application-menu-expanded',
),
),
),
phutil_tag(
'span',
array(
'class' => 'phabricator-menu-button-icon sprite-menu menu-icon-app',
),
''));
}
private function renderPhabricatorMenu() {
$user = $this->getUser();
$controller = $this->getController();
$applications = PhabricatorApplication::getAllInstalledApplications();
$applications = msort($applications, 'getName');
$core = array();
$more = array();
$actions = array();
require_celerity_resource('sprite-apps-large-css');
$group_core = PhabricatorApplication::GROUP_CORE;
foreach ($applications as $application) {
if ($application->shouldAppearInLaunchView()) {
$icon = $application->getIconName().'-light-large';
$item = id(new PhabricatorMenuItemView())
->setName($application->getName())
->setHref($application->getBaseURI())
->appendChild($this->renderMenuIcon($icon));
if ($application->getApplicationGroup() == $group_core) {
$core[] = $item;
} else {
$more[] = $item;
}
}
$app_actions = $application->buildMainMenuItems($user, $controller);
foreach ($app_actions as $action) {
$actions[] = $action;
}
}
$view = new PhabricatorMenuView();
$view->addClass('phabricator-dark-menu');
$view->addClass('phabricator-core-menu');
$search = $this->renderSearch();
$view->appendChild($search);
$view
->newLabel(pht('Home'))
->addClass('phabricator-core-item-device');
$view->addMenuItem(
id(new PhabricatorMenuItemView())
->addClass('phabricator-core-item-device')
->setName(pht('Phabricator Home'))
->setHref('/')
->appendChild($this->renderMenuIcon('logo-light-large')));
if ($controller && $controller->getCurrentApplication()) {
$application = $controller->getCurrentApplication();
$icon = $application->getIconName().'-light-large';
$view->addMenuItem(
id(new PhabricatorMenuItemView())
->addClass('phabricator-core-item-device')
->setName(pht('%s Home', $application->getName()))
->appendChild($this->renderMenuIcon($icon))
->setHref($controller->getApplicationURI()));
}
if ($core) {
$view->addMenuItem(
id(new PhabricatorMenuItemView())
->addClass('phabricator-core-item-device')
->setType(PhabricatorMenuItemView::TYPE_LABEL)
->setName(pht('Core Applications')));
foreach ($core as $item) {
$item->addClass('phabricator-core-item-device');
$view->addMenuItem($item);
}
}
if ($actions) {
$actions = msort($actions, 'getSortOrder');
$view->addMenuItem(
id(new PhabricatorMenuItemView())
->addClass('phabricator-core-item-device')
->setType(PhabricatorMenuItemView::TYPE_LABEL)
->setName(pht('Actions')));
foreach ($actions as $action) {
$icon = $action->getIcon();
if ($icon) {
if ($action->getSelected()) {
$action->appendChild($this->renderMenuIcon($icon.'-blue-large'));
} else {
$action->appendChild($this->renderMenuIcon($icon.'-light-large'));
}
}
$view->addMenuItem($action);
}
}
if ($more) {
$view->addMenuItem(
id(new PhabricatorMenuItemView())
->addClass('phabricator-core-item-device')
->setType(PhabricatorMenuItemView::TYPE_LABEL)
->setName(pht('More Applications')));
foreach ($more as $item) {
$item->addClass('phabricator-core-item-device');
$view->addMenuItem($item);
}
}
return $view;
}
private function renderPhabricatorLogo() {
- return phutil_render_tag(
+ return phutil_tag(
'a',
array(
'class' => 'phabricator-main-menu-logo',
'href' => '/',
),
phutil_tag(
'span',
array(
'class' => 'sprite-menu phabricator-main-menu-logo-image',
),
''));
}
private function renderNotificationMenu() {
$user = $this->user;
require_celerity_resource('phabricator-notification-css');
require_celerity_resource('phabricator-notification-menu-css');
require_celerity_resource('sprite-menu-css');
$count_id = celerity_generate_unique_node_id();
$dropdown_id = celerity_generate_unique_node_id();
$bubble_id = celerity_generate_unique_node_id();
$count_number = id(new PhabricatorFeedStoryNotification())
->countUnread($user);
if ($count_number > 999) {
$count_number = "\xE2\x88\x9E";
}
$count_tag = phutil_tag(
'span',
array(
'id' => $count_id,
'class' => 'phabricator-main-menu-alert-count'
),
$count_number);
$icon_tag = phutil_tag(
'span',
array(
'class' => 'sprite-menu phabricator-main-menu-alert-icon',
),
'');
$container_classes = array(
'phabricator-main-menu-alert-bubble',
'sprite-menu',
'alert-notifications',
);
if ($count_number) {
$container_classes[] = 'alert-unread';
}
$bubble_tag = phutil_tag(
'a',
array(
'href' => '/notification/',
'class' => implode(' ', $container_classes),
'id' => $bubble_id,
),
array($icon_tag, $count_tag));
Javelin::initBehavior(
'aphlict-dropdown',
array(
'bubbleID' => $bubble_id,
'countID' => $count_id,
'dropdownID' => $dropdown_id,
));
$notification_dropdown = javelin_render_tag(
'div',
array(
'id' => $dropdown_id,
'class' => 'phabricator-notification-menu',
'sigil' => 'phabricator-notification-menu',
'style' => 'display: none;',
),
'');
return array($bubble_tag, $notification_dropdown);
}
private function renderMenuIcon($name) {
return phutil_tag(
'span',
array(
'class' => 'phabricator-core-menu-icon '.
'sprite-apps-large app-'.$name,
),
'');
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, May 1, 5:27 PM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
109053
Default Alt Text
(73 KB)

Event Timeline