LocalJson::get_nested_array_value()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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