@@ -12,9 +12,7 @@
Loading
12 12
    public const TOKEN = 'token';
13 13
    public const TOPIC = 'topic';
14 14
15 -
    /**
16 -
     * @internal
17 -
     */
15 +
    /** @internal */
18 16
    public const UNKNOWN = 'unknown';
19 17
20 18
    public const TYPES = [

@@ -44,6 +44,11 @@
Loading
44 44
        return $this->name;
45 45
    }
46 46
47 +
    public function expression(): string
48 +
    {
49 +
        return $this->expression;
50 +
    }
51 +
47 52
    public function withExpression(string $expression): self
48 53
    {
49 54
        $condition = clone $this;

@@ -7,7 +7,6 @@
Loading
7 7
use Kreait\Firebase\Exception\InvalidArgumentException;
8 8
use Kreait\Firebase\Util\JSON;
9 9
use Psr\Http\Message\ResponseInterface;
10 -
use Throwable;
11 10
12 11
class Template implements \JsonSerializable
13 12
{
@@ -17,6 +16,9 @@
Loading
17 16
    /** @var Parameter[] */
18 17
    private $parameters = [];
19 18
19 +
    /** @var ParameterGroup[] */
20 +
    private $parameterGroups = [];
21 +
20 22
    /** @var Condition[] */
21 23
    private $conditions = [];
22 24
@@ -29,15 +31,14 @@
Loading
29 31
30 32
    public static function new(): self
31 33
    {
32 -
        $template = new self();
33 -
        $template->etag = '*';
34 -
        $template->parameters = [];
35 -
36 -
        return $template;
34 +
        return new self();
37 35
    }
38 36
39 37
    /**
40 38
     * @internal
39 +
     *
40 +
     * @deprecated 5.10.0
41 +
     * @codeCoverageIgnore
41 42
     */
42 43
    public static function fromResponse(ResponseInterface $response): self
43 44
    {
@@ -57,24 +58,69 @@
Loading
57 58
        $template->etag = $etag ?? '*';
58 59
59 60
        foreach ((array) ($data['conditions'] ?? []) as $conditionData) {
60 -
            $template->conditions[(string) $conditionData['name']] = Condition::fromArray($conditionData);
61 +
            $template = $template->withCondition(self::buildCondition($conditionData['name'], $conditionData));
61 62
        }
62 63
63 64
        foreach ((array) ($data['parameters'] ?? []) as $name => $parameterData) {
64 -
            $template->parameters[(string) $name] = Parameter::fromArray([(string) $name => $parameterData]);
65 +
            $template = $template->withParameter(self::buildParameter($name, $parameterData));
66 +
        }
67 +
68 +
        foreach ((array) ($data['parameterGroups'] ?? []) as $name => $parameterGroupData) {
69 +
            $template = $template->withParameterGroup(self::buildParameterGroup($name, $parameterGroupData));
65 70
        }
66 71
67 72
        if (\is_array($data['version'] ?? null)) {
68 -
            try {
69 -
                $template->version = Version::fromArray($data['version']);
70 -
            } catch (Throwable $e) {
71 -
                $template->version = null;
72 -
            }
73 +
            $template->version = Version::fromArray($data['version']);
73 74
        }
74 75
75 76
        return $template;
76 77
    }
77 78
79 +
    /**
80 +
     * @param array<string, string> $data
81 +
     */
82 +
    private static function buildCondition(string $name, array $data): Condition
83 +
    {
84 +
        $condition = Condition::named($name)->withExpression($data['expression']);
85 +
86 +
        if ($tagColor = $data['tagColor'] ?? null) {
87 +
            $condition = $condition->withTagColor(new TagColor($tagColor));
88 +
        }
89 +
90 +
        return $condition;
91 +
    }
92 +
93 +
    /**
94 +
     * @param array<string, mixed> $data
95 +
     */
96 +
    private static function buildParameter(string $name, array $data): Parameter
97 +
    {
98 +
        $parameter = Parameter::named($name)
99 +
            ->withDescription((string) ($data['description'] ?? ''))
100 +
            ->withDefaultValue(DefaultValue::fromArray($data['defaultValue'] ?? []));
101 +
102 +
        foreach ((array) ($data['conditionalValues'] ?? []) as $key => $conditionalValueData) {
103 +
            $parameter = $parameter->withConditionalValue(new ConditionalValue($key, $conditionalValueData['value']));
104 +
        }
105 +
106 +
        return $parameter;
107 +
    }
108 +
109 +
    /**
110 +
     * @param array<string, mixed> $parameterGroupData
111 +
     */
112 +
    private static function buildParameterGroup(string $name, array $parameterGroupData): ParameterGroup
113 +
    {
114 +
        $group = ParameterGroup::named($name)
115 +
            ->withDescription((string) ($parameterGroupData['description'] ?? ''));
116 +
117 +
        foreach ($parameterGroupData['parameters'] ?? [] as $parameterName => $parameterData) {
118 +
            $group = $group->withParameter(self::buildParameter($parameterName, $parameterData));
119 +
        }
120 +
121 +
        return $group;
122 +
    }
123 +
78 124
    /**
79 125
     * @internal
80 126
     */
@@ -83,6 +129,14 @@
Loading
83 129
        return $this->etag;
84 130
    }
85 131
132 +
    /**
133 +
     * @return Condition[]
134 +
     */
135 +
    public function conditions(): array
136 +
    {
137 +
        return $this->conditions;
138 +
    }
139 +
86 140
    /**
87 141
     * @return Parameter[]
88 142
     */
@@ -91,6 +145,14 @@
Loading
91 145
        return $this->parameters;
92 146
    }
93 147
148 +
    /**
149 +
     * @return ParameterGroup[]
150 +
     */
151 +
    public function parameterGroups(): array
152 +
    {
153 +
        return $this->parameterGroups;
154 +
    }
155 +
94 156
    public function version(): ?Version
95 157
    {
96 158
        return $this->version;
@@ -106,6 +168,14 @@
Loading
106 168
        return $template;
107 169
    }
108 170
171 +
    public function withParameterGroup(ParameterGroup $parameterGroup): Template
172 +
    {
173 +
        $template = clone $this;
174 +
        $template->parameterGroups[$parameterGroup->name()] = $parameterGroup;
175 +
176 +
        return $template;
177 +
    }
178 +
109 179
    public function withCondition(Condition $condition): Template
110 180
    {
111 181
        $template = clone $this;
@@ -118,7 +188,7 @@
Loading
118 188
    {
119 189
        foreach ($parameter->conditionalValues() as $conditionalValue) {
120 190
            if (!\array_key_exists($conditionalValue->conditionName(), $this->conditions)) {
121 -
                $message = 'The conditional value of the parameter named "%s" referes to a condition "%s" which does not exist.';
191 +
                $message = 'The conditional value of the parameter named "%s" refers to a condition "%s" which does not exist.';
122 192
123 193
                throw new InvalidArgumentException(\sprintf($message, $parameter->name(), $conditionalValue->conditionName()));
124 194
            }
@@ -130,11 +200,10 @@
Loading
130 200
     */
131 201
    public function jsonSerialize(): array
132 202
    {
133 -
        $result = [
134 -
            'conditions' => \array_values($this->conditions),
135 -
            'parameters' => $this->parameters,
203 +
        return [
204 +
            'conditions' => !empty($this->conditions) ? \array_values($this->conditions) : null,
205 +
            'parameters' => !empty($this->parameters) ? $this->parameters : null,
206 +
            'parameterGroups' => !empty($this->parameterGroups) ? $this->parameterGroups : null,
136 207
        ];
137 -
138 -
        return \array_filter($result);
139 208
    }
140 209
}

@@ -92,6 +92,9 @@
Loading
92 92
    }
93 93
94 94
    /**
95 +
     * @deprecated 5.10.0
96 +
     * @codeCoverageIgnore
97 +
     *
95 98
     * @param array<string, mixed> $data
96 99
     */
97 100
    public static function fromArray(array $data): self

@@ -0,0 +1,71 @@
Loading
1 +
<?php
2 +
3 +
declare(strict_types=1);
4 +
5 +
namespace Kreait\Firebase\RemoteConfig;
6 +
7 +
final class ParameterGroup implements \JsonSerializable
8 +
{
9 +
    /** @var string */
10 +
    private $name;
11 +
12 +
    /** @var string */
13 +
    private $description = '';
14 +
15 +
    /** @var Parameter[] */
16 +
    private $parameters = [];
17 +
18 +
    private function __construct()
19 +
    {
20 +
    }
21 +
22 +
    public static function named(string $name): self
23 +
    {
24 +
        $group = new self();
25 +
        $group->name = $name;
26 +
27 +
        return $group;
28 +
    }
29 +
30 +
    public function name(): string
31 +
    {
32 +
        return $this->name;
33 +
    }
34 +
35 +
    public function description(): string
36 +
    {
37 +
        return $this->description;
38 +
    }
39 +
40 +
    /**
41 +
     * @return Parameter[]
42 +
     */
43 +
    public function parameters(): array
44 +
    {
45 +
        return $this->parameters;
46 +
    }
47 +
48 +
    public function withDescription(string $description): self
49 +
    {
50 +
        $group = clone $this;
51 +
        $group->description = $description;
52 +
53 +
        return $group;
54 +
    }
55 +
56 +
    public function withParameter(Parameter $parameter): self
57 +
    {
58 +
        $group = clone $this;
59 +
        $group->parameters[$parameter->name()] = $parameter;
60 +
61 +
        return $group;
62 +
    }
63 +
64 +
    public function jsonSerialize()
65 +
    {
66 +
        return [
67 +
            'description' => $this->description,
68 +
            'parameters' => $this->parameters,
69 +
        ];
70 +
    }
71 +
}

@@ -13,6 +13,7 @@
Loading
13 13
use Kreait\Firebase\RemoteConfig\Version;
14 14
use Kreait\Firebase\RemoteConfig\VersionNumber;
15 15
use Kreait\Firebase\Util\JSON;
16 +
use Psr\Http\Message\ResponseInterface;
16 17
use Traversable;
17 18
18 19
/**
@@ -39,7 +40,7 @@
Loading
39 40
     */
40 41
    public function get(): Template
41 42
    {
42 -
        return Template::fromResponse($this->client->getTemplate());
43 +
        return $this->buildTemplateFromResponse($this->client->getTemplate());
43 44
    }
44 45
45 46
    /**
@@ -52,9 +53,7 @@
Loading
52 53
     */
53 54
    public function validate($template): void
54 55
    {
55 -
        $template = $template instanceof Template ? $template : Template::fromArray($template);
56 -
57 -
        $this->client->validateTemplate($template);
56 +
        $this->client->validateTemplate($this->ensureTemplate($template));
58 57
    }
59 58
60 59
    /**
@@ -66,9 +65,9 @@
Loading
66 65
     */
67 66
    public function publish($template): string
68 67
    {
69 -
        $template = $template instanceof Template ? $template : Template::fromArray($template);
70 -
71 -
        $etag = $this->client->publishTemplate($template)->getHeader('ETag');
68 +
        $etag = $this->client
69 +
            ->publishTemplate($this->ensureTemplate($template))
70 +
            ->getHeader('ETag');
72 71
73 72
        return \array_shift($etag) ?: '';
74 73
    }
@@ -76,16 +75,14 @@
Loading
76 75
    /**
77 76
     * Returns a version with the given number.
78 77
     *
79 -
     * @param VersionNumber|mixed $versionNumber
78 +
     * @param VersionNumber|int|string $versionNumber
80 79
     *
81 80
     * @throws VersionNotFound
82 81
     * @throws RemoteConfigException if something went wrong
83 82
     */
84 83
    public function getVersion($versionNumber): Version
85 84
    {
86 -
        $versionNumber = $versionNumber instanceof VersionNumber
87 -
            ? $versionNumber
88 -
            : VersionNumber::fromValue($versionNumber);
85 +
        $versionNumber = $this->ensureVersionNumber($versionNumber);
89 86
90 87
        foreach ($this->listVersions() as $version) {
91 88
            if ($version->versionNumber()->equalsTo($versionNumber)) {
@@ -99,20 +96,16 @@
Loading
99 96
    /**
100 97
     * Returns a version with the given number.
101 98
     *
102 -
     * @param VersionNumber|mixed $versionNumber
99 +
     * @param VersionNumber|int|string $versionNumber
103 100
     *
104 101
     * @throws VersionNotFound
105 102
     * @throws RemoteConfigException if something went wrong
106 103
     */
107 104
    public function rollbackToVersion($versionNumber): Template
108 105
    {
109 -
        $versionNumber = $versionNumber instanceof VersionNumber
110 -
            ? $versionNumber
111 -
            : VersionNumber::fromValue($versionNumber);
112 -
113 -
        $response = $this->client->rollbackToVersion($versionNumber);
106 +
        $versionNumber = $this->ensureVersionNumber($versionNumber);
114 107
115 -
        return Template::fromResponse($response);
108 +
        return $this->buildTemplateFromResponse($this->client->rollbackToVersion($versionNumber));
116 109
    }
117 110
118 111
    /**
@@ -145,4 +138,30 @@
Loading
145 138
            $pageToken = $result['nextPageToken'] ?? null;
146 139
        } while ($pageToken);
147 140
    }
141 +
142 +
    /**
143 +
     * @param Template|array<string, mixed> $value
144 +
     */
145 +
    private function ensureTemplate($value): Template
146 +
    {
147 +
        return $value instanceof Template ? $value : Template::fromArray($value);
148 +
    }
149 +
150 +
    /**
151 +
     * @param VersionNumber|int|string $value
152 +
     */
153 +
    private function ensureVersionNumber($value): VersionNumber
154 +
    {
155 +
        return $value instanceof VersionNumber ? $value : VersionNumber::fromValue($value);
156 +
    }
157 +
158 +
    private function buildTemplateFromResponse(ResponseInterface $response): Template
159 +
    {
160 +
        $etagHeader = $response->getHeader('ETag');
161 +
        $etag = \array_shift($etagHeader) ?: '*';
162 +
163 +
        $data = JSON::decode((string) $response->getBody(), true);
164 +
165 +
        return Template::fromArray($data, $etag);
166 +
    }
148 167
}
Files Complexity Coverage
src/Firebase 1,460 66.05%
Project Totals (148 files) 1460 66.05%
1
comment:
2
  layout: "reach,diff"
3

4
coverage:
5
  status:
6
    project:
7
      default:
8
        informational: true
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading