public function execute()
 {
     if (!$this->getUser()->isAllowed(self::$right)) {
         $this->dieUsage('Permission denied', 'permissiondenied');
     }
     $params = $this->extractRequestParams();
     $action = $params['do'];
     $output = array();
     if ($action === 'associate' || $action === 'dissociate') {
         // Group is mandatory only for these two actions
         if (!isset($params['group'])) {
             $this->dieUsageMsg(array('missingparam', 'group'));
         }
         if (!isset($params['aggregategroup'])) {
             $this->dieUsageMsg(array('missingparam', 'aggregategroup'));
         }
         $aggregateGroup = $params['aggregategroup'];
         $subgroups = TranslateMetadata::getSubgroups($aggregateGroup);
         if (count($subgroups) === 0) {
             // For newly created groups the subgroups value might be empty,
             // but check that.
             if (TranslateMetadata::get($aggregateGroup, 'name') === false) {
                 $this->dieUsage('Invalid aggregate message group', 'invalidaggregategroup');
             }
             $subgroups = array();
         }
         $subgroupId = $params['group'];
         $group = MessageGroups::getGroup($subgroupId);
         // Add or remove from the list
         if ($action === 'associate') {
             if (!$group instanceof WikiPageMessageGroup) {
                 $this->dieUsage('Group does not exist or invalid', 'invalidgroup');
             }
             $subgroups[] = $subgroupId;
             $subgroups = array_unique($subgroups);
         } elseif ($action === 'dissociate') {
             // Allow removal of non-existing groups
             $subgroups = array_flip($subgroups);
             unset($subgroups[$subgroupId]);
             $subgroups = array_flip($subgroups);
         }
         TranslateMetadata::setSubgroups($aggregateGroup, $subgroups);
         $logParams = array('aggregategroup' => TranslateMetadata::get($aggregateGroup, 'name'), 'aggregategroup-id' => $aggregateGroup);
         /* Note that to allow removing no longer existing groups from
          * aggregate message groups, the message group object $group
          * might not always be available. In this case we need to fake
          * some title. */
         $title = $group ? $group->getTitle() : Title::newFromText("Special:Translate/{$subgroupId}");
         $entry = new ManualLogEntry('pagetranslation', $action);
         $entry->setPerformer($this->getUser());
         $entry->setTarget($title);
         // @todo
         // $entry->setComment( $comment );
         $entry->setParameters($logParams);
         $logid = $entry->insert();
         $entry->publish($logid);
     } elseif ($action === 'remove') {
         if (!isset($params['aggregategroup'])) {
             $this->dieUsageMsg(array('missingparam', 'aggregategroup'));
         }
         TranslateMetadata::deleteGroup($params['aggregategroup']);
         // @todo Logging
     } elseif ($action === 'add') {
         if (!isset($params['groupname'])) {
             $this->dieUsageMsg(array('missingparam', 'groupname'));
         }
         $name = trim($params['groupname']);
         if (strlen($name) === 0) {
             $this->dieUsage('Invalid aggregate message group name', 'invalidaggregategroupname');
         }
         if (!isset($params['groupdescription'])) {
             $this->dieUsageMsg(array('missingparam', 'groupdescription'));
         }
         $desc = trim($params['groupdescription']);
         $aggregateGroupId = self::generateAggregateGroupId($name);
         // Throw error if group already exists
         $nameExists = MessageGroups::labelExists($name);
         if ($nameExists) {
             $this->dieUsage('Message group already exists', 'duplicateaggregategroup');
         }
         // ID already exists- Generate a new ID by adding a number to it.
         $idExists = MessageGroups::getGroup($aggregateGroupId);
         if ($idExists) {
             $i = 1;
             while ($idExists) {
                 $tempId = $aggregateGroupId . "-" . $i;
                 $idExists = MessageGroups::getGroup($tempId);
                 $i++;
             }
             $aggregateGroupId = $tempId;
         }
         TranslateMetadata::set($aggregateGroupId, 'name', $name);
         TranslateMetadata::set($aggregateGroupId, 'description', $desc);
         TranslateMetadata::setSubgroups($aggregateGroupId, array());
         // Once new aggregate group added, we need to show all the pages that can be added to that.
         $output['groups'] = self::getAllPages();
         $output['aggregategroupId'] = $aggregateGroupId;
         // @todo Logging
     } elseif ($action === 'update') {
         if (!isset($params['groupname'])) {
             $this->dieUsageMsg(array('missingparam', 'groupname'));
         }
         $name = trim($params['groupname']);
         if (strlen($name) === 0) {
             $this->dieUsage('Invalid aggregate message group name', 'invalidaggregategroupname');
         }
         $desc = trim($params['groupdescription']);
         $aggregateGroupId = $params['aggregategroup'];
         $oldName = TranslateMetadata::get($aggregateGroupId, 'name');
         $oldDesc = TranslateMetadata::get($aggregateGroupId, 'description');
         // Error if the label exists already
         $exists = MessageGroups::labelExists($name);
         if ($exists && $oldName !== $name) {
             $this->dieUsage('Message group name already exists', 'duplicateaggregategroup');
         }
         if ($oldName === $name && $oldDesc === $desc) {
             $this->dieUsage('Invalid update', 'invalidupdate');
         }
         TranslateMetadata::set($aggregateGroupId, 'name', $name);
         TranslateMetadata::set($aggregateGroupId, 'description', $desc);
     }
     // If we got this far, nothing has failed
     $output['result'] = 'ok';
     $this->getResult()->addValue(null, $this->getModuleName(), $output);
     // Cache needs to be cleared after any changes to groups
     MessageGroups::singleton()->recache();
     MessageIndexRebuildJob::newJob()->insert();
 }
 /**
  * @param AggregateMessageGroup $parent
  * @return string
  */
 protected function listSubgroups(AggregateMessageGroup $parent)
 {
     $out = '';
     $id = $this->htmlIdForGroup($parent, 'mw-tpa-grouplist-');
     $out = Html::openElement('ol', array('id' => $id));
     // Not calling $parent->getGroups() because it has done filtering already
     $subgroupIds = TranslateMetadata::getSubgroups($parent->getId());
     // Get the respective groups and sort them
     $subgroups = MessageGroups::getGroupsById($subgroupIds);
     uasort($subgroups, array('MessageGroups', 'groupLabelSort'));
     // Add missing invalid group ids back, not returned by getGroupsById
     foreach ($subgroupIds as $id) {
         if (!isset($subgroups[$id])) {
             $subgroups[$id] = null;
         }
     }
     foreach ($subgroups as $id => $group) {
         $remove = '';
         if ($this->hasPermission) {
             $remove = Html::element('span', array('class' => 'tp-aggregate-remove-button', 'data-groupid' => $id));
         }
         if ($group) {
             $text = Linker::linkKnown($group->getTitle());
             $note = MessageGroups::getPriority($id);
         } else {
             $text = htmlspecialchars($id);
             $note = $this->msg('tpt-aggregategroup-invalid-group')->escaped();
         }
         $out .= Html::rawElement('li', array(), "{$text}{$remove} {$note}");
     }
     $out .= Html::closeElement('ol');
     return $out;
 }
 /**
  * Get all the aggregate messages groups defined in translate_metadata table.
  *
  * @return array
  */
 protected static function loadAggregateGroups()
 {
     $dbw = wfGetDB(DB_MASTER);
     $tables = array('translate_metadata');
     $fields = array('tmd_group', 'tmd_value');
     $conds = array('tmd_key' => 'subgroups');
     $res = $dbw->select($tables, $fields, $conds, __METHOD__);
     $groups = array();
     foreach ($res as $row) {
         $id = $row->tmd_group;
         $conf = array();
         $conf['BASIC'] = array('id' => $id, 'label' => TranslateMetadata::get($id, 'name'), 'description' => TranslateMetadata::get($id, 'description'), 'meta' => 1, 'class' => 'AggregateMessageGroup', 'namespace' => NS_TRANSLATIONS);
         $conf['GROUPS'] = TranslateMetadata::getSubgroups($id);
         $group = MessageGroupBase::factory($conf);
         $groups[$id] = $group;
     }
     return $groups;
 }