public function execute()
 {
     $user = $this->getUser();
     $requestParams = $this->extractRequestParams();
     $group = MessageGroups::getGroup($requestParams['group']);
     $code = $requestParams['language'];
     if (!$group || MessageGroups::isDynamic($group)) {
         $this->dieUsageMsg(array('missingparam', 'group'));
     }
     $stateConfig = $group->getMessageGroupStates()->getStates();
     if (!$stateConfig) {
         $this->dieUsage('Message group review not in use', 'disabled');
     }
     if (!$user->isAllowed(self::$right)) {
         $this->dieUsage('Permission denied', 'permissiondenied');
     }
     if ($user->isBlocked()) {
         $this->dieUsage('You have been blocked', 'blocked');
     }
     $requestParams = $this->extractRequestParams();
     $languages = Language::fetchLanguageNames();
     if (!isset($languages[$code])) {
         $this->dieUsageMsg(array('missingparam', 'language'));
     }
     $targetState = $requestParams['state'];
     if (!isset($stateConfig[$targetState])) {
         $this->dieUsage('The requested state is invalid', 'invalidstate');
     }
     if (is_array($stateConfig[$targetState]) && isset($stateConfig[$targetState]['right']) && !$user->isAllowed($stateConfig[$targetState]['right'])) {
         $this->dieUsage('Permission denied', 'permissiondenied');
     }
     self::changeState($group, $code, $targetState, $user);
     $output = array('review' => array('group' => $group->getId(), 'language' => $code, 'state' => $targetState));
     $this->getResult()->addValue(null, $this->getModuleName(), $output);
 }
 protected function getData()
 {
     $params = $this->extractRequestParams();
     $group = MessageGroups::getGroup($params['group']);
     if (!$group) {
         $this->dieUsageMsg(array('missingparam', 'mcgroup'));
     } elseif (MessageGroups::isDynamic($group)) {
         $this->dieUsage('Dynamic message groups are not supported here', 'invalidparam');
     }
     return MessageGroupStats::forGroup($group->getId());
 }
 protected function isValidValue($value)
 {
     $group = MessageGroups::getGroup($value);
     if ($group) {
         if (MessageGroups::isDynamic($group)) {
             /* Dynamic groups are not listed, but it is possible to end up
              * on this page with a dynamic group by navigating from
              * translation or proofreading activity or by giving group id
              * of dynamic group explicitly. Ignore dynamic group to avoid
              * throwing exceptions later. */
             $group = false;
         } else {
             $this->target = $group->getId();
         }
     }
     return (bool) $group;
 }
 public function output()
 {
     if (MessageGroups::isDynamic($this->group)) {
         return 'Not supported';
     }
     $ffs = null;
     if ($this->group instanceof FileBasedMessageGroup) {
         $ffs = $this->group->getFFS();
     }
     if (!$ffs instanceof GettextFFS) {
         $group = FileBasedMessageGroup::newFromMessageGroup($this->group);
         $ffs = new GettextFFS($group);
     }
     $ffs->setOfflineMode('true');
     $code = $this->options['language'];
     $id = $this->group->getID();
     $filename = "{$id}_{$code}.po";
     header("Content-Disposition: attachment; filename=\"{$filename}\"");
     return $ffs->writeIntoVariable($this->collection);
 }
 protected function setup($parameters)
 {
     $request = $this->getRequest();
     $isBeta = self::isBeta($request);
     $defaults = array('taction' => 'translate', 'task' => $isBeta ? 'custom' : 'untranslated', 'language' => $this->getLanguage()->getCode(), 'group' => $isBeta ? '!additions' : '', 'offset' => '', 'limit' => $isBeta ? 0 : 100, 'optional' => '0');
     // Dump everything here
     $nondefaults = array();
     $parameters = array_map('trim', explode(';', $parameters));
     $pars = array();
     foreach ($parameters as $_) {
         if ($_ === '') {
             continue;
         }
         if (strpos($_, '=') !== false) {
             list($key, $value) = array_map('trim', explode('=', $_, 2));
         } else {
             $key = 'group';
             $value = $_;
         }
         $pars[$key] = $value;
     }
     foreach ($defaults as $v => $t) {
         if (is_bool($t)) {
             $r = isset($pars[$v]) ? (bool) $pars[$v] : $defaults[$v];
             $r = $request->getBool($v, $r);
         } elseif (is_int($t)) {
             $r = isset($pars[$v]) ? (int) $pars[$v] : $defaults[$v];
             $r = $request->getInt($v, $r);
         } elseif (is_string($t)) {
             $r = isset($pars[$v]) ? (string) $pars[$v] : $defaults[$v];
             $r = $request->getText($v, $r);
         }
         if (!isset($r)) {
             throw new MWException('$r was not set');
         }
         wfAppendToArrayIfNotDefault($v, $r, $defaults, $nondefaults);
     }
     // Fix defaults based on what we got
     if (isset($nondefaults['taction'])) {
         if ($nondefaults['taction'] === 'proofread') {
             if ($this->getUser()->isAllowed('translate-messagereview')) {
                 $defaults['task'] = 'acceptqueue';
             } else {
                 $defaults['task'] = 'reviewall';
             }
         } elseif ($nondefaults['taction'] === 'export') {
             $defaults['task'] = '';
         }
     }
     if ($isBeta) {
         /* @todo fix all the places in Translate to create correct links.
          * The least effort way is to change them once we totally drop the
          * old UI. The penalty is only http redirect in some cases. More
          * effort would be to create utilities like makeTranslationLink
          * and makeProofreadLink.
          */
         $this->rewriteLegacyUrls($nondefaults);
     }
     $this->defaults = $defaults;
     $this->nondefaults = $nondefaults;
     Hooks::run('TranslateGetSpecialTranslateOptions', array(&$defaults, &$nondefaults));
     $this->options = $nondefaults + $defaults;
     $this->group = MessageGroups::getGroup($this->options['group']);
     if ($this->group) {
         $this->options['group'] = $this->group->getId();
     }
     $this->task = TranslateTasks::getTask($this->options['task']);
     if ($this->group && MessageGroups::isDynamic($this->group)) {
         $this->group->setLanguage($this->options['language']);
     }
 }
 /**
  * @param $resultPageSet ApiPageSet
  */
 private function run($resultPageSet = null)
 {
     $params = $this->extractRequestParams();
     $group = MessageGroups::getGroup($params['group']);
     if (!$group) {
         $this->dieUsageMsg(array('missingparam', 'mcgroup'));
     }
     if (MessageGroups::isDynamic($group)) {
         /**
          * @var RecentMessageGroup $group
          */
         $group->setLanguage($params['language']);
     }
     $result = $this->getResult();
     $languages = $group->getTranslatableLanguages();
     if ($languages !== null && !isset($languages[$params['language']])) {
         $this->dieUsage('Translation to this language is disabled', 'translate-language-disabled');
     }
     $messages = $group->initCollection($params['language']);
     foreach ($params['filter'] as $filter) {
         $value = null;
         if (strpos($filter, ':') !== false) {
             list($filter, $value) = explode(':', $filter, 2);
         }
         /* The filtering params here are swapped wrt MessageCollection.
          * There (fuzzy) means do not show fuzzy, which is the same as !fuzzy
          * here and fuzzy here means (fuzzy, false) there. */
         try {
             if ($filter[0] === '!') {
                 $messages->filter(substr($filter, 1), true, $value);
             } else {
                 $messages->filter($filter, false, $value);
             }
         } catch (MWException $e) {
             $this->dieUsage($e->getMessage(), 'invalidfilter');
         }
     }
     $resultSize = count($messages);
     $offsets = $messages->slice($params['offset'], $params['limit']);
     $batchSize = count($messages);
     list(, $forwardsOffset, $startOffset) = $offsets;
     $result->addValue(array('query', 'metadata'), 'state', self::getWorkflowState($group->getId(), $params['language']));
     $result->addValue(array('query', 'metadata'), 'resultsize', $resultSize);
     $result->addValue(array('query', 'metadata'), 'remaining', $resultSize - $startOffset - $batchSize);
     $messages->loadTranslations();
     $pages = array();
     if ($forwardsOffset !== false) {
         $this->setContinueEnumParameter('offset', $forwardsOffset);
     }
     $props = array_flip($params['prop']);
     /** @var Title $title */
     foreach ($messages->keys() as $mkey => $title) {
         if (is_null($resultPageSet)) {
             $data = $this->extractMessageData($result, $props, $messages[$mkey]);
             $data['title'] = $title->getPrefixedText();
             $result->addValue(array('query', $this->getModuleName()), null, $data);
         } else {
             $pages[] = $title;
         }
     }
     if (is_null($resultPageSet)) {
         if (defined('ApiResult::META_CONTENT')) {
             $result->addIndexedTagName(array('query', $this->getModuleName()), 'message');
         } else {
             $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'message');
         }
     } else {
         $resultPageSet->populateFromTitles($pages);
     }
 }
 /**
  * Get the workflow states applicable to the given message group
  *
  * @param MessageGroup $group
  * @return boolean|array Associative array with states as key and localized state
  * labels as values
  */
 protected function getWorkflowStates(MessageGroup $group)
 {
     if (MessageGroups::isDynamic($group)) {
         return false;
     }
     $stateConfig = $group->getMessageGroupStates()->getStates();
     if (!is_array($stateConfig) || $stateConfig === array()) {
         return false;
     }
     $user = $this->getUser();
     foreach ($stateConfig as $state => $config) {
         if (is_array($config)) {
             // Check if user is allowed to change states generally
             $allowed = $user->isAllowed('translate-groupreview');
             // Check further restrictions
             if ($allowed && isset($config['right'])) {
                 $allowed = $user->isAllowed($config['right']);
             }
             if ($allowed) {
                 $stateConfig[$state]['canchange'] = 1;
             }
             $stateConfig[$state]['name'] = $this->msg("translate-workflow-state-{$state}")->text();
         }
     }
     return $stateConfig;
 }
 /**
  * Returns stats for given group in given language.
  * @param $id string Group id
  * @param $code string Language code
  * @return null[]|int[]
  */
 public static function forItem($id, $code)
 {
     $res = self::selectRowsIdLang($id, $code);
     $stats = self::extractResults($res);
     /* In case some code calls this for dynamic groups, return the default
      * values for unknown/incomplete stats. Calculating these numbers don't
      * make sense for dynamic groups, and would just throw an exception. */
     $group = MessageGroups::getGroup($id);
     if (MessageGroups::isDynamic($group)) {
         $stats[$id][$code] = self::getUnknownStats();
     }
     if (!isset($stats[$id][$code])) {
         $stats[$id][$code] = self::forItemInternal($stats, $group, $code);
     }
     self::queueUpdates();
     return $stats[$id][$code];
 }
 protected function getWorkflowStatus()
 {
     global $wgTranslateWorkflowStates, $wgUser;
     if (!$wgTranslateWorkflowStates) {
         return false;
     }
     if (MessageGroups::isDynamic($this->group)) {
         return false;
     }
     $dbr = wfGetDB(DB_SLAVE);
     $current = $dbr->selectField('translate_groupreviews', 'tgr_state', array('tgr_group' => $this->options['group'], 'tgr_lang' => $this->options['language']), __METHOD__);
     if ($wgUser->isAllowed('translate-groupreview')) {
         $selector = new XmlSelect('workflow');
         $selector->setAttribute('class', 'mw-translate-workflowselector');
         $selector->setDefault($current);
         $selector->addOption(wfMessage('translate-workflow-state-')->text(), '');
         foreach (array_keys($wgTranslateWorkflowStates) as $state) {
             $stateMessage = wfMessage("translate-workflow-state-{$state}");
             $stateText = $stateMessage->isBlank() ? $state : $stateMessage->text();
             $selector->addOption($stateText, $state);
         }
         $state = $selector->getHTML();
         $attributes = array('type' => 'button', 'id' => 'mw-translate-workflowset', 'data-token' => ApiGroupReview::getToken(0, ''), 'data-group' => $this->options['group'], 'data-language' => $this->options['language'], 'style' => 'visibility: hidden;', 'value' => 'Set');
         $state .= Html::element('input', $attributes);
     } elseif (strval($current) !== '') {
         $state = $current;
     } else {
         $state = wfMessage('translate-workflow-state-')->escaped();
     }
     $message = wfMessage('translate-workflowstatus')->rawParams($state);
     $box = Html::rawElement('div', array('id' => 'mw-sp-translate-workflow'), $message->escaped());
     return $box;
 }