Completed
Push — master ( 25c62b...5520ba )
by Morris
29:40
created

PreviewController::fetchPreview()   C

Complexity

Conditions 7
Paths 19

Size

Total Lines 37
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 25
nc 19
nop 6
dl 0
loc 37
rs 6.7272
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
/**
4
 * @copyright Copyright (c) 2016, Roeland Jago Douma <[email protected]>
5
 *
6
 * @author Morris Jobke <[email protected]>
7
 * @author Roeland Jago Douma <[email protected]>
8
 *
9
 * @license GNU AGPL version 3 or any later version
10
 *
11
 * This program is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License as
13
 * published by the Free Software Foundation, either version 3 of the
14
 * License, or (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 *
24
 */
25
26
namespace OC\Core\Controller;
27
28
use OCP\AppFramework\Controller;
29
use OCP\AppFramework\Utility\ITimeFactory;
30
use OCP\Files\File;
31
use OCP\AppFramework\Http;
32
use OCP\AppFramework\Http\DataResponse;
33
use OCP\AppFramework\Http\FileDisplayResponse;
34
use OCP\Files\IRootFolder;
35
use OCP\Files\Node;
36
use OCP\Files\NotFoundException;
37
use OCP\IPreview;
38
use OCP\IRequest;
39
40
class PreviewController extends Controller {
41
42
	/** @var string */
43
	private $userId;
44
45
	/** @var IRootFolder */
46
	private $root;
47
48
	/** @var IPreview */
49
	private $preview;
50
51
	/** @var ITimeFactory */
52
	private $timeFactory;
53
54
	/**
55
	 * PreviewController constructor.
56
	 *
57
	 * @param string $appName
58
	 * @param IRequest $request
59
	 * @param IPreview $preview
60
	 * @param IRootFolder $root
61
	 * @param string $userId
62
	 * @param ITimeFactory $timeFactory
63
	 */
64
	public function __construct(string $appName,
65
								IRequest $request,
66
								IPreview $preview,
67
								IRootFolder $root,
68
								string $userId,
69
								ITimeFactory $timeFactory
70
	) {
71
		parent::__construct($appName, $request);
72
73
		$this->preview = $preview;
74
		$this->root = $root;
75
		$this->userId = $userId;
76
		$this->timeFactory = $timeFactory;
77
	}
78
79
	/**
80
	 * @NoAdminRequired
81
	 * @NoCSRFRequired
82
	 *
83
	 * @param string $file
84
	 * @param int $x
85
	 * @param int $y
86
	 * @param bool $a
87
	 * @param bool $forceIcon
88
	 * @param string $mode
89
	 * @return DataResponse|FileDisplayResponse
90
	 */
91
	public function getPreview (
92
		string $file = '',
93
		int $x = 32,
94
		int $y = 32,
95
		bool $a = false,
96
		bool $forceIcon = true,
97
		string $mode = 'fill'): Http\Response {
98
99 View Code Duplication
		if ($file === '' || $x === 0 || $y === 0) {
100
			return new DataResponse([], Http::STATUS_BAD_REQUEST);
101
		}
102
103
		try {
104
			$userFolder = $this->root->getUserFolder($this->userId);
105
			$node = $userFolder->get($file);
106
		} catch (NotFoundException $e) {
107
			return new DataResponse([], Http::STATUS_NOT_FOUND);
108
		}
109
110
		return $this->fetchPreview($node, $x, $y, $a, $forceIcon, $mode);
111
	}
112
113
	/**
114
	 * @NoAdminRequired
115
	 * @NoCSRFRequired
116
	 *
117
	 * @param int $fileId
118
	 * @param int $x
119
	 * @param int $y
120
	 * @param bool $a
121
	 * @param bool $forceIcon
122
	 * @param string $mode
123
	 *
124
	 * @return DataResponse|FileDisplayResponse
125
	 */
126
	public function getPreviewByFileId(
127
		int $fileId = -1,
128
		int $x = 32,
129
		int $y = 32,
130
		bool $a = false,
131
		bool $forceIcon = true,
132
		string $mode = 'fill') {
133
134 View Code Duplication
		if ($fileId === -1 || $x === 0 || $y === 0) {
135
			return new DataResponse([], Http::STATUS_BAD_REQUEST);
136
		}
137
138
		$userFolder = $this->root->getUserFolder($this->userId);
139
		$nodes = $userFolder->getById($fileId);
140
141
		if (\count($nodes) === 0) {
142
			return new DataResponse([], Http::STATUS_NOT_FOUND);
143
		}
144
145
		$node = array_pop($nodes);
146
147
		return $this->fetchPreview($node, $x, $y, $a, $forceIcon, $mode);
0 ignored issues
show
Bug introduced by
It seems like $node defined by array_pop($nodes) on line 145 can be null; however, OC\Core\Controller\Previ...troller::fetchPreview() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
148
	}
149
150
	/**
151
	 * @param Node $node
152
	 * @param int $x
153
	 * @param int $y
154
	 * @param bool $a
155
	 * @param bool $forceIcon
156
	 * @param string $mode
157
	 * @return DataResponse|FileDisplayResponse
158
	 */
159
	private function fetchPreview(
160
		Node $node,
161
		int $x,
162
		int $y,
163
		bool $a = false,
164
		bool $forceIcon = true,
165
		string $mode) : Http\Response {
166
167
		if (!($node instanceof File) || (!$forceIcon && !$this->preview->isAvailable($node))) {
168
			return new DataResponse([], Http::STATUS_NOT_FOUND);
169
		}
170
		if (!$node->isReadable()) {
171
			return new DataResponse([], Http::STATUS_FORBIDDEN);
172
		}
173
174
		try {
175
			$f = $this->preview->getPreview($node, $x, $y, !$a, $mode);
176
			$response = new FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]);
177
178
			// Let cache this!
179
			$response->addHeader('Pragma', 'public');
180
181
			// Cache previews for 24H
182
			$response->cacheFor(3600 * 24);
183
			$expires = new \DateTime();
184
			$expires->setTimestamp($this->timeFactory->getTime());
185
			$expires->add(new \DateInterval('P1D'));
186
			$response->addHeader('Expires', $expires->format(\DateTime::RFC2822));
187
188
			return $response;
189
		} catch (NotFoundException $e) {
190
			return new DataResponse([], Http::STATUS_NOT_FOUND);
191
		} catch (\InvalidArgumentException $e) {
192
			return new DataResponse([], Http::STATUS_BAD_REQUEST);
193
		}
194
195
	}
196
}
197