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;
 }