public function loadNamedObjects(PhabricatorObjectQuery $query, array $names) { $id_map = array(); foreach ($names as $name) { $id = (int) substr($name, 1); $id_map[$id][] = $name; } $objects = id(new PonderQuestionQuery())->setViewer($query->getViewer())->withIDs(array_keys($id_map))->execute(); $results = array(); foreach ($objects as $id => $object) { foreach (idx($id_map, $id, array()) as $name) { $results[$name] = $object; } } return $results; }
public function loadNamedObjects(PhabricatorObjectQuery $query, array $names) { $id_map = array(); foreach ($names as $name) { $id = substr($name, 1); $id_map[$id][] = $name; } $objects = id(new PhabricatorRepositoryQuery())->setViewer($query->getViewer())->withCallsigns(array_keys($id_map))->execute(); $results = array(); foreach ($objects as $object) { $callsign = $object->getCallsign(); foreach (idx($id_map, $callsign, array()) as $name) { $results[$name] = $object; } } return $results; }
public function loadNamedObjects(PhabricatorObjectQuery $query, array $names) { $id_map = array(); foreach ($names as $name) { // Maybe normalize these some day? $id = $name; $id_map[$id][] = $name; } $objects = id(new PhabricatorMailingListQuery())->setViewer($query->getViewer())->withEmails(array_keys($id_map))->execute(); $results = array(); foreach ($objects as $id => $object) { $email = $object->getEmail(); foreach (idx($id_map, $email, array()) as $name) { $results[$name] = $object; } } return $results; }
public function loadNamedObjects(PhabricatorObjectQuery $query, array $names) { $id_map = array(); foreach ($names as $name) { $id = substr($name, 1); $id = phutil_utf8_strtolower($id); $id_map[$id][] = $name; } $objects = id(new PhabricatorPeopleQuery())->setViewer($query->getViewer())->withUsernames(array_keys($id_map))->execute(); $results = array(); foreach ($objects as $id => $object) { $user_key = $object->getUsername(); $user_key = phutil_utf8_strtolower($user_key); foreach (idx($id_map, $user_key, array()) as $name) { $results[$name] = $object; } } return $results; }
public function loadNamedObjects(PhabricatorObjectQuery $query, array $names) { // If the user types "#YoloSwag", we still want to match "#yoloswag", so // we normalize, query, and then map back to the original inputs. $map = array(); foreach ($names as $key => $slug) { $map[$this->normalizeSlug(substr($slug, 1))][] = $slug; } $projects = id(new PhabricatorProjectQuery())->setViewer($query->getViewer())->withSlugs(array_keys($map))->needSlugs(true)->execute(); $result = array(); foreach ($projects as $project) { $slugs = $project->getSlugs(); $slug_strs = mpull($slugs, 'getSlug'); foreach ($slug_strs as $slug) { $slug_map = idx($map, $slug, array()); foreach ($slug_map as $original) { $result[$original] = $project; } } } return $result; }
public function validateApplicationTransactions(PhabricatorApplicationTransactionEditor $editor, $type, array $xactions) { $errors = parent::validateApplicationTransactions($editor, $type, $xactions); // If the user is adding PHIDs, make sure the new PHIDs are valid and // visible to the actor. It's OK for a user to edit a field which includes // some invalid or restricted values, but they can't add new ones. foreach ($xactions as $xaction) { $old = $this->decodeValue($xaction->getOldValue()); $new = $this->decodeValue($xaction->getNewValue()); $add = array_diff($new, $old); $invalid = PhabricatorObjectQuery::loadInvalidPHIDsForViewer($editor->getActor(), $add); if ($invalid) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Some of the selected PHIDs in field "%s" are invalid or ' . 'restricted: %s.', $this->getFieldName(), implode(', ', $invalid)), $xaction); $errors[] = $error; $this->setFieldError(pht('Invalid')); } } return $errors; }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE: case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY: foreach ($xactions as $xaction) { foreach ($xaction->getNewValue() as $pattern) { // Check for invalid regular expressions. $regexp = PhabricatorRepository::extractBranchRegexp($pattern); if ($regexp !== null) { $ok = @preg_match($regexp, ''); if ($ok === false) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Expression "%s" is not a valid regular expression. Note ' . 'that you must include delimiters.', $regexp), $xaction); $errors[] = $error; continue; } } // Check for formatting mistakes like `regex(...)` instead of // `regexp(...)`. $matches = null; if (preg_match('/^([^(]+)\\(.*\\)\\z/', $pattern, $matches)) { switch ($matches[1]) { case 'regexp': break; default: $error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Matching function "%s(...)" is not recognized. Valid ' . 'functions are: regexp(...).', $matches[1]), $xaction); $errors[] = $error; break; } } } } break; case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI: foreach ($xactions as $xaction) { $new_uri = $xaction->getNewValue(); try { PhabricatorRepository::assertValidRemoteURI($new_uri); } catch (Exception $ex) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), $ex->getMessage(), $xaction); } } break; case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL: $ok = PassphraseCredentialControl::validateTransactions($this->getActor(), $xactions); if (!$ok) { foreach ($xactions as $xaction) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('The selected credential does not exist, or you do not have ' . 'permission to use it.'), $xaction); } } break; case PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS: foreach ($xactions as $xaction) { $old = nonempty($xaction->getOldValue(), array()); $new = nonempty($xaction->getNewValue(), array()); $add = array_diff($new, $old); $invalid = PhabricatorObjectQuery::loadInvalidPHIDsForViewer($this->getActor(), $add); if ($invalid) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Some of the selected automation blueprints are invalid ' . 'or restricted: %s.', implode(', ', $invalid)), $xaction); } } break; case PhabricatorRepositoryTransaction::TYPE_SLUG: foreach ($xactions as $xaction) { $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); if (!strlen($new)) { continue; } if ($new === $old) { continue; } try { PhabricatorRepository::asssertValidRepositorySlug($new); } catch (Exception $ex) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), $ex->getMessage(), $xaction); continue; } $other = id(new PhabricatorRepositoryQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withSlugs(array($new))->executeOne(); if ($other && $other->getID() !== $object->getID()) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Duplicate'), pht('The selected repository short name is already in use by ' . 'another repository. Choose a unique short name.'), $xaction); continue; } } break; } return $errors; }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY: case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY: foreach ($xactions as $xaction) { foreach ($xaction->getNewValue() as $pattern) { // Check for invalid regular expressions. $regexp = PhabricatorRepository::extractBranchRegexp($pattern); if ($regexp !== null) { $ok = @preg_match($regexp, ''); if ($ok === false) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Expression "%s" is not a valid regular expression. Note ' . 'that you must include delimiters.', $regexp), $xaction); $errors[] = $error; continue; } } // Check for formatting mistakes like `regex(...)` instead of // `regexp(...)`. $matches = null; if (preg_match('/^([^(]+)\\(.*\\)\\z/', $pattern, $matches)) { switch ($matches[1]) { case 'regexp': break; default: $error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Matching function "%s(...)" is not recognized. Valid ' . 'functions are: regexp(...).', $matches[1]), $xaction); $errors[] = $error; break; } } } } break; case PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS: foreach ($xactions as $xaction) { $old = nonempty($xaction->getOldValue(), array()); $new = nonempty($xaction->getNewValue(), array()); $add = array_diff($new, $old); $invalid = PhabricatorObjectQuery::loadInvalidPHIDsForViewer($this->getActor(), $add); if ($invalid) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Some of the selected automation blueprints are invalid ' . 'or restricted: %s.', implode(', ', $invalid)), $xaction); } } break; case PhabricatorRepositoryTransaction::TYPE_VCS: $vcs_map = PhabricatorRepositoryType::getAllRepositoryTypes(); $current_vcs = $object->getVersionControlSystem(); if (!$this->getIsNewObject()) { foreach ($xactions as $xaction) { if ($xaction->getNewValue() == $current_vcs) { continue; } $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Immutable'), pht('You can not change the version control system an existing ' . 'repository uses. It can only be set when a repository is ' . 'first created.'), $xaction); } } else { $value = $object->getVersionControlSystem(); foreach ($xactions as $xaction) { $value = $xaction->getNewValue(); if (empty($vcs_map[$value])) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Specified version control system must be a VCS ' . 'recognized by Phabricator: %s.', implode(', ', array_keys($vcs_map))), $xaction); } } if (!strlen($value)) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('When creating a repository, you must specify a valid ' . 'underlying version control system: %s.', implode(', ', array_keys($vcs_map))), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } } break; case PhabricatorRepositoryTransaction::TYPE_NAME: $missing = $this->validateIsEmptyTextField($object->getName(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('Repository name is required.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } break; case PhabricatorRepositoryTransaction::TYPE_ACTIVATE: $status_map = PhabricatorRepository::getStatusMap(); foreach ($xactions as $xaction) { $status = $xaction->getNewValue(); if (empty($status_map[$status])) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Repository status "%s" is not valid.', $status), $xaction); } } break; case PhabricatorRepositoryTransaction::TYPE_ENCODING: foreach ($xactions as $xaction) { // Make sure the encoding is valid by converting to UTF-8. This tests // that the user has mbstring installed, and also that they didn't // type a garbage encoding name. Note that we're converting from // UTF-8 to the target encoding, because mbstring is fine with // converting from a nonsense encoding. $encoding = $xaction->getNewValue(); if (!strlen($encoding)) { continue; } try { phutil_utf8_convert('.', $encoding, 'UTF-8'); } catch (Exception $ex) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Repository encoding "%s" is not valid: %s', $encoding, $ex->getMessage()), $xaction); } } break; case PhabricatorRepositoryTransaction::TYPE_SLUG: foreach ($xactions as $xaction) { $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); if (!strlen($new)) { continue; } if ($new === $old) { continue; } try { PhabricatorRepository::assertValidRepositorySlug($new); } catch (Exception $ex) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), $ex->getMessage(), $xaction); continue; } $other = id(new PhabricatorRepositoryQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withSlugs(array($new))->executeOne(); if ($other && $other->getID() !== $object->getID()) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Duplicate'), pht('The selected repository short name is already in use by ' . 'another repository. Choose a unique short name.'), $xaction); continue; } } break; case PhabricatorRepositoryTransaction::TYPE_CALLSIGN: foreach ($xactions as $xaction) { $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); if (!strlen($new)) { continue; } if ($new === $old) { continue; } try { PhabricatorRepository::assertValidCallsign($new); } catch (Exception $ex) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), $ex->getMessage(), $xaction); continue; } $other = id(new PhabricatorRepositoryQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withCallsigns(array($new))->executeOne(); if ($other && $other->getID() !== $object->getID()) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Duplicate'), pht('The selected callsign ("%s") is already in use by another ' . 'repository. Choose a unique callsign.', $new), $xaction); continue; } } break; case PhabricatorRepositoryTransaction::TYPE_SYMBOLS_SOURCES: foreach ($xactions as $xaction) { $old = $object->getSymbolSources(); $new = $xaction->getNewValue(); // If the viewer is adding new repositories, make sure they are // valid and visible. $add = array_diff($new, $old); if (!$add) { continue; } $repositories = id(new PhabricatorRepositoryQuery())->setViewer($this->getActor())->withPHIDs($add)->execute(); $repositories = mpull($repositories, null, 'getPHID'); foreach ($add as $phid) { if (isset($repositories[$phid])) { continue; } $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Repository ("%s") does not exist, or you do not have ' . 'permission to see it.', $phid), $xaction); break; } } break; } return $errors; }