r113229 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r113228‎ | r113229 | r113230 >
Date:14:08, 7 March 2012
Author:nikerabbit
Status:ok
Tags:i18nreview 
Comment:
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) (history)

Diff [purge]

Index: trunk/extensions/Translate/MessageGroups.php
@@ -1391,66 +1391,111 @@
13921392 }
13931393
13941394 /**
1395 - * Returns group strucuted into sub groups. First group in each subgroup is
1396 - * considered as the main group.
 1395+ * Returns a tree of message groups. First group in each subgroup is
 1396+ * the aggregate group. Groups can be nested infinitely, though in practice
 1397+ * other code might not handle more than two (or even one) nesting levels.
 1398+ * One group can exist multiple times in differents parts of the tree.
 1399+ * In other words: [Group1, Group2, [AggGroup, Group3, Group4]]
 1400+ * @throws MWException If cyclic structure is detected.
13971401 * @return array
13981402 */
13991403 public static function getGroupStructure() {
1400 - global $wgTranslateGroupStructure;
1401 -
14021404 $groups = self::getAllGroups();
1403 -
 1405+
 1406+ // Determine the top level groups of the tree
 1407+ $tree = $groups;
14041408 $structure = array();
14051409 foreach ( $groups as $id => $o ) {
1406 - if ( !MessageGroups::getGroup( $id )->exists() ) {
 1410+ if ( !$o->exists() ) {
 1411+ unset( $groups[$id], $tree[$id] );
14071412 continue;
14081413 }
14091414
1410 - foreach ( $wgTranslateGroupStructure as $pattern => $hypergroup ) {
1411 - if ( preg_match( $pattern, $id ) ) {
1412 - // Emulate deepArraySet, because AFAIK php does not have one
1413 - self::deepArraySet( $structure, $hypergroup, $id, $o );
1414 - // We need to continue the outer loop, because we have finished this item.
1415 - continue 2;
 1415+ if ( $o instanceof AggregateMessageGroup ) {
 1416+ foreach ( $o->getGroups() as $sid => $so ) {
 1417+ unset( $tree[$sid] );
14161418 }
14171419 }
1418 -
1419 - // Does not belong to any subgroup, just shove it into main level.
1420 - $structure[$id] = $o;
14211420 }
14221421
1423 - // Sort top-level groups according to labels, not ids
1424 - $labels = array();
1425 - foreach ( $structure as $id => $data ) {
1426 - // Either it is a group itself, or the first group of the array
1427 - $nid = is_array( $data ) ? key( $data ) : $id;
1428 - $labels[$id] = $groups[$nid]->getLabel();
 1422+ /* Now we have two things left in $tree array:
 1423+ * - solitaries: top-level non-aggregate message groups
 1424+ * - top-level aggregate message groups */
 1425+ usort( $tree, array( __CLASS__, 'groupLabelSort' ) );
 1426+ foreach ( $tree as $index => $group ) {
 1427+ if ( $group instanceof AggregateMessageGroup ) {
 1428+ $tree[$index] = self::subGroups( $group );
 1429+ }
14291430 }
1430 - natcasesort( $labels );
14311431
1432 - $sorted = array();
1433 - foreach ( array_keys( $labels ) as $id ) {
1434 - $sorted[$id] = $structure[$id];
 1432+ /* Essentially we are done now. Cyclic groups can cause part of the
 1433+ * groups not be included at all, because they have all unset each
 1434+ * other in the first loop. So now we check if there are groups left
 1435+ * over. */
 1436+ $used = array();
 1437+ // Hack to allow passing by reference
 1438+ array_walk_recursive( $tree, array( __CLASS__, 'collectGroupIds' ), array( &$used ) );
 1439+ $unused = array_diff( array_keys( $groups ), array_keys( $used ) );
 1440+ if ( count( $unused ) ) {
 1441+ foreach ( $unused as $index => $id ) {
 1442+ if ( !$groups[$id] instanceof AggregateMessageGroup ) {
 1443+ unset( $unused[$index] );
 1444+ }
 1445+ }
 1446+
 1447+ // Only list the aggregate groups, other groups cannot cause cycles
 1448+ $participants = implode( ', ', $unused );
 1449+ throw new MWException( "Found cyclic aggregate message groups: $participants" );
14351450 }
14361451
1437 - return $sorted;
 1452+ return $tree;
14381453 }
14391454
1440 - /**
1441 - * Function do do $array[level1][level2]...[levelN][$key] = $value, if we have
1442 - * the indexes in an array.
1443 - * @param $array
1444 - * @param $indexes array
1445 - * @param $key
1446 - * @param $value
1447 - */
1448 - public static function deepArraySet( &$array, array $indexes, $key, $value ) {
1449 - foreach ( $indexes as $index ) {
1450 - if ( !isset( $array[$index] ) ) $array[$index] = array();
1451 - $array = &$array[$index];
 1455+ /// See getGroupStructure, just collects ids into array
 1456+ public static function collectGroupIds( $value, $key, $used ) {
 1457+ $used[0][$value->getId()] = true;
 1458+ }
 1459+
 1460+ /// Sorts groups by label value
 1461+ public static function groupLabelSort( $a, $b ) {
 1462+ $al = $a->getLabel();
 1463+ $bl = $b->getLabel();
 1464+ return strcasecmp( $al, $bl );
 1465+ }
 1466+
 1467+ /// Helper for getGroupStructure
 1468+ protected static function subGroups( AggregateMessageGroup $parent ) {
 1469+ static $recursionGuard = array();
 1470+
 1471+ $pid = $parent->getId();
 1472+ if ( isset( $recursionGuard[$pid] ) ) {
 1473+ $tid = $pid;
 1474+ $path = array( $tid );
 1475+ do {
 1476+ $tid = $recursionGuard[$tid];
 1477+ $path[] = $tid;
 1478+ // Until we have gone full cycle
 1479+ } while ( $tid !== $pid );
 1480+ $path = implode( ' > ', $path );
 1481+ throw new MWException( "Found cyclic aggregate message groups: $path" );
14521482 }
14531483
1454 - $array[$key] = $value;
 1484+ // We don't care about the ids.
 1485+ $tree = array_values( $parent->getGroups() );
 1486+ usort( $tree, array( __CLASS__, 'groupLabelSort' ) );
 1487+ // Expand aggregate groups (if any left) after sorting to form a tree
 1488+ foreach ( $tree as $index => $group ) {
 1489+ if ( $group instanceof AggregateMessageGroup ) {
 1490+ $sid = $group->getId();
 1491+ $recursionGuard[$pid] = $sid;
 1492+ $tree[$index] = self::subGroups( $group );
 1493+ unset( $recursionGuard[$pid] );
 1494+ }
 1495+ }
 1496+
 1497+ // Parent group must be first item in the array
 1498+ array_unshift( $tree, $parent );
 1499+ return $tree;
14551500 }
14561501
14571502 }

Status & tagging log