Index: trunk/extensions/Translate/Translate.php |
— | — | @@ -45,6 +45,7 @@ |
46 | 46 | $wgExtensionMessagesFiles['Translate'] = "$dir/Translate.i18n.php"; |
47 | 47 | $wgExtensionMessagesFiles['FirstSteps'] = "$dir/FirstSteps.i18n.php"; |
48 | 48 | $wgExtensionMessagesFiles['PageTranslation'] = "$dir/PageTranslation.i18n.php"; |
| 49 | +$wgExtensionMessagesFiles['AggregateGroups'] = "$dir/PageTranslation.i18n.php"; |
49 | 50 | $wgExtensionMessagesFiles['TranslateGroupDescriptions'] = "$dir/TranslateGroupDescriptions.i18n.php"; |
50 | 51 | $wgExtensionMessagesFiles['TranslateAlias'] = "$dir/Translate.alias.php"; |
51 | 52 | $wgExtensionMessagesFiles['TranslateMagic'] = "$dir/Translate.magic.php"; |
— | — | @@ -81,6 +82,7 @@ |
82 | 83 | $wgSpecialPages['SupportedLanguages'] = 'SpecialSupportedLanguages'; |
83 | 84 | // Unlisted special page; does not need $wgSpecialPageGroups. |
84 | 85 | $wgSpecialPages['MyLanguage'] = 'SpecialMyLanguage'; |
| 86 | +$wgSpecialPages['AggregateGroups'] = 'SpecialAggregateGroups'; |
85 | 87 | |
86 | 88 | // API |
87 | 89 | $wgAPIListModules['messagecollection'] = 'ApiQueryMessageCollection'; |
— | — | @@ -89,9 +91,11 @@ |
90 | 92 | $wgAPIMetaModules['messagetranslations'] = 'ApiQueryMessageTranslations'; |
91 | 93 | $wgAPIModules['translationreview'] = 'ApiTranslationReview'; |
92 | 94 | $wgAPIModules['groupreview'] = 'ApiGroupReview'; |
| 95 | +$wgAPIModules['aggregategroups'] = 'ApiAggregateGroups'; |
93 | 96 | $wgAPIModules['ttmserver'] = 'ApiTTMServer'; |
94 | 97 | $wgHooks['APIQueryInfoTokens'][] = 'ApiTranslationReview::injectTokenFunction'; |
95 | 98 | $wgHooks['APIQueryInfoTokens'][] = 'ApiGroupReview::injectTokenFunction'; |
| 99 | +$wgHooks['APIQueryInfoTokens'][] = 'ApiAggregateGroups::injectTokenFunction'; |
96 | 100 | |
97 | 101 | // Register hooks. |
98 | 102 | $wgHooks['EditPage::showEditForm:initial'][] = 'TranslateEditAddons::addTools'; |
— | — | @@ -254,6 +258,12 @@ |
255 | 259 | 'position' => 'top', |
256 | 260 | ) + $resourcePaths; |
257 | 261 | |
| 262 | +$wgResourceModules['ext.translate.special.aggregategroups'] = array( |
| 263 | + 'scripts' => 'resources/ext.translate.special.aggregategroups.js', |
| 264 | + 'styles' => 'resources/ext.translate.special.aggregategroups.css', |
| 265 | + 'position' => 'top', |
| 266 | +) + $resourcePaths; |
| 267 | + |
258 | 268 | $wgResourceModules['ext.translate.special.supportedlanguages'] = array( |
259 | 269 | 'styles' => 'resources/ext.translate.special.supportedlanguages.css', |
260 | 270 | 'position' => 'top', |
Index: trunk/extensions/Translate/_autoload.php |
— | — | @@ -54,6 +54,7 @@ |
55 | 55 | * There are few more special pages in page translation section. |
56 | 56 | * @{ |
57 | 57 | */ |
| 58 | +$wgAutoloadClasses['SpecialAggregateGroups'] = "$dir/specials/SpecialAggregateGroups.php"; |
58 | 59 | $wgAutoloadClasses['SpecialFirstSteps'] = "$dir/specials/SpecialFirstSteps.php"; |
59 | 60 | $wgAutoloadClasses['SpecialImportTranslations'] = "$dir/specials/SpecialImportTranslations.php"; |
60 | 61 | $wgAutoloadClasses['SpecialLanguageStats'] = "$dir/specials/SpecialLanguageStats.php"; |
— | — | @@ -180,6 +181,7 @@ |
181 | 182 | * @{ |
182 | 183 | */ |
183 | 184 | $wgAutoloadClasses['ApiGroupReview'] = "$dir/api/ApiGroupReview.php"; |
| 185 | +$wgAutoloadClasses['ApiAggregateGroups'] = "$dir/api/ApiAggregateGroups.php"; |
184 | 186 | $wgAutoloadClasses['ApiQueryMessageCollection'] = "$dir/api/ApiQueryMessageCollection.php"; |
185 | 187 | $wgAutoloadClasses['ApiQueryMessageGroupStats'] = "$dir/api/ApiQueryMessageGroupStats.php"; |
186 | 188 | $wgAutoloadClasses['ApiQueryMessageGroups'] = "$dir/api/ApiQueryMessageGroups.php"; |
Index: trunk/extensions/Translate/PageTranslation.i18n.php |
— | — | @@ -112,6 +112,12 @@ |
113 | 113 | |
114 | 114 | 'tpt-download-page' => 'Export page with translations', |
115 | 115 | |
| 116 | + 'tpt-aggregategroups' => 'Aggregate Groups', |
| 117 | + 'tpt-aggregategroup-add' => 'Add', |
| 118 | + 'tpt-aggregategroup-save' => 'Save', |
| 119 | + 'tpt-aggregategroup-add-new' => 'Add a new aggregate group', |
| 120 | + 'tpt-aggregategroup-new-name' => 'Name:', |
| 121 | + 'tpt-aggregategroup-new-description' => 'Description(optional):', |
116 | 122 | 'pt-parse-open' => 'Unbalanced <translate> tag. |
117 | 123 | Translation template: <pre>$1</pre>', |
118 | 124 | 'pt-parse-close' => 'Unbalanced </translate> tag. |
Index: trunk/extensions/Translate/specials/SpecialAggregateGroups.php |
— | — | @@ -0,0 +1,191 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Contains logic for special page Special:AggregateGroups. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @author Santhosh Thottingal |
| 8 | + * @copyright Copyright © 2012 Santhosh Thottingal |
| 9 | + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later |
| 10 | + */ |
| 11 | + |
| 12 | +class SpecialAggregateGroups extends SpecialPage { |
| 13 | + |
| 14 | + /** |
| 15 | + * @var User |
| 16 | + */ |
| 17 | + protected $user; |
| 18 | + |
| 19 | + function __construct() { |
| 20 | + parent::__construct( 'AggregateGroups' ); |
| 21 | + } |
| 22 | + |
| 23 | + public function execute( $parameters ) { |
| 24 | + $this->setHeaders(); |
| 25 | + |
| 26 | + global $wgRequest, $wgOut, $wgUser; |
| 27 | + $this->user = $wgUser; |
| 28 | + $request = $wgRequest; |
| 29 | + |
| 30 | + // Check permissions |
| 31 | + if ( !$this->user->isAllowed( 'translate-manage' ) ) { |
| 32 | + $wgOut->permissionRequired( 'translate-manage' ); |
| 33 | + return; |
| 34 | + } |
| 35 | + |
| 36 | + // Check permissions |
| 37 | + if ( $wgRequest->wasPosted() && !$this->user->matchEditToken( $wgRequest->getText( 'token' ) ) ) { |
| 38 | + self::superDebug( __METHOD__, "token failure", $this->user ); |
| 39 | + $wgOut->permissionRequired( 'translate-manage' ); |
| 40 | + return; |
| 41 | + } |
| 42 | + $wgOut->setPageTitle( wfMsg( 'tpt-aggregategroups' ) ); |
| 43 | + $this->showAggregateGroups(); |
| 44 | + |
| 45 | + } |
| 46 | + |
| 47 | + public function loadPagesFromDB() { |
| 48 | + $dbr = wfGetDB( DB_MASTER ); |
| 49 | + $tables = array( 'page', 'revtag' ); |
| 50 | + $vars = array( 'page_id', 'page_title', 'page_namespace', 'page_latest', 'MAX(rt_revision) as rt_revision', 'rt_type' ); |
| 51 | + $conds = array( |
| 52 | + 'page_id=rt_page', |
| 53 | + 'rt_type' => array( RevTag::getType( 'tp:mark' ), RevTag::getType( 'tp:tag' ) ), |
| 54 | + ); |
| 55 | + $options = array( |
| 56 | + 'ORDER BY' => 'page_namespace, page_title', |
| 57 | + 'GROUP BY' => 'page_id, rt_type', |
| 58 | + ); |
| 59 | + $res = $dbr->select( $tables, $vars, $conds, __METHOD__, $options ); |
| 60 | + |
| 61 | + return $res; |
| 62 | + } |
| 63 | + |
| 64 | + protected function buildPageArray( /*db result*/ $res ) { |
| 65 | + $pages = array(); |
| 66 | + foreach ( $res as $r ) { |
| 67 | + // We have multiple rows for same page, because of different tags |
| 68 | + if ( !isset( $pages[$r->page_id] ) ) { |
| 69 | + $pages[$r->page_id] = array(); |
| 70 | + $title = Title::newFromRow( $r ); |
| 71 | + $pages[$r->page_id]['title'] = $title; |
| 72 | + $pages[$r->page_id]['latest'] = intval( $title->getLatestRevID() ); |
| 73 | + } |
| 74 | + |
| 75 | + $tag = RevTag::typeToTag( $r->rt_type ); |
| 76 | + $pages[$r->page_id][$tag] = intval( $r->rt_revision ); |
| 77 | + } |
| 78 | + return $pages; |
| 79 | + } |
| 80 | + |
| 81 | + |
| 82 | + protected function showAggregateGroups() { |
| 83 | + global $wgOut; |
| 84 | + $wgOut->addModules( 'ext.translate.special.aggregategroups' ); |
| 85 | + |
| 86 | + $aggregategroups = ApiAggregateGroups::getAggregateGroups( ); |
| 87 | + $res = $this->loadPagesFromDB(); |
| 88 | + $pages = $this->buildPageArray( $res ); |
| 89 | + $pages = $this->filterUnGroupedPages( $pages, $aggregategroups ); |
| 90 | + foreach ( $aggregategroups as $id => $group ) { |
| 91 | + $wgOut->addHtml( "<div id='tpt-aggregate-group'>" ); |
| 92 | + |
| 93 | + $removeSpan = Html::element( 'span', array( |
| 94 | + 'class' => 'tp-aggregate-remove-ag-button', |
| 95 | + 'id' => $id ) ) ; |
| 96 | + $wgOut->addHtml( "<h2 id='$id'>" . $group['name'] . $removeSpan . "</h2>" ); |
| 97 | + |
| 98 | + $wgOut->addHtml( "<p>" . $group['description'] . "</p>" ); |
| 99 | + |
| 100 | + $wgOut->addHtml( "<ol id='tp-aggregate-groups-ol-$id'>" ); |
| 101 | + $subgroups = $group['subgroups']; |
| 102 | + foreach ( $subgroups as $subgroupId => $subgroup ) { |
| 103 | + $removeSpan = Html::element( 'span', array( |
| 104 | + 'class' => 'tp-aggregate-remove-button', |
| 105 | + 'id' => $subgroupId ) ); |
| 106 | + if ( $subgroup ) { |
| 107 | + $wgOut->addHtml( "<li>" . |
| 108 | + Linker::linkKnown( $subgroup->getTitle(), |
| 109 | + null, |
| 110 | + array( 'id' => $subgroupId ) |
| 111 | + ) |
| 112 | + . "$removeSpan </li>" ); |
| 113 | + } |
| 114 | + } |
| 115 | + $wgOut->addHtml( "</ol>" ); |
| 116 | + |
| 117 | + $this->groupSelector ( $pages, $id ); |
| 118 | + $addButton = Html::element( 'input', |
| 119 | + array( 'type' => 'button', |
| 120 | + 'value' => wfMsg( 'tpt-aggregategroup-add' ), |
| 121 | + 'id' => $id, 'class' => 'tp-aggregate-add-button' ) |
| 122 | + ); |
| 123 | + $wgOut->addHtml( $addButton ); |
| 124 | + $wgOut->addHtml( "</div>" ); |
| 125 | + } |
| 126 | + |
| 127 | + |
| 128 | + $wgOut->addHtml( Html::element( 'input', |
| 129 | + array( 'type' => 'hidden', |
| 130 | + 'id' => 'token', |
| 131 | + 'value' => ApiAggregateGroups::getToken( 0, '' ) |
| 132 | + ) ) ); |
| 133 | + $wgOut->addHtml( "<br/><a class='tpt-add-new-group' href='#'>" . |
| 134 | + wfMsg( 'tpt-aggregategroup-add-new' ) . |
| 135 | + "</a>" ); |
| 136 | + $newGroupNameLabel = wfMsg( 'tpt-aggregategroup-new-name' ); |
| 137 | + $newGroupName = Html::element( 'input', array( 'class' => 'tp-aggregategroup-add-name' ) ); |
| 138 | + $newGroupDescriptionLabel = wfMsg( 'tpt-aggregategroup-new-description' ); |
| 139 | + $newGroupDescription = Html::element( 'input', |
| 140 | + array( 'class' => 'tp-aggregategroup-add-description' ) |
| 141 | + ); |
| 142 | + $saveButton = Html::element( 'input', |
| 143 | + array( 'type' => 'button', |
| 144 | + 'value' => wfMsg( 'tpt-aggregategroup-save' ), |
| 145 | + 'id' => 'tpt-aggregategroups-save', 'class' => 'tp-aggregate-save-button' ) |
| 146 | + ); |
| 147 | + $newGroupDiv = Html::rawElement( 'div', |
| 148 | + array( 'class' => 'tpt-add-new-group hidden' ) , |
| 149 | + "$newGroupNameLabel $newGroupName <br/> $newGroupDescriptionLabel $newGroupDescription <br/> $saveButton" ); |
| 150 | + $wgOut->addHtml( $newGroupDiv ); |
| 151 | + } |
| 152 | + |
| 153 | + protected function groupSelector( $pages, $id ) { |
| 154 | + global $wgOut; |
| 155 | + $out = $wgOut; |
| 156 | + if ( !count( $pages ) ) { |
| 157 | + $wgOut->addWikiMsg( 'tpt-list-nopages' ); |
| 158 | + return; |
| 159 | + } |
| 160 | + $options = "\n"; |
| 161 | + if ( count( $pages ) ) { |
| 162 | + foreach ( $pages as $pageId => $page ) { |
| 163 | + $title = $page['title']->getText(); |
| 164 | + $pageid = TranslatablePage::getMessageGroupIdFromTitle( $page['title'] ) ; |
| 165 | + $options .= Xml::option( $title , $pageid, false , array( 'id' => $pageid ) ) . "\n"; |
| 166 | + } |
| 167 | + } |
| 168 | + $selector = Xml::tags( 'select', |
| 169 | + array( |
| 170 | + 'id' => 'tp-aggregate-groups-select-' . $id, |
| 171 | + 'name' => 'group', |
| 172 | + 'class' => 'tp-aggregate-group-chooser', |
| 173 | + ), |
| 174 | + $options |
| 175 | + ); |
| 176 | + $out->addHtml( $selector ); |
| 177 | + } |
| 178 | + |
| 179 | + protected function filterUnGroupedPages( $pages, $aggregategroups ) { |
| 180 | + foreach ( $aggregategroups as $aggregategroup ) { |
| 181 | + $subgroups = $aggregategroup['subgroups']; |
| 182 | + foreach ( $pages as $id => $page ) { |
| 183 | + $pageid = TranslatablePage::getMessageGroupIdFromTitle( $page['title'] ) ; |
| 184 | + if ( isset( $subgroups[$pageid] ) ) { |
| 185 | + unset( $pages[$id] ); |
| 186 | + } |
| 187 | + } |
| 188 | + } |
| 189 | + return $pages; |
| 190 | + } |
| 191 | + |
| 192 | +} |
Property changes on: trunk/extensions/Translate/specials/SpecialAggregateGroups.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 193 | + native |
Index: trunk/extensions/Translate/api/ApiAggregateGroups.php |
— | — | @@ -0,0 +1,187 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * API module for managing aggregate groups |
| 5 | + * @file |
| 6 | + * @author Santhosh Thottingal |
| 7 | + * @copyright Copyright © 2011, Santhosh Thottingal |
| 8 | + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later |
| 9 | + */ |
| 10 | + |
| 11 | +/** |
| 12 | + * API module for managing aggregate groups |
| 13 | + * |
| 14 | + * @ingroup API TranslateAPI |
| 15 | + */ |
| 16 | +class ApiAggregateGroups extends ApiBase { |
| 17 | + protected static $right = 'translate-manage'; |
| 18 | + protected static $salt = 'translate-manage'; |
| 19 | + |
| 20 | + public function execute() { |
| 21 | + global $wgUser; |
| 22 | + |
| 23 | + if ( !$wgUser->isallowed( self::$right ) ) { |
| 24 | + $this->dieUsage( 'Permission denied', 'permissiondenied' ); |
| 25 | + } |
| 26 | + |
| 27 | + $requestParams = $this->extractRequestParams(); |
| 28 | + $aggregateGroup = $requestParams['aggregategroup']; |
| 29 | + if ( $requestParams['do'] === 'associate' ) { |
| 30 | + $group = $requestParams['group']; |
| 31 | + $aggregateGroups = TranslateMetadata::get( $aggregateGroup, 'subgroups' ); |
| 32 | + if ( trim( $aggregateGroups ) ) { |
| 33 | + $aggregateGroups = array_map( 'trim', explode( ',', $aggregateGroups ) ); |
| 34 | + } |
| 35 | + else { |
| 36 | + $aggregateGroups = array(); |
| 37 | + } |
| 38 | + $aggregateGroups[] = $group; |
| 39 | + $aggregateGroups = array_unique( $aggregateGroups ); |
| 40 | + $newSubGroups = implode( ',', $aggregateGroups ); |
| 41 | + TranslateMetadata::set( $aggregateGroup, 'subgroups' , $newSubGroups ) ; |
| 42 | + } |
| 43 | + if ( $requestParams['do'] === 'dissociate' ) { |
| 44 | + $group = $requestParams['group']; |
| 45 | + $aggregateGroups = TranslateMetadata::get( $aggregateGroup, 'subgroups' ); |
| 46 | + $aggregateGroups = array_flip( explode( ',', $aggregateGroups ) ) ; |
| 47 | + if ( isset( $aggregateGroups[$group] ) ) { |
| 48 | + unset( $aggregateGroups[$group] ); |
| 49 | + } |
| 50 | + $aggregateGroups = array_flip( $aggregateGroups ); |
| 51 | + TranslateMetadata::set( $aggregateGroup, 'subgroups' , implode( ',', $aggregateGroups ) ) ; |
| 52 | + } |
| 53 | + if ( $requestParams['do'] === 'remove' ) { |
| 54 | + TranslateMetadata::set( $aggregateGroup, 'subgroups', false ) ; |
| 55 | + TranslateMetadata::set( $aggregateGroup, 'name', false ) ; |
| 56 | + TranslateMetadata::set( $aggregateGroup, 'description', false ) ; |
| 57 | + } |
| 58 | + if ( $requestParams['do'] === 'add' ) { |
| 59 | + TranslateMetadata::set( $aggregateGroup, 'subgroups' , '' ) ; |
| 60 | + if ( trim( $requestParams['groupname'] ) ) { |
| 61 | + TranslateMetadata::set( $aggregateGroup, 'name' , trim( $requestParams['groupname'] ) ) ; |
| 62 | + } |
| 63 | + if ( trim( $requestParams['groupdescription'] ) ) { |
| 64 | + TranslateMetadata::set( $aggregateGroup, 'description' , trim( $requestParams['groupdescription'] ) ) ; |
| 65 | + } |
| 66 | + } |
| 67 | + $output = array( 'result' => 'ok' ); |
| 68 | + $this->getResult()->addValue( null, $this->getModuleName(), $output ); |
| 69 | + } |
| 70 | + |
| 71 | + public function isWriteMode() { |
| 72 | + return true; |
| 73 | + } |
| 74 | + |
| 75 | + public function getTokenSalt() { |
| 76 | + return self::$salt; |
| 77 | + } |
| 78 | + public function needsToken() { |
| 79 | + return true; |
| 80 | + } |
| 81 | + |
| 82 | + public function getAllowedParams() { |
| 83 | + global $wgTranslateWorkflowStates; |
| 84 | + return array( |
| 85 | + 'do' => array( |
| 86 | + ApiBase::PARAM_TYPE => array( 'associate', 'dissociate', 'remove' , 'add' ), |
| 87 | + ApiBase::PARAM_REQUIRED => true, |
| 88 | + ), |
| 89 | + 'aggregategroup' => array( |
| 90 | + ApiBase::PARAM_TYPE => 'string', |
| 91 | + ApiBase::PARAM_REQUIRED => true, |
| 92 | + ), |
| 93 | + 'group' => array( |
| 94 | + ApiBase::PARAM_TYPE => array_keys( MessageGroups::getAllGroups() ), |
| 95 | + ), |
| 96 | + 'groupname' => array( |
| 97 | + ApiBase::PARAM_TYPE => 'string', |
| 98 | + ), |
| 99 | + 'groupdescription' => array( |
| 100 | + ApiBase::PARAM_TYPE => 'string', |
| 101 | + ), |
| 102 | + 'token' => array( |
| 103 | + ApiBase::PARAM_TYPE => 'string', |
| 104 | + ApiBase::PARAM_REQUIRED => true, |
| 105 | + ), |
| 106 | + ); |
| 107 | + } |
| 108 | + |
| 109 | + public function getParamDescription() { |
| 110 | + return array( |
| 111 | + 'do' => 'Required operation, Either of associate, dissociate, add or remove', |
| 112 | + 'group' => 'Message group id', |
| 113 | + 'aggregategroup' => 'Aggregate group id', |
| 114 | + 'groupname' => 'Aggregate group name', |
| 115 | + 'groupdescription' => 'Aggregate group description', |
| 116 | + 'token' => 'A token previously acquired with action=query&prop=info&intoken=aggregategroups', |
| 117 | + ); |
| 118 | + } |
| 119 | + |
| 120 | + public static function getAggregateGroups() { |
| 121 | + $dbr = wfGetDB( DB_MASTER ); |
| 122 | + $tables = array( 'translate_metadata' ); |
| 123 | + $vars = array( 'tmd_group', 'tmd_value' ); |
| 124 | + $conds = array( |
| 125 | + 'tmd_key' => 'subgroups', |
| 126 | + ); |
| 127 | + $options = array( |
| 128 | + 'ORDER BY' => 'tmd_group', |
| 129 | + ); |
| 130 | + $res = $dbr->select( $tables, $vars, $conds, __METHOD__, $options ); |
| 131 | + $aggregateGroups = array(); |
| 132 | + foreach ( $res as $r ) { |
| 133 | + $aggregateGroups[$r->tmd_group] = array(); |
| 134 | + $aggregateGroups[$r->tmd_group]['id'] = $r->tmd_group; |
| 135 | + $aggregateGroups[$r->tmd_group]['name'] = TranslateMetadata::get( $r->tmd_group, 'name' ); |
| 136 | + $aggregateGroups[$r->tmd_group]['description'] = TranslateMetadata::get( $r->tmd_group, 'description' ); |
| 137 | + $subGroupsArray = explode( ',', $r->tmd_value ) ; |
| 138 | + $subGroups = array(); |
| 139 | + foreach ( $subGroupsArray as $subGroup ) { |
| 140 | + $subGroups[$subGroup] = MessageGroups::getGroup( trim( $subGroup ) ); |
| 141 | + } |
| 142 | + $aggregateGroups[$r->tmd_group]['subgroups'] = $subGroups ; |
| 143 | + } |
| 144 | + return $aggregateGroups; |
| 145 | + } |
| 146 | + |
| 147 | + public function getDescription() { |
| 148 | + return 'Manage aggregate groups'; |
| 149 | + } |
| 150 | + |
| 151 | + public function getPossibleErrors() { |
| 152 | + $right = self::$right; |
| 153 | + return array_merge( parent::getPossibleErrors(), array( |
| 154 | + array( 'code' => 'permissiondenied', 'info' => "You must have $right right" ), |
| 155 | + ) ); |
| 156 | + } |
| 157 | + |
| 158 | + public function getExamples() { |
| 159 | + return array( |
| 160 | + "api.php?action=aggregategroups&do=associate&group=groupId&aggregategroup=aggregateGroupId", |
| 161 | + ); |
| 162 | + } |
| 163 | + |
| 164 | + public function getVersion() { |
| 165 | + return __CLASS__ . ': $Id$'; |
| 166 | + } |
| 167 | + |
| 168 | + public static function getToken( $pageid, $title ) { |
| 169 | + global $wgUser; |
| 170 | + if ( !$wgUser->isAllowed( self::$right ) ) { |
| 171 | + return false; |
| 172 | + } |
| 173 | + |
| 174 | + static $cachedToken = null; |
| 175 | + if ( !is_null( $cachedToken ) ) { |
| 176 | + return $cachedToken; |
| 177 | + } |
| 178 | + |
| 179 | + $cachedToken = $wgUser->getEditToken( self::$salt ); |
| 180 | + return $cachedToken; |
| 181 | + } |
| 182 | + |
| 183 | + public static function injectTokenFunction( &$list ) { |
| 184 | + $list['aggregategroups'] = array( __CLASS__, 'getToken' ); |
| 185 | + return true; // Hooks must return bool |
| 186 | + } |
| 187 | + |
| 188 | +} |
Property changes on: trunk/extensions/Translate/api/ApiAggregateGroups.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 189 | + native |
Added: svn:keywords |
2 | 190 | + Id |
Index: trunk/extensions/Translate/resources/ext.translate.special.aggregategroups.css |
— | — | @@ -0,0 +1,24 @@ |
| 2 | +span.tp-aggregate-remove-ag-button, |
| 3 | +span.tp-aggregate-remove-button{ |
| 4 | + /* @embed */ |
| 5 | + background: url(images/remove.png) no-repeat scroll left center transparent; |
| 6 | + padding: 10px; |
| 7 | + cursor: pointer; |
| 8 | +} |
| 9 | + |
| 10 | +a.tpt-add-new-group{ |
| 11 | + /* @embed */ |
| 12 | + background: url(images/add.png) no-repeat scroll left center transparent; |
| 13 | + padding-left: 20px; |
| 14 | +} |
| 15 | +div.tpt-add-new-group.hidden { |
| 16 | + display:none; |
| 17 | +} |
| 18 | + |
| 19 | +input.tp-aggregategroup-add-name { |
| 20 | + width: 250px; |
| 21 | +} |
| 22 | + |
| 23 | +input.tp-aggregategroup-add-description { |
| 24 | + width: 500px; |
| 25 | +} |
Property changes on: trunk/extensions/Translate/resources/ext.translate.special.aggregategroups.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 26 | + native |
Index: trunk/extensions/Translate/resources/images/remove.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/Translate/resources/images/remove.png |
___________________________________________________________________ |
Added: svn:mime-type |
2 | 27 | + image/png |
Index: trunk/extensions/Translate/resources/images/add.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/Translate/resources/images/add.png |
___________________________________________________________________ |
Added: svn:mime-type |
3 | 28 | + image/png |
Index: trunk/extensions/Translate/resources/ext.translate.special.aggregategroups.js |
— | — | @@ -0,0 +1,151 @@ |
| 2 | +jQuery( function( $ ) { |
| 3 | + |
| 4 | + $( document ).ready( function () { |
| 5 | + |
| 6 | + function associate( event ){ |
| 7 | + var aggregategroup = event.target.id; |
| 8 | + var selected = $( '#tp-aggregate-groups-select-'+ aggregategroup + ' option:selected' ).text(); |
| 9 | + var group = $( '#tp-aggregate-groups-select-'+ aggregategroup + ' option:selected' ).val(); |
| 10 | + var $select= $( 'select.tp-aggregate-group-chooser' ) ; |
| 11 | + |
| 12 | + var successFunction = function( data, textStatus ) { |
| 13 | + if ( data.error ) { |
| 14 | + alert( data.error.info ); |
| 15 | + }else{ |
| 16 | + $( '#tp-aggregate-groups-ol-'+ aggregategroup ).append( '<li><a id='+group+' href='+selected+'>'+selected+'</a><span class=\'tp-aggregate-remove-button\' id='+group+'></span></li>' ); |
| 17 | + $( 'option#'+ group ).remove(); |
| 18 | + $( 'span#'+group ).on ( "click", function(event){ dissociate(event); } ); |
| 19 | + } |
| 20 | + }; |
| 21 | + |
| 22 | + var params = { |
| 23 | + action: "aggregategroups", |
| 24 | + 'do' : 'associate', |
| 25 | + token: $( "#token" ).val(), |
| 26 | + group: group, |
| 27 | + aggregategroup: aggregategroup, |
| 28 | + format: "json" |
| 29 | + }; |
| 30 | + $.post( mw.util.wikiScript( "api" ), params, successFunction ); |
| 31 | + } |
| 32 | + |
| 33 | + function dissociate(event){ |
| 34 | + var group = event.target.id; |
| 35 | + var selected = $( 'a#'+group ).text(); |
| 36 | + var $select= $( 'select.tp-aggregate-group-chooser' ) ; |
| 37 | + var aggregategroup = $( 'a#'+group ).closest( 'div' ).find( 'h2' ).attr( 'id' ); |
| 38 | + |
| 39 | + var successFunction = function( data, textStatus ) { |
| 40 | + if ( data.error ) { |
| 41 | + alert( data.error.info ); |
| 42 | + }else{ |
| 43 | + $select.each( function(){ |
| 44 | + $( this ).append( '<option value="'+group+'">'+selected+'</option>' ); |
| 45 | + } ); |
| 46 | + $( 'span#'+ group ).closest( 'li' ).remove(); |
| 47 | + } |
| 48 | + }; |
| 49 | + |
| 50 | + var params = { |
| 51 | + action: "aggregategroups", |
| 52 | + 'do' : 'dissociate', |
| 53 | + token: $( "#token" ).val(), |
| 54 | + group: group, |
| 55 | + aggregategroup: aggregategroup, |
| 56 | + format: "json" |
| 57 | + }; |
| 58 | + $.post( mw.util.wikiScript( "api" ), params, successFunction ); |
| 59 | + } |
| 60 | + |
| 61 | + function removeGroup(event){ |
| 62 | + var aggregategroup = event.target.id; |
| 63 | + var $select= $( 'select.tp-aggregate-group-chooser') ; |
| 64 | + |
| 65 | + var successFunction = function( data, textStatus ) { |
| 66 | + if ( data.error ) { |
| 67 | + alert( data.error.info ); |
| 68 | + }else{ |
| 69 | + $( 'span#'+ aggregategroup ).parent().parent().find('li a').each(function(){ |
| 70 | + $groupId = $( this ).attr('id'); |
| 71 | + $groupName = $( this ).text(); |
| 72 | + $select.each( function(){ |
| 73 | + $ (this ).append('<option value="'+$groupId+'">'+$groupName+'</option>'); |
| 74 | + } ); |
| 75 | + }); |
| 76 | + $( 'span#'+ aggregategroup ).closest('div#tpt-aggregate-group').remove(); |
| 77 | + } |
| 78 | + }; |
| 79 | + |
| 80 | + var params = { |
| 81 | + action: "aggregategroups", |
| 82 | + 'do' : 'remove', |
| 83 | + token: $( "#token" ).val(), |
| 84 | + aggregategroup: aggregategroup, |
| 85 | + format: "json" |
| 86 | + }; |
| 87 | + $.post( mw.util.wikiScript( "api" ), params, successFunction ); |
| 88 | + } |
| 89 | + |
| 90 | + $( 'input.tp-aggregate-add-button' ).on ( "click", function( event ){ |
| 91 | + associate(event); |
| 92 | + } ); |
| 93 | + |
| 94 | + $( 'span.tp-aggregate-remove-button' ).on ( "click", function( event ){ |
| 95 | + dissociate(event); |
| 96 | + } ); |
| 97 | + |
| 98 | + $( 'span.tp-aggregate-remove-ag-button' ).on ( "click", function( event ){ |
| 99 | + removeGroup(event); |
| 100 | + } ); |
| 101 | + |
| 102 | + $( 'a.tpt-add-new-group' ).on ( "click", function( event ){ |
| 103 | + $( 'div.tpt-add-new-group' ).removeClass( 'hidden' ); |
| 104 | + } ); |
| 105 | + |
| 106 | + $( '#tpt-aggregategroups-save' ). on ( "click", function( event ){ |
| 107 | + var aggregateGroup = $( 'input.tp-aggregategroup-add-name' ).val().toLowerCase().replace( ' ', '_'); |
| 108 | + var aggregateGroupName = $( 'input.tp-aggregategroup-add-name' ).val(); |
| 109 | + var aggregateGroupDesc = $( 'input.tp-aggregategroup-add-description' ).val(); |
| 110 | + var $select= $( 'select.tp-aggregate-group-chooser' ) ; |
| 111 | + |
| 112 | + var successFunction = function( data, textStatus ) { |
| 113 | + if ( data.error ) { |
| 114 | + alert( data.error.info ); |
| 115 | + }else{ |
| 116 | + $removeSpan = $( '<span>' ).attr( 'id', aggregateGroup ).addClass( 'tp-aggregate-remove-ag-button' ); |
| 117 | + $div = $( "<div id='tpt-aggregate-group'>" ) |
| 118 | + .append ( $( '<h2>' ).attr( 'id', aggregateGroup ).text( aggregateGroupName ) |
| 119 | + .append ( $removeSpan ) ) |
| 120 | + .append ( $('<p>').text( aggregateGroupDesc ) ) |
| 121 | + .append ( $('<ol id=\'tp-aggregate-groups-ol-'+aggregateGroup+'\'>') ); |
| 122 | + |
| 123 | + if ( $select.length > 0 ){ |
| 124 | + var $groupSelector = $( $( 'select.tp-aggregate-group-chooser')[0] ).clone(); |
| 125 | + $groupSelector.attr('id', 'tp-aggregate-groups-select-' + aggregateGroup); |
| 126 | + var $addButton = $( $( 'input.tp-aggregate-add-button')[0]).clone(); |
| 127 | + $addButton.attr( 'id', aggregateGroup); |
| 128 | + $div.append( $groupSelector ).append( $addButton ); |
| 129 | + $addButton.on ( "click", function( event ){ associate(event); } ); |
| 130 | + $removeSpan.on ( "click", function( event ){ removeGroup(event); } ); |
| 131 | + $( 'div.tpt-add-new-group' ).addClass('hidden'); |
| 132 | + }else{ |
| 133 | + // First group in the wiki. Cannot clone the group selector, just reload this time. |
| 134 | + location.reload(); |
| 135 | + } |
| 136 | + $( 'a.tpt-add-new-group' ).before ( $div ) ; |
| 137 | + } |
| 138 | + }; |
| 139 | + |
| 140 | + var params = { |
| 141 | + action: "aggregategroups", |
| 142 | + 'do' : 'add', |
| 143 | + token: $( "#token" ).val(), |
| 144 | + aggregategroup: aggregateGroup, |
| 145 | + groupname : aggregateGroupName, |
| 146 | + groupdescription: aggregateGroupDesc, |
| 147 | + format: "json" |
| 148 | + }; |
| 149 | + $.post( mw.util.wikiScript( "api" ), params, successFunction ); |
| 150 | + } ) |
| 151 | + } ); |
| 152 | +} ); |
Property changes on: trunk/extensions/Translate/resources/ext.translate.special.aggregategroups.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 153 | + native |
Index: trunk/extensions/Translate/Translate.alias.php |
— | — | @@ -23,6 +23,7 @@ |
24 | 24 | 'SupportedLanguages' => array( 'SupportedLanguages' ), |
25 | 25 | 'MyLanguage' => array( 'MyLanguage' ), |
26 | 26 | 'PageTranslationDeletePage' => array( 'PageTranslationDeletePage' ), |
| 27 | + 'AggregateGroups' => Array( 'AggregateGroups' ), |
27 | 28 | ); |
28 | 29 | |
29 | 30 | /** Afrikaans (Afrikaans) */ |
— | — | @@ -822,4 +823,4 @@ |
823 | 824 | 'FirstSteps' => array( '入門' ), |
824 | 825 | 'SupportedLanguages' => array( '支持的語言' ), |
825 | 826 | 'MyLanguage' => array( '我的語言' ), |
826 | | -); |
\ No newline at end of file |
| 827 | +); |