blob: 60b8be6e0d3d93fe9321edd71e558b88aaa21fd6 [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\Translation\Util;
13
14/**
15 * ArrayConverter generates tree like structure from a message catalogue.
16 * e.g. this
17 * 'foo.bar1' => 'test1',
18 * 'foo.bar2' => 'test2'
19 * converts to follows:
20 * foo:
21 * bar1: test1
22 * bar2: test2.
23 *
24 * @author Gennady Telegin <gtelegin@gmail.com>
25 */
26class ArrayConverter
27{
28 /**
29 * Converts linear messages array to tree-like array.
30 * For example this array('foo.bar' => 'value') will be converted to ['foo' => ['bar' => 'value']].
31 *
32 * @param array $messages Linear messages array
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +020033 */
Matthias Andreas Benkard1ba53812022-12-27 17:32:58 +010034 public static function expandToTree(array $messages): array
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +020035 {
36 $tree = [];
37
38 foreach ($messages as $id => $value) {
39 $referenceToElement = &self::getElementByPath($tree, explode('.', $id));
40
41 $referenceToElement = $value;
42
43 unset($referenceToElement);
44 }
45
46 return $tree;
47 }
48
49 private static function &getElementByPath(array &$tree, array $parts)
50 {
51 $elem = &$tree;
52 $parentOfElem = null;
53
54 foreach ($parts as $i => $part) {
55 if (isset($elem[$part]) && \is_string($elem[$part])) {
56 /* Process next case:
57 * 'foo': 'test1',
58 * 'foo.bar': 'test2'
59 *
60 * $tree['foo'] was string before we found array {bar: test2}.
61 * Treat new element as string too, e.g. add $tree['foo.bar'] = 'test2';
62 */
63 $elem = &$elem[implode('.', \array_slice($parts, $i))];
64 break;
65 }
66 $parentOfElem = &$elem;
67 $elem = &$elem[$part];
68 }
69
70 if ($elem && \is_array($elem) && $parentOfElem) {
71 /* Process next case:
72 * 'foo.bar': 'test1'
73 * 'foo': 'test2'
74 *
75 * $tree['foo'] was array = {bar: 'test1'} before we found string constant `foo`.
76 * Cancel treating $tree['foo'] as array and cancel back it expansion,
77 * e.g. make it $tree['foo.bar'] = 'test1' again.
78 */
79 self::cancelExpand($parentOfElem, $part, $elem);
80 }
81
82 return $elem;
83 }
84
85 private static function cancelExpand(array &$tree, string $prefix, array $node)
86 {
87 $prefix .= '.';
88
89 foreach ($node as $id => $value) {
90 if (\is_string($value)) {
91 $tree[$prefix.$id] = $value;
92 } else {
93 self::cancelExpand($tree, $prefix.$id, $value);
94 }
95 }
96 }
97}