Completed
Push — stable9 ( ab68a4...eef0b3 )
by Olivier
10s
created

SearchMediaService   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 192
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 0 Features 1
Metric Value
wmc 23
c 4
b 0
f 1
lcom 1
cbo 1
dl 0
loc 192
ccs 57
cts 57
cp 1
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getMediaFiles() 0 7 1
A searchFolder() 0 20 4
A isPreviewAvailable() 0 14 3
A addFolderToAlbumsArray() 0 4 1
A addFileToImagesArray() 0 5 1
A addMediaFile() 0 7 2
A haveEnoughPictures() 0 7 2
A searchSubFolders() 0 14 4
A folderNeedsToBeSearched() 0 3 3
A abortSearch() 0 3 2
1
<?php
2
/**
3
 * ownCloud - galleryplus
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Olivier Paroz <[email protected]>
9
 *
10
 * @copyright Olivier Paroz 2014-2016
11
 */
12
13
namespace OCA\GalleryPlus\Service;
14
15
use OCP\Files\Folder;
16
use OCP\Files\File;
17
18
/**
19
 * Searches the instance for media files which can be shown
20
 *
21
 * @package OCA\GalleryPlus\Service
22
 */
23
class SearchMediaService extends FilesService {
24
25
	/** @var null|array<string,string|int> */
26
	private $images = [];
27
	/** @var null|array<string,string|int> */
28
	private $albums = [];
29
	/** @var string[] */
30
	private $supportedMediaTypes;
31
32
	/**
33
	 * This returns the list of all media files which can be shown starting from the given folder
34
	 *
35
	 * @param Folder $folderNode the current album
36
	 * @param string[] $supportedMediaTypes the list of supported media types
37
	 * @param array $features the list of supported features
38
	 *
39
	 * @return array<null|array<string,string|int>> all the images we could find
40
	 */
41 13
	public function getMediaFiles($folderNode, $supportedMediaTypes, $features) {
42 13
		$this->supportedMediaTypes = $supportedMediaTypes;
43 13
		$this->features = $features;
44 13
		$this->searchFolder($folderNode);
45
46 13
		return [$this->images, $this->albums];
47
	}
48
49
	/**
50
	 * Look for media files and folders in the given folder
51
	 *
52
	 * @param Folder $folder
53
	 * @param int $subDepth
54
	 *
55
	 * @return int
56
	 */
57 13
	private function searchFolder($folder, $subDepth = 0) {
58 13
		$albumImageCounter = 0;
59 13
		$subFolders = [];
60 13
		$this->addFolderToAlbumsArray($folder);
61 13
		$nodes = $this->getNodes($folder, $subDepth);
62 13
		foreach ($nodes as $node) {
63 13
			if (!$this->isAllowedAndAvailable($node)) {
64 1
				continue;
65
			}
66 13
			$nodeType = $this->getNodeType($node);
67 13
			$subFolders = array_merge($subFolders, $this->getAllowedSubFolder($node, $nodeType));
68 13
			$albumImageCounter = $this->addMediaFile($node, $nodeType, $albumImageCounter);
69 13
			if ($this->haveEnoughPictures($albumImageCounter, $subDepth)) {
70 13
				break;
71
			}
72
		}
73 13
		$albumImageCounter = $this->searchSubFolders($subFolders, $subDepth, $albumImageCounter);
74
75 13
		return $albumImageCounter;
76
	}
77
78
	/**
79
	 * Adds the node to the list of images if it's a file and we can generate a preview of it
80
	 *
81
	 * @param File|Folder $node
82
	 * @param string $nodeType
83
	 * @param int $albumImageCounter
84
	 *
85
	 * @return int
86
	 */
87 13
	private function addMediaFile($node, $nodeType, $albumImageCounter) {
88 13
		if ($nodeType === 'file') {
89 13
			$albumImageCounter = $albumImageCounter + (int)$this->isPreviewAvailable($node);
90
		}
91
92 13
		return $albumImageCounter;
93
	}
94
95
	/**
96
	 * Checks if we've collected enough pictures to be able to build the view
97
	 *
98
	 * An album is full when we find max 4 pictures at the same level
99
	 *
100
	 * @param int $albumImageCounter
101
	 * @param int $subDepth
102
	 *
103
	 * @return bool
104
	 */
105 13
	private function haveEnoughPictures($albumImageCounter, $subDepth) {
106 13
		if ($subDepth === 0) {
107 13
			return false;
108
		}
109
110 11
		return $albumImageCounter === 4;
111
	}
112
113
	/**
114
	 * Looks for pictures in sub-folders
115
	 *
116
	 * If we're at level 0, we need to look for pictures in sub-folders no matter what
117
	 * If we're at deeper levels, we only need to go further if we haven't managed to find one
118
	 * picture in the current folder
119
	 *
120
	 * @param array <Folder> $subFolders
121
	 * @param int $subDepth
122
	 * @param int $albumImageCounter
123
	 *
124
	 * @return int
125
	 */
126 13
	private function searchSubFolders($subFolders, $subDepth, $albumImageCounter) {
127 13
		if ($this->folderNeedsToBeSearched($subFolders, $subDepth, $albumImageCounter)) {
128 11
			$subDepth++;
129 11
			foreach ($subFolders as $subFolder) {
130
				//$this->logger->debug("Sub-Node path : {path}", ['path' => $subFolder->getPath()]);
131 11
				$albumImageCounter = $this->searchFolder($subFolder, $subDepth);
132 11
				if ($this->abortSearch($subDepth, $albumImageCounter)) {
133 11
					break;
134
				}
135
			}
136
		}
137
138 13
		return $albumImageCounter;
139
	}
140
141
	/**
142
	 * Checks if we need to look for media files in the specified folder
143
	 *
144
	 * @param array <Folder> $subFolders
145
	 * @param int $subDepth
146
	 * @param int $albumImageCounter
147
	 *
148
	 * @return bool
149
	 */
150 13
	private function folderNeedsToBeSearched($subFolders, $subDepth, $albumImageCounter) {
151 13
		return !empty($subFolders) && ($subDepth === 0 || $albumImageCounter === 0);
152
	}
153
154
	/**
155
	 * Returns true if there is no need to check any other sub-folder at the same depth level
156
	 *
157
	 * @param int $subDepth
158
	 * @param int $count
159
	 *
160
	 * @return bool
161
	 */
162 11
	private function abortSearch($subDepth, $count) {
163 11
		return $subDepth > 1 && $count > 0;
164
	}
165
166
	/**
167
	 * Returns true if the file is of a supported media type and adds it to the array of items to
168
	 * return
169
	 *
170
	 * @todo We could potentially check if the file is readable ($file->stat() maybe) in order to
171
	 *     only return valid files, but this may slow down operations
172
	 *
173
	 * @param File $file the file to test
174
	 *
175
	 * @return bool
176
	 */
177 14
	private function isPreviewAvailable($file) {
178
		try {
179 14
			$mimeType = $file->getMimeType();
180 14
			if (in_array($mimeType, $this->supportedMediaTypes)) {
181 12
				$this->addFileToImagesArray($mimeType, $file);
182
183 13
				return true;
184
			}
185 1
		} catch (\Exception $exception) {
186 1
			return false;
187
		}
188
189 5
		return false;
190
	}
191
192
	/**
193
	 * Adds a folder to the albums array
194
	 *
195
	 * @param Folder $folder the folder to add to the albums array
196
	 */
197 13
	private function addFolderToAlbumsArray($folder) {
198 13
		$albumData = $this->getFolderData($folder);
199 13
		$this->albums[$albumData['path']] = $albumData;
200 13
	}
201
202
	/**
203
	 * Adds a file to the images array
204
	 *
205
	 * @param string $mimeType the media type of the file to add to the images array
206
	 * @param File $file the file to add to the images array
207
	 */
208 12
	private function addFileToImagesArray($mimeType, $file) {
209 12
		$imageData = $this->getNodeData($file);
210 12
		$imageData['mimetype'] = $mimeType;
211 12
		$this->images[] = $imageData;
212 12
	}
213
214
}
215