Passed
Push — master ( fda064...6b712c )
by Pauli
05:03
created

DetailsHelper::getDetails()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 44
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 6
Bugs 0 Features 0
Metric Value
cc 6
eloc 22
c 6
b 0
f 0
nc 9
nop 2
dl 0
loc 44
ccs 0
cts 21
cp 0
crap 42
rs 8.9457
1
<?php
2
3
/**
4
 * ownCloud - Music app
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Pauli Järvinen <[email protected]>
10
 * @copyright Pauli Järvinen 2018, 2019
11
 */
12
13
namespace OCA\Music\Utility;
14
15
use \OCA\Music\AppFramework\Core\Logger;
16
17
18
19
class DetailsHelper {
20
	private $extractor;
21
	private $logger;
22
23
	public function __construct(
24
			Extractor $extractor,
25
			Logger $logger) {
26
		$this->extractor = $extractor;
27
		$this->logger = $logger;
28
	}
29
30
	/**
31
	 * @param integer $fileId
32
	 * @param Folder $userFolder
0 ignored issues
show
Bug introduced by
The type OCA\Music\Utility\Folder 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...
33
	 * $return array|null
34
	 */
35
	public function getDetails($fileId, $userFolder) {
36
		$fileNodes = $userFolder->getById($fileId);
37
		if (\count($fileNodes) > 0) {
38
			$data = $this->extractor->extract($fileNodes[0]);
39
40
			// remove intermediate arrays
41
			$data['comments'] = self::flattenComments($data['comments']);
42
43
			// cleanup strings from invalid characters
44
			\array_walk($data['audio'], ['self', 'sanitizeString']);
45
			\array_walk($data['comments'], ['self', 'sanitizeString']);
46
47
			$result = [
48
				'fileinfo' => $data['audio'],
49
				'tags' => $data['comments']
50
			];
51
52
			// binary data has to be encoded
53
			if (\array_key_exists('picture', $result['tags'])) {
54
				$result['tags']['picture'] = self::encodePictureTag($result['tags']['picture']);
55
			}
56
57
			// 'streams' contains duplicate data
58
			unset($result['fileinfo']['streams']);
59
60
			// one track number is enough
61
			if (\array_key_exists('track', $result['tags'])
62
				&& \array_key_exists('track_number', $result['tags'])) {
63
				unset($result['tags']['track']);
64
			}
65
66
			// add track length
67
			if (\array_key_exists('playtime_seconds', $data)) {
68
				$result['length'] = \ceil($data['playtime_seconds']);
69
			} else {
70
				$result['length'] = null;
71
			}
72
73
			// add file path
74
			$result['path'] = $userFolder->getRelativePath($fileNodes[0]->getPath());
75
76
			return $result;
77
		}
78
		return null;
79
	}
80
81
	/**
82
	 * @param integer $fileId
83
	 * @param Folder $userFolder
84
	 * $return string|null
85
	 */
86
	public function getLyrics($fileId, $userFolder) {
87
		$lyrics = null;
88
		$fileNodes = $userFolder->getById($fileId);
89
		if (\count($fileNodes) > 0) {
90
			$data = $this->extractor->extract($fileNodes[0]);
91
			$lyrics = ExtractorGetID3::getFirstOfTags($data, ['unsynchronised_lyric', 'unsynced lyrics', 'LYRICS']);
92
		}
93
		return $lyrics;
94
	}
95
96
	/**
97
	 * Base64 encode the picture binary data and wrap it so that it can be directly used as
98
	 * src of an HTML img element.
99
	 * @param string $pic
100
	 * @return string|null
101
	 */
102
	private static function encodePictureTag($pic) {
103
		if ($pic['data']) {
104
			return 'data:' . $pic['image_mime'] . ';base64,' . \base64_encode($pic['data']);
105
		} else {
106
			return null;
107
		}
108
	}
109
110
	/**
111
	 * Remove potentially invalid characters from the string.
112
	 * @param $item
113
	 */
114
	private static function sanitizeString(&$item){
115
		if (is_string($item)) {
116
			$item = \mb_convert_encoding($item, 'UTF-8', 'UTF-8');
117
		}
118
	}
119
120
	/**
121
	 * In the 'comments' field from the extractor, the value for each key is a 1-element
122
	 * array containing the actual tag value. Remove these intermediate arrays.
123
	 * @param array $array
124
	 * @return array
125
	 */
126
	private static function flattenComments($array) {
127
		// key 'text' is an exception, its value is an associative array
128
		$textArray = null;
129
130
		foreach ($array as $key => $value) {
131
			if ($key === 'text') {
132
				$textArray = $value;
133
			} else {
134
				$array[$key] = $value[0];
135
			}
136
		}
137
138
		if (!empty($textArray)) {
139
			$array = \array_merge($array, $textArray);
140
			unset($array['text']);
141
		} 
142
143
		return $array;
144
	}
145
146
}
147