Completed
Push — master ( 0da6f6...548426 )
by Morris
38:31 queued 16:41
created

Quota::free_space()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 15
nc 4
nop 1
dl 0
loc 20
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Jörn Friedrich Dreyer <[email protected]>
6
 * @author Lukas Reschke <[email protected]>
7
 * @author Morris Jobke <[email protected]>
8
 * @author Robin Appelman <[email protected]>
9
 * @author Robin McCorkell <[email protected]>
10
 * @author Vincent Petry <[email protected]>
11
 *
12
 * @license AGPL-3.0
13
 *
14
 * This code is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License, version 3,
16
 * as published by the Free Software Foundation.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
 * GNU Affero General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Affero General Public License, version 3,
24
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
25
 *
26
 */
27
28
namespace OC\Files\Storage\Wrapper;
29
30
use OCP\Files\Cache\ICacheEntry;
31
use OCP\Files\Storage\IStorage;
32
33
class Quota extends Wrapper {
34
35
	/**
36
	 * @var int $quota
37
	 */
38
	protected $quota;
39
40
	/**
41
	 * @var string $sizeRoot
42
	 */
43
	protected $sizeRoot;
44
45
	/**
46
	 * @param array $parameters
47
	 */
48
	public function __construct($parameters) {
49
		parent::__construct($parameters);
50
		$this->quota = $parameters['quota'];
51
		$this->sizeRoot = isset($parameters['root']) ? $parameters['root'] : '';
52
	}
53
54
	/**
55
	 * @return int quota value
56
	 */
57
	public function getQuota() {
58
		return $this->quota;
59
	}
60
61
	/**
62
	 * @param string $path
63
	 * @param \OC\Files\Storage\Storage $storage
64
	 */
65
	protected function getSize($path, $storage = null) {
66
		if (is_null($storage)) {
67
			$cache = $this->getCache();
68
		} else {
69
			$cache = $storage->getCache();
70
		}
71
		$data = $cache->get($path);
72
		if ($data instanceof ICacheEntry and isset($data['size'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
73
			return $data['size'];
74
		} else {
75
			return \OCP\Files\FileInfo::SPACE_NOT_COMPUTED;
76
		}
77
	}
78
79
	/**
80
	 * Get free space as limited by the quota
81
	 *
82
	 * @param string $path
83
	 * @return int
84
	 */
85
	public function free_space($path) {
86
		if ($this->quota < 0 || strpos($path, 'cache') === 0) {
87
			return $this->storage->free_space($path);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $this->storage->free_space($path); of type integer|false adds false to the return on line 87 which is incompatible with the return type documented by OC\Files\Storage\Wrapper\Quota::free_space of type integer. It seems like you forgot to handle an error condition.
Loading history...
88
		} else {
89
			$used = $this->getSize($this->sizeRoot);
90
			if ($used < 0) {
91
				return \OCP\Files\FileInfo::SPACE_NOT_COMPUTED;
92
			} else {
93
				$free = $this->storage->free_space($path);
94
				$quotaFree = max($this->quota - $used, 0);
0 ignored issues
show
Bug Compatibility introduced by
The expression max($this->quota - $used, 0); of type integer|double adds the type double to the return on line 101 which is incompatible with the return type declared by the interface OCP\Files\Storage::free_space of type integer|false.
Loading history...
95
				// if free space is known
96
				if ($free >= 0) {
97
					$free = min($free, $quotaFree);
0 ignored issues
show
Bug Compatibility introduced by
The expression min($free, $quotaFree); of type integer|false|double adds the type double to the return on line 101 which is incompatible with the return type declared by the interface OCP\Files\Storage::free_space of type integer|false.
Loading history...
98
				} else {
99
					$free = $quotaFree;
100
				}
101
				return $free;
102
			}
103
		}
104
	}
105
106
	/**
107
	 * see http://php.net/manual/en/function.file_put_contents.php
108
	 *
109
	 * @param string $path
110
	 * @param string $data
111
	 * @return bool
112
	 */
113
	public function file_put_contents($path, $data) {
114
		$free = $this->free_space($path);
115
		if ($free < 0 or strlen($data) < $free) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
116
			return $this->storage->file_put_contents($path, $data);
117
		} else {
118
			return false;
119
		}
120
	}
121
122
	/**
123
	 * see http://php.net/manual/en/function.copy.php
124
	 *
125
	 * @param string $source
126
	 * @param string $target
127
	 * @return bool
128
	 */
129 View Code Duplication
	public function copy($source, $target) {
130
		$free = $this->free_space($target);
131
		if ($free < 0 or $this->getSize($source) < $free) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
132
			return $this->storage->copy($source, $target);
133
		} else {
134
			return false;
135
		}
136
	}
137
138
	/**
139
	 * see http://php.net/manual/en/function.fopen.php
140
	 *
141
	 * @param string $path
142
	 * @param string $mode
143
	 * @return resource
144
	 */
145
	public function fopen($path, $mode) {
146
		$source = $this->storage->fopen($path, $mode);
147
148
		// don't apply quota for part files
149
		if (!$this->isPartFile($path)) {
150
			$free = $this->free_space($path);
151
			if ($source && $free >= 0 && $mode !== 'r' && $mode !== 'rb') {
152
				// only apply quota for files, not metadata, trash or others
153
				if (strpos(ltrim($path, '/'), 'files/') === 0) {
154
					return \OC\Files\Stream\Quota::wrap($source, $free);
155
				}
156
			}
157
		}
158
		return $source;
159
	}
160
161
	/**
162
	 * Checks whether the given path is a part file
163
	 *
164
	 * @param string $path Path that may identify a .part file
165
	 * @return string File path without .part extension
166
	 * @note this is needed for reusing keys
167
	 */
168
	private function isPartFile($path) {
169
		$extension = pathinfo($path, PATHINFO_EXTENSION);
170
171
		return ($extension === 'part');
172
	}
173
174
	/**
175
	 * @param IStorage $sourceStorage
176
	 * @param string $sourceInternalPath
177
	 * @param string $targetInternalPath
178
	 * @return bool
179
	 */
180 View Code Duplication
	public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
181
		$free = $this->free_space($targetInternalPath);
182
		if ($free < 0 or $this->getSize($sourceInternalPath, $sourceStorage) < $free) {
0 ignored issues
show
Documentation introduced by
$sourceStorage is of type object<OCP\Files\Storage\IStorage>, but the function expects a object<OC\Files\Storage\Storage>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
183
			return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
184
		} else {
185
			return false;
186
		}
187
	}
188
189
	/**
190
	 * @param IStorage $sourceStorage
191
	 * @param string $sourceInternalPath
192
	 * @param string $targetInternalPath
193
	 * @return bool
194
	 */
195 View Code Duplication
	public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
196
		$free = $this->free_space($targetInternalPath);
197
		if ($free < 0 or $this->getSize($sourceInternalPath, $sourceStorage) < $free) {
0 ignored issues
show
Documentation introduced by
$sourceStorage is of type object<OCP\Files\Storage\IStorage>, but the function expects a object<OC\Files\Storage\Storage>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
198
			return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
199
		} else {
200
			return false;
201
		}
202
	}
203
204
	public function mkdir($path) {
205
		if ($this->quota === 0.0) {
206
			return false;
207
		}
208
209
		return parent::mkdir($path);
210
	}
211
}
212