Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/config/custom/PhabricatorConfigJSONOptionType.php b/src/applications/config/custom/PhabricatorConfigJSONOptionType.php
index 84d4ad2441..521424a9ea 100644
--- a/src/applications/config/custom/PhabricatorConfigJSONOptionType.php
+++ b/src/applications/config/custom/PhabricatorConfigJSONOptionType.php
@@ -1,50 +1,43 @@
<?php
abstract class PhabricatorConfigJSONOptionType
extends PhabricatorConfigOptionType {
public function readRequest(
PhabricatorConfigOption $option,
AphrontRequest $request) {
$e_value = null;
$errors = array();
$storage_value = $request->getStr('value');
$display_value = $request->getStr('value');
if (strlen($display_value)) {
- $storage_value = phutil_json_decode($display_value);
- if ($storage_value === null) {
+ try {
+ $storage_value = phutil_json_decode($display_value);
+ $this->validateOption($option, $storage_value);
+ } catch (Exception $ex) {
$e_value = pht('Invalid');
- $errors[] = pht(
- 'Configuration value should be specified in JSON. The provided '.
- 'value is not valid JSON.');
- } else {
- try {
- $this->validateOption($option, $storage_value);
- } catch (Exception $ex) {
- $e_value = pht('Invalid');
- $errors[] = $ex->getMessage();
- }
+ $errors[] = $ex->getMessage();
}
} else {
$storage_value = null;
}
return array($e_value, $errors, $storage_value, $display_value);
}
public function renderControl(
PhabricatorConfigOption $option,
$display_value,
$e_value) {
return id(new AphrontFormTextAreaControl())
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
->setName('value')
->setLabel(pht('Value'))
->setValue($display_value)
->setError($e_value);
}
}
diff --git a/src/applications/dashboard/paneltype/PhabricatorDashboardPanelTypeTabs.php b/src/applications/dashboard/paneltype/PhabricatorDashboardPanelTypeTabs.php
index a0c16aa5f3..3a2318841a 100644
--- a/src/applications/dashboard/paneltype/PhabricatorDashboardPanelTypeTabs.php
+++ b/src/applications/dashboard/paneltype/PhabricatorDashboardPanelTypeTabs.php
@@ -1,129 +1,126 @@
<?php
final class PhabricatorDashboardPanelTypeTabs
extends PhabricatorDashboardPanelType {
public function getPanelTypeKey() {
return 'tabs';
}
public function getPanelTypeName() {
return pht('Tab Panel');
}
public function getPanelTypeDescription() {
return pht(
'Use tabs to switch between several other panels.');
}
public function getFieldSpecifications() {
return array(
'config' => array(
'name' => pht('Tabs'),
'type' => 'dashboard.tabs',
),
);
}
public function shouldRenderAsync() {
// The actual tab panel itself is cheap to render.
return false;
}
public function renderPanelContent(
PhabricatorUser $viewer,
PhabricatorDashboardPanel $panel,
PhabricatorDashboardPanelRenderingEngine $engine) {
$config = $panel->getProperty('config');
if (!is_array($config)) {
// NOTE: The older version of this panel stored raw JSON.
- $config = phutil_json_decode($config, null);
- if ($config === null) {
- throw new Exception(pht('The configuration is not valid JSON.'));
- }
+ $config = phutil_json_decode($config);
}
$list = id(new PHUIListView())
->setType(PHUIListView::NAVBAR_LIST);
$selected = 0;
$node_ids = array();
foreach ($config as $idx => $tab_spec) {
$node_ids[$idx] = celerity_generate_unique_node_id();
}
foreach ($config as $idx => $tab_spec) {
$list->addMenuItem(
id(new PHUIListItemView())
->setHref('#')
->setSelected($idx == $selected)
->addSigil('dashboard-tab-panel-tab')
->setMetadata(array('idx' => $idx))
->setName(idx($tab_spec, 'name', pht('Nameless Tab'))));
}
$ids = ipull($config, 'panelID');
if ($ids) {
$panels = id(new PhabricatorDashboardPanelQuery())
->setViewer($viewer)
->withIDs($ids)
->execute();
} else {
$panels = array();
}
$parent_phids = $engine->getParentPanelPHIDs();
$parent_phids[] = $panel->getPHID();
// TODO: Currently, we'll load all the panels on page load. It would be
// vaguely nice to load hidden panels only when the user selects them.
// TODO: Maybe we should persist which panel the user selected, so it
// remains selected across page loads.
$content = array();
$no_headers = PhabricatorDashboardPanelRenderingEngine::HEADER_MODE_NONE;
foreach ($config as $idx => $tab_spec) {
$panel_id = idx($tab_spec, 'panelID');
$panel = idx($panels, $panel_id);
if ($panel) {
$panel_content = id(new PhabricatorDashboardPanelRenderingEngine())
->setViewer($viewer)
->setEnableAsyncRendering(true)
->setParentPanelPHIDs($parent_phids)
->setPanel($panel)
->setHeaderMode($no_headers)
->renderPanel();
} else {
$panel_content = pht('(Invalid Panel)');
}
$content[] = phutil_tag(
'div',
array(
'id' => $node_ids[$idx],
'style' => ($idx == $selected) ? null : 'display: none',
),
$panel_content);
}
Javelin::initBehavior('dashboard-tab-panel');
return javelin_tag(
'div',
array(
'sigil' => 'dashboard-tab-panel-container',
'meta' => array(
'panels' => $node_ids,
),
),
array(
$list,
$content,
));
}
}
diff --git a/src/applications/differential/customfield/DifferentialAuditorsField.php b/src/applications/differential/customfield/DifferentialAuditorsField.php
index c756c1e9e9..1e82075186 100644
--- a/src/applications/differential/customfield/DifferentialAuditorsField.php
+++ b/src/applications/differential/customfield/DifferentialAuditorsField.php
@@ -1,57 +1,61 @@
<?php
final class DifferentialAuditorsField
extends DifferentialStoredCustomField {
public function getFieldKey() {
return 'phabricator:auditors';
}
public function getFieldName() {
return pht('Auditors');
}
public function getFieldDescription() {
return pht('Allows commits to trigger audits explicitly.');
}
public function getValueForStorage() {
return json_encode($this->getValue());
}
public function setValueFromStorage($value) {
- $this->setValue(phutil_json_decode($value));
+ try {
+ $this->setValue(phutil_json_decode($value));
+ } catch (PhutilJSONParserException $ex) {
+ $this->setValue(array());
+ }
return $this;
}
public function shouldAppearInCommitMessage() {
return true;
}
public function shouldAllowEditInCommitMessage() {
return true;
}
public function canDisableField() {
return false;
}
public function getRequiredHandlePHIDsForCommitMessage() {
return nonempty($this->getValue(), array());
}
public function parseCommitMessageValue($value) {
return $this->parseObjectList(
$value,
array(
PhabricatorPeoplePHIDTypeUser::TYPECONST,
PhabricatorProjectPHIDTypeProject::TYPECONST,
));
}
public function renderCommitMessageValue(array $handles) {
return $this->renderObjectList($handles);
}
}
diff --git a/src/applications/differential/customfield/DifferentialJIRAIssuesField.php b/src/applications/differential/customfield/DifferentialJIRAIssuesField.php
index d179952bd4..12c7ea9ebb 100644
--- a/src/applications/differential/customfield/DifferentialJIRAIssuesField.php
+++ b/src/applications/differential/customfield/DifferentialJIRAIssuesField.php
@@ -1,310 +1,314 @@
<?php
final class DifferentialJIRAIssuesField
extends DifferentialStoredCustomField {
private $error;
public function getFieldKey() {
return 'phabricator:jira-issues';
}
public function getFieldKeyForConduit() {
return 'jira.issues';
}
public function isFieldEnabled() {
return (bool)PhabricatorAuthProviderOAuth1JIRA::getJIRAProvider();
}
public function canDisableField() {
return false;
}
public function getValueForStorage() {
return json_encode($this->getValue());
}
public function setValueFromStorage($value) {
- $this->setValue(phutil_json_decode($value));
+ try {
+ $this->setValue(phutil_json_decode($value));
+ } catch (PhutilJSONParserException $ex) {
+ $this->setValue(array());
+ }
return $this;
}
public function getFieldName() {
return pht('JIRA Issues');
}
public function getFieldDescription() {
return pht('Lists associated JIRA issues.');
}
public function shouldAppearInPropertyView() {
return true;
}
public function renderPropertyViewLabel() {
return $this->getFieldName();
}
public function renderPropertyViewValue(array $handles) {
$xobjs = $this->loadDoorkeeperExternalObjects($this->getValue());
if (!$xobjs) {
return null;
}
$links = array();
foreach ($xobjs as $xobj) {
$links[] = id(new DoorkeeperTagView())
->setExternalObject($xobj);
}
return phutil_implode_html(phutil_tag('br'), $links);
}
private function buildDoorkeeperRefs($value) {
$provider = PhabricatorAuthProviderOAuth1JIRA::getJIRAProvider();
$refs = array();
if ($value) {
foreach ($value as $jira_key) {
$refs[] = id(new DoorkeeperObjectRef())
->setApplicationType(DoorkeeperBridgeJIRA::APPTYPE_JIRA)
->setApplicationDomain($provider->getProviderDomain())
->setObjectType(DoorkeeperBridgeJIRA::OBJTYPE_ISSUE)
->setObjectID($jira_key);
}
}
return $refs;
}
private function loadDoorkeeperExternalObjects($value) {
$refs = $this->buildDoorkeeperRefs($value);
if (!$refs) {
return array();
}
$xobjs = id(new DoorkeeperExternalObjectQuery())
->setViewer($this->getViewer())
->withObjectKeys(mpull($refs, 'getObjectKey'))
->execute();
return $xobjs;
}
public function shouldAppearInEditView() {
return PhabricatorAuthProviderOAuth1JIRA::getJIRAProvider();
}
public function shouldAppearInApplicationTransactions() {
return PhabricatorAuthProviderOAuth1JIRA::getJIRAProvider();
}
public function readValueFromRequest(AphrontRequest $request) {
$this->setValue($request->getStrList($this->getFieldKey()));
return $this;
}
public function renderEditControl(array $handles) {
return id(new AphrontFormTextControl())
->setLabel(pht('JIRA Issues'))
->setCaption(
pht('Example: %s', phutil_tag('tt', array(), 'JIS-3, JIS-9')))
->setName($this->getFieldKey())
->setValue(implode(', ', nonempty($this->getValue(), array())))
->setError($this->error);
}
public function getOldValueForApplicationTransactions() {
return array_unique(nonempty($this->getValue(), array()));
}
public function getNewValueForApplicationTransactions() {
return array_unique(nonempty($this->getValue(), array()));
}
public function validateApplicationTransactions(
PhabricatorApplicationTransactionEditor $editor,
$type,
array $xactions) {
$this->error = null;
$errors = parent::validateApplicationTransactions(
$editor,
$type,
$xactions);
$transaction = null;
foreach ($xactions as $xaction) {
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
$add = array_diff($new, $old);
if (!$add) {
continue;
}
// Only check that the actor can see newly added JIRA refs. You're
// allowed to remove refs or make no-op changes even if you aren't
// linked to JIRA.
try {
$refs = id(new DoorkeeperImportEngine())
->setViewer($this->getViewer())
->setRefs($this->buildDoorkeeperRefs($add))
->setThrowOnMissingLink(true)
->execute();
} catch (DoorkeeperMissingLinkException $ex) {
$this->error = pht('Not Linked');
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Not Linked'),
pht(
'You can not add JIRA issues (%s) to this revision because your '.
'Phabricator account is not linked to a JIRA account.',
implode(', ', $add)),
$xaction);
continue;
}
$bad = array();
foreach ($refs as $ref) {
if (!$ref->getIsVisible()) {
$bad[] = $ref->getObjectID();
}
}
if ($bad) {
$bad = implode(', ', $bad);
$this->error = pht('Invalid');
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Some JIRA issues could not be loaded. They may not exist, or '.
'you may not have permission to view them: %s',
$bad),
$xaction);
}
}
return $errors;
}
public function getApplicationTransactionTitle(
PhabricatorApplicationTransaction $xaction) {
$old = $xaction->getOldValue();
if (!is_array($old)) {
$old = array();
}
$new = $xaction->getNewValue();
if (!is_array($new)) {
$new = array();
}
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
$author_phid = $xaction->getAuthorPHID();
if ($add && $rem) {
return pht(
'%s updated JIRA issue(s): added %d %s; removed %d %s.',
$xaction->renderHandleLink($author_phid),
new PhutilNumber(count($add)),
implode(', ', $add),
new PhutilNumber(count($rem)),
implode(', ', $rem));
} else if ($add) {
return pht(
'%s added %d JIRA issue(s): %s.',
$xaction->renderHandleLink($author_phid),
new PhutilNumber(count($add)),
implode(', ', $add));
} else if ($rem) {
return pht(
'%s removed %d JIRA issue(s): %s.',
$xaction->renderHandleLink($author_phid),
new PhutilNumber(count($rem)),
implode(', ', $rem));
}
return parent::getApplicationTransactionTitle($xaction);
}
public function applyApplicationTransactionExternalEffects(
PhabricatorApplicationTransaction $xaction) {
// Update the CustomField storage.
parent::applyApplicationTransactionExternalEffects($xaction);
// Now, synchronize the Doorkeeper edges.
$revision = $this->getObject();
$revision_phid = $revision->getPHID();
$edge_type = PhabricatorEdgeConfig::TYPE_PHOB_HAS_JIRAISSUE;
$xobjs = $this->loadDoorkeeperExternalObjects($xaction->getNewValue());
$edge_dsts = mpull($xobjs, 'getPHID');
$edges = PhabricatorEdgeQuery::loadDestinationPHIDs(
$revision_phid,
$edge_type);
$editor = id(new PhabricatorEdgeEditor())
->setActor($this->getViewer());
foreach (array_diff($edges, $edge_dsts) as $rem_edge) {
$editor->removeEdge($revision_phid, $edge_type, $rem_edge);
}
foreach (array_diff($edge_dsts, $edges) as $add_edge) {
$editor->addEdge($revision_phid, $edge_type, $add_edge);
}
$editor->save();
}
public function shouldAppearInCommitMessage() {
return true;
}
public function shouldAppearInCommitMessageTemplate() {
return true;
}
public function getCommitMessageLabels() {
return array(
'JIRA',
'JIRA Issues',
'JIRA Issue',
);
}
public function parseValueFromCommitMessage($value) {
return preg_split('/[\s,]+/', $value, $limit = -1, PREG_SPLIT_NO_EMPTY);
}
public function readValueFromCommitMessage($value) {
$this->setValue($value);
return $this;
}
public function renderCommitMessageValue(array $handles) {
$value = $this->getValue();
if (!$value) {
return null;
}
return implode(', ', $value);
}
public function shouldAppearInConduitDictionary() {
return true;
}
}
diff --git a/src/applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php b/src/applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php
index 1f177fae1b..8396237bc5 100644
--- a/src/applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php
+++ b/src/applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php
@@ -1,65 +1,58 @@
<?php
final class DifferentialCommitMessageParserTestCase
extends PhabricatorTestCase {
public function testDifferentialCommitMessageParser() {
$dir = dirname(__FILE__).'/messages/';
$list = Filesystem::listDirectory($dir, $include_hidden = false);
foreach ($list as $file) {
if (!preg_match('/.txt$/', $file)) {
continue;
}
$data = Filesystem::readFile($dir.$file);
$divider = "~~~~~~~~~~\n";
$parts = explode($divider, $data);
if (count($parts) !== 4) {
throw new Exception(
pht(
'Expected test file "%s" to contain four parts (message, fields, '.
'output, errors) divided by "~~~~~~~~~~".',
$file));
}
list($message, $fields, $output, $errors) = $parts;
- $fields = phutil_json_decode($fields, null);
- $output = phutil_json_decode($output, null);
- $errors = phutil_json_decode($errors, null);
-
- if ($fields === null || $output === null || $errors === null) {
- throw new Exception(
- pht(
- 'Expected test file "%s" to contain valid JSON in its sections.',
- $file));
- }
+ $fields = phutil_json_decode($fields);
+ $output = phutil_json_decode($output);
+ $errors = phutil_json_decode($errors);
$parser = id(new DifferentialCommitMessageParser())
->setLabelMap($fields)
->setTitleKey('title')
->setSummaryKey('summary');
$result_output = $parser->parseCorpus($message);
$result_errors = $parser->getErrors();
$this->assertEqual($output, $result_output);
$this->assertEqual($errors, $result_errors);
}
}
public function testDifferentialCommitMessageParserNormalization() {
$map = array(
'Test Plan' => 'test plan',
'REVIEWERS' => 'reviewers',
'sUmmArY' => 'summary',
);
foreach ($map as $input => $expect) {
$this->assertEqual(
$expect,
DifferentialCommitMessageParser::normalizeFieldLabel($input),
pht('Field normalization of label "%s".', $input));
}
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Dec 2, 5:09 AM (21 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
431657
Default Alt Text
(18 KB)

Event Timeline