Completed
Pull Request — master (#93)
by Janis
07:58
created

FileService   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 263
Duplicated Lines 5.32 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 17.07%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 25
lcom 1
cbo 5
dl 14
loc 263
ccs 7
cts 41
cp 0.1707
rs 10
c 1
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A checkSharedWithInitiator() 0 10 2
A buildTarget() 0 8 2
A buildSource() 0 9 2
A buildFileInfo() 0 16 3
A getCorrectType() 0 7 2
A execRemove() 0 3 1
A getFileContents() 0 3 1
A fileExists() 0 3 1
A buildNotExistingFilename() 0 3 1
B buildTargetForShared() 7 26 3
B buildTargetNotForShared() 7 27 3
A checkMimeType() 0 6 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * Nextcloud - OCR
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Janis Koehr <[email protected]>
10
 * @copyright Janis Koehr 2017
11
 */
12
namespace OCA\Ocr\Service;
13
14
use OCA\Ocr\Db\FileMapper;
15
use OCA\Ocr\Db\File;
16
use OCP\ILogger;
17
use OCA\Ocr\Db\ShareMapper;
18
use OCP\IL10N;
19
use OCA\Ocr\Constants\OcrConstants;
20
21
/**
22
 * Class FileService
23
 *
24
 * @package OCA\Ocr\Service
25
 */
26
class FileService {
27
	
28
	/**
29
	 *
30
	 * @var ILogger
31
	 */
32
	private $logger;
33
	
34
	/**
35
	 *
36
	 * @var FileMapper
37
	 */
38
	private $fileMapper;
39
	
40
	/**
41
	 *
42
	 * @var ShareMapper
43
	 */
44
	private $shareMapper;
45
	
46
	/**
47
	 *
48
	 * @var string
49
	 */
50
	private $userId;
51
	
52
	/**
53
	 *
54
	 * @var IL10N
55
	 */
56
	private $l10n;
57 6
	public function __construct(IL10N $l10n, ILogger $logger, $userId, FileMapper $fileMapper, ShareMapper $shareMapper) {
58 6
		$this->l10n = $l10n;
59 6
		$this->logger = $logger;
60 6
		$this->userId = $userId;
61 6
		$this->fileMapper = $fileMapper;
62 6
		$this->shareMapper = $shareMapper;
63 6
	}
64
	
65
	/**
66
	 * Checks if shared with the process initiator
67
	 *
68
	 * @param File $fileInfo        	
69
	 * @return boolean|null
70
	 */
71
	public function checkSharedWithInitiator($fileInfo) {
72
		$owner = str_replace ( 'home::', '', $fileInfo->getStoragename () );
73
		if ($this->userId === $owner) {
74
			// user is owner (no shared file)
75
			return false;
76
		} else {
77
			// user is not owner (shared file)
78
			return true;
79
		}
80
	}
81
	
82
	/**
83
	 * Builds the target name.
84
	 *
85
	 * @param File $fileInfo        	
86
	 * @param boolean $shared        	
87
	 * @return string
88
	 */
89
	public function buildTarget($fileInfo, $shared) {
90
		if ($shared) {
91
			$target = $this->buildTargetForShared ( $fileInfo );
92
		} else {
93
			$target = $this->buildTargetNotForShared ( $fileInfo );
94
		}
95
		return $target;
96
	}
97
	
98
	/**
99
	 * Builds the source name.
100
	 *
101
	 * @param File $fileInfo        	
102
	 * @param boolean $shared        	
103
	 * @return string
104
	 */
105
	public function buildSource($fileInfo, $shared) {
106
		$source = $fileInfo->getPath ();
107
		if ($shared) {
108
			$source = str_replace ( 'home::', '', $fileInfo->getStoragename () ) . '/' . $source;
109
		} else {
110
			$source = $this->userId . '/' . $source;
111
		}
112
		return $source;
113
	}
114
	
115
	/**
116
	 * Returns the fileInfo for each file in files and checks
117
	 * if it has a allowed MIME type and some other conditions.
118
	 *
119
	 * @param array $files        	
120
	 * @return File[]
121
	 * @throws NotFoundException
122
	 */
123
	public function buildFileInfo($files) {
124
		$fileArray = array ();
125
		foreach ( $files as $file ) {
126
			// Check if anything is missing and file type is correct
127
			if (! empty ( $file ['id'] )) {
128
				
129
				$fileInfo = $this->fileMapper->find ( $file ['id'] );
130
				$this->checkMimeType ( $fileInfo );
131
				
132
				array_push ( $fileArray, $fileInfo );
133
			} else {
134
				throw new NotFoundException ( $this->l10n->t ( 'Wrong parameter.' ) );
135
			}
136
		}
137
		return $fileArray;
138
	}
139
	
140
	/**
141
	 * Determines the correct type for the ocr process worker.
142
	 *
143
	 * @param File $fileInfo        	
144
	 * @return integer
145
	 */
146
	public function getCorrectType($fileInfo) {
147
		if ($fileInfo->getMimetype () === OcrConstants::MIME_TYPE_PDF) {
148
			return OcrConstants::OCRmyPDF;
149
		} else {
150
			return OcrConstants::TESSERACT;
151
		}
152
	}
153
	
154
	/**
155
	 * Executes the exec function with a remove statement for a given file path.
156
	 *
157
	 * @codeCoverageIgnore
158
	 *
159
	 * @param string $pathToFile        	
160
	 */
161
	public function execRemove($pathToFile) {
162
		exec ( 'rm ' . $pathToFile );
163
	}
164
	
165
	/**
166
	 * Wraps the static file_get_contents method of php.
167
	 *
168
	 * @codeCoverageIgnore
169
	 *
170
	 * @param string $pathToFile        	
171
	 * @return string
172
	 */
173
	public function getFileContents($pathToFile) {
174
		return file_get_contents ( $pathToFile );
175
	}
176
	
177
	/**
178
	 * Wraps the static file_exists method of php.
179
	 *
180
	 * @codeCoverageIgnore
181
	 *
182
	 * @param string $pathToFile        	
183
	 * @return boolean
184
	 */
185
	public function fileExists($pathToFile) {
186
		return file_exists ( $pathToFile );
187
	}
188
	
189
	/**
190
	 * Wraps the static function \OCP\Files::buildNotExistingFileName() in order to be able to test everything else.
191
	 *
192
	 * @codeCoverageIgnore
193
	 *
194
	 * @param string $filePath        	
195
	 * @param string $fileName        	
196
	 * @return string
197
	 */
198
	public function buildNotExistingFilename($filePath, $fileName) {
199
		return \OCP\Files::buildNotExistingFileName ( $filePath, $fileName . '_OCR.pdf' );
200
	}
201
	
202
	/**
203
	 * Returns a not existing file name for pdf or image processing
204
	 * protected as of testing issues with static methods.
205
	 * (Actually
206
	 * it will be mocked partially) FIXME: Change this behaviour as soon as the buidlNotExistingFileName function is not static anymore
207
	 * @codeCoverageIgnore
208
	 *
209
	 * @param File $fileInfo        	
210
	 * @return string
211
	 */
212
	private function buildTargetForShared(File $fileInfo) {
213
		$share = $this->shareMapper->find ( $fileInfo->getFileid (), $this->userId, str_replace ( 'home::', '', $fileInfo->getStoragename () ) );
214
		
215
		// get rid of the .png or .pdf and so on
216
		$fileName = substr ( $share->getFileTarget (), 0, (strrpos ( $share->getFileTarget (), '.' )) ); // '/thedom.png' => '/thedom' || '/Test/thedom.png' => '/Test/thedom'
1 ignored issue
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
217
		                                                                                                 
218
		// remove everything in front of and including of the first appearance of a slash from behind
219
		$fileName = substr ( strrchr ( $fileName, "/" ), 1 ); // '/thedom' => 'thedom' || '/Test/thedom' => 'thedom'
1 ignored issue
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
220
		                                                      
221
		// eliminate the file name from the path
222
		$filePath = dirname ( $share->getFileTarget () ); // '/thedom.png' => '/' || '/Test/thedom.png' => '/Test'
1 ignored issue
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
223
		                                                  
224
		// replace the first slash
225
		$pos = strpos ( $filePath, '/' );
226
		if ($pos !== false) {
227
			$filePath = substr_replace ( $filePath, '', $pos, strlen ( '/' ) ); // '/' => '' || '/Test/' => 'Test'
1 ignored issue
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
228
		}
229
		
230 View Code Duplication
		if ($fileInfo->getMimetype () === OcrConstants::MIME_TYPE_PDF) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
231
			// PDFs:
232
			return $this->buildNotExistingFilename ( $filePath, $fileName . '_OCR.pdf' );
233
		} else {
234
			// IMAGES:
235
			return $this->buildNotExistingFilename ( $filePath, $fileName . '_OCR.txt' );
236
		}
237
	}
238
	
239
	/**
240
	 * Returns a not existing file name for PDF or image processing
241
	 * protected as of testing issues with static methods.
242
	 * (Actually
243
	 * it will be mocked partially) FIXME: Change this behaviour as soon as the buidlNotExistingFileName function is not static anymore
244
	 * @codeCoverageIgnore
245
	 *
246
	 * @param File $fileInfo        	
247
	 * @return string
248
	 */
249
	private function buildTargetNotForShared(File $fileInfo) {
250
		// get rid of the .png or .pdf and so on
251
		$fileName = substr ( $fileInfo->getName (), 0, (strrpos ( $fileInfo->getName (), '.' )) ); // 'thedom.png' => 'thedom'
1 ignored issue
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
252
		                                                                                           
253
		// eliminate the file name from the path
254
		$filePath = str_replace ( $fileInfo->getName (), '', $fileInfo->getPath () ); // 'files/Test/thedom.png' => 'files/Test/' || 'files/thedom.png' => 'files/'
1 ignored issue
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
255
		                                                                              
256
		// and get the path on top of the files/ dir
257
		$filePath = str_replace ( 'files', '', $filePath ); // 'files/Test/' => '/Test/' || 'files/' => '/'
1 ignored issue
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
258
		                                                    
259
		// remove the last slash
260
		$filePath = substr_replace ( $filePath, '', strrpos ( $filePath, '/' ), strlen ( '/' ) ); // '/Test/' => '/Test' || '/' => ''
1 ignored issue
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
261
		                                                                                          
262
		// replace the first slash
263
		$pos = strpos ( $filePath, '/' );
264
		if ($pos !== false) {
265
			$filePath = substr_replace ( $filePath, '', $pos, strlen ( '/' ) ); // '/Test' => '// 'Test' || '/' => ''
266
		}
267
		
268 View Code Duplication
		if ($fileInfo->getMimetype () === OcrConstants::MIME_TYPE_PDF) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
269
			// PDFs:
270
			return $this->buildNotExistingFilename ( $filePath, $fileName . '_OCR.pdf' );
271
		} else {
272
			// IMAGES:
273
			return $this->buildNotExistingFilename ( $filePath, $fileName . '_OCR.txt' );
274
		}
275
	}
276
	
277
	/**
278
	 * Checks a MIME type for a specifically given FileInfo.
279
	 *
280
	 * @param File $fileInfo        	
281
	 */
282
	private function checkMimeType(File $fileInfo) {
283
		if (! $fileInfo || ! in_array ( $fileInfo->getMimetype (), OcrConstants::ALLOWED_MIME_TYPES )) {
284
			$this->logger->debug ( 'Getting FileInfo did not work or not included in the ALLOWED_MIMETYPES array.' );
285
			throw new NotFoundException ( $this->l10n->t ( 'Wrong MIME type.' ) );
286
		}
287
	}
288
}