Completed
Pull Request — master (#93)
by Janis
13:30
created

FileService::buildTargetForShared()   B

Complexity

Conditions 4
Paths 16

Size

Total Lines 30
Code Lines 15

Duplication

Lines 7
Ratio 23.33 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 7
loc 30
rs 8.5806
c 1
b 0
f 0
cc 4
eloc 15
nc 16
nop 1
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\OcrJob;
15
use OCA\Ocr\Db\FileMapper;
16
use OCA\Ocr\Db\File;
17
use OCP\ILogger;
18
use OCA\Ocr\Db\ShareMapper;
19
use OCP\IL10N;
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
	
58
	/**
59
	 * Supported MIME types for OCR processing
60
	 */
61
	private static $ALLOWED_MIMETYPES = [ 
0 ignored issues
show
Unused Code introduced by
The property $ALLOWED_MIMETYPES is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
62
			'application/pdf',
63
			'image/png',
64
			'image/jpeg',
65
			'image/tiff',
66
			'image/jp2',
67
			'image/jpm',
68
			'image/jpx',
69
			'image/webp',
70
			'image/gif' 
71
	];
72
	
73
	/**
74
	 * The correct MIME type for a PDF file
75
	 */
76
	private static $MIMETYPE_PDF = 'application/pdf';
0 ignored issues
show
Unused Code introduced by
The property $MIMETYPE_PDF is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
77
	
78
	/**
79
	 * The supported image MIME types by tesseract
80
	 */
81
	private static $MIMETYPES_IMAGE = [ 
0 ignored issues
show
Unused Code introduced by
The property $MIMETYPES_IMAGE is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
82
			'image/png',
83
			'image/jpeg',
84
			'image/tiff',
85
			'image/jp2',
86
			'image/jpm',
87
			'image/jpx',
88
			'image/webp',
89
			'image/gif' 
90
	];
91
	public function __construct(IL10N $l10n, ILogger $logger, $userId, FileMapper $fileMapper, ShareMapper $shareMapper) {
92
		$this->l10n = $l10n;
93
		$this->logger = $logger;
94
		$this->userId = $userId;
95
		$this->fileMapper = $fileMapper;
96
		$this->shareMapper = $shareMapper;
97
	}
98
	
99
	/**
100
	 * Checks if shared with the process initiator
101
	 *
102
	 * @param File $fileInfo        	
103
	 * @return boolean|null
104
	 */
105
	public function checkSharedWithInitiator($fileInfo) {
106
		try {
107
			$owner = str_replace ( 'home::', '', $fileInfo->getStoragename () );
108
			if ($this->userId === $owner) {
109
				// user is owner (no shared file)
110
				return false;
111
			} else {
112
				// user is not owner (shared file)
113
				return true;
114
			}
115
		} catch ( Exception $e ) {
0 ignored issues
show
Bug introduced by
The class OCA\Ocr\Service\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
116
			$this->handleException ( $e );
117
		}
118
	}
119
	
120
	/**
121
	 * Builds the target name.
122
	 *
123
	 * @param File $fileInfo        	
124
	 * @param boolean $shared        	
125
	 * @return string
126
	 */
127
	public function buildTarget($fileInfo, $shared) {
128
		if ($shared) {
129
			$target = $this->buildTargetForShared ( $fileInfo );
130
		} else {
131
			$target = $this->buildTargetNotForShared ( $fileInfo );
132
		}
133
		return $target;
134
	}
135
	
136
	/**
137
	 * Builds the source name.
138
	 *
139
	 * @param File $fileInfo        	
140
	 * @param boolean $shared        	
141
	 * @return string
142
	 */
143
	public function buildSource($fileInfo, $shared) {
144
		$source = $fileInfo->getPath ();
145
		if ($shared) {
146
			$source = str_replace ( 'home::', '', $fileInfo->getStoragename () ) . '/' . $source;
147
		} else {
148
			$source = $this->userId . '/' . $source;
149
		}
150
		return $source;
151
	}
152
	
153
	/**
154
	 * Returns the fileInfo for each file in files and checks
155
	 * if it has a allowed MIME type and some other conditions.
156
	 *
157
	 * @param array $files        	
158
	 * @return File[]
159
	 * @throws NotFoundException
160
	 */
161
	public function buildFileInfo($files) {
162
		try {
163
			$fileArray = array ();
164
			foreach ( $files as $file ) {
165
				// Check if anything is missing and file type is correct
166
				if (! empty ( $file ['id'] )) {
167
					
168
					$fileInfo = $this->fileMapper->find ( $file ['id'] );
169
					$this->checkMimeType ( $fileInfo );
170
					
171
					array_push ( $fileArray, $fileInfo );
172
				} else {
173
					throw new NotFoundException ( $this->l10n->t ( 'Wrong parameter.' ) );
174
				}
175
			}
176
			return $fileArray;
177
		} catch ( Exception $e ) {
0 ignored issues
show
Bug introduced by
The class OCA\Ocr\Service\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
178
			$this->handleException ( $e );
179
		}
180
	}
181
	
182
	/**
183
	 * Removes ".txt" from the newName of a OCR job
184
	 *
185
	 * @param $job OcrJob        	
186
	 * @return string
187
	 */
188
	public function removeFileExtension($job) {
189
		return substr ( $job->getTarget (), 0, strrpos ( $job->getTarget (), '_OCR' ) );
190
	}
191
	
192
	/**
193
	 * Determines the correct type for the ocr process worker.
194
	 * TODO: adjust according to expected
195
	 *
196
	 * @param File $fileInfo        	
197
	 * @return string
198
	 */
199
	public function getCorrectType($fileInfo) {
200
		if ($fileInfo->getMimetype () === FileService::$MIMETYPE_PDF) {
201
			return 'mypdf';
202
		} else {
203
			return 'tess';
204
		}
205
	}
206
	
207
	/**
208
	 * Executes the exec function with a remove statement for a given file path.
209
	 *
210
	 * @codeCoverageIgnore
211
	 * 
212
	 * @param string $pathToFile        	
213
	 */
214
	public function execRemove($pathToFile) {
215
		exec ( 'rm ' . $pathToFile );
216
	}
217
	
218
	/**
219
	 * Wraps the static file_get_contents method of php.
220
	 *
221
	 * @codeCoverageIgnore
222
	 * 
223
	 * @param string $pathToFile        	
224
	 * @return string
225
	 */
226
	public function getFileContents($pathToFile) {
227
		return file_get_contents ( $pathToFile );
228
	}
229
	
230
	/**
231
	 * Wraps the static file_exists method of php.
232
	 *
233
	 * @codeCoverageIgnore
234
	 * 
235
	 * @param string $pathToFile        	
236
	 * @return boolean
237
	 */
238
	public function fileExists($pathToFile) {
239
		return file_exists ( $pathToFile );
240
	}
241
	
242
	/**
243
	 * Returns a not existing file name for pdf or image processing
244
	 * protected as of testing issues with static methods.
245
	 * (Actually
246
	 * it will be mocked partially) FIXME: Change this behaviour as soon as the buidlNotExistingFileName function is not static anymore
247
	 * @codeCoverageIgnore
248
	 *
249
	 * @param File $fileInfo        	
250
	 * @return string
251
	 */
252
	protected function buildTargetForShared(File $fileInfo) {
253
		try {
254
			$share = $this->shareMapper->find ( $fileInfo->getFileid (), $this->userId, str_replace ( 'home::', '', $fileInfo->getStoragename () ) );
255
			
256
			// get rid of the .png or .pdf and so on
257
			$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...
258
			                                                                                                 
259
			// remove everything in front of and including of the first appearance of a slash from behind
260
			$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...
261
			                                                      
262
			// eliminate the file name from the path
263
			$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...
264
			                                                  
265
			// replace the first slash
266
			$pos = strpos ( $filePath, '/' );
267
			if ($pos !== false) {
268
				$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...
269
			}
270
			
271 View Code Duplication
			if ($fileInfo->getMimetype () === FileService::$MIMETYPE_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...
272
				// PDFs:
273
				return \OCP\Files::buildNotExistingFileName ( $filePath, $fileName . '_OCR.pdf' );
274
			} else {
275
				// IMAGES:
276
				return \OCP\Files::buildNotExistingFileName ( $filePath, $fileName . '_OCR.txt' );
277
			}
278
		} catch ( Exception $e ) {
0 ignored issues
show
Bug introduced by
The class OCA\Ocr\Service\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
279
			$this->handleException ( $e );
280
		}
281
	}
282
	
283
	/**
284
	 * Returns a not existing file name for PDF or image processing
285
	 * protected as of testing issues with static methods.
286
	 * (Actually
287
	 * it will be mocked partially) FIXME: Change this behaviour as soon as the buidlNotExistingFileName function is not static anymore
288
	 * @codeCoverageIgnore
289
	 *
290
	 * @param File $fileInfo        	
291
	 * @return string
292
	 */
293
	protected function buildTargetNotForShared(File $fileInfo) {
294
		try {
295
			// get rid of the .png or .pdf and so on
296
			$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...
297
			                                                                                           
298
			// eliminate the file name from the path
299
			$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...
300
			                                                                              
301
			// and get the path on top of the files/ dir
302
			$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...
303
			                                                    
304
			// remove the last slash
305
			$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...
306
			                                                                                          
307
			// replace the first slash
308
			$pos = strpos ( $filePath, '/' );
309
			if ($pos !== false) {
310
				$filePath = substr_replace ( $filePath, '', $pos, strlen ( '/' ) ); // '/Test' => '// 'Test' || '/' => ''
311
			}
312
			
313 View Code Duplication
			if ($fileInfo->getMimetype () === FileService::$MIMETYPE_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...
314
				// PDFs:
315
				return \OCP\Files::buildNotExistingFileName ( $filePath, $fileName . '_OCR.pdf' );
316
			} else {
317
				// IMAGES:
318
				return \OCP\Files::buildNotExistingFileName ( $filePath, $fileName . '_OCR.txt' );
319
			}
320
		} catch ( Exception $e ) {
0 ignored issues
show
Bug introduced by
The class OCA\Ocr\Service\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
321
			$this->handleException ( $e );
322
		}
323
	}
324
	
325
	/**
326
	 * Checks a MIME type for a specifically given FileInfo.
327
	 *
328
	 * @param File $fileInfo        	
329
	 */
330
	private function checkMimeType(File $fileInfo) {
331
		try {
332
			if (! $fileInfo || ! in_array ( $fileInfo->getMimetype (), FileService::$ALLOWED_MIMETYPES )) {
333
				$this->logger->debug ( 'Getting FileInfo did not work or not included in the ALLOWED_MIMETYPES array.', [ 
334
						'app' => 'ocr' 
335
				] );
336
				throw new NotFoundException ( $this->l10n->t ( 'Wrong MIME type.' ) );
337
			}
338
		} catch ( Exception $e ) {
0 ignored issues
show
Bug introduced by
The class OCA\Ocr\Service\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
339
			$this->handleException ( $e );
340
		}
341
	}
342
	
343
	/**
344
	 * Handle the possible thrown Exceptions from all methods of this class.
345
	 *
346
	 * @param Exception $e        	
347
	 * @throws Exception
348
	 * @throws NotFoundException
349
	 */
350 View Code Duplication
	private function handleException($e) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
351
		$this->logger->logException ( $e, [ 
352
				'app' => 'ocr',
353
				'message' => 'Exception during file service function processing' 
354
		] );
355
		if ($e instanceof NotFoundException) {
356
			throw new NotFoundException ( $e->getMessage () );
357
		} else {
358
			throw $e;
359
		}
360
	}
361
}