https://www.mediawiki.org/wiki/Special:Code/MediaWiki/113229

Revision: 113229
Author:   nikerabbit
Date:     2012-03-07 14:08:14 +0000 (Wed, 07 Mar 2012)
Log Message:
-----------
Deprecating $wgTranslateGroupStructure.
The message group tree is now only based on aggregate groups and their 
subgroups.
Cycles not allowed, but one group can have multiple parents and thus occur more 
than once in the tree in difference places.
Will remove the global variable and other related code in later commit.

Modified Paths:
--------------
    trunk/extensions/Translate/MessageGroups.php

Modified: trunk/extensions/Translate/MessageGroups.php
===================================================================
--- trunk/extensions/Translate/MessageGroups.php        2012-03-07 14:05:28 UTC 
(rev 113228)
+++ trunk/extensions/Translate/MessageGroups.php        2012-03-07 14:08:14 UTC 
(rev 113229)
@@ -1391,66 +1391,111 @@
        }
 
        /**
-        * Returns group strucuted into sub groups. First group in each 
subgroup is
-        * considered as the main group.
+        * Returns a tree of message groups. First group in each subgroup is
+        * the aggregate group. Groups can be nested infinitely, though in 
practice
+        * other code might not handle more than two (or even one) nesting 
levels.
+        * One group can exist multiple times in differents parts of the tree.
+        * In other words: [Group1, Group2, [AggGroup, Group3, Group4]]
+        * @throws MWException If cyclic structure is detected.
         * @return array
         */
        public static function getGroupStructure() {
-               global $wgTranslateGroupStructure;
-
                $groups = self::getAllGroups();
-
+               
+               // Determine the top level groups of the tree
+               $tree = $groups;
                $structure = array();
                foreach ( $groups as $id => $o ) {
-                       if ( !MessageGroups::getGroup( $id )->exists() ) {
+                       if ( !$o->exists() ) {
+                               unset( $groups[$id], $tree[$id] );
                                continue;
                        }
 
-                       foreach ( $wgTranslateGroupStructure as $pattern => 
$hypergroup ) {
-                               if ( preg_match( $pattern, $id ) ) {
-                                       // Emulate deepArraySet, because AFAIK 
php does not have one
-                                       self::deepArraySet( $structure, 
$hypergroup, $id, $o );
-                                       // We need to continue the outer loop, 
because we have finished this item.
-                                       continue 2;
+                       if ( $o instanceof AggregateMessageGroup ) {
+                               foreach ( $o->getGroups() as $sid => $so ) {
+                                       unset( $tree[$sid] );
                                }
                        }
-
-                       // Does not belong to any subgroup, just shove it into 
main level.
-                       $structure[$id] = $o;
                }
 
-               // Sort top-level groups according to labels, not ids
-               $labels = array();
-               foreach ( $structure as $id => $data ) {
-                       // Either it is a group itself, or the first group of 
the array
-                       $nid = is_array( $data ) ? key( $data ) : $id;
-                       $labels[$id] = $groups[$nid]->getLabel();
+               /* Now we have two things left in $tree array:
+                * - solitaries: top-level non-aggregate message groups
+                * - top-level aggregate message groups */
+               usort( $tree, array( __CLASS__, 'groupLabelSort' ) );
+               foreach ( $tree as $index => $group ) {
+                       if ( $group instanceof AggregateMessageGroup ) {
+                               $tree[$index] = self::subGroups( $group );
+                       }
                }
-               natcasesort( $labels );
 
-               $sorted = array();
-               foreach ( array_keys( $labels ) as $id ) {
-                       $sorted[$id] = $structure[$id];
+               /* Essentially we are done now. Cyclic groups can cause part of 
the
+                * groups not be included at all, because they have all unset 
each
+                * other in the first loop. So now we check if there are groups 
left
+                * over. */
+               $used = array();
+               // Hack to allow passing by reference
+               array_walk_recursive( $tree, array( __CLASS__, 
'collectGroupIds' ), array( &$used ) );
+               $unused = array_diff( array_keys( $groups ), array_keys( $used 
) );
+               if ( count( $unused ) ) {
+                       foreach ( $unused as $index => $id ) {
+                               if ( !$groups[$id] instanceof 
AggregateMessageGroup ) {
+                                       unset( $unused[$index] );
+                               }
+                       }
+
+                       // Only list the aggregate groups, other groups cannot 
cause cycles
+                       $participants = implode( ', ', $unused );
+                       throw new MWException( "Found cyclic aggregate message 
groups: $participants" );
                }
 
-               return $sorted;
+               return $tree;
        }
 
-       /**
-        * Function do do $array[level1][level2]...[levelN][$key] = $value, if 
we have
-        * the indexes in an array.
-        * @param $array
-        * @param $indexes array
-        * @param $key
-        * @param $value
-        */
-       public static function deepArraySet( &$array, array $indexes, $key, 
$value ) {
-               foreach ( $indexes as $index ) {
-                       if ( !isset( $array[$index] ) ) $array[$index] = 
array();
-                       $array = &$array[$index];
+       /// See getGroupStructure, just collects ids into array
+       public static function collectGroupIds( $value, $key, $used ) {
+               $used[0][$value->getId()] = true;
+       }
+
+       /// Sorts groups by label value
+       public static function groupLabelSort( $a, $b ) {
+               $al = $a->getLabel();
+               $bl = $b->getLabel();
+               return strcasecmp( $al, $bl );
+       }
+
+       /// Helper for getGroupStructure
+       protected static function subGroups( AggregateMessageGroup $parent ) {
+               static $recursionGuard = array();
+
+               $pid = $parent->getId();
+               if ( isset( $recursionGuard[$pid] ) ) {
+                       $tid = $pid;
+                       $path = array( $tid );
+                       do {
+                               $tid = $recursionGuard[$tid];
+                               $path[] = $tid;
+                               // Until we have gone full cycle
+                       } while ( $tid !== $pid );
+                       $path = implode( ' > ', $path );
+                       throw new MWException( "Found cyclic aggregate message 
groups: $path" );
                }
 
-               $array[$key] = $value;
+               // We don't care about the ids.
+               $tree = array_values( $parent->getGroups() );
+               usort( $tree, array( __CLASS__, 'groupLabelSort' ) );
+               // Expand aggregate groups (if any left) after sorting to form 
a tree
+               foreach ( $tree as $index => $group ) {
+                       if ( $group instanceof AggregateMessageGroup ) {
+                               $sid = $group->getId();
+                               $recursionGuard[$pid] = $sid;
+                               $tree[$index] = self::subGroups( $group );
+                               unset( $recursionGuard[$pid] );
+                       }
+               }
+
+               // Parent group must be first item in the array
+               array_unshift( $tree, $parent );
+               return $tree;
        }
 
 }


_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to