Path: blob/master/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php
12242 views
<?php12/**3* Common code for standard field types which store lists of PHIDs.4*/5abstract class PhabricatorStandardCustomFieldPHIDs6extends PhabricatorStandardCustomField {78public function buildFieldIndexes() {9$indexes = array();1011$value = $this->getFieldValue();12if (is_array($value)) {13foreach ($value as $phid) {14$indexes[] = $this->newStringIndex($phid);15}16}1718return $indexes;19}2021public function readValueFromRequest(AphrontRequest $request) {22$value = $request->getArr($this->getFieldKey());23$this->setFieldValue($value);24}2526public function getValueForStorage() {27$value = $this->getFieldValue();28if (!$value) {29return null;30}3132return json_encode(array_values($value));33}3435public function setValueFromStorage($value) {36// NOTE: We're accepting either a JSON string (a real storage value) or37// an array (from HTTP parameter prefilling). This is a little hacky, but38// should hold until this can get cleaned up more thoroughly.39// TODO: Clean this up.4041$result = array();42if ($value !== null && !is_array($value)) {43$value = json_decode($value, true);44if (is_array($value)) {45$result = array_values($value);46}47}4849$this->setFieldValue($value);5051return $this;52}5354public function readApplicationSearchValueFromRequest(55PhabricatorApplicationSearchEngine $engine,56AphrontRequest $request) {57return $request->getArr($this->getFieldKey());58}5960public function applyApplicationSearchConstraintToQuery(61PhabricatorApplicationSearchEngine $engine,62PhabricatorCursorPagedPolicyAwareQuery $query,63$value) {64if ($value) {65$query->withApplicationSearchContainsConstraint(66$this->newStringIndex(null),67$value);68}69}7071public function getRequiredHandlePHIDsForPropertyView() {72$value = $this->getFieldValue();73if ($value) {74return $value;75}76return array();77}7879public function renderPropertyViewValue(array $handles) {80$value = $this->getFieldValue();81if (!$value) {82return null;83}8485$handles = mpull($handles, 'renderHovercardLink');86$handles = phutil_implode_html(', ', $handles);87return $handles;88}8990public function getRequiredHandlePHIDsForEdit() {91$value = $this->getFieldValue();92if ($value) {93return $value;94} else {95return array();96}97}9899public function getApplicationTransactionRequiredHandlePHIDs(100PhabricatorApplicationTransaction $xaction) {101102$old = $this->decodeValue($xaction->getOldValue());103$new = $this->decodeValue($xaction->getNewValue());104105$add = array_diff($new, $old);106$rem = array_diff($old, $new);107108return array_merge($add, $rem);109}110111public function getApplicationTransactionTitle(112PhabricatorApplicationTransaction $xaction) {113$author_phid = $xaction->getAuthorPHID();114115$old = $this->decodeValue($xaction->getOldValue());116$new = $this->decodeValue($xaction->getNewValue());117118$add = array_diff($new, $old);119$rem = array_diff($old, $new);120121if ($add && !$rem) {122return pht(123'%s updated %s, added %d: %s.',124$xaction->renderHandleLink($author_phid),125$this->getFieldName(),126phutil_count($add),127$xaction->renderHandleList($add));128} else if ($rem && !$add) {129return pht(130'%s updated %s, removed %s: %s.',131$xaction->renderHandleLink($author_phid),132$this->getFieldName(),133phutil_count($rem),134$xaction->renderHandleList($rem));135} else {136return pht(137'%s updated %s, added %s: %s; removed %s: %s.',138$xaction->renderHandleLink($author_phid),139$this->getFieldName(),140phutil_count($add),141$xaction->renderHandleList($add),142phutil_count($rem),143$xaction->renderHandleList($rem));144}145}146147public function getApplicationTransactionTitleForFeed(148PhabricatorApplicationTransaction $xaction) {149$author_phid = $xaction->getAuthorPHID();150$object_phid = $xaction->getObjectPHID();151152$old = $this->decodeValue($xaction->getOldValue());153$new = $this->decodeValue($xaction->getNewValue());154155$add = array_diff($new, $old);156$rem = array_diff($old, $new);157158if ($add && !$rem) {159return pht(160'%s updated %s for %s, added %d: %s.',161$xaction->renderHandleLink($author_phid),162$this->getFieldName(),163$xaction->renderHandleLink($object_phid),164phutil_count($add),165$xaction->renderHandleList($add));166} else if ($rem && !$add) {167return pht(168'%s updated %s for %s, removed %s: %s.',169$xaction->renderHandleLink($author_phid),170$this->getFieldName(),171$xaction->renderHandleLink($object_phid),172phutil_count($rem),173$xaction->renderHandleList($rem));174} else {175return pht(176'%s updated %s for %s, added %s: %s; removed %s: %s.',177$xaction->renderHandleLink($author_phid),178$this->getFieldName(),179$xaction->renderHandleLink($object_phid),180phutil_count($add),181$xaction->renderHandleList($add),182phutil_count($rem),183$xaction->renderHandleList($rem));184}185}186187public function validateApplicationTransactions(188PhabricatorApplicationTransactionEditor $editor,189$type,190array $xactions) {191192$errors = parent::validateApplicationTransactions(193$editor,194$type,195$xactions);196197// If the user is adding PHIDs, make sure the new PHIDs are valid and198// visible to the actor. It's OK for a user to edit a field which includes199// some invalid or restricted values, but they can't add new ones.200201foreach ($xactions as $xaction) {202$old = $this->decodeValue($xaction->getOldValue());203$new = $this->decodeValue($xaction->getNewValue());204205$add = array_diff($new, $old);206207$invalid = PhabricatorObjectQuery::loadInvalidPHIDsForViewer(208$editor->getActor(),209$add);210211if ($invalid) {212$error = new PhabricatorApplicationTransactionValidationError(213$type,214pht('Invalid'),215pht(216'Some of the selected PHIDs in field "%s" are invalid or '.217'restricted: %s.',218$this->getFieldName(),219implode(', ', $invalid)),220$xaction);221$errors[] = $error;222$this->setFieldError(pht('Invalid'));223}224}225226return $errors;227}228229public function shouldAppearInHerald() {230return true;231}232233public function getHeraldFieldConditions() {234return array(235HeraldAdapter::CONDITION_INCLUDE_ALL,236HeraldAdapter::CONDITION_INCLUDE_ANY,237HeraldAdapter::CONDITION_INCLUDE_NONE,238HeraldAdapter::CONDITION_EXISTS,239HeraldAdapter::CONDITION_NOT_EXISTS,240);241}242243public function getHeraldFieldStandardType() {244return HeraldField::STANDARD_PHID_NULLABLE;245}246247public function getHeraldFieldValue() {248// If the field has a `null` value, make sure we hand an `array()` to249// Herald.250$value = parent::getHeraldFieldValue();251if ($value) {252return $value;253}254return array();255}256257protected function decodeValue($value) {258if ($value === null) {259return array();260}261262$value = json_decode($value);263if (!is_array($value)) {264$value = array();265}266267return $value;268}269270protected function getHTTPParameterType() {271return new AphrontPHIDListHTTPParameterType();272}273274}275276277