Passed
Push — master ( 6129a8...4c81f5 )
by Morris
29:36 queued 13:12
created

MarkDown::getThumbnail()   F

Complexity

Conditions 20
Paths 6154

Size

Total Lines 105
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 20
eloc 63
c 1
b 0
f 0
nc 6154
nop 3
dl 0
loc 105
rs 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 * @author Robin Appelman <[email protected]>
7
 * @author Roeland Jago Douma <[email protected]>
8
 *
9
 * @license AGPL-3.0
10
 *
11
 * This code is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License, version 3,
13
 * as published by the Free Software Foundation.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License, version 3,
21
 * along with this program. If not, see <http://www.gnu.org/licenses/>
22
 *
23
 */
24
25
namespace OC\Preview;
26
27
use OCP\Files\File;
28
use OCP\IImage;
29
30
class MarkDown extends TXT {
31
	/**
32
	 * {@inheritDoc}
33
	 */
34
	public function getMimeType(): string {
35
		return '/text\/(x-)?markdown/';
36
	}
37
38
	public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
39
		$content = $file->fopen('r');
40
41
		if ($content === false) {
0 ignored issues
show
introduced by
The condition $content === false is always false.
Loading history...
42
			return null;
43
		}
44
45
		$content = stream_get_contents($content,3000);
46
47
		//don't create previews of empty text files
48
		if (trim($content) === '') {
49
			return null;
50
		}
51
52
		// Merge text paragraph lines that might belong together
53
		$content = preg_replace('/^(\s*)\*\s/mU', '$1- ', $content);
54
55
		$content = preg_replace('/((?!^(\s*-|#)).*)(\w|\\|\.)(\r\n|\n|\r)(\w|\*)/mU', '$1 $3', $content);
56
57
		// Remove markdown symbols that we cannot easily represent in rendered text in the preview
58
		$content = preg_replace('/\*\*(.*)\*\*/U', '$1', $content);
59
		$content = preg_replace('/\*(.*)\*/U', '$1', $content);
60
		$content = preg_replace('/\_\_(.*)\_\_/U', '$1', $content);
61
		$content = preg_replace('/\_(.*)\_/U', '$1', $content);
62
		$content = preg_replace('/\~\~(.*)\~\~/U', '$1', $content);
63
64
		$content = preg_replace('/\!?\[((.|\n)*)\]\((.*)\)/mU', '$1 ($3)', $content);
65
		$content = preg_replace('/\n\n+/', "\n", $content);
66
67
		$content = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $content);
68
69
		$lines = preg_split("/\r\n|\n|\r/", $content);
70
71
		// Define text size of text file preview
72
		$fontSize = $maxX ? (int) ((1 / ($maxX >= 512 ? 60 : 40) * $maxX)) : 10;
73
74
		$image = imagecreate($maxX, $maxY);
75
		imagecolorallocate($image, 255, 255, 255);
76
		$textColor = imagecolorallocate($image, 0, 0, 0);
77
78
		$fontFile  = __DIR__ . '/../../../core/fonts/NotoSans-Regular.ttf';
79
		$fontFileBold  = __DIR__ . '/../../../core/fonts/NotoSans-Bold.ttf';
80
81
		$canUseTTF = function_exists('imagettftext');
82
83
		$textOffset = (int)min($maxX * 0.05, $maxY * 0.05);
84
		$nextLineStart = 0;
85
		$y = $textOffset;
86
		foreach ($lines as $line) {
87
			$actualFontSize = $fontSize;
88
			if (mb_strpos($line, '# ') === 0) {
89
				$actualFontSize *= 2;
90
			}
91
			if (mb_strpos($line, '## ') === 0) {
92
				$actualFontSize *= 1.8;
93
			}
94
			if (mb_strpos($line, '### ') === 0) {
95
				$actualFontSize *= 1.6;
96
			}
97
			if (mb_strpos($line, '#### ') === 0) {
98
				$actualFontSize *= 1.4;
99
			}
100
			if (mb_strpos($line, '##### ') === 0) {
101
				$actualFontSize *= 1.2;
102
			}
103
			if (mb_strpos($line, '###### ') === 0) {
104
				$actualFontSize *= 1.1;
105
			}
106
107
			// Add spacing before headlines
108
			if ($actualFontSize !== $fontSize && $y !== $textOffset) {
109
				$y += (int)($actualFontSize * 2);
110
			}
111
112
			$x = $textOffset;
113
			$y += (int)($nextLineStart + $actualFontSize);
114
115
			if ($canUseTTF === true) {
116
				$wordWrap = (int)((1 / $actualFontSize * 1.3) * $maxX);
117
118
				// Get rid of markdown symbols that we still needed for the font size
119
				$line = preg_replace('/^#*\s/', '', $line);
120
121
				$wrappedText = wordwrap($line, $wordWrap,"\n");
122
				$linesWrapped = count(explode("\n", $wrappedText));
123
				imagettftext($image, $actualFontSize, 0, $x, $y, $textColor, $actualFontSize === $fontSize ? $fontFile : $fontFileBold, $wrappedText);
124
				$nextLineStart = (int)($linesWrapped * ceil($actualFontSize * 2));
125
				if ($actualFontSize !== $fontSize && $y !== $textOffset) {
126
					$nextLineStart -= $actualFontSize;
127
				}
128
			} else {
129
				$y -= (int)$fontSize;
130
				imagestring($image, 1, $x, $y, $line, $textColor);
131
				$nextLineStart = $fontSize;
132
			}
133
134
			if ($y >= $maxY) {
135
				break;
136
			}
137
		}
138
139
		$imageObject = new \OC_Image();
140
		$imageObject->setResource($image);
141
142
		return $imageObject->valid() ? $imageObject : null;
143
	}
144
}
145