Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
QueryMessageGroupsActionApi.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\MessageGroupProcessing;
5
7use ApiBase;
8use ApiQuery;
9use ApiQueryBase;
14use MessageGroup;
15use Wikimedia\ParamValidator\ParamValidator;
16
25class QueryMessageGroupsActionApi extends ApiQueryBase {
26 private HookRunner $hookRunner;
27 private MessageGroupMetadata $messageGroupMetadata;
28 private MessageGroupSubscription $groupSubscription;
29
30 public function __construct(
31 ApiQuery $query,
32 string $moduleName,
33 HookRunner $hookRunner,
34 MessageGroupMetadata $messageGroupMetadata,
35 MessageGroupSubscription $groupSubscription
36 ) {
37 parent::__construct( $query, $moduleName, 'mg' );
38 $this->hookRunner = $hookRunner;
39 $this->messageGroupMetadata = $messageGroupMetadata;
40 $this->groupSubscription = $groupSubscription;
41 }
42
43 public function execute(): void {
44 $params = $this->extractRequestParams();
45 $filter = $params['filter'];
46
47 $groups = [];
48 $props = array_flip( $params['prop'] );
49
50 $needsMetadata = isset( $props['prioritylangs'] ) || isset( $props['priorityforce'] );
51
52 if ( $params['format'] === 'flat' ) {
53 if ( $params['root'] !== '' ) {
54 $group = MessageGroups::getGroup( $params['root'] );
55 if ( $group ) {
56 $groups[$params['root']] = $group;
57 }
58 } else {
60 usort( $groups, [ MessageGroups::class, 'groupLabelSort' ] );
61 }
62 } elseif ( $params['root'] !== '' ) {
63 // format=tree from now on, as it is the only other valid option
64 $group = MessageGroups::getGroup( $params['root'] );
65 if ( $group instanceof AggregateMessageGroup ) {
66 $childIds = [];
67 $groups = MessageGroups::subGroups( $group, $childIds );
68 // The parent group is the first, ignore it
69 array_shift( $groups );
70 }
71 } else {
73 }
74
75 if ( $params['root'] === '' ) {
76 $dynamicGroups = [];
77 foreach ( array_keys( MessageGroups::getDynamicGroups() ) as $id ) {
78 $dynamicGroups[$id] = MessageGroups::getGroup( $id );
79 }
80 // Have dynamic groups appear first in the list
81 $groups = $dynamicGroups + $groups;
82 }
83 '@phan-var (MessageGroup|array)[] $groups';
84
85 // Do not list the sandbox group. The code that knows it
86 // exists can access it directly.
87 if ( isset( $groups['!sandbox'] ) ) {
88 unset( $groups['!sandbox'] );
89 }
90
91 $result = $this->getResult();
92 $matcher = new StringMatcher( '', $filter );
94 foreach ( $groups as $index => $mixed ) {
95 // array when Format = tree
96 $group = is_array( $mixed ) ? reset( $mixed ) : $mixed;
97 if ( $filter !== [] && !$matcher->matches( $group->getId() ) ) {
98 unset( $groups[$index] );
99 continue;
100 }
101
102 if (
103 $params['languageFilter'] !== '' &&
104 $this->messageGroupMetadata->isExcluded( $group->getId(), $params['languageFilter'] )
105 ) {
106 unset( $groups[$index] );
107 }
108 }
109
110 if ( $needsMetadata && $groups ) {
111 // FIXME: This doesn't preload subgroups in a tree structure
112 $this->messageGroupMetadata->preloadGroups( array_keys( $groups ), __METHOD__ );
113 }
114
116 foreach ( $groups as $index => $mixed ) {
117 $a = $this->formatGroup( $mixed, $props );
118
119 $result->setIndexedTagName( $a, 'group' );
120
121 // @todo Add a continue?
122 $fit = $result->addValue( [ 'query', $this->getModuleName() ], null, $a );
123 if ( !$fit ) {
124 // Even if we're not going to give a continue, no point carrying on
125 // if the result is full
126 break;
127 }
128 }
129
130 $result->addIndexedTagName( [ 'query', $this->getModuleName() ], 'group' );
131 }
132
138 protected function formatGroup( $mixed, array $props, int $depth = 0 ): array {
139 $params = $this->extractRequestParams();
140 $context = $this->getContext();
141
142 // Default
143 $g = $mixed;
144 $subgroups = [];
145
146 // Format = tree and has subgroups
147 if ( is_array( $mixed ) ) {
148 $g = array_shift( $mixed );
149 $subgroups = $mixed;
150 }
151
152 $a = [];
153
154 $groupId = $g->getId();
155
156 if ( isset( $props['id'] ) ) {
157 $a['id'] = $groupId;
158 }
159
160 if ( isset( $props['label'] ) ) {
161 $a['label'] = $g->getLabel( $context );
162 }
163
164 if ( isset( $props['description'] ) ) {
165 $a['description'] = $g->getDescription( $context );
166 }
167
168 if ( isset( $props['class'] ) ) {
169 $a['class'] = get_class( $g );
170 }
171
172 if ( isset( $props['namespace'] ) ) {
173 $a['namespace'] = $g->getNamespace();
174 }
175
176 if ( isset( $props['exists'] ) ) {
177 $a['exists'] = $g->exists();
178 }
179
180 if ( isset( $props['icon'] ) ) {
181 $formats = Utilities::getIcon( $g, $params['iconsize'] );
182 if ( $formats ) {
183 $a['icon'] = $formats;
184 }
185 }
186
187 if ( isset( $props['priority'] ) ) {
188 $priority = MessageGroups::getPriority( $g );
189 $a['priority'] = $priority ?: 'default';
190 }
191
192 if ( isset( $props['prioritylangs'] ) ) {
193 $prioritylangs = $this->messageGroupMetadata->get( $groupId, 'prioritylangs' );
194 $a['prioritylangs'] = $prioritylangs ? explode( ',', $prioritylangs ) : false;
195 }
196
197 if ( isset( $props['priorityforce'] ) ) {
198 $a['priorityforce'] = ( $this->messageGroupMetadata->get( $groupId, 'priorityforce' ) === 'on' );
199 }
200
201 if ( isset( $props['workflowstates'] ) ) {
202 $a['workflowstates'] = $this->getWorkflowStates( $g );
203 }
204
205 if ( isset( $props['sourcelanguage'] ) ) {
206 $a['sourcelanguage'] = $g->getSourceLanguage();
207 }
208
209 if (
210 isset( $props['subscription'] ) &&
211 $this->groupSubscription->canUserSubscribeToGroup( $g, $this->getUser() )->isOK()
212 ) {
213 $a['subscription'] = $this->groupSubscription->isUserSubscribedTo( $g, $this->getUser() );
214 }
215
216 $this->hookRunner->onTranslateProcessAPIMessageGroupsProperties( $a, $props, $params, $g );
217
218 // Depth only applies to tree format
219 if ( $depth >= $params['depth'] && $params['format'] === 'tree' ) {
220 $a['groupcount'] = count( $subgroups );
221
222 // Prevent going further down in the three
223 return $a;
224 }
225
226 // Always empty array for flat format, only sometimes for tree format
227 if ( $subgroups !== [] ) {
228 foreach ( $subgroups as $sg ) {
229 $a['groups'][] = $this->formatGroup( $sg, $props );
230 }
231 $result = $this->getResult();
232 $result->setIndexedTagName( $a['groups'], 'group' );
233 }
234
235 return $a;
236 }
237
243 private function getWorkflowStates( MessageGroup $group ) {
244 if ( MessageGroups::isDynamic( $group ) ) {
245 return false;
246 }
247
248 $stateConfig = $group->getMessageGroupStates()->getStates();
249
250 if ( !is_array( $stateConfig ) || $stateConfig === [] ) {
251 return false;
252 }
253
254 $user = $this->getUser();
255
256 foreach ( $stateConfig as $state => $config ) {
257 if ( is_array( $config ) ) {
258 // Check if user is allowed to change states generally
259 $allowed = $user->isAllowed( 'translate-groupreview' );
260 // Check further restrictions
261 if ( $allowed && isset( $config['right'] ) ) {
262 $allowed = $user->isAllowed( $config['right'] );
263 }
264
265 if ( $allowed ) {
266 $stateConfig[$state]['canchange'] = 1;
267 }
268
269 $stateConfig[$state]['name'] =
270 $this->msg( "translate-workflow-state-$state" )->text();
271 }
272 }
273
274 return $stateConfig;
275 }
276
277 protected function getAllowedParams(): array {
278 $allowedParams = [
279 'depth' => [
280 ParamValidator::PARAM_TYPE => 'integer',
281 ParamValidator::PARAM_DEFAULT => 100,
282 ],
283 'filter' => [
284 ParamValidator::PARAM_TYPE => 'string',
285 ParamValidator::PARAM_DEFAULT => '',
286 ParamValidator::PARAM_ISMULTI => true,
287 ],
288 'format' => [
289 ParamValidator::PARAM_TYPE => [ 'flat', 'tree' ],
290 ParamValidator::PARAM_DEFAULT => 'flat',
291 ],
292 'iconsize' => [
293 ParamValidator::PARAM_TYPE => 'integer',
294 ParamValidator::PARAM_DEFAULT => 64,
295 ],
296 'prop' => [
297 ParamValidator::PARAM_TYPE => array_keys( $this->getPropertyList() ),
298 ParamValidator::PARAM_DEFAULT => 'id|label|description|class|exists',
299 ParamValidator::PARAM_ISMULTI => true,
300 ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
301 ],
302 'root' => [
303 ParamValidator::PARAM_TYPE => 'string',
304 ParamValidator::PARAM_DEFAULT => '',
305 ],
306 'languageFilter' => [
307 ParamValidator::PARAM_TYPE => 'string',
308 ParamValidator::PARAM_DEFAULT => '',
309 ]
310 ];
311 $this->hookRunner->onTranslateGetAPIMessageGroupsParameterList( $allowedParams );
312
313 return $allowedParams;
314 }
315
321 private function getPropertyList(): array {
322 $properties = array_flip( [
323 'id',
324 'label',
325 'description',
326 'class',
327 'namespace',
328 'exists',
329 'icon',
330 'priority',
331 'prioritylangs',
332 'priorityforce',
333 'workflowstates',
334 'sourcelanguage',
335 'subscription'
336 ] );
337
338 $this->hookRunner->onTranslateGetAPIMessageGroupsPropertyDescs( $properties );
339
340 return $properties;
341 }
342
343 protected function getExamplesMessages(): array {
344 return [
345 'action=query&meta=messagegroups' => 'apihelp-query+messagegroups-example-1',
346 ];
347 }
348}
return[ 'Translate:AggregateGroupManager'=> static function(MediaWikiServices $services):AggregateGroupManager { return new AggregateGroupManager( $services->getTitleFactory());}, 'Translate:AggregateGroupMessageGroupFactory'=> static function(MediaWikiServices $services):AggregateGroupMessageGroupFactory { return new AggregateGroupMessageGroupFactory($services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:ConfigHelper'=> static function():ConfigHelper { return new ConfigHelper();}, 'Translate:CsvTranslationImporter'=> static function(MediaWikiServices $services):CsvTranslationImporter { return new CsvTranslationImporter( $services->getWikiPageFactory());}, 'Translate:EntitySearch'=> static function(MediaWikiServices $services):EntitySearch { return new EntitySearch($services->getMainWANObjectCache(), $services->getCollationFactory() ->makeCollation( 'uca-default-u-kn'), MessageGroups::singleton(), $services->getNamespaceInfo(), $services->get( 'Translate:MessageIndex'), $services->getTitleParser(), $services->getTitleFormatter());}, 'Translate:ExternalMessageSourceStateComparator'=> static function(MediaWikiServices $services):ExternalMessageSourceStateComparator { return new ExternalMessageSourceStateComparator(new SimpleStringComparator(), $services->getRevisionLookup(), $services->getPageStore());}, 'Translate:ExternalMessageSourceStateImporter'=> static function(MediaWikiServices $services):ExternalMessageSourceStateImporter { return new ExternalMessageSourceStateImporter($services->get( 'Translate:GroupSynchronizationCache'), $services->getJobQueueGroup(), LoggerFactory::getInstance( 'Translate.GroupSynchronization'), $services->get( 'Translate:MessageIndex'), $services->getTitleFactory(), new ServiceOptions(ExternalMessageSourceStateImporter::CONSTRUCTOR_OPTIONS, $services->getMainConfig()));}, 'Translate:FileBasedMessageGroupFactory'=> static function(MediaWikiServices $services):FileBasedMessageGroupFactory { return new FileBasedMessageGroupFactory(new MessageGroupConfigurationParser(), new ServiceOptions(FileBasedMessageGroupFactory::SERVICE_OPTIONS, $services->getMainConfig()),);}, 'Translate:FileFormatFactory'=> static function(MediaWikiServices $services):FileFormatFactory { return new FileFormatFactory( $services->getObjectFactory());}, 'Translate:GroupSynchronizationCache'=> static function(MediaWikiServices $services):GroupSynchronizationCache { return new GroupSynchronizationCache( $services->get( 'Translate:PersistentCache'));}, 'Translate:HookDefinedMessageGroupFactory'=> static function(MediaWikiServices $services):HookDefinedMessageGroupFactory { return new HookDefinedMessageGroupFactory( $services->get( 'Translate:HookRunner'));}, 'Translate:HookRunner'=> static function(MediaWikiServices $services):HookRunner { return new HookRunner( $services->getHookContainer());}, 'Translate:MessageBundleMessageGroupFactory'=> static function(MediaWikiServices $services):MessageBundleMessageGroupFactory { return new MessageBundleMessageGroupFactory($services->get( 'Translate:MessageGroupMetadata'), new ServiceOptions(MessageBundleMessageGroupFactory::SERVICE_OPTIONS, $services->getMainConfig()),);}, 'Translate:MessageBundleStore'=> static function(MediaWikiServices $services):MessageBundleStore { return new MessageBundleStore($services->get( 'Translate:RevTagStore'), $services->getJobQueueGroup(), $services->getLanguageNameUtils(), $services->get( 'Translate:MessageIndex'), $services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:MessageBundleTranslationLoader'=> static function(MediaWikiServices $services):MessageBundleTranslationLoader { return new MessageBundleTranslationLoader( $services->getLanguageFallback());}, 'Translate:MessageGroupMetadata'=> static function(MediaWikiServices $services):MessageGroupMetadata { return new MessageGroupMetadata( $services->getDBLoadBalancer());}, 'Translate:MessageGroupReviewStore'=> static function(MediaWikiServices $services):MessageGroupReviewStore { return new MessageGroupReviewStore($services->getDBLoadBalancer(), $services->get( 'Translate:HookRunner'));}, 'Translate:MessageGroupStatsTableFactory'=> static function(MediaWikiServices $services):MessageGroupStatsTableFactory { return new MessageGroupStatsTableFactory($services->get( 'Translate:ProgressStatsTableFactory'), $services->getDBLoadBalancer(), $services->getLinkRenderer(), $services->get( 'Translate:MessageGroupReviewStore'), $services->get( 'Translate:MessageGroupMetadata'), $services->getMainConfig() ->get( 'TranslateWorkflowStates') !==false);}, 'Translate:MessageGroupSubscription'=> static function(MediaWikiServices $services):MessageGroupSubscription { return new MessageGroupSubscription($services->get( 'Translate:MessageGroupSubscriptionStore'), $services->getJobQueueGroup(), $services->getUserIdentityLookup(), LoggerFactory::getInstance( 'Translate.MessageGroupSubscription'), new ServiceOptions(MessageGroupSubscription::CONSTRUCTOR_OPTIONS, $services->getMainConfig()));}, 'Translate:MessageGroupSubscriptionHookHandler'=> static function(MediaWikiServices $services):MessageGroupSubscriptionHookHandler { return new MessageGroupSubscriptionHookHandler($services->get( 'Translate:MessageGroupSubscription'), $services->getUserFactory());}, 'Translate:MessageGroupSubscriptionStore'=> static function(MediaWikiServices $services):MessageGroupSubscriptionStore { return new MessageGroupSubscriptionStore( $services->getDBLoadBalancerFactory());}, 'Translate:MessageIndex'=> static function(MediaWikiServices $services):MessageIndex { $params=(array) $services->getMainConfig() ->get( 'TranslateMessageIndex');$class=array_shift( $params);$implementationMap=['HashMessageIndex'=> HashMessageIndex::class, 'CDBMessageIndex'=> CDBMessageIndex::class, 'DatabaseMessageIndex'=> DatabaseMessageIndex::class, 'hash'=> HashMessageIndex::class, 'cdb'=> CDBMessageIndex::class, 'database'=> DatabaseMessageIndex::class,];$messageIndexStoreClass=$implementationMap[$class] ?? $implementationMap['database'];return new MessageIndex(new $messageIndexStoreClass, $services->getMainWANObjectCache(), $services->getJobQueueGroup(), $services->get( 'Translate:HookRunner'), LoggerFactory::getInstance( 'Translate'), $services->getMainObjectStash(), $services->getDBLoadBalancerFactory(), $services->get( 'Translate:MessageGroupSubscription'), new ServiceOptions(MessageIndex::SERVICE_OPTIONS, $services->getMainConfig()),);}, 'Translate:MessagePrefixStats'=> static function(MediaWikiServices $services):MessagePrefixStats { return new MessagePrefixStats( $services->getTitleParser());}, 'Translate:ParsingPlaceholderFactory'=> static function():ParsingPlaceholderFactory { return new ParsingPlaceholderFactory();}, 'Translate:PersistentCache'=> static function(MediaWikiServices $services):PersistentCache { return new PersistentDatabaseCache($services->getDBLoadBalancer(), $services->getJsonCodec());}, 'Translate:ProgressStatsTableFactory'=> static function(MediaWikiServices $services):ProgressStatsTableFactory { return new ProgressStatsTableFactory($services->getLinkRenderer(), $services->get( 'Translate:ConfigHelper'), $services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:RevTagStore'=> static function(MediaWikiServices $services):RevTagStore { return new RevTagStore( $services->getDBLoadBalancer());}, 'Translate:SubpageListBuilder'=> static function(MediaWikiServices $services):SubpageListBuilder { return new SubpageListBuilder($services->get( 'Translate:TranslatableBundleFactory'), $services->getLinkBatchFactory());}, 'Translate:TranslatableBundleDeleter'=> static function(MediaWikiServices $services):TranslatableBundleDeleter { return new TranslatableBundleDeleter($services->getMainObjectStash(), $services->getJobQueueGroup(), $services->get( 'Translate:SubpageListBuilder'), $services->get( 'Translate:TranslatableBundleFactory'));}, 'Translate:TranslatableBundleExporter'=> static function(MediaWikiServices $services):TranslatableBundleExporter { return new TranslatableBundleExporter($services->get( 'Translate:SubpageListBuilder'), $services->getWikiExporterFactory(), $services->getDBLoadBalancer());}, 'Translate:TranslatableBundleFactory'=> static function(MediaWikiServices $services):TranslatableBundleFactory { return new TranslatableBundleFactory($services->get( 'Translate:TranslatablePageStore'), $services->get( 'Translate:MessageBundleStore'));}, 'Translate:TranslatableBundleImporter'=> static function(MediaWikiServices $services):TranslatableBundleImporter { return new TranslatableBundleImporter($services->getWikiImporterFactory(), $services->get( 'Translate:TranslatablePageParser'), $services->getRevisionLookup(), $services->getNamespaceInfo(), $services->getTitleFactory());}, 'Translate:TranslatableBundleMover'=> static function(MediaWikiServices $services):TranslatableBundleMover { return new TranslatableBundleMover($services->getMovePageFactory(), $services->getJobQueueGroup(), $services->getLinkBatchFactory(), $services->get( 'Translate:TranslatableBundleFactory'), $services->get( 'Translate:SubpageListBuilder'), $services->getDBLoadBalancerFactory(), $services->getMainConfig() ->get( 'TranslatePageMoveLimit'));}, 'Translate:TranslatableBundleStatusStore'=> static function(MediaWikiServices $services):TranslatableBundleStatusStore { return new TranslatableBundleStatusStore($services->getDBLoadBalancer() ->getConnection(DB_PRIMARY), $services->getCollationFactory() ->makeCollation( 'uca-default-u-kn'), $services->getDBLoadBalancer() ->getMaintenanceConnectionRef(DB_PRIMARY));}, 'Translate:TranslatablePageMarker'=> static function(MediaWikiServices $services):TranslatablePageMarker { return new TranslatablePageMarker($services->getDBLoadBalancer(), $services->getJobQueueGroup(), $services->getLinkRenderer(), MessageGroups::singleton(), $services->get( 'Translate:MessageIndex'), $services->getTitleFormatter(), $services->getTitleParser(), $services->get( 'Translate:TranslatablePageParser'), $services->get( 'Translate:TranslatablePageStore'), $services->get( 'Translate:TranslatablePageStateStore'), $services->get( 'Translate:TranslationUnitStoreFactory'), $services->get( 'Translate:MessageGroupMetadata'), $services->getWikiPageFactory(), $services->get( 'Translate:TranslatablePageView'));}, 'Translate:TranslatablePageMessageGroupFactory'=> static function(MediaWikiServices $services):TranslatablePageMessageGroupFactory { return new TranslatablePageMessageGroupFactory(new ServiceOptions(TranslatablePageMessageGroupFactory::SERVICE_OPTIONS, $services->getMainConfig()),);}, 'Translate:TranslatablePageParser'=> static function(MediaWikiServices $services):TranslatablePageParser { return new TranslatablePageParser($services->get( 'Translate:ParsingPlaceholderFactory'));}, 'Translate:TranslatablePageStateStore'=> static function(MediaWikiServices $services):TranslatablePageStateStore { return new TranslatablePageStateStore($services->get( 'Translate:PersistentCache'), $services->getPageStore());}, 'Translate:TranslatablePageStore'=> static function(MediaWikiServices $services):TranslatablePageStore { return new TranslatablePageStore($services->get( 'Translate:MessageIndex'), $services->getJobQueueGroup(), $services->get( 'Translate:RevTagStore'), $services->getDBLoadBalancer(), $services->get( 'Translate:TranslatableBundleStatusStore'), $services->get( 'Translate:TranslatablePageParser'), $services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:TranslatablePageView'=> static function(MediaWikiServices $services):TranslatablePageView { return new TranslatablePageView($services->getDBLoadBalancerFactory(), $services->get( 'Translate:TranslatablePageStateStore'), new ServiceOptions(TranslatablePageView::SERVICE_OPTIONS, $services->getMainConfig()));}, 'Translate:TranslateSandbox'=> static function(MediaWikiServices $services):TranslateSandbox { return new TranslateSandbox($services->getUserFactory(), $services->getDBLoadBalancer(), $services->getPermissionManager(), $services->getAuthManager(), $services->getUserGroupManager(), $services->getActorStore(), $services->getUserOptionsManager(), $services->getJobQueueGroup(), $services->get( 'Translate:HookRunner'), new ServiceOptions(TranslateSandbox::CONSTRUCTOR_OPTIONS, $services->getMainConfig()));}, 'Translate:TranslationStashReader'=> static function(MediaWikiServices $services):TranslationStashReader { $db=$services->getDBLoadBalancer() ->getConnection(DB_REPLICA);return new TranslationStashStorage( $db);}, 'Translate:TranslationStatsDataProvider'=> static function(MediaWikiServices $services):TranslationStatsDataProvider { return new TranslationStatsDataProvider(new ServiceOptions(TranslationStatsDataProvider::CONSTRUCTOR_OPTIONS, $services->getMainConfig()), $services->getObjectFactory(), $services->getDBLoadBalancer());}, 'Translate:TranslationUnitStoreFactory'=> static function(MediaWikiServices $services):TranslationUnitStoreFactory { return new TranslationUnitStoreFactory( $services->getDBLoadBalancer());}, 'Translate:TranslatorActivity'=> static function(MediaWikiServices $services):TranslatorActivity { $query=new TranslatorActivityQuery($services->getMainConfig(), $services->getDBLoadBalancer());return new TranslatorActivity($services->getMainObjectStash(), $query, $services->getJobQueueGroup());}, 'Translate:TtmServerFactory'=> static function(MediaWikiServices $services):TtmServerFactory { $config=$services->getMainConfig();$default=$config->get( 'TranslateTranslationDefaultService');if( $default===false) { $default=null;} return new TtmServerFactory( $config->get( 'TranslateTranslationServices'), $default);}]
@phpcs-require-sorted-array
Groups multiple message groups together as one group.
Hook runner for the Translate extension.
Manage user subscriptions to message groups and trigger notifications.
static getGroup(string $id)
Fetch a message group by id.
static getPriority( $group)
We want to de-emphasize time sensitive groups like news for 2009.
static getDynamicGroups()
Contents on these groups changes on a whim.
static getGroupStructure()
Returns a tree of message groups.
static subGroups(AggregateMessageGroup $parent, array &$childIds=[], string $fname='caller')
Like getGroupStructure but start from one root which must be an AggregateMessageGroup.
Offers functionality for reading and updating Translate group related metadata.
The versatile default implementation of StringMangler interface.
Essentially random collection of helper functions, similar to GlobalFunctions.php.
Definition Utilities.php:31
Interface for message groups.
getMessageGroupStates()
Get the message group workflow state configuration.