Passed
Push — master ( 62782a...a28cef )
by Marcel
04:19
created

LocalJson::readData()   C

Complexity

Conditions 12
Paths 7

Size

Total Lines 71
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 42
nc 7
nop 1
dl 0
loc 71
rs 6.9666
c 1
b 0
f 0

How to fix   Long Method    Complexity   

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
 * Analytics
4
 *
5
 * SPDX-FileCopyrightText: 2019-2022 Marcel Scherello
6
 * SPDX-License-Identifier: AGPL-3.0-or-later
7
 */
8
9
namespace OCA\Analytics\Datasource;
10
11
use OCP\Files\IRootFolder;
0 ignored issues
show
Bug introduced by
The type OCP\Files\IRootFolder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use OCP\IL10N;
0 ignored issues
show
Bug introduced by
The type OCP\IL10N was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Psr\Log\LoggerInterface;
0 ignored issues
show
Bug introduced by
The type Psr\Log\LoggerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
15
class LocalJson implements IDatasource
16
{
17
	private $rootFolder;
18
    private LoggerInterface $logger;
19
    private IL10N $l10n;
20
21
    public function __construct(
22
        IL10N           $l10n,
23
		IRootFolder $rootFolder,
24
        LoggerInterface $logger
25
    )
26
    {
27
        $this->l10n = $l10n;
28
		$this->rootFolder = $rootFolder;
29
        $this->logger = $logger;
30
    }
31
32
    /**
33
     * @return string Display Name of the datasource
34
     */
35
    public function getName(): string
36
    {
37
        return $this->l10n->t('Local') . ': JSON';
38
    }
39
40
    /**
41
     * @return int digit unique datasource id
42
     */
43
    public function getId(): int
44
    {
45
        return 6;
46
    }
47
48
    /**
49
     * @return array available options of the datasoure
50
     */
51
    public function getTemplate(): array
52
    {
53
        $template = array();
54
		$template[] = ['id' => 'link', 'name' => $this->l10n->t('LocalCsv'), 'placeholder' => $this->l10n->t('LocalCsv'), 'type' => 'filePicker'];
55
        $template[] = ['id' => 'path', 'name' => $this->l10n->t('Object path'), 'placeholder' => 'x/y/z'];
56
        $template[] = ['id' => 'timestamp', 'name' => $this->l10n->t('Timestamp of data load'), 'placeholder' => 'true-' . $this->l10n->t('Yes') . '/false-' . $this->l10n->t('No'), 'type' => 'tf'];
57
        return $template;
58
    }
59
60
    /**
61
     * Read the Data
62
     * @param $option
63
     * @return array available options of the datasoure
64
     */
65
    public function readData($option): array
66
    {
67
		$error = 0;
68
		$path = $option['path'];
69
		$file = $this->rootFolder->getUserFolder($option['user_id'])->get($option['link']);
70
		$rawResult = $file->getContent();
71
72
		$json = json_decode($rawResult, true);
73
74
        // check if a specific array of values should be extracted
75
        // e.g. {BTC,tmsp,price}
76
        preg_match_all("/(?<={).*(?=})/", $path, $matches);
77
        if (count($matches[0]) > 0) {
78
            // array extraction
79
80
            // check if absolute path is in front of the array
81
            // e.g. data/data{from,to,intensity/forecast}
82
            $firstArray = strpos($path, '{');
83
            if ($firstArray && $firstArray !== 0) {
84
                $singlePath = substr($path, 0, $firstArray);
85
                $json = $this->get_nested_array_value($json, $singlePath);
86
            }
87
88
            // separate the fields of the array {BTC,tmsp,price}
89
            $paths = explode(',', $matches[0][0]);
90
            // fill up with dummies in case of missing columns
91
            while (count($paths) < 3) {
92
                array_unshift($paths, 'empty');
93
            }
94
            foreach ($json as $rowArray) {
95
                // get the array fields from the json
96
                // if no match is not found, the field name will be used as a constant string
97
                $dim1 = $this->get_nested_array_value($rowArray, $paths[0]) ?: $paths[0];
98
                $dim2 = $this->get_nested_array_value($rowArray, $paths[1]) ?: $paths[1];
99
                $val = $this->get_nested_array_value($rowArray, $paths[2]) ?: $paths[2];
100
                $data[] = [$dim1, $dim2, $val];
101
            }
102
        } else {
103
            // single value extraction
104
            // e.g. data/currentHashrate,data/averageHashrate
105
            $paths = explode(',', $path);
106
            foreach ($paths as $singlePath) {
107
                // e.g. data/currentHashrate
108
                $array = $this->get_nested_array_value($json, $singlePath);
109
110
                if (is_array($array)) {
111
                    // if the tartet is an array itself
112
                    foreach ($array as $key => $value) {
113
                        $pathArray = explode('/', $singlePath);
114
                        $group = end($pathArray);
115
                        $data[] = [$group, $key, $value];
116
                    }
117
                } else {
118
                    $pathArray = explode('/', $singlePath);
119
                    $key = end($pathArray);
120
                    $data[] = ['', $key, $array];
121
                }
122
            }
123
        }
124
125
        $header = array();
126
        $header[0] = '';
127
        $header[1] = 'Key';
128
        $header[2] = 'Value';
129
130
        return [
131
            'header' => $header,
132
            'dimensions' => array_slice($header, 0, count($header) - 1),
133
            'data' => $data,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $data does not seem to be defined for all execution paths leading up to this point.
Loading history...
134
            'rawdata' => $rawResult,
135
            'error' => $error,
136
        ];
137
    }
138
139
    /**
140
     * get array object from string
141
     *
142
     * @NoAdminRequired
143
     * @param $array
144
     * @param $path
145
     * @return array|string|null
146
     */
147
    private function get_nested_array_value(&$array, $path)
148
    {
149
        $pathParts = explode('/', $path);
150
        $current = &$array;
151
        foreach ($pathParts as $key) {
152
            $current = &$current[$key];
153
        }
154
        return $current;
155
    }
156
}