Passed
Push — master ( 516f42...c66c88 )
by Pauli
03:14
created

Playlist::toApi()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
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 Morris Jobke <[email protected]>
10
 * @author Pauli Järvinen <[email protected]>
11
 * @copyright Morris Jobke 2014
12
 * @copyright Pauli Järvinen 2017 - 2025
13
 */
14
15
namespace OCA\Music\Db;
16
17
use OCA\Music\Utility\Util;
18
use OCP\IURLGenerator;
19
20
/**
21
 * @method string getName()
22
 * @method setName(string $name)
23
 * @method string getTrackIds()
24
 * @method setTrackIds(string $trackIds)
25
 * @method string getComment()
26
 * @method setComment(string $comment)
27
 * @method ?string getStarred()
28
 * @method void setStarred(?string $timestamp)
29
 * @method ?int getRating()
30
 * @method setRating(?int $rating)
31
 */
32
class Playlist extends Entity {
33
	public $name;
34
	public $trackIds;
35
	public $comment;
36
	public $starred;
37
	public $rating;
38
39
	// injected separately when needed
40
	private $duration;
41
	private $readOnly;
42
43
	public function __construct() {
44
		$this->addType('rating', 'int');
45
	}
46
47
	public function getDuration() : ?int {
48
		return $this->duration;
49
	}
50
51
	public function setDuration(?int $duration) : void {
52
		$this->duration = $duration;
53
	}
54
55
	public function getReadOnly() : bool {
56
		return $this->readOnly ?? false;
57
	}
58
59
	public function setReadOnly(bool $readOnly) : void {
60
		$this->readOnly = $readOnly;
61
	}
62
63
	public function getTrackCount() : int {
64
		return \count($this->getTrackIdsAsArray());
65
	}
66
67
	/**
68
	 * @return int[]
69
	 */
70
	public function getTrackIdsAsArray() : array {
71
		if ($this->isEmpty()) {
72
			return [];
73
		} else {
74
			$encoded = \substr($this->trackIds, 1, -1); // omit leading and trailing '|'
75
			return \array_map('intval', \explode('|', $encoded));
76
		}
77
	}
78
79
	/**
80
	 * @param int[] $trackIds
81
	 */
82
	public function setTrackIdsFromArray(array $trackIds) : void {
83
		// encode to format like "|123|45|667|"
84
		$this->setTrackIds('|' . \implode('|', $trackIds) . '|');
85
	}
86
87
	public function getTrackIdsHash() : ?string {
88
		return $this->isEmpty() ? null : \md5($this->getTrackIds());
89
	}
90
91
	public function toApi(IURLGenerator $urlGenerator) : array {
92
		return [
93
			'name' => $this->getName(),
94
			'trackIds' => $this->getTrackIdsAsArray(),
95
			'id' => $this->getId(),
96
			'created' => $this->getCreated(),
97
			'updated' => $this->getUpdated(),
98
			'comment' => $this->getComment(),
99
			'cover' => $this->getCoverUrl($urlGenerator)
100
		];
101
	}
102
103
	public function toShivaApi(IURLGenerator $urlGenerator) : array {
104
		$trackIds = $this->getTrackIdsAsArray();
105
		return [
106
			'name' => $this->getName(),
107
			'lenght' => \count($trackIds),
108
			'tracks' => \array_map(fn($id, $index) => [
109
				'id' => $id,
110
				'index' => $index,
111
				'uri' => $urlGenerator->linkToRoute('music.shivaApi.track', ['id' => $id])
112
			], $trackIds, \array_keys($trackIds)),
113
			'id' => $this->getId(),
114
			'creation_date' => $this->getCreated()
115
		];
116
	}
117
118
	public function toAmpacheApi(callable $createImageUrl, bool $includeTracks) : array {
119
		$result = [
120
			'id' => (string)$this->getId(),
121
			'name' => $this->getName(),
122
			'owner' => $this->getUserId(),
123
			'art' => $createImageUrl($this),
124
			'flag' => !empty($this->getStarred()),
125
			'rating' => $this->getRating() ?? 0,
126
			'type' => 'Private',
127
			'has_access' => !$this->getReadOnly(),
128
			'has_collaborate' => !$this->getReadOnly(),
129
			'last_update' => \strtotime($this->getUpdated()),
130
			'md5' => $this->getTrackIdsHash()
131
		];
132
		$result['has_art'] = !empty($result['art']);
133
134
		if ($includeTracks) {
135
			$ids = $this->getTrackIdsAsArray();
136
			$result['items'] = ['playlisttrack' => \array_map(fn(int $trackId, int $index) => [
137
				'id' => (string)$trackId,
138
				'text' => $index + 1
139
			], $ids, \array_keys($ids))];
140
		} else {
141
			$result['items'] = $this->getTrackCount();
142
		}
143
144
		return $result;
145
	}
146
147
	public function toSubsonicApi() : array {
148
		return [
149
			'id' => (string)$this->getId(),
150
			'name' => $this->getName(),
151
			'owner' => $this->userId,
152
			'public' => false,
153
			'songCount' => $this->getTrackCount(),
154
			'duration' => $this->getDuration(),
155
			'comment' => $this->getComment() ?: '',
156
			'created' => Util::formatZuluDateTime($this->getCreated()),
157
			'changed' => Util::formatZuluDateTime($this->getUpdated()),
158
			'coverArt' => 'pl-' . $this->getId() // work around: DSub always fetches the art using ID like "pl-NNN" even if we would use some other format here
159
		];
160
	}
161
162
	private function isEmpty() : bool {
163
		// the list is empty if there is nothing between the leading and trailing '|'
164
		return (!$this->trackIds || \strlen($this->trackIds) < 3);
165
	}
166
167
	private function getCoverUrl(IURLGenerator $urlGenerator) : ?string {
168
		// the list might not have an id in case it's a generated playlist
169
		if ($this->getId() && !$this->isEmpty()) {
170
			return $urlGenerator->linkToRoute('music.playlistApi.getCover', ['id' => $this->getId()]);
171
		} else {
172
			return null;
173
		}
174
	}
175
}
176