NotificationResolver::resolve()   B
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 211

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 211
rs 8
c 0
b 0
f 0
cc 1
nc 1
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace OneSignal\Resolver;
6
7
use DateTimeInterface;
8
use OneSignal\Config;
9
use Symfony\Component\OptionsResolver\Options;
10
use Symfony\Component\OptionsResolver\OptionsResolver;
11
12
class NotificationResolver implements ResolverInterface
13
{
14
    public const SEND_AFTER_FORMAT = 'Y-m-d H:i:sO';
15
    public const DELIVERY_TIME_OF_DAY_FORMAT = 'g:iA';
16
17
    private $config;
18
19
    public function __construct(Config $config)
20
    {
21
        $this->config = $config;
22
    }
23
24
    /**
25
     * {@inheritdoc}
26
     */
27
    public function resolve(array $data): array
28
    {
29
        return (new OptionsResolver())
30
            ->setDefined('contents')
31
            ->setAllowedTypes('contents', 'array')
32
            ->setDefined('headings')
33
            ->setAllowedTypes('headings', 'array')
34
            ->setDefined('subtitle')
35
            ->setAllowedTypes('subtitle', 'array')
36
            ->setDefined('isIos')
37
            ->setAllowedTypes('isIos', 'bool')
38
            ->setDefined('isAndroid')
39
            ->setAllowedTypes('isAndroid', 'bool')
40
            ->setDefined('isWP')
41
            ->setAllowedTypes('isWP', 'bool')
42
            ->setDefined('isWP_WNS')
43
            ->setAllowedTypes('isWP_WNS', 'bool')
44
            ->setDefined('isAdm')
45
            ->setAllowedTypes('isAdm', 'bool')
46
            ->setDefined('isChrome')
47
            ->setAllowedTypes('isChrome', 'bool')
48
            ->setDefined('isChromeWeb')
49
            ->setAllowedTypes('isChromeWeb', 'bool')
50
            ->setDefined('isFirefox')
51
            ->setAllowedTypes('isFirefox', 'bool')
52
            ->setDefined('isSafari')
53
            ->setAllowedTypes('isSafari', 'bool')
54
            ->setDefined('isAnyWeb')
55
            ->setAllowedTypes('isAnyWeb', 'bool')
56
            ->setDefined('included_segments')
57
            ->setAllowedTypes('included_segments', 'array')
58
            ->setDefined('excluded_segments')
59
            ->setAllowedTypes('excluded_segments', 'array')
60
            ->setDefined('include_player_ids')
61
            ->setAllowedTypes('include_player_ids', 'array')
62
            ->setDefined('include_ios_tokens')
63
            ->setAllowedTypes('include_ios_tokens', 'array')
64
            ->setDefined('include_android_reg_ids')
65
            ->setAllowedTypes('include_android_reg_ids', 'array')
66
            ->setDefined('include_external_user_ids')
67
            ->setAllowedTypes('include_external_user_ids', 'array')
68
            ->setDefined('channel_for_external_user_ids')
69
            ->setAllowedTypes('channel_for_external_user_ids', 'string')
70
            ->setAllowedValues('channel_for_external_user_ids', ['push', 'email'])
71
            ->setDefined('include_email_tokens')
72
            ->setAllowedTypes('include_email_tokens', 'array')
73
            ->setDefined('include_wp_uris')
74
            ->setAllowedTypes('include_wp_uris', 'array')
75
            ->setDefined('include_wp_wns_uris')
76
            ->setAllowedTypes('include_wp_wns_uris', 'array')
77
            ->setDefined('include_amazon_reg_ids')
78
            ->setAllowedTypes('include_amazon_reg_ids', 'array')
79
            ->setDefined('include_chrome_reg_ids')
80
            ->setAllowedTypes('include_chrome_reg_ids', 'array')
81
            ->setDefined('include_chrome_web_reg_ids')
82
            ->setAllowedTypes('include_chrome_web_reg_ids', 'array')
83
            ->setDefined('app_ids')
84
            ->setAllowedTypes('app_ids', 'array')
85
            ->setDefined('filters')
86
            ->setAllowedTypes('filters', 'array')
87
            ->setNormalizer('filters', function (Options $options, array $values) {
88
                return $this->normalizeFilters($options, $values);
89
            })
90
            ->setDefined('ios_badgeType')
91
            ->setAllowedTypes('ios_badgeType', 'string')
92
            ->setAllowedValues('ios_badgeType', ['None', 'SetTo', 'Increase'])
93
            ->setDefined('ios_badgeCount')
94
            ->setAllowedTypes('ios_badgeCount', 'int')
95
            ->setDefined('ios_sound')
96
            ->setAllowedTypes('ios_sound', 'string')
97
            ->setDefined('android_sound')
98
            ->setAllowedTypes('android_sound', 'string')
99
            ->setDefined('adm_sound')
100
            ->setAllowedTypes('adm_sound', 'string')
101
            ->setDefined('wp_sound')
102
            ->setAllowedTypes('wp_sound', 'string')
103
            ->setDefined('wp_wns_sound')
104
            ->setAllowedTypes('wp_wns_sound', 'string')
105
            ->setDefined('data')
106
            ->setAllowedTypes('data', 'array')
107
            ->setDefined('buttons')
108
            ->setAllowedTypes('buttons', 'array')
109
            ->setNormalizer('buttons', function (Options $options, array $values) {
110
                return $this->normalizeButtons($values);
111
            })
112
            ->setDefined('android_channel_id')
113
            ->setAllowedTypes('android_channel_id', 'string')
114
            ->setDefined('existing_android_channel_id')
115
            ->setAllowedTypes('existing_android_channel_id', 'string')
116
            ->setDefined('android_background_layout')
117
            ->setAllowedTypes('android_background_layout', 'array')
118
            ->setAllowedValues('android_background_layout', function (array $layouts) {
119
                return $this->filterAndroidBackgroundLayout($layouts);
120
            })
121
            ->setDefined('small_icon')
122
            ->setAllowedTypes('small_icon', 'string')
123
            ->setDefined('large_icon')
124
            ->setAllowedTypes('large_icon', 'string')
125
            ->setDefined('ios_attachments')
126
            ->setAllowedTypes('ios_attachments', 'array')
127
            ->setAllowedValues('ios_attachments', function (array $attachments) {
128
                return $this->filterIosAttachments($attachments);
129
            })
130
            ->setDefined('big_picture')
131
            ->setAllowedTypes('big_picture', 'string')
132
            ->setDefined('adm_small_icon')
133
            ->setAllowedTypes('adm_small_icon', 'string')
134
            ->setDefined('adm_large_icon')
135
            ->setAllowedTypes('adm_large_icon', 'string')
136
            ->setDefined('adm_big_picture')
137
            ->setAllowedTypes('adm_big_picture', 'string')
138
            ->setDefined('web_buttons')
139
            ->setAllowedTypes('web_buttons', 'array')
140
            ->setAllowedValues('web_buttons', function (array $buttons) {
141
                return $this->filterWebButtons($buttons);
142
            })
143
            ->setDefined('ios_category')
144
            ->setAllowedTypes('ios_category', 'string')
145
            ->setDefined('chrome_icon')
146
            ->setAllowedTypes('chrome_icon', 'string')
147
            ->setDefined('chrome_big_picture')
148
            ->setAllowedTypes('chrome_big_picture', 'string')
149
            ->setDefined('chrome_web_icon')
150
            ->setAllowedTypes('chrome_web_icon', 'string')
151
            ->setDefined('chrome_web_image')
152
            ->setAllowedTypes('chrome_web_image', 'string')
153
            ->setDefined('chrome_web_badge')
154
            ->setAllowedTypes('chrome_web_badge', 'string')
155
            ->setDefined('firefox_icon')
156
            ->setAllowedTypes('firefox_icon', 'string')
157
            ->setDefined('url')
158
            ->setAllowedTypes('url', 'string')
159
            ->setAllowedValues('url', function (string $value) {
160
                return $this->filterUrl($value);
161
            })
162
            ->setDefined('web_url')
163
            ->setAllowedTypes('web_url', 'string')
164
            ->setAllowedValues('web_url', function (string $value) {
165
                return $this->filterUrl($value);
166
            })
167
            ->setDefined('app_url')
168
            ->setAllowedTypes('app_url', 'string')
169
            ->setDefined('send_after')
170
            ->setAllowedTypes('send_after', DateTimeInterface::class)
171
            ->setNormalizer('send_after', function (Options $options, DateTimeInterface $value) {
172
                return $this->normalizeDateTime($options, $value, self::SEND_AFTER_FORMAT);
173
            })
174
            ->setDefined('delayed_option')
175
            ->setAllowedTypes('delayed_option', 'string')
176
            ->setAllowedValues('delayed_option', ['timezone', 'last-active'])
177
            ->setDefined('delivery_time_of_day')
178
            ->setAllowedTypes('delivery_time_of_day', DateTimeInterface::class)
179
            ->setNormalizer('delivery_time_of_day', function (Options $options, DateTimeInterface $value) {
180
                return $this->normalizeDateTime($options, $value, self::DELIVERY_TIME_OF_DAY_FORMAT);
181
            })
182
            ->setDefined('android_led_color')
183
            ->setAllowedTypes('android_led_color', 'string')
184
            ->setDefined('android_accent_color')
185
            ->setAllowedTypes('android_accent_color', 'string')
186
            ->setDefined('android_visibility')
187
            ->setAllowedTypes('android_visibility', 'int')
188
            ->setAllowedValues('android_visibility', [-1, 0, 1])
189
            ->setDefined('collapse_id')
190
            ->setAllowedTypes('collapse_id', 'string')
191
            ->setDefined('content_available')
192
            ->setAllowedTypes('content_available', 'bool')
193
            ->setDefined('mutable_content')
194
            ->setAllowedTypes('mutable_content', 'bool')
195
            ->setDefined('android_background_data')
196
            ->setAllowedTypes('android_background_data', 'bool')
197
            ->setDefined('amazon_background_data')
198
            ->setAllowedTypes('amazon_background_data', 'bool')
199
            ->setDefined('template_id')
200
            ->setAllowedTypes('template_id', 'string')
201
            ->setDefined('android_group')
202
            ->setAllowedTypes('android_group', 'string')
203
            ->setDefined('android_group_message')
204
            ->setAllowedTypes('android_group_message', 'array')
205
            ->setDefined('adm_group')
206
            ->setAllowedTypes('adm_group', 'string')
207
            ->setDefined('adm_group_message')
208
            ->setAllowedTypes('adm_group_message', 'array')
209
            ->setDefined('thread_id')
210
            ->setAllowedTypes('thread_id', 'string')
211
            ->setDefined('summary_arg')
212
            ->setAllowedTypes('summary_arg', 'string')
213
            ->setDefined('summary_arg_count')
214
            ->setAllowedTypes('summary_arg_count', 'int')
215
            ->setDefined('ttl')
216
            ->setAllowedTypes('ttl', 'int')
217
            ->setDefined('priority')
218
            ->setAllowedTypes('priority', 'int')
219
            ->setDefault('app_id', $this->config->getApplicationId())
220
            ->setAllowedTypes('app_id', 'string')
221
            ->setDefined('email_subject')
222
            ->setAllowedTypes('email_subject', 'string')
223
            ->setDefined('email_body')
224
            ->setAllowedTypes('email_body', 'string')
225
            ->setDefined('email_from_name')
226
            ->setAllowedTypes('email_from_name', 'string')
227
            ->setDefined('email_from_address')
228
            ->setAllowedTypes('email_from_address', 'string')
229
            ->setDefined('external_id')
230
            ->setAllowedTypes('external_id', 'string')
231
            ->setDefined('web_push_topic')
232
            ->setAllowedTypes('web_push_topic', 'string')
233
            ->setDefined('apns_push_type_override')
234
            ->setAllowedTypes('apns_push_type_override', 'string')
235
            ->setAllowedValues('apns_push_type_override', ['voip'])
236
            ->resolve($data);
237
    }
238
239
    private function normalizeFilters(Options $options, array $values): array
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
240
    {
241
        $filters = [];
242
243
        foreach ($values as $filter) {
244
            if (isset($filter['field'])) {
245
                $filters[] = $filter;
246
            } elseif (isset($filter['operator'])) {
247
                $filters[] = ['operator' => 'OR'];
248
            }
249
        }
250
251
        return $filters;
252
    }
253
254
    /**
255
     * @param mixed $value
256
     */
257
    private function filterUrl($value): bool
258
    {
259
        return (bool) filter_var($value, FILTER_VALIDATE_URL);
260
    }
261
262
    private function normalizeButtons(array $values): array
263
    {
264
        $buttons = [];
265
266
        foreach ($values as $button) {
267
            if (!isset($button['text'])) {
268
                continue;
269
            }
270
271
            $buttons[] = [
272
                'id' => $button['id'] ?? random_int(0, PHP_INT_MAX),
273
                'text' => $button['text'],
274
                'icon' => $button['icon'] ?? null,
275
            ];
276
        }
277
278
        return $buttons;
279
    }
280
281
    private function filterAndroidBackgroundLayout(array $layouts): bool
282
    {
283
        if (count($layouts) === 0) {
284
            return false;
285
        }
286
287
        $requiredKeys = ['image', 'headings_color', 'contents_color'];
288
289
        foreach ($layouts as $k => $v) {
290
            if (!is_string($v) || !in_array($k, $requiredKeys, true)) {
291
                return false;
292
            }
293
        }
294
295
        return true;
296
    }
297
298
    private function filterIosAttachments(array $attachments): bool
299
    {
300
        foreach ($attachments as $key => $value) {
301
            if (!is_string($key) || !is_string($value)) {
302
                return false;
303
            }
304
        }
305
306
        return true;
307
    }
308
309
    private function filterWebButtons(array $buttons): bool
310
    {
311
        $requiredKeys = ['id', 'text', 'icon', 'url'];
312
313
        foreach ($buttons as $button) {
314
            if (!is_array($button)) {
315
                return false;
316
            }
317
318
            if (count(array_intersect_key(array_flip($requiredKeys), $button)) !== count($requiredKeys)) {
319
                return false;
320
            }
321
        }
322
323
        return true;
324
    }
325
326
    private function normalizeDateTime(Options $options, DateTimeInterface $value, string $format): string
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
327
    {
328
        return $value->format($format);
329
    }
330
}
331