Passed
Push — master ( 384962...a2213c )
by Benjamin
26:55 queued 19:06
created

Metadata::getSubContinentCode()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 1
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
1
<?php
2
/**
3
 * @link      https://dukt.net/analytics/
4
 * @copyright Copyright (c) 2018, Dukt
5
 * @license   https://github.com/dukt/analytics/blob/master/LICENSE.md
6
 */
7
8
namespace dukt\analytics\services;
9
10
use Craft;
11
use yii\base\Component;
12
use craft\helpers\Json;
13
use dukt\analytics\models\Column;
14
use dukt\analytics\Plugin as Analytics;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, dukt\analytics\services\Analytics. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
15
16
class Metadata extends Component
17
{
18
    // Properties
19
    // =========================================================================
20
21
    /**
22
     * @var array|null
23
     */
24
    private $groups;
25
26
    /**
27
     * @var array|null
28
     */
29
    private $dimensions;
30
31
    /**
32
     * @var array|null
33
     */
34
    private $metrics;
35
36
    /**
37
     * @var array|null
38
     */
39
    private $columns;
40
41
    /**
42
     * @var array|null
43
     */
44
    private $selectDimensionOptions;
45
46
    /**
47
     * @var array|null
48
     */
49
    private $selectMetricOptions;
50
51
    // Public Methods
52
    // =========================================================================
53
54
    /**
55
     * Checks whether the dimensions & metrics file exists
56
     *
57
     * @return bool
58
     */
59
    public function dimmetsFileExists(): bool
60
    {
61
        $path = Analytics::$plugin->metadata->getDimmetsFilePath();
62
63
        if (file_exists($path)) {
64
            return true;
65
        }
66
67
        return false;
68
    }
69
70
    /**
71
     * Returns available data types for Google Analytics
72
     *
73
     * @param mixed
74
     *
75
     * @return array
76
     */
77
    public function getGoogleAnalyticsDataTypes(): array
78
    {
79
        $columns = $this->getColumns();
80
81
        $dataTypes = [];
82
83
        foreach ($columns as $column) {
84
            if (!isset($dataTypes[$column->dataType]) && !empty($column->dataType)) {
85
                $dataTypes[$column->dataType] = $column->dataType;
86
            }
87
        }
88
89
        return $dataTypes;
90
    }
91
92
    /**
93
     * Returns available data types
94
     *
95
     * @param mixed
96
     *
97
     * @return array
98
     */
99
    public function getDataTypes(): array
100
    {
101
        return [
102
            'string',
103
            'integer',
104
            'percent',
105
            'time',
106
            'currency',
107
            'float',
108
            'date'
109
        ];
110
    }
111
112
    /**
113
     * Get a dimension or a metric label from its id
114
     *
115
     * @param string $id
116
     *
117
     * @return mixed
118
     */
119
    public function getDimMet($id)
120
    {
121
        $columns = $this->getColumns();
122
123
        if (isset($columns[$id])) {
124
            return $columns[$id]->uiName;
125
        }
126
127
        return null;
128
    }
129
130
    /**
131
     * Returns columns based on a search string `$q`
132
     *
133
     * @param string $q
134
     *
135
     * @return array
136
     */
137
    public function searchColumns($q): array
138
    {
139
        $columns = $this->getColumns();
140
        $results = [];
141
142
        foreach ($columns as $column) {
143
            if (stripos($column->id, $q) !== false || stripos($column->uiName, $q) !== false) {
144
                $results[] = $column;
145
            }
146
        }
147
148
        return $results;
149
    }
150
151
    /**
152
     * Returns columns
153
     *
154
     * @param string $type
155
     *
156
     * @return array
157
     */
158
    public function getColumns(string $type = null): array
159
    {
160
        if (!$this->columns) {
161
            $this->columns = $this->_loadColumns();
162
        }
163
164
        if (!$type) {
165
            return $this->columns;
166
        }
167
168
        return $this->getColumnsByType($type);
169
    }
170
171
    /**
172
     * Returns dimension columns
173
     *
174
     * @return array
175
     */
176
    public function getDimensions(): array
177
    {
178
        if (!$this->dimensions) {
179
            $this->dimensions = $this->getColumns('DIMENSION');
180
        }
181
182
        return $this->dimensions;
183
    }
184
185
    /**
186
     * Returns column groups
187
     *
188
     * @param string|null $type
189
     *
190
     * @return array
191
     */
192
    public function getColumnGroups(string $type = null): array
193
    {
194
        if ($type && isset($this->groups[$type])) {
195
            return $this->groups[$type];
196
        }
197
198
        $groups = $this->_getColumnGroups($type);
199
200
        if ($type) {
201
            $this->groups[$type] = $groups;
202
        }
203
204
        return $groups;
205
    }
206
207
    /**
208
     * Returns select dimension options
209
     *
210
     * @param array $filters
211
     *
212
     * @return array
213
     */
214
    public function getSelectDimensionOptions(array $filters = null): array
215
    {
216
        if (!$this->selectDimensionOptions) {
217
            $this->selectDimensionOptions = $this->getSelectOptions('DIMENSION');
218
        }
219
220
        if ($filters) {
221
            $this->selectDimensionOptions = $this->filterOptions($this->selectDimensionOptions, $filters);
222
        }
223
224
        return $this->selectDimensionOptions;
225
    }
226
227
    /**
228
     * Returns select metric options
229
     *
230
     * @param array $filters
231
     *
232
     * @return array
233
     */
234
    public function getSelectMetricOptions(array $filters = null): array
235
    {
236
        if (!$this->selectMetricOptions) {
237
            $this->selectMetricOptions = $this->getSelectOptions('METRIC');
238
        }
239
240
        if ($filters) {
241
            $this->selectMetricOptions = $this->filterOptions($this->selectMetricOptions, $filters);
242
        }
243
244
        return $this->selectMetricOptions;
245
    }
246
247
    /**
248
     * Returns select options
249
     *
250
     * @param null  $type
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $type is correct as it would always require null to be passed?
Loading history...
251
     * @param array $filters
252
     *
253
     * @return array
254
     */
255
    public function getSelectOptions($type = null, array $filters = null): array
256
    {
257
        $options = [];
258
259
        foreach ($this->getColumnGroups($type) as $group) {
260
            $options[]['optgroup'] = Craft::t('analytics', $group);
261
262
            foreach ($this->getColumns($type) as $column) {
263
                if ($column->group === $group) {
264
                    $options[$column->id] = Craft::t('analytics', $column->uiName);
265
                }
266
            }
267
        }
268
269
        if ($filters) {
270
            $options = $this->filterOptions($options, $filters);
271
        }
272
273
        return $options;
274
    }
275
276
    /**
277
     * Returns the metrics
278
     *
279
     * @return array
280
     */
281
    public function getMetrics(): array
282
    {
283
        if (!$this->metrics) {
284
            $this->metrics = $this->getColumns('METRIC');
285
        }
286
287
        return $this->metrics;
288
    }
289
290
    /**
291
     * Returns the file path of the dimensions-metrics.json file
292
     *
293
     * @return string|bool
294
     */
295
    public function getDimmetsFilePath()
296
    {
297
        return Craft::getAlias('@dukt/analytics/etc/data/dimensions-metrics.json');
298
    }
299
300
    // Private Methods
301
    // =========================================================================
302
303
    /**
304
     * Loads the columns from the dimensions-metrics.json file
305
     *
306
     * @return array
307
     */
308
    private function _loadColumns(): array
309
    {
310
        $cols = [];
311
        $path = Analytics::$plugin->metadata->getDimmetsFilePath();
312
        $contents = file_get_contents($path);
313
        $columnsResponse = Json::decode($contents);
314
315
        if (!$columnsResponse) {
316
            return $cols;
317
        }
318
319
        foreach ($columnsResponse as $columnResponse) {
320
            $cols[$columnResponse['id']] = new Column($columnResponse);
321
322
            if ($columnResponse['id'] === 'ga:countryIsoCode') {
323
                $cols[$columnResponse['id']]->uiName = 'Country';
324
            }
325
        }
326
327
        return $cols;
328
    }
329
330
    /**
331
     * @param array $options
332
     * @param array $filters
333
     *
334
     * @return array
335
     */
336
    private function filterOptions(array $options, array $filters): array
337
    {
338
        if (\count($filters) === 0) {
339
            return $options;
340
        }
341
342
        return $this->getFilteredOptions($options, $filters);
343
    }
344
345
    /**
346
     * Get filtered options.
347
     *
348
     * @param array $options
349
     * @param array $filters
350
     *
351
     * @return array
352
     */
353
    private function getFilteredOptions(array $options, array $filters): array
354
    {
355
        $filteredOptions = [];
356
        $optgroup = null;
357
        $lastOptgroup = null;
358
359
        foreach ($options as $id => $option) {
360
            if (isset($option['optgroup'])) {
361
                $optgroup = null;
362
                $lastOptgroup = $option['optgroup'];
363
                continue;
364
            }
365
366
            foreach ($filters as $filter) {
367
                if ($id !== $filter) {
368
                    continue;
369
                }
370
371
                if (!$optgroup) {
372
                    $optgroup = $lastOptgroup;
373
                    $filteredOptions[]['optgroup'] = $optgroup;
374
                }
375
376
                $filteredOptions[$id] = $option;
377
            }
378
        }
379
380
        return $filteredOptions;
381
    }
382
383
    /**
384
     * Get column groups.
385
     *
386
     * @param string|null $type
387
     * @return array
388
     */
389
    private function _getColumnGroups(string $type = null): array
390
    {
391
        $groups = [];
392
393
        foreach ($this->getColumns() as $column) {
394
            if (!$type || ($type && $column->type === $type)) {
395
                $groups[$column->group] = $column->group;
396
            }
397
        }
398
399
        return $groups;
400
    }
401
402
    /**
403
     * Get columns by type.
404
     *
405
     * @param string $type
406
     * @return array
407
     */
408
    private function getColumnsByType(string $type): array
409
    {
410
        $columns = [];
411
412
        foreach ($this->columns as $column) {
413
            if ($column->type === $type) {
414
                $columns[] = $column;
415
            }
416
        }
417
418
        return $columns;
419
    }
420
}
421