Passed
Push — master ( 4c60ff...437d93 )
by Julius
15:25 queued 12s
created
lib/private/Files/Cache/SearchBuilder.php 2 patches
Indentation   +195 added lines, -195 removed lines patch added patch discarded remove patch
@@ -37,199 +37,199 @@
 block discarded – undo
37 37
  * Tools for transforming search queries into database queries
38 38
  */
39 39
 class SearchBuilder {
40
-	protected static $searchOperatorMap = [
41
-		ISearchComparison::COMPARE_LIKE => 'iLike',
42
-		ISearchComparison::COMPARE_EQUAL => 'eq',
43
-		ISearchComparison::COMPARE_GREATER_THAN => 'gt',
44
-		ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'gte',
45
-		ISearchComparison::COMPARE_LESS_THAN => 'lt',
46
-		ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lte',
47
-	];
48
-
49
-	protected static $searchOperatorNegativeMap = [
50
-		ISearchComparison::COMPARE_LIKE => 'notLike',
51
-		ISearchComparison::COMPARE_EQUAL => 'neq',
52
-		ISearchComparison::COMPARE_GREATER_THAN => 'lte',
53
-		ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'lt',
54
-		ISearchComparison::COMPARE_LESS_THAN => 'gte',
55
-		ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lt',
56
-	];
57
-
58
-	public const TAG_FAVORITE = '_$!<Favorite>!$_';
59
-
60
-	/** @var IMimeTypeLoader */
61
-	private $mimetypeLoader;
62
-
63
-	public function __construct(
64
-		IMimeTypeLoader $mimetypeLoader
65
-	) {
66
-		$this->mimetypeLoader = $mimetypeLoader;
67
-	}
68
-
69
-	/**
70
-	 * Whether or not the tag tables should be joined to complete the search
71
-	 *
72
-	 * @param ISearchOperator $operator
73
-	 * @return boolean
74
-	 */
75
-	public function shouldJoinTags(ISearchOperator $operator) {
76
-		if ($operator instanceof ISearchBinaryOperator) {
77
-			return array_reduce($operator->getArguments(), function ($shouldJoin, ISearchOperator $operator) {
78
-				return $shouldJoin || $this->shouldJoinTags($operator);
79
-			}, false);
80
-		} elseif ($operator instanceof ISearchComparison) {
81
-			return $operator->getField() === 'tagname' || $operator->getField() === 'favorite';
82
-		}
83
-		return false;
84
-	}
85
-
86
-	/**
87
-	 * @param IQueryBuilder $builder
88
-	 * @param ISearchOperator $operator
89
-	 */
90
-	public function searchOperatorArrayToDBExprArray(IQueryBuilder $builder, array $operators) {
91
-		return array_filter(array_map(function ($operator) use ($builder) {
92
-			return $this->searchOperatorToDBExpr($builder, $operator);
93
-		}, $operators));
94
-	}
95
-
96
-	public function searchOperatorToDBExpr(IQueryBuilder $builder, ISearchOperator $operator) {
97
-		$expr = $builder->expr();
98
-		if ($operator instanceof ISearchBinaryOperator) {
99
-			if (count($operator->getArguments()) === 0) {
100
-				return null;
101
-			}
102
-
103
-			switch ($operator->getType()) {
104
-				case ISearchBinaryOperator::OPERATOR_NOT:
105
-					$negativeOperator = $operator->getArguments()[0];
106
-					if ($negativeOperator instanceof ISearchComparison) {
107
-						return $this->searchComparisonToDBExpr($builder, $negativeOperator, self::$searchOperatorNegativeMap);
108
-					} else {
109
-						throw new \InvalidArgumentException('Binary operators inside "not" is not supported');
110
-					}
111
-				// no break
112
-				case ISearchBinaryOperator::OPERATOR_AND:
113
-					return call_user_func_array([$expr, 'andX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments()));
114
-				case ISearchBinaryOperator::OPERATOR_OR:
115
-					return call_user_func_array([$expr, 'orX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments()));
116
-				default:
117
-					throw new \InvalidArgumentException('Invalid operator type: ' . $operator->getType());
118
-			}
119
-		} elseif ($operator instanceof ISearchComparison) {
120
-			return $this->searchComparisonToDBExpr($builder, $operator, self::$searchOperatorMap);
121
-		} else {
122
-			throw new \InvalidArgumentException('Invalid operator type: ' . get_class($operator));
123
-		}
124
-	}
125
-
126
-	private function searchComparisonToDBExpr(IQueryBuilder $builder, ISearchComparison $comparison, array $operatorMap) {
127
-		$this->validateComparison($comparison);
128
-
129
-		[$field, $value, $type] = $this->getOperatorFieldAndValue($comparison);
130
-		if (isset($operatorMap[$type])) {
131
-			$queryOperator = $operatorMap[$type];
132
-			return $builder->expr()->$queryOperator($field, $this->getParameterForValue($builder, $value));
133
-		} else {
134
-			throw new \InvalidArgumentException('Invalid operator type: ' . $comparison->getType());
135
-		}
136
-	}
137
-
138
-	private function getOperatorFieldAndValue(ISearchComparison $operator) {
139
-		$field = $operator->getField();
140
-		$value = $operator->getValue();
141
-		$type = $operator->getType();
142
-		if ($field === 'mimetype') {
143
-			$value = (string)$value;
144
-			if ($operator->getType() === ISearchComparison::COMPARE_EQUAL) {
145
-				$value = (int)$this->mimetypeLoader->getId($value);
146
-			} elseif ($operator->getType() === ISearchComparison::COMPARE_LIKE) {
147
-				// transform "mimetype='foo/%'" to "mimepart='foo'"
148
-				if (preg_match('|(.+)/%|', $value, $matches)) {
149
-					$field = 'mimepart';
150
-					$value = (int)$this->mimetypeLoader->getId($matches[1]);
151
-					$type = ISearchComparison::COMPARE_EQUAL;
152
-				} elseif (strpos($value, '%') !== false) {
153
-					throw new \InvalidArgumentException('Unsupported query value for mimetype: ' . $value . ', only values in the format "mime/type" or "mime/%" are supported');
154
-				} else {
155
-					$field = 'mimetype';
156
-					$value = (int)$this->mimetypeLoader->getId($value);
157
-					$type = ISearchComparison::COMPARE_EQUAL;
158
-				}
159
-			}
160
-		} elseif ($field === 'favorite') {
161
-			$field = 'tag.category';
162
-			$value = self::TAG_FAVORITE;
163
-		} elseif ($field === 'tagname') {
164
-			$field = 'tag.category';
165
-		} elseif ($field === 'fileid') {
166
-			$field = 'file.fileid';
167
-		} elseif ($field === 'path' && $type === ISearchComparison::COMPARE_EQUAL) {
168
-			$field = 'path_hash';
169
-			$value = md5((string)$value);
170
-		}
171
-		return [$field, $value, $type];
172
-	}
173
-
174
-	private function validateComparison(ISearchComparison $operator) {
175
-		$types = [
176
-			'mimetype' => 'string',
177
-			'mtime' => 'integer',
178
-			'name' => 'string',
179
-			'path' => 'string',
180
-			'size' => 'integer',
181
-			'tagname' => 'string',
182
-			'favorite' => 'boolean',
183
-			'fileid' => 'integer',
184
-			'storage' => 'integer',
185
-		];
186
-		$comparisons = [
187
-			'mimetype' => ['eq', 'like'],
188
-			'mtime' => ['eq', 'gt', 'lt', 'gte', 'lte'],
189
-			'name' => ['eq', 'like'],
190
-			'path' => ['eq', 'like'],
191
-			'size' => ['eq', 'gt', 'lt', 'gte', 'lte'],
192
-			'tagname' => ['eq', 'like'],
193
-			'favorite' => ['eq'],
194
-			'fileid' => ['eq'],
195
-			'storage' => ['eq'],
196
-		];
197
-
198
-		if (!isset($types[$operator->getField()])) {
199
-			throw new \InvalidArgumentException('Unsupported comparison field ' . $operator->getField());
200
-		}
201
-		$type = $types[$operator->getField()];
202
-		if (gettype($operator->getValue()) !== $type) {
203
-			throw new \InvalidArgumentException('Invalid type for field ' . $operator->getField());
204
-		}
205
-		if (!in_array($operator->getType(), $comparisons[$operator->getField()])) {
206
-			throw new \InvalidArgumentException('Unsupported comparison for field  ' . $operator->getField() . ': ' . $operator->getType());
207
-		}
208
-	}
209
-
210
-	private function getParameterForValue(IQueryBuilder $builder, $value) {
211
-		if ($value instanceof \DateTime) {
212
-			$value = $value->getTimestamp();
213
-		}
214
-		if (is_numeric($value)) {
215
-			$type = IQueryBuilder::PARAM_INT;
216
-		} else {
217
-			$type = IQueryBuilder::PARAM_STR;
218
-		}
219
-		return $builder->createNamedParameter($value, $type);
220
-	}
221
-
222
-	/**
223
-	 * @param IQueryBuilder $query
224
-	 * @param ISearchOrder[] $orders
225
-	 */
226
-	public function addSearchOrdersToQuery(IQueryBuilder $query, array $orders) {
227
-		foreach ($orders as $order) {
228
-			$field = $order->getField();
229
-			if ($field === 'fileid') {
230
-				$field = 'file.fileid';
231
-			}
232
-			$query->addOrderBy($field, $order->getDirection());
233
-		}
234
-	}
40
+    protected static $searchOperatorMap = [
41
+        ISearchComparison::COMPARE_LIKE => 'iLike',
42
+        ISearchComparison::COMPARE_EQUAL => 'eq',
43
+        ISearchComparison::COMPARE_GREATER_THAN => 'gt',
44
+        ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'gte',
45
+        ISearchComparison::COMPARE_LESS_THAN => 'lt',
46
+        ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lte',
47
+    ];
48
+
49
+    protected static $searchOperatorNegativeMap = [
50
+        ISearchComparison::COMPARE_LIKE => 'notLike',
51
+        ISearchComparison::COMPARE_EQUAL => 'neq',
52
+        ISearchComparison::COMPARE_GREATER_THAN => 'lte',
53
+        ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'lt',
54
+        ISearchComparison::COMPARE_LESS_THAN => 'gte',
55
+        ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lt',
56
+    ];
57
+
58
+    public const TAG_FAVORITE = '_$!<Favorite>!$_';
59
+
60
+    /** @var IMimeTypeLoader */
61
+    private $mimetypeLoader;
62
+
63
+    public function __construct(
64
+        IMimeTypeLoader $mimetypeLoader
65
+    ) {
66
+        $this->mimetypeLoader = $mimetypeLoader;
67
+    }
68
+
69
+    /**
70
+     * Whether or not the tag tables should be joined to complete the search
71
+     *
72
+     * @param ISearchOperator $operator
73
+     * @return boolean
74
+     */
75
+    public function shouldJoinTags(ISearchOperator $operator) {
76
+        if ($operator instanceof ISearchBinaryOperator) {
77
+            return array_reduce($operator->getArguments(), function ($shouldJoin, ISearchOperator $operator) {
78
+                return $shouldJoin || $this->shouldJoinTags($operator);
79
+            }, false);
80
+        } elseif ($operator instanceof ISearchComparison) {
81
+            return $operator->getField() === 'tagname' || $operator->getField() === 'favorite';
82
+        }
83
+        return false;
84
+    }
85
+
86
+    /**
87
+     * @param IQueryBuilder $builder
88
+     * @param ISearchOperator $operator
89
+     */
90
+    public function searchOperatorArrayToDBExprArray(IQueryBuilder $builder, array $operators) {
91
+        return array_filter(array_map(function ($operator) use ($builder) {
92
+            return $this->searchOperatorToDBExpr($builder, $operator);
93
+        }, $operators));
94
+    }
95
+
96
+    public function searchOperatorToDBExpr(IQueryBuilder $builder, ISearchOperator $operator) {
97
+        $expr = $builder->expr();
98
+        if ($operator instanceof ISearchBinaryOperator) {
99
+            if (count($operator->getArguments()) === 0) {
100
+                return null;
101
+            }
102
+
103
+            switch ($operator->getType()) {
104
+                case ISearchBinaryOperator::OPERATOR_NOT:
105
+                    $negativeOperator = $operator->getArguments()[0];
106
+                    if ($negativeOperator instanceof ISearchComparison) {
107
+                        return $this->searchComparisonToDBExpr($builder, $negativeOperator, self::$searchOperatorNegativeMap);
108
+                    } else {
109
+                        throw new \InvalidArgumentException('Binary operators inside "not" is not supported');
110
+                    }
111
+                // no break
112
+                case ISearchBinaryOperator::OPERATOR_AND:
113
+                    return call_user_func_array([$expr, 'andX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments()));
114
+                case ISearchBinaryOperator::OPERATOR_OR:
115
+                    return call_user_func_array([$expr, 'orX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments()));
116
+                default:
117
+                    throw new \InvalidArgumentException('Invalid operator type: ' . $operator->getType());
118
+            }
119
+        } elseif ($operator instanceof ISearchComparison) {
120
+            return $this->searchComparisonToDBExpr($builder, $operator, self::$searchOperatorMap);
121
+        } else {
122
+            throw new \InvalidArgumentException('Invalid operator type: ' . get_class($operator));
123
+        }
124
+    }
125
+
126
+    private function searchComparisonToDBExpr(IQueryBuilder $builder, ISearchComparison $comparison, array $operatorMap) {
127
+        $this->validateComparison($comparison);
128
+
129
+        [$field, $value, $type] = $this->getOperatorFieldAndValue($comparison);
130
+        if (isset($operatorMap[$type])) {
131
+            $queryOperator = $operatorMap[$type];
132
+            return $builder->expr()->$queryOperator($field, $this->getParameterForValue($builder, $value));
133
+        } else {
134
+            throw new \InvalidArgumentException('Invalid operator type: ' . $comparison->getType());
135
+        }
136
+    }
137
+
138
+    private function getOperatorFieldAndValue(ISearchComparison $operator) {
139
+        $field = $operator->getField();
140
+        $value = $operator->getValue();
141
+        $type = $operator->getType();
142
+        if ($field === 'mimetype') {
143
+            $value = (string)$value;
144
+            if ($operator->getType() === ISearchComparison::COMPARE_EQUAL) {
145
+                $value = (int)$this->mimetypeLoader->getId($value);
146
+            } elseif ($operator->getType() === ISearchComparison::COMPARE_LIKE) {
147
+                // transform "mimetype='foo/%'" to "mimepart='foo'"
148
+                if (preg_match('|(.+)/%|', $value, $matches)) {
149
+                    $field = 'mimepart';
150
+                    $value = (int)$this->mimetypeLoader->getId($matches[1]);
151
+                    $type = ISearchComparison::COMPARE_EQUAL;
152
+                } elseif (strpos($value, '%') !== false) {
153
+                    throw new \InvalidArgumentException('Unsupported query value for mimetype: ' . $value . ', only values in the format "mime/type" or "mime/%" are supported');
154
+                } else {
155
+                    $field = 'mimetype';
156
+                    $value = (int)$this->mimetypeLoader->getId($value);
157
+                    $type = ISearchComparison::COMPARE_EQUAL;
158
+                }
159
+            }
160
+        } elseif ($field === 'favorite') {
161
+            $field = 'tag.category';
162
+            $value = self::TAG_FAVORITE;
163
+        } elseif ($field === 'tagname') {
164
+            $field = 'tag.category';
165
+        } elseif ($field === 'fileid') {
166
+            $field = 'file.fileid';
167
+        } elseif ($field === 'path' && $type === ISearchComparison::COMPARE_EQUAL) {
168
+            $field = 'path_hash';
169
+            $value = md5((string)$value);
170
+        }
171
+        return [$field, $value, $type];
172
+    }
173
+
174
+    private function validateComparison(ISearchComparison $operator) {
175
+        $types = [
176
+            'mimetype' => 'string',
177
+            'mtime' => 'integer',
178
+            'name' => 'string',
179
+            'path' => 'string',
180
+            'size' => 'integer',
181
+            'tagname' => 'string',
182
+            'favorite' => 'boolean',
183
+            'fileid' => 'integer',
184
+            'storage' => 'integer',
185
+        ];
186
+        $comparisons = [
187
+            'mimetype' => ['eq', 'like'],
188
+            'mtime' => ['eq', 'gt', 'lt', 'gte', 'lte'],
189
+            'name' => ['eq', 'like'],
190
+            'path' => ['eq', 'like'],
191
+            'size' => ['eq', 'gt', 'lt', 'gte', 'lte'],
192
+            'tagname' => ['eq', 'like'],
193
+            'favorite' => ['eq'],
194
+            'fileid' => ['eq'],
195
+            'storage' => ['eq'],
196
+        ];
197
+
198
+        if (!isset($types[$operator->getField()])) {
199
+            throw new \InvalidArgumentException('Unsupported comparison field ' . $operator->getField());
200
+        }
201
+        $type = $types[$operator->getField()];
202
+        if (gettype($operator->getValue()) !== $type) {
203
+            throw new \InvalidArgumentException('Invalid type for field ' . $operator->getField());
204
+        }
205
+        if (!in_array($operator->getType(), $comparisons[$operator->getField()])) {
206
+            throw new \InvalidArgumentException('Unsupported comparison for field  ' . $operator->getField() . ': ' . $operator->getType());
207
+        }
208
+    }
209
+
210
+    private function getParameterForValue(IQueryBuilder $builder, $value) {
211
+        if ($value instanceof \DateTime) {
212
+            $value = $value->getTimestamp();
213
+        }
214
+        if (is_numeric($value)) {
215
+            $type = IQueryBuilder::PARAM_INT;
216
+        } else {
217
+            $type = IQueryBuilder::PARAM_STR;
218
+        }
219
+        return $builder->createNamedParameter($value, $type);
220
+    }
221
+
222
+    /**
223
+     * @param IQueryBuilder $query
224
+     * @param ISearchOrder[] $orders
225
+     */
226
+    public function addSearchOrdersToQuery(IQueryBuilder $query, array $orders) {
227
+        foreach ($orders as $order) {
228
+            $field = $order->getField();
229
+            if ($field === 'fileid') {
230
+                $field = 'file.fileid';
231
+            }
232
+            $query->addOrderBy($field, $order->getDirection());
233
+        }
234
+    }
235 235
 }
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -74,7 +74,7 @@  discard block
 block discarded – undo
74 74
 	 */
75 75
 	public function shouldJoinTags(ISearchOperator $operator) {
76 76
 		if ($operator instanceof ISearchBinaryOperator) {
77
-			return array_reduce($operator->getArguments(), function ($shouldJoin, ISearchOperator $operator) {
77
+			return array_reduce($operator->getArguments(), function($shouldJoin, ISearchOperator $operator) {
78 78
 				return $shouldJoin || $this->shouldJoinTags($operator);
79 79
 			}, false);
80 80
 		} elseif ($operator instanceof ISearchComparison) {
@@ -88,7 +88,7 @@  discard block
 block discarded – undo
88 88
 	 * @param ISearchOperator $operator
89 89
 	 */
90 90
 	public function searchOperatorArrayToDBExprArray(IQueryBuilder $builder, array $operators) {
91
-		return array_filter(array_map(function ($operator) use ($builder) {
91
+		return array_filter(array_map(function($operator) use ($builder) {
92 92
 			return $this->searchOperatorToDBExpr($builder, $operator);
93 93
 		}, $operators));
94 94
 	}
@@ -114,12 +114,12 @@  discard block
 block discarded – undo
114 114
 				case ISearchBinaryOperator::OPERATOR_OR:
115 115
 					return call_user_func_array([$expr, 'orX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments()));
116 116
 				default:
117
-					throw new \InvalidArgumentException('Invalid operator type: ' . $operator->getType());
117
+					throw new \InvalidArgumentException('Invalid operator type: '.$operator->getType());
118 118
 			}
119 119
 		} elseif ($operator instanceof ISearchComparison) {
120 120
 			return $this->searchComparisonToDBExpr($builder, $operator, self::$searchOperatorMap);
121 121
 		} else {
122
-			throw new \InvalidArgumentException('Invalid operator type: ' . get_class($operator));
122
+			throw new \InvalidArgumentException('Invalid operator type: '.get_class($operator));
123 123
 		}
124 124
 	}
125 125
 
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
 			$queryOperator = $operatorMap[$type];
132 132
 			return $builder->expr()->$queryOperator($field, $this->getParameterForValue($builder, $value));
133 133
 		} else {
134
-			throw new \InvalidArgumentException('Invalid operator type: ' . $comparison->getType());
134
+			throw new \InvalidArgumentException('Invalid operator type: '.$comparison->getType());
135 135
 		}
136 136
 	}
137 137
 
@@ -140,20 +140,20 @@  discard block
 block discarded – undo
140 140
 		$value = $operator->getValue();
141 141
 		$type = $operator->getType();
142 142
 		if ($field === 'mimetype') {
143
-			$value = (string)$value;
143
+			$value = (string) $value;
144 144
 			if ($operator->getType() === ISearchComparison::COMPARE_EQUAL) {
145
-				$value = (int)$this->mimetypeLoader->getId($value);
145
+				$value = (int) $this->mimetypeLoader->getId($value);
146 146
 			} elseif ($operator->getType() === ISearchComparison::COMPARE_LIKE) {
147 147
 				// transform "mimetype='foo/%'" to "mimepart='foo'"
148 148
 				if (preg_match('|(.+)/%|', $value, $matches)) {
149 149
 					$field = 'mimepart';
150
-					$value = (int)$this->mimetypeLoader->getId($matches[1]);
150
+					$value = (int) $this->mimetypeLoader->getId($matches[1]);
151 151
 					$type = ISearchComparison::COMPARE_EQUAL;
152 152
 				} elseif (strpos($value, '%') !== false) {
153
-					throw new \InvalidArgumentException('Unsupported query value for mimetype: ' . $value . ', only values in the format "mime/type" or "mime/%" are supported');
153
+					throw new \InvalidArgumentException('Unsupported query value for mimetype: '.$value.', only values in the format "mime/type" or "mime/%" are supported');
154 154
 				} else {
155 155
 					$field = 'mimetype';
156
-					$value = (int)$this->mimetypeLoader->getId($value);
156
+					$value = (int) $this->mimetypeLoader->getId($value);
157 157
 					$type = ISearchComparison::COMPARE_EQUAL;
158 158
 				}
159 159
 			}
@@ -166,7 +166,7 @@  discard block
 block discarded – undo
166 166
 			$field = 'file.fileid';
167 167
 		} elseif ($field === 'path' && $type === ISearchComparison::COMPARE_EQUAL) {
168 168
 			$field = 'path_hash';
169
-			$value = md5((string)$value);
169
+			$value = md5((string) $value);
170 170
 		}
171 171
 		return [$field, $value, $type];
172 172
 	}
@@ -196,14 +196,14 @@  discard block
 block discarded – undo
196 196
 		];
197 197
 
198 198
 		if (!isset($types[$operator->getField()])) {
199
-			throw new \InvalidArgumentException('Unsupported comparison field ' . $operator->getField());
199
+			throw new \InvalidArgumentException('Unsupported comparison field '.$operator->getField());
200 200
 		}
201 201
 		$type = $types[$operator->getField()];
202 202
 		if (gettype($operator->getValue()) !== $type) {
203
-			throw new \InvalidArgumentException('Invalid type for field ' . $operator->getField());
203
+			throw new \InvalidArgumentException('Invalid type for field '.$operator->getField());
204 204
 		}
205 205
 		if (!in_array($operator->getType(), $comparisons[$operator->getField()])) {
206
-			throw new \InvalidArgumentException('Unsupported comparison for field  ' . $operator->getField() . ': ' . $operator->getType());
206
+			throw new \InvalidArgumentException('Unsupported comparison for field  '.$operator->getField().': '.$operator->getType());
207 207
 		}
208 208
 	}
209 209
 
Please login to merge, or discard this patch.
lib/private/Files/Cache/Cache.php 2 patches
Indentation   +987 added lines, -987 removed lines patch added patch discarded remove patch
@@ -70,991 +70,991 @@
 block discarded – undo
70 70
  * - ChangePropagator: updates the mtime and etags of parent folders whenever a change to the cache is made to the cache by the updater
71 71
  */
72 72
 class Cache implements ICache {
73
-	use MoveFromCacheTrait {
74
-		MoveFromCacheTrait::moveFromCache as moveFromCacheFallback;
75
-	}
76
-
77
-	/**
78
-	 * @var array partial data for the cache
79
-	 */
80
-	protected $partial = [];
81
-
82
-	/**
83
-	 * @var string
84
-	 */
85
-	protected $storageId;
86
-
87
-	private $storage;
88
-
89
-	/**
90
-	 * @var Storage $storageCache
91
-	 */
92
-	protected $storageCache;
93
-
94
-	/** @var IMimeTypeLoader */
95
-	protected $mimetypeLoader;
96
-
97
-	/**
98
-	 * @var IDBConnection
99
-	 */
100
-	protected $connection;
101
-
102
-	/**
103
-	 * @var IEventDispatcher
104
-	 */
105
-	protected $eventDispatcher;
106
-
107
-	/** @var QuerySearchHelper */
108
-	protected $querySearchHelper;
109
-
110
-	/**
111
-	 * @param IStorage $storage
112
-	 */
113
-	public function __construct(IStorage $storage) {
114
-		$this->storageId = $storage->getId();
115
-		$this->storage = $storage;
116
-		if (strlen($this->storageId) > 64) {
117
-			$this->storageId = md5($this->storageId);
118
-		}
119
-
120
-		$this->storageCache = new Storage($storage);
121
-		$this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
122
-		$this->connection = \OC::$server->getDatabaseConnection();
123
-		$this->eventDispatcher = \OC::$server->get(IEventDispatcher::class);
124
-		$this->querySearchHelper = \OC::$server->query(QuerySearchHelper::class);
125
-	}
126
-
127
-	protected function getQueryBuilder() {
128
-		return new CacheQueryBuilder(
129
-			$this->connection,
130
-			\OC::$server->getSystemConfig(),
131
-			\OC::$server->getLogger()
132
-		);
133
-	}
134
-
135
-	/**
136
-	 * Get the numeric storage id for this cache's storage
137
-	 *
138
-	 * @return int
139
-	 */
140
-	public function getNumericStorageId() {
141
-		return $this->storageCache->getNumericId();
142
-	}
143
-
144
-	/**
145
-	 * get the stored metadata of a file or folder
146
-	 *
147
-	 * @param string | int $file either the path of a file or folder or the file id for a file or folder
148
-	 * @return ICacheEntry|false the cache entry as array of false if the file is not found in the cache
149
-	 */
150
-	public function get($file) {
151
-		$query = $this->getQueryBuilder();
152
-		$query->selectFileCache();
153
-
154
-		if (is_string($file) or $file == '') {
155
-			// normalize file
156
-			$file = $this->normalize($file);
157
-
158
-			$query->whereStorageId($this->getNumericStorageId())
159
-				->wherePath($file);
160
-		} else { //file id
161
-			$query->whereFileId($file);
162
-		}
163
-
164
-		$result = $query->execute();
165
-		$data = $result->fetch();
166
-		$result->closeCursor();
167
-
168
-		//merge partial data
169
-		if (!$data and is_string($file) and isset($this->partial[$file])) {
170
-			return $this->partial[$file];
171
-		} elseif (!$data) {
172
-			return $data;
173
-		} else {
174
-			return self::cacheEntryFromData($data, $this->mimetypeLoader);
175
-		}
176
-	}
177
-
178
-	/**
179
-	 * Create a CacheEntry from database row
180
-	 *
181
-	 * @param array $data
182
-	 * @param IMimeTypeLoader $mimetypeLoader
183
-	 * @return CacheEntry
184
-	 */
185
-	public static function cacheEntryFromData($data, IMimeTypeLoader $mimetypeLoader) {
186
-		//fix types
187
-		$data['fileid'] = (int)$data['fileid'];
188
-		$data['parent'] = (int)$data['parent'];
189
-		$data['size'] = 0 + $data['size'];
190
-		$data['mtime'] = (int)$data['mtime'];
191
-		$data['storage_mtime'] = (int)$data['storage_mtime'];
192
-		$data['encryptedVersion'] = (int)$data['encrypted'];
193
-		$data['encrypted'] = (bool)$data['encrypted'];
194
-		$data['storage_id'] = $data['storage'];
195
-		$data['storage'] = (int)$data['storage'];
196
-		$data['mimetype'] = $mimetypeLoader->getMimetypeById($data['mimetype']);
197
-		$data['mimepart'] = $mimetypeLoader->getMimetypeById($data['mimepart']);
198
-		if ($data['storage_mtime'] == 0) {
199
-			$data['storage_mtime'] = $data['mtime'];
200
-		}
201
-		$data['permissions'] = (int)$data['permissions'];
202
-		if (isset($data['creation_time'])) {
203
-			$data['creation_time'] = (int)$data['creation_time'];
204
-		}
205
-		if (isset($data['upload_time'])) {
206
-			$data['upload_time'] = (int)$data['upload_time'];
207
-		}
208
-		return new CacheEntry($data);
209
-	}
210
-
211
-	/**
212
-	 * get the metadata of all files stored in $folder
213
-	 *
214
-	 * @param string $folder
215
-	 * @return ICacheEntry[]
216
-	 */
217
-	public function getFolderContents($folder) {
218
-		$fileId = $this->getId($folder);
219
-		return $this->getFolderContentsById($fileId);
220
-	}
221
-
222
-	/**
223
-	 * get the metadata of all files stored in $folder
224
-	 *
225
-	 * @param int $fileId the file id of the folder
226
-	 * @return ICacheEntry[]
227
-	 */
228
-	public function getFolderContentsById($fileId) {
229
-		if ($fileId > -1) {
230
-			$query = $this->getQueryBuilder();
231
-			$query->selectFileCache()
232
-				->whereParent($fileId)
233
-				->orderBy('name', 'ASC');
234
-
235
-			$result = $query->execute();
236
-			$files = $result->fetchAll();
237
-			$result->closeCursor();
238
-
239
-			return array_map(function (array $data) {
240
-				return self::cacheEntryFromData($data, $this->mimetypeLoader);
241
-			}, $files);
242
-		}
243
-		return [];
244
-	}
245
-
246
-	/**
247
-	 * insert or update meta data for a file or folder
248
-	 *
249
-	 * @param string $file
250
-	 * @param array $data
251
-	 *
252
-	 * @return int file id
253
-	 * @throws \RuntimeException
254
-	 */
255
-	public function put($file, array $data) {
256
-		if (($id = $this->getId($file)) > -1) {
257
-			$this->update($id, $data);
258
-			return $id;
259
-		} else {
260
-			return $this->insert($file, $data);
261
-		}
262
-	}
263
-
264
-	/**
265
-	 * insert meta data for a new file or folder
266
-	 *
267
-	 * @param string $file
268
-	 * @param array $data
269
-	 *
270
-	 * @return int file id
271
-	 * @throws \RuntimeException
272
-	 */
273
-	public function insert($file, array $data) {
274
-		// normalize file
275
-		$file = $this->normalize($file);
276
-
277
-		if (isset($this->partial[$file])) { //add any saved partial data
278
-			$data = array_merge($this->partial[$file], $data);
279
-			unset($this->partial[$file]);
280
-		}
281
-
282
-		$requiredFields = ['size', 'mtime', 'mimetype'];
283
-		foreach ($requiredFields as $field) {
284
-			if (!isset($data[$field])) { //data not complete save as partial and return
285
-				$this->partial[$file] = $data;
286
-				return -1;
287
-			}
288
-		}
289
-
290
-		$data['path'] = $file;
291
-		if (!isset($data['parent'])) {
292
-			$data['parent'] = $this->getParentId($file);
293
-		}
294
-		$data['name'] = basename($file);
295
-
296
-		[$values, $extensionValues] = $this->normalizeData($data);
297
-		$storageId = $this->getNumericStorageId();
298
-		$values['storage'] = $storageId;
299
-
300
-		try {
301
-			$builder = $this->connection->getQueryBuilder();
302
-			$builder->insert('filecache');
303
-
304
-			foreach ($values as $column => $value) {
305
-				$builder->setValue($column, $builder->createNamedParameter($value));
306
-			}
307
-
308
-			if ($builder->execute()) {
309
-				$fileId = $builder->getLastInsertId();
310
-
311
-				if (count($extensionValues)) {
312
-					$query = $this->getQueryBuilder();
313
-					$query->insert('filecache_extended');
314
-
315
-					$query->setValue('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT));
316
-					foreach ($extensionValues as $column => $value) {
317
-						$query->setValue($column, $query->createNamedParameter($value));
318
-					}
319
-					$query->execute();
320
-				}
321
-
322
-				$event = new CacheEntryInsertedEvent($this->storage, $file, $fileId, $storageId);
323
-				$this->eventDispatcher->dispatch(CacheInsertEvent::class, $event);
324
-				$this->eventDispatcher->dispatchTyped($event);
325
-				return $fileId;
326
-			}
327
-		} catch (UniqueConstraintViolationException $e) {
328
-			// entry exists already
329
-			if ($this->connection->inTransaction()) {
330
-				$this->connection->commit();
331
-				$this->connection->beginTransaction();
332
-			}
333
-		}
334
-
335
-		// The file was created in the mean time
336
-		if (($id = $this->getId($file)) > -1) {
337
-			$this->update($id, $data);
338
-			return $id;
339
-		} else {
340
-			throw new \RuntimeException('File entry could not be inserted but could also not be selected with getId() in order to perform an update. Please try again.');
341
-		}
342
-	}
343
-
344
-	/**
345
-	 * update the metadata of an existing file or folder in the cache
346
-	 *
347
-	 * @param int $id the fileid of the existing file or folder
348
-	 * @param array $data [$key => $value] the metadata to update, only the fields provided in the array will be updated, non-provided values will remain unchanged
349
-	 */
350
-	public function update($id, array $data) {
351
-		if (isset($data['path'])) {
352
-			// normalize path
353
-			$data['path'] = $this->normalize($data['path']);
354
-		}
355
-
356
-		if (isset($data['name'])) {
357
-			// normalize path
358
-			$data['name'] = $this->normalize($data['name']);
359
-		}
360
-
361
-		[$values, $extensionValues] = $this->normalizeData($data);
362
-
363
-		if (count($values)) {
364
-			$query = $this->getQueryBuilder();
365
-
366
-			$query->update('filecache')
367
-				->whereFileId($id)
368
-				->andWhere($query->expr()->orX(...array_map(function ($key, $value) use ($query) {
369
-					return $query->expr()->orX(
370
-						$query->expr()->neq($key, $query->createNamedParameter($value)),
371
-						$query->expr()->isNull($key)
372
-					);
373
-				}, array_keys($values), array_values($values))));
374
-
375
-			foreach ($values as $key => $value) {
376
-				$query->set($key, $query->createNamedParameter($value));
377
-			}
378
-
379
-			$query->execute();
380
-		}
381
-
382
-		if (count($extensionValues)) {
383
-			try {
384
-				$query = $this->getQueryBuilder();
385
-				$query->insert('filecache_extended');
386
-
387
-				$query->setValue('fileid', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT));
388
-				foreach ($extensionValues as $column => $value) {
389
-					$query->setValue($column, $query->createNamedParameter($value));
390
-				}
391
-
392
-				$query->execute();
393
-			} catch (UniqueConstraintViolationException $e) {
394
-				$query = $this->getQueryBuilder();
395
-				$query->update('filecache_extended')
396
-					->whereFileId($id)
397
-					->andWhere($query->expr()->orX(...array_map(function ($key, $value) use ($query) {
398
-						return $query->expr()->orX(
399
-							$query->expr()->neq($key, $query->createNamedParameter($value)),
400
-							$query->expr()->isNull($key)
401
-						);
402
-					}, array_keys($extensionValues), array_values($extensionValues))));
403
-
404
-				foreach ($extensionValues as $key => $value) {
405
-					$query->set($key, $query->createNamedParameter($value));
406
-				}
407
-
408
-				$query->execute();
409
-			}
410
-		}
411
-
412
-		$path = $this->getPathById($id);
413
-		// path can still be null if the file doesn't exist
414
-		if ($path !== null) {
415
-			$event = new CacheEntryUpdatedEvent($this->storage, $path, $id, $this->getNumericStorageId());
416
-			$this->eventDispatcher->dispatch(CacheUpdateEvent::class, $event);
417
-			$this->eventDispatcher->dispatchTyped($event);
418
-		}
419
-	}
420
-
421
-	/**
422
-	 * extract query parts and params array from data array
423
-	 *
424
-	 * @param array $data
425
-	 * @return array
426
-	 */
427
-	protected function normalizeData(array $data): array {
428
-		$fields = [
429
-			'path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'storage_mtime', 'encrypted',
430
-			'etag', 'permissions', 'checksum', 'storage'];
431
-		$extensionFields = ['metadata_etag', 'creation_time', 'upload_time'];
432
-
433
-		$doNotCopyStorageMTime = false;
434
-		if (array_key_exists('mtime', $data) && $data['mtime'] === null) {
435
-			// this horrific magic tells it to not copy storage_mtime to mtime
436
-			unset($data['mtime']);
437
-			$doNotCopyStorageMTime = true;
438
-		}
439
-
440
-		$params = [];
441
-		$extensionParams = [];
442
-		foreach ($data as $name => $value) {
443
-			if (array_search($name, $fields) !== false) {
444
-				if ($name === 'path') {
445
-					$params['path_hash'] = md5($value);
446
-				} elseif ($name === 'mimetype') {
447
-					$params['mimepart'] = $this->mimetypeLoader->getId(substr($value, 0, strpos($value, '/')));
448
-					$value = $this->mimetypeLoader->getId($value);
449
-				} elseif ($name === 'storage_mtime') {
450
-					if (!$doNotCopyStorageMTime && !isset($data['mtime'])) {
451
-						$params['mtime'] = $value;
452
-					}
453
-				} elseif ($name === 'encrypted') {
454
-					if (isset($data['encryptedVersion'])) {
455
-						$value = $data['encryptedVersion'];
456
-					} else {
457
-						// Boolean to integer conversion
458
-						$value = $value ? 1 : 0;
459
-					}
460
-				}
461
-				$params[$name] = $value;
462
-			}
463
-			if (array_search($name, $extensionFields) !== false) {
464
-				$extensionParams[$name] = $value;
465
-			}
466
-		}
467
-		return [$params, array_filter($extensionParams)];
468
-	}
469
-
470
-	/**
471
-	 * get the file id for a file
472
-	 *
473
-	 * A file id is a numeric id for a file or folder that's unique within an owncloud instance which stays the same for the lifetime of a file
474
-	 *
475
-	 * File ids are easiest way for apps to store references to a file since unlike paths they are not affected by renames or sharing
476
-	 *
477
-	 * @param string $file
478
-	 * @return int
479
-	 */
480
-	public function getId($file) {
481
-		// normalize file
482
-		$file = $this->normalize($file);
483
-
484
-		$query = $this->getQueryBuilder();
485
-		$query->select('fileid')
486
-			->from('filecache')
487
-			->whereStorageId($this->getNumericStorageId())
488
-			->wherePath($file);
489
-
490
-		$result = $query->execute();
491
-		$id = $result->fetchOne();
492
-		$result->closeCursor();
493
-
494
-		return $id === false ? -1 : (int)$id;
495
-	}
496
-
497
-	/**
498
-	 * get the id of the parent folder of a file
499
-	 *
500
-	 * @param string $file
501
-	 * @return int
502
-	 */
503
-	public function getParentId($file) {
504
-		if ($file === '') {
505
-			return -1;
506
-		} else {
507
-			$parent = $this->getParentPath($file);
508
-			return (int)$this->getId($parent);
509
-		}
510
-	}
511
-
512
-	private function getParentPath($path) {
513
-		$parent = dirname($path);
514
-		if ($parent === '.') {
515
-			$parent = '';
516
-		}
517
-		return $parent;
518
-	}
519
-
520
-	/**
521
-	 * check if a file is available in the cache
522
-	 *
523
-	 * @param string $file
524
-	 * @return bool
525
-	 */
526
-	public function inCache($file) {
527
-		return $this->getId($file) != -1;
528
-	}
529
-
530
-	/**
531
-	 * remove a file or folder from the cache
532
-	 *
533
-	 * when removing a folder from the cache all files and folders inside the folder will be removed as well
534
-	 *
535
-	 * @param string $file
536
-	 */
537
-	public function remove($file) {
538
-		$entry = $this->get($file);
539
-
540
-		if ($entry) {
541
-			$query = $this->getQueryBuilder();
542
-			$query->delete('filecache')
543
-				->whereFileId($entry->getId());
544
-			$query->execute();
545
-
546
-			$query = $this->getQueryBuilder();
547
-			$query->delete('filecache_extended')
548
-				->whereFileId($entry->getId());
549
-			$query->execute();
550
-
551
-			if ($entry->getMimeType() == FileInfo::MIMETYPE_FOLDER) {
552
-				$this->removeChildren($entry);
553
-			}
554
-
555
-			$this->eventDispatcher->dispatchTyped(new CacheEntryRemovedEvent($this->storage, $entry->getPath(), $entry->getId(), $this->getNumericStorageId()));
556
-		}
557
-	}
558
-
559
-	/**
560
-	 * Get all sub folders of a folder
561
-	 *
562
-	 * @param ICacheEntry $entry the cache entry of the folder to get the subfolders for
563
-	 * @return ICacheEntry[] the cache entries for the subfolders
564
-	 */
565
-	private function getSubFolders(ICacheEntry $entry) {
566
-		$children = $this->getFolderContentsById($entry->getId());
567
-		return array_filter($children, function ($child) {
568
-			return $child->getMimeType() == FileInfo::MIMETYPE_FOLDER;
569
-		});
570
-	}
571
-
572
-	/**
573
-	 * Recursively remove all children of a folder
574
-	 *
575
-	 * @param ICacheEntry $entry the cache entry of the folder to remove the children of
576
-	 * @throws \OC\DatabaseException
577
-	 */
578
-	private function removeChildren(ICacheEntry $entry) {
579
-		$parentIds = [$entry->getId()];
580
-		$queue = [$entry->getId()];
581
-
582
-		// we walk depth first trough the file tree, removing all filecache_extended attributes while we walk
583
-		// and collecting all folder ids to later use to delete the filecache entries
584
-		while ($entryId = array_pop($queue)) {
585
-			$children = $this->getFolderContentsById($entryId);
586
-			$childIds = array_map(function (ICacheEntry $cacheEntry) {
587
-				return $cacheEntry->getId();
588
-			}, $children);
589
-
590
-			$query = $this->getQueryBuilder();
591
-			$query->delete('filecache_extended')
592
-				->where($query->expr()->in('fileid', $query->createNamedParameter($childIds, IQueryBuilder::PARAM_INT_ARRAY)));
593
-			$query->execute();
594
-
595
-			/** @var ICacheEntry[] $childFolders */
596
-			$childFolders = array_filter($children, function ($child) {
597
-				return $child->getMimeType() == FileInfo::MIMETYPE_FOLDER;
598
-			});
599
-			foreach ($childFolders as $folder) {
600
-				$parentIds[] = $folder->getId();
601
-				$queue[] = $folder->getId();
602
-			}
603
-		}
604
-
605
-		$query = $this->getQueryBuilder();
606
-		$query->delete('filecache')
607
-			->whereParentIn($parentIds);
608
-		$query->execute();
609
-	}
610
-
611
-	/**
612
-	 * Move a file or folder in the cache
613
-	 *
614
-	 * @param string $source
615
-	 * @param string $target
616
-	 */
617
-	public function move($source, $target) {
618
-		$this->moveFromCache($this, $source, $target);
619
-	}
620
-
621
-	/**
622
-	 * Get the storage id and path needed for a move
623
-	 *
624
-	 * @param string $path
625
-	 * @return array [$storageId, $internalPath]
626
-	 */
627
-	protected function getMoveInfo($path) {
628
-		return [$this->getNumericStorageId(), $path];
629
-	}
630
-
631
-	/**
632
-	 * Move a file or folder in the cache
633
-	 *
634
-	 * @param ICache $sourceCache
635
-	 * @param string $sourcePath
636
-	 * @param string $targetPath
637
-	 * @throws \OC\DatabaseException
638
-	 * @throws \Exception if the given storages have an invalid id
639
-	 */
640
-	public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
641
-		if ($sourceCache instanceof Cache) {
642
-			// normalize source and target
643
-			$sourcePath = $this->normalize($sourcePath);
644
-			$targetPath = $this->normalize($targetPath);
645
-
646
-			$sourceData = $sourceCache->get($sourcePath);
647
-			if ($sourceData === false) {
648
-				throw new \Exception('Invalid source storage path: ' . $sourcePath);
649
-			}
650
-
651
-			$sourceId = $sourceData['fileid'];
652
-			$newParentId = $this->getParentId($targetPath);
653
-
654
-			[$sourceStorageId, $sourcePath] = $sourceCache->getMoveInfo($sourcePath);
655
-			[$targetStorageId, $targetPath] = $this->getMoveInfo($targetPath);
656
-
657
-			if (is_null($sourceStorageId) || $sourceStorageId === false) {
658
-				throw new \Exception('Invalid source storage id: ' . $sourceStorageId);
659
-			}
660
-			if (is_null($targetStorageId) || $targetStorageId === false) {
661
-				throw new \Exception('Invalid target storage id: ' . $targetStorageId);
662
-			}
663
-
664
-			$this->connection->beginTransaction();
665
-			if ($sourceData['mimetype'] === 'httpd/unix-directory') {
666
-				//update all child entries
667
-				$sourceLength = mb_strlen($sourcePath);
668
-				$query = $this->connection->getQueryBuilder();
669
-
670
-				$fun = $query->func();
671
-				$newPathFunction = $fun->concat(
672
-					$query->createNamedParameter($targetPath),
673
-					$fun->substring('path', $query->createNamedParameter($sourceLength + 1, IQueryBuilder::PARAM_INT))// +1 for the leading slash
674
-				);
675
-				$query->update('filecache')
676
-					->set('storage', $query->createNamedParameter($targetStorageId, IQueryBuilder::PARAM_INT))
677
-					->set('path_hash', $fun->md5($newPathFunction))
678
-					->set('path', $newPathFunction)
679
-					->where($query->expr()->eq('storage', $query->createNamedParameter($sourceStorageId, IQueryBuilder::PARAM_INT)))
680
-					->andWhere($query->expr()->like('path', $query->createNamedParameter($this->connection->escapeLikeParameter($sourcePath) . '/%')));
681
-
682
-				try {
683
-					$query->execute();
684
-				} catch (\OC\DatabaseException $e) {
685
-					$this->connection->rollBack();
686
-					throw $e;
687
-				}
688
-			}
689
-
690
-			$query = $this->getQueryBuilder();
691
-			$query->update('filecache')
692
-				->set('storage', $query->createNamedParameter($targetStorageId))
693
-				->set('path', $query->createNamedParameter($targetPath))
694
-				->set('path_hash', $query->createNamedParameter(md5($targetPath)))
695
-				->set('name', $query->createNamedParameter(basename($targetPath)))
696
-				->set('parent', $query->createNamedParameter($newParentId, IQueryBuilder::PARAM_INT))
697
-				->whereFileId($sourceId);
698
-			$query->execute();
699
-
700
-			$this->connection->commit();
701
-
702
-			if ($sourceCache->getNumericStorageId() !== $this->getNumericStorageId()) {
703
-				$this->eventDispatcher->dispatchTyped(new CacheEntryRemovedEvent($this->storage, $sourcePath, $sourceId, $sourceCache->getNumericStorageId()));
704
-				$event = new CacheEntryInsertedEvent($this->storage, $targetPath, $sourceId, $this->getNumericStorageId());
705
-				$this->eventDispatcher->dispatch(CacheInsertEvent::class, $event);
706
-				$this->eventDispatcher->dispatchTyped($event);
707
-			} else {
708
-				$event = new CacheEntryUpdatedEvent($this->storage, $targetPath, $sourceId, $this->getNumericStorageId());
709
-				$this->eventDispatcher->dispatch(CacheUpdateEvent::class, $event);
710
-				$this->eventDispatcher->dispatchTyped($event);
711
-			}
712
-		} else {
713
-			$this->moveFromCacheFallback($sourceCache, $sourcePath, $targetPath);
714
-		}
715
-	}
716
-
717
-	/**
718
-	 * remove all entries for files that are stored on the storage from the cache
719
-	 */
720
-	public function clear() {
721
-		$query = $this->getQueryBuilder();
722
-		$query->delete('filecache')
723
-			->whereStorageId($this->getNumericStorageId());
724
-		$query->execute();
725
-
726
-		$query = $this->connection->getQueryBuilder();
727
-		$query->delete('storages')
728
-			->where($query->expr()->eq('id', $query->createNamedParameter($this->storageId)));
729
-		$query->execute();
730
-	}
731
-
732
-	/**
733
-	 * Get the scan status of a file
734
-	 *
735
-	 * - Cache::NOT_FOUND: File is not in the cache
736
-	 * - Cache::PARTIAL: File is not stored in the cache but some incomplete data is known
737
-	 * - Cache::SHALLOW: The folder and it's direct children are in the cache but not all sub folders are fully scanned
738
-	 * - Cache::COMPLETE: The file or folder, with all it's children) are fully scanned
739
-	 *
740
-	 * @param string $file
741
-	 *
742
-	 * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
743
-	 */
744
-	public function getStatus($file) {
745
-		// normalize file
746
-		$file = $this->normalize($file);
747
-
748
-		$query = $this->getQueryBuilder();
749
-		$query->select('size')
750
-			->from('filecache')
751
-			->whereStorageId($this->getNumericStorageId())
752
-			->wherePath($file);
753
-
754
-		$result = $query->execute();
755
-		$size = $result->fetchOne();
756
-		$result->closeCursor();
757
-
758
-		if ($size !== false) {
759
-			if ((int)$size === -1) {
760
-				return self::SHALLOW;
761
-			} else {
762
-				return self::COMPLETE;
763
-			}
764
-		} else {
765
-			if (isset($this->partial[$file])) {
766
-				return self::PARTIAL;
767
-			} else {
768
-				return self::NOT_FOUND;
769
-			}
770
-		}
771
-	}
772
-
773
-	/**
774
-	 * search for files matching $pattern
775
-	 *
776
-	 * @param string $pattern the search pattern using SQL search syntax (e.g. '%searchstring%')
777
-	 * @return ICacheEntry[] an array of cache entries where the name matches the search pattern
778
-	 */
779
-	public function search($pattern) {
780
-		$operator = new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', $pattern);
781
-		return $this->searchQuery(new SearchQuery($operator, 0, 0, [], null));
782
-	}
783
-
784
-	/**
785
-	 * search for files by mimetype
786
-	 *
787
-	 * @param string $mimetype either a full mimetype to search ('text/plain') or only the first part of a mimetype ('image')
788
-	 *        where it will search for all mimetypes in the group ('image/*')
789
-	 * @return ICacheEntry[] an array of cache entries where the mimetype matches the search
790
-	 */
791
-	public function searchByMime($mimetype) {
792
-		if (strpos($mimetype, '/') === false) {
793
-			$operator = new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype . '/%');
794
-		} else {
795
-			$operator = new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $mimetype);
796
-		}
797
-		return $this->searchQuery(new SearchQuery($operator, 0, 0, [], null));
798
-	}
799
-
800
-	public function searchQuery(ISearchQuery $searchQuery) {
801
-		return current($this->querySearchHelper->searchInCaches($searchQuery, [$this]));
802
-	}
803
-
804
-	/**
805
-	 * Re-calculate the folder size and the size of all parent folders
806
-	 *
807
-	 * @param string|boolean $path
808
-	 * @param array $data (optional) meta data of the folder
809
-	 */
810
-	public function correctFolderSize($path, $data = null, $isBackgroundScan = false) {
811
-		$this->calculateFolderSize($path, $data);
812
-		if ($path !== '') {
813
-			$parent = dirname($path);
814
-			if ($parent === '.' or $parent === '/') {
815
-				$parent = '';
816
-			}
817
-			if ($isBackgroundScan) {
818
-				$parentData = $this->get($parent);
819
-				if ($parentData['size'] !== -1 && $this->getIncompleteChildrenCount($parentData['fileid']) === 0) {
820
-					$this->correctFolderSize($parent, $parentData, $isBackgroundScan);
821
-				}
822
-			} else {
823
-				$this->correctFolderSize($parent);
824
-			}
825
-		}
826
-	}
827
-
828
-	/**
829
-	 * get the incomplete count that shares parent $folder
830
-	 *
831
-	 * @param int $fileId the file id of the folder
832
-	 * @return int
833
-	 */
834
-	public function getIncompleteChildrenCount($fileId) {
835
-		if ($fileId > -1) {
836
-			$query = $this->getQueryBuilder();
837
-			$query->select($query->func()->count())
838
-				->from('filecache')
839
-				->whereParent($fileId)
840
-				->andWhere($query->expr()->lt('size', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
841
-
842
-			$result = $query->execute();
843
-			$size = (int)$result->fetchOne();
844
-			$result->closeCursor();
845
-
846
-			return $size;
847
-		}
848
-		return -1;
849
-	}
850
-
851
-	/**
852
-	 * calculate the size of a folder and set it in the cache
853
-	 *
854
-	 * @param string $path
855
-	 * @param array $entry (optional) meta data of the folder
856
-	 * @return int
857
-	 */
858
-	public function calculateFolderSize($path, $entry = null) {
859
-		$totalSize = 0;
860
-		if (is_null($entry) or !isset($entry['fileid'])) {
861
-			$entry = $this->get($path);
862
-		}
863
-		if (isset($entry['mimetype']) && $entry['mimetype'] === FileInfo::MIMETYPE_FOLDER) {
864
-			$id = $entry['fileid'];
865
-
866
-			$query = $this->getQueryBuilder();
867
-			$query->selectAlias($query->func()->sum('size'), 'f1')
868
-				->selectAlias($query->func()->min('size'), 'f2')
869
-				->from('filecache')
870
-				->whereStorageId($this->getNumericStorageId())
871
-				->whereParent($id);
872
-
873
-			$result = $query->execute();
874
-			$row = $result->fetch();
875
-			$result->closeCursor();
876
-
877
-			if ($row) {
878
-				[$sum, $min] = array_values($row);
879
-				$sum = 0 + $sum;
880
-				$min = 0 + $min;
881
-				if ($min === -1) {
882
-					$totalSize = $min;
883
-				} else {
884
-					$totalSize = $sum;
885
-				}
886
-				if ($entry['size'] !== $totalSize) {
887
-					$this->update($id, ['size' => $totalSize]);
888
-				}
889
-			}
890
-		}
891
-		return $totalSize;
892
-	}
893
-
894
-	/**
895
-	 * get all file ids on the files on the storage
896
-	 *
897
-	 * @return int[]
898
-	 */
899
-	public function getAll() {
900
-		$query = $this->getQueryBuilder();
901
-		$query->select('fileid')
902
-			->from('filecache')
903
-			->whereStorageId($this->getNumericStorageId());
904
-
905
-		$result = $query->execute();
906
-		$files = $result->fetchAll(\PDO::FETCH_COLUMN);
907
-		$result->closeCursor();
908
-
909
-		return array_map(function ($id) {
910
-			return (int)$id;
911
-		}, $files);
912
-	}
913
-
914
-	/**
915
-	 * find a folder in the cache which has not been fully scanned
916
-	 *
917
-	 * If multiple incomplete folders are in the cache, the one with the highest id will be returned,
918
-	 * use the one with the highest id gives the best result with the background scanner, since that is most
919
-	 * likely the folder where we stopped scanning previously
920
-	 *
921
-	 * @return string|bool the path of the folder or false when no folder matched
922
-	 */
923
-	public function getIncomplete() {
924
-		$query = $this->getQueryBuilder();
925
-		$query->select('path')
926
-			->from('filecache')
927
-			->whereStorageId($this->getNumericStorageId())
928
-			->andWhere($query->expr()->lt('size', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
929
-			->orderBy('fileid', 'DESC')
930
-			->setMaxResults(1);
931
-
932
-		$result = $query->execute();
933
-		$path = $result->fetchOne();
934
-		$result->closeCursor();
935
-
936
-		return $path;
937
-	}
938
-
939
-	/**
940
-	 * get the path of a file on this storage by it's file id
941
-	 *
942
-	 * @param int $id the file id of the file or folder to search
943
-	 * @return string|null the path of the file (relative to the storage) or null if a file with the given id does not exists within this cache
944
-	 */
945
-	public function getPathById($id) {
946
-		$query = $this->getQueryBuilder();
947
-		$query->select('path')
948
-			->from('filecache')
949
-			->whereStorageId($this->getNumericStorageId())
950
-			->whereFileId($id);
951
-
952
-		$result = $query->execute();
953
-		$path = $result->fetchOne();
954
-		$result->closeCursor();
955
-
956
-		if ($path === false) {
957
-			return null;
958
-		}
959
-
960
-		return (string)$path;
961
-	}
962
-
963
-	/**
964
-	 * get the storage id of the storage for a file and the internal path of the file
965
-	 * unlike getPathById this does not limit the search to files on this storage and
966
-	 * instead does a global search in the cache table
967
-	 *
968
-	 * @param int $id
969
-	 * @return array first element holding the storage id, second the path
970
-	 * @deprecated use getPathById() instead
971
-	 */
972
-	public static function getById($id) {
973
-		$query = \OC::$server->getDatabaseConnection()->getQueryBuilder();
974
-		$query->select('path', 'storage')
975
-			->from('filecache')
976
-			->where($query->expr()->eq('fileid', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
977
-
978
-		$result = $query->execute();
979
-		$row = $result->fetch();
980
-		$result->closeCursor();
981
-
982
-		if ($row) {
983
-			$numericId = $row['storage'];
984
-			$path = $row['path'];
985
-		} else {
986
-			return null;
987
-		}
988
-
989
-		if ($id = Storage::getStorageId($numericId)) {
990
-			return [$id, $path];
991
-		} else {
992
-			return null;
993
-		}
994
-	}
995
-
996
-	/**
997
-	 * normalize the given path
998
-	 *
999
-	 * @param string $path
1000
-	 * @return string
1001
-	 */
1002
-	public function normalize($path) {
1003
-		return trim(\OC_Util::normalizeUnicode($path), '/');
1004
-	}
1005
-
1006
-	/**
1007
-	 * Copy a file or folder in the cache
1008
-	 *
1009
-	 * @param ICache $sourceCache
1010
-	 * @param ICacheEntry $sourceEntry
1011
-	 * @param string $targetPath
1012
-	 * @return int fileid of copied entry
1013
-	 */
1014
-	public function copyFromCache(ICache $sourceCache, ICacheEntry $sourceEntry, string $targetPath): int {
1015
-		if ($sourceEntry->getId() < 0) {
1016
-			throw new \RuntimeException("Invalid source cache entry on copyFromCache");
1017
-		}
1018
-		$data = $this->cacheEntryToArray($sourceEntry);
1019
-		$fileId = $this->put($targetPath, $data);
1020
-		if ($fileId <= 0) {
1021
-			throw new \RuntimeException("Failed to copy to " . $targetPath . " from cache with source data " . json_encode($data) . " ");
1022
-		}
1023
-		if ($sourceEntry->getMimeType() === ICacheEntry::DIRECTORY_MIMETYPE) {
1024
-			$folderContent = $sourceCache->getFolderContentsById($sourceEntry->getId());
1025
-			foreach ($folderContent as $subEntry) {
1026
-				$subTargetPath = $targetPath . '/' . $subEntry->getName();
1027
-				$this->copyFromCache($sourceCache, $subEntry, $subTargetPath);
1028
-			}
1029
-		}
1030
-		return $fileId;
1031
-	}
1032
-
1033
-	private function cacheEntryToArray(ICacheEntry $entry): array {
1034
-		return [
1035
-			'size' => $entry->getSize(),
1036
-			'mtime' => $entry->getMTime(),
1037
-			'storage_mtime' => $entry->getStorageMTime(),
1038
-			'mimetype' => $entry->getMimeType(),
1039
-			'mimepart' => $entry->getMimePart(),
1040
-			'etag' => $entry->getEtag(),
1041
-			'permissions' => $entry->getPermissions(),
1042
-			'encrypted' => $entry->isEncrypted(),
1043
-			'creation_time' => $entry->getCreationTime(),
1044
-			'upload_time' => $entry->getUploadTime(),
1045
-			'metadata_etag' => $entry->getMetadataEtag(),
1046
-		];
1047
-	}
1048
-
1049
-	public function getQueryFilterForStorage(): ISearchOperator {
1050
-		return new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', $this->getNumericStorageId());
1051
-	}
1052
-
1053
-	public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {
1054
-		if ($rawEntry->getStorageId() === $this->getNumericStorageId()) {
1055
-			return $rawEntry;
1056
-		} else {
1057
-			return null;
1058
-		}
1059
-	}
73
+    use MoveFromCacheTrait {
74
+        MoveFromCacheTrait::moveFromCache as moveFromCacheFallback;
75
+    }
76
+
77
+    /**
78
+     * @var array partial data for the cache
79
+     */
80
+    protected $partial = [];
81
+
82
+    /**
83
+     * @var string
84
+     */
85
+    protected $storageId;
86
+
87
+    private $storage;
88
+
89
+    /**
90
+     * @var Storage $storageCache
91
+     */
92
+    protected $storageCache;
93
+
94
+    /** @var IMimeTypeLoader */
95
+    protected $mimetypeLoader;
96
+
97
+    /**
98
+     * @var IDBConnection
99
+     */
100
+    protected $connection;
101
+
102
+    /**
103
+     * @var IEventDispatcher
104
+     */
105
+    protected $eventDispatcher;
106
+
107
+    /** @var QuerySearchHelper */
108
+    protected $querySearchHelper;
109
+
110
+    /**
111
+     * @param IStorage $storage
112
+     */
113
+    public function __construct(IStorage $storage) {
114
+        $this->storageId = $storage->getId();
115
+        $this->storage = $storage;
116
+        if (strlen($this->storageId) > 64) {
117
+            $this->storageId = md5($this->storageId);
118
+        }
119
+
120
+        $this->storageCache = new Storage($storage);
121
+        $this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
122
+        $this->connection = \OC::$server->getDatabaseConnection();
123
+        $this->eventDispatcher = \OC::$server->get(IEventDispatcher::class);
124
+        $this->querySearchHelper = \OC::$server->query(QuerySearchHelper::class);
125
+    }
126
+
127
+    protected function getQueryBuilder() {
128
+        return new CacheQueryBuilder(
129
+            $this->connection,
130
+            \OC::$server->getSystemConfig(),
131
+            \OC::$server->getLogger()
132
+        );
133
+    }
134
+
135
+    /**
136
+     * Get the numeric storage id for this cache's storage
137
+     *
138
+     * @return int
139
+     */
140
+    public function getNumericStorageId() {
141
+        return $this->storageCache->getNumericId();
142
+    }
143
+
144
+    /**
145
+     * get the stored metadata of a file or folder
146
+     *
147
+     * @param string | int $file either the path of a file or folder or the file id for a file or folder
148
+     * @return ICacheEntry|false the cache entry as array of false if the file is not found in the cache
149
+     */
150
+    public function get($file) {
151
+        $query = $this->getQueryBuilder();
152
+        $query->selectFileCache();
153
+
154
+        if (is_string($file) or $file == '') {
155
+            // normalize file
156
+            $file = $this->normalize($file);
157
+
158
+            $query->whereStorageId($this->getNumericStorageId())
159
+                ->wherePath($file);
160
+        } else { //file id
161
+            $query->whereFileId($file);
162
+        }
163
+
164
+        $result = $query->execute();
165
+        $data = $result->fetch();
166
+        $result->closeCursor();
167
+
168
+        //merge partial data
169
+        if (!$data and is_string($file) and isset($this->partial[$file])) {
170
+            return $this->partial[$file];
171
+        } elseif (!$data) {
172
+            return $data;
173
+        } else {
174
+            return self::cacheEntryFromData($data, $this->mimetypeLoader);
175
+        }
176
+    }
177
+
178
+    /**
179
+     * Create a CacheEntry from database row
180
+     *
181
+     * @param array $data
182
+     * @param IMimeTypeLoader $mimetypeLoader
183
+     * @return CacheEntry
184
+     */
185
+    public static function cacheEntryFromData($data, IMimeTypeLoader $mimetypeLoader) {
186
+        //fix types
187
+        $data['fileid'] = (int)$data['fileid'];
188
+        $data['parent'] = (int)$data['parent'];
189
+        $data['size'] = 0 + $data['size'];
190
+        $data['mtime'] = (int)$data['mtime'];
191
+        $data['storage_mtime'] = (int)$data['storage_mtime'];
192
+        $data['encryptedVersion'] = (int)$data['encrypted'];
193
+        $data['encrypted'] = (bool)$data['encrypted'];
194
+        $data['storage_id'] = $data['storage'];
195
+        $data['storage'] = (int)$data['storage'];
196
+        $data['mimetype'] = $mimetypeLoader->getMimetypeById($data['mimetype']);
197
+        $data['mimepart'] = $mimetypeLoader->getMimetypeById($data['mimepart']);
198
+        if ($data['storage_mtime'] == 0) {
199
+            $data['storage_mtime'] = $data['mtime'];
200
+        }
201
+        $data['permissions'] = (int)$data['permissions'];
202
+        if (isset($data['creation_time'])) {
203
+            $data['creation_time'] = (int)$data['creation_time'];
204
+        }
205
+        if (isset($data['upload_time'])) {
206
+            $data['upload_time'] = (int)$data['upload_time'];
207
+        }
208
+        return new CacheEntry($data);
209
+    }
210
+
211
+    /**
212
+     * get the metadata of all files stored in $folder
213
+     *
214
+     * @param string $folder
215
+     * @return ICacheEntry[]
216
+     */
217
+    public function getFolderContents($folder) {
218
+        $fileId = $this->getId($folder);
219
+        return $this->getFolderContentsById($fileId);
220
+    }
221
+
222
+    /**
223
+     * get the metadata of all files stored in $folder
224
+     *
225
+     * @param int $fileId the file id of the folder
226
+     * @return ICacheEntry[]
227
+     */
228
+    public function getFolderContentsById($fileId) {
229
+        if ($fileId > -1) {
230
+            $query = $this->getQueryBuilder();
231
+            $query->selectFileCache()
232
+                ->whereParent($fileId)
233
+                ->orderBy('name', 'ASC');
234
+
235
+            $result = $query->execute();
236
+            $files = $result->fetchAll();
237
+            $result->closeCursor();
238
+
239
+            return array_map(function (array $data) {
240
+                return self::cacheEntryFromData($data, $this->mimetypeLoader);
241
+            }, $files);
242
+        }
243
+        return [];
244
+    }
245
+
246
+    /**
247
+     * insert or update meta data for a file or folder
248
+     *
249
+     * @param string $file
250
+     * @param array $data
251
+     *
252
+     * @return int file id
253
+     * @throws \RuntimeException
254
+     */
255
+    public function put($file, array $data) {
256
+        if (($id = $this->getId($file)) > -1) {
257
+            $this->update($id, $data);
258
+            return $id;
259
+        } else {
260
+            return $this->insert($file, $data);
261
+        }
262
+    }
263
+
264
+    /**
265
+     * insert meta data for a new file or folder
266
+     *
267
+     * @param string $file
268
+     * @param array $data
269
+     *
270
+     * @return int file id
271
+     * @throws \RuntimeException
272
+     */
273
+    public function insert($file, array $data) {
274
+        // normalize file
275
+        $file = $this->normalize($file);
276
+
277
+        if (isset($this->partial[$file])) { //add any saved partial data
278
+            $data = array_merge($this->partial[$file], $data);
279
+            unset($this->partial[$file]);
280
+        }
281
+
282
+        $requiredFields = ['size', 'mtime', 'mimetype'];
283
+        foreach ($requiredFields as $field) {
284
+            if (!isset($data[$field])) { //data not complete save as partial and return
285
+                $this->partial[$file] = $data;
286
+                return -1;
287
+            }
288
+        }
289
+
290
+        $data['path'] = $file;
291
+        if (!isset($data['parent'])) {
292
+            $data['parent'] = $this->getParentId($file);
293
+        }
294
+        $data['name'] = basename($file);
295
+
296
+        [$values, $extensionValues] = $this->normalizeData($data);
297
+        $storageId = $this->getNumericStorageId();
298
+        $values['storage'] = $storageId;
299
+
300
+        try {
301
+            $builder = $this->connection->getQueryBuilder();
302
+            $builder->insert('filecache');
303
+
304
+            foreach ($values as $column => $value) {
305
+                $builder->setValue($column, $builder->createNamedParameter($value));
306
+            }
307
+
308
+            if ($builder->execute()) {
309
+                $fileId = $builder->getLastInsertId();
310
+
311
+                if (count($extensionValues)) {
312
+                    $query = $this->getQueryBuilder();
313
+                    $query->insert('filecache_extended');
314
+
315
+                    $query->setValue('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT));
316
+                    foreach ($extensionValues as $column => $value) {
317
+                        $query->setValue($column, $query->createNamedParameter($value));
318
+                    }
319
+                    $query->execute();
320
+                }
321
+
322
+                $event = new CacheEntryInsertedEvent($this->storage, $file, $fileId, $storageId);
323
+                $this->eventDispatcher->dispatch(CacheInsertEvent::class, $event);
324
+                $this->eventDispatcher->dispatchTyped($event);
325
+                return $fileId;
326
+            }
327
+        } catch (UniqueConstraintViolationException $e) {
328
+            // entry exists already
329
+            if ($this->connection->inTransaction()) {
330
+                $this->connection->commit();
331
+                $this->connection->beginTransaction();
332
+            }
333
+        }
334
+
335
+        // The file was created in the mean time
336
+        if (($id = $this->getId($file)) > -1) {
337
+            $this->update($id, $data);
338
+            return $id;
339
+        } else {
340
+            throw new \RuntimeException('File entry could not be inserted but could also not be selected with getId() in order to perform an update. Please try again.');
341
+        }
342
+    }
343
+
344
+    /**
345
+     * update the metadata of an existing file or folder in the cache
346
+     *
347
+     * @param int $id the fileid of the existing file or folder
348
+     * @param array $data [$key => $value] the metadata to update, only the fields provided in the array will be updated, non-provided values will remain unchanged
349
+     */
350
+    public function update($id, array $data) {
351
+        if (isset($data['path'])) {
352
+            // normalize path
353
+            $data['path'] = $this->normalize($data['path']);
354
+        }
355
+
356
+        if (isset($data['name'])) {
357
+            // normalize path
358
+            $data['name'] = $this->normalize($data['name']);
359
+        }
360
+
361
+        [$values, $extensionValues] = $this->normalizeData($data);
362
+
363
+        if (count($values)) {
364
+            $query = $this->getQueryBuilder();
365
+
366
+            $query->update('filecache')
367
+                ->whereFileId($id)
368
+                ->andWhere($query->expr()->orX(...array_map(function ($key, $value) use ($query) {
369
+                    return $query->expr()->orX(
370
+                        $query->expr()->neq($key, $query->createNamedParameter($value)),
371
+                        $query->expr()->isNull($key)
372
+                    );
373
+                }, array_keys($values), array_values($values))));
374
+
375
+            foreach ($values as $key => $value) {
376
+                $query->set($key, $query->createNamedParameter($value));
377
+            }
378
+
379
+            $query->execute();
380
+        }
381
+
382
+        if (count($extensionValues)) {
383
+            try {
384
+                $query = $this->getQueryBuilder();
385
+                $query->insert('filecache_extended');
386
+
387
+                $query->setValue('fileid', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT));
388
+                foreach ($extensionValues as $column => $value) {
389
+                    $query->setValue($column, $query->createNamedParameter($value));
390
+                }
391
+
392
+                $query->execute();
393
+            } catch (UniqueConstraintViolationException $e) {
394
+                $query = $this->getQueryBuilder();
395
+                $query->update('filecache_extended')
396
+                    ->whereFileId($id)
397
+                    ->andWhere($query->expr()->orX(...array_map(function ($key, $value) use ($query) {
398
+                        return $query->expr()->orX(
399
+                            $query->expr()->neq($key, $query->createNamedParameter($value)),
400
+                            $query->expr()->isNull($key)
401
+                        );
402
+                    }, array_keys($extensionValues), array_values($extensionValues))));
403
+
404
+                foreach ($extensionValues as $key => $value) {
405
+                    $query->set($key, $query->createNamedParameter($value));
406
+                }
407
+
408
+                $query->execute();
409
+            }
410
+        }
411
+
412
+        $path = $this->getPathById($id);
413
+        // path can still be null if the file doesn't exist
414
+        if ($path !== null) {
415
+            $event = new CacheEntryUpdatedEvent($this->storage, $path, $id, $this->getNumericStorageId());
416
+            $this->eventDispatcher->dispatch(CacheUpdateEvent::class, $event);
417
+            $this->eventDispatcher->dispatchTyped($event);
418
+        }
419
+    }
420
+
421
+    /**
422
+     * extract query parts and params array from data array
423
+     *
424
+     * @param array $data
425
+     * @return array
426
+     */
427
+    protected function normalizeData(array $data): array {
428
+        $fields = [
429
+            'path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'storage_mtime', 'encrypted',
430
+            'etag', 'permissions', 'checksum', 'storage'];
431
+        $extensionFields = ['metadata_etag', 'creation_time', 'upload_time'];
432
+
433
+        $doNotCopyStorageMTime = false;
434
+        if (array_key_exists('mtime', $data) && $data['mtime'] === null) {
435
+            // this horrific magic tells it to not copy storage_mtime to mtime
436
+            unset($data['mtime']);
437
+            $doNotCopyStorageMTime = true;
438
+        }
439
+
440
+        $params = [];
441
+        $extensionParams = [];
442
+        foreach ($data as $name => $value) {
443
+            if (array_search($name, $fields) !== false) {
444
+                if ($name === 'path') {
445
+                    $params['path_hash'] = md5($value);
446
+                } elseif ($name === 'mimetype') {
447
+                    $params['mimepart'] = $this->mimetypeLoader->getId(substr($value, 0, strpos($value, '/')));
448
+                    $value = $this->mimetypeLoader->getId($value);
449
+                } elseif ($name === 'storage_mtime') {
450
+                    if (!$doNotCopyStorageMTime && !isset($data['mtime'])) {
451
+                        $params['mtime'] = $value;
452
+                    }
453
+                } elseif ($name === 'encrypted') {
454
+                    if (isset($data['encryptedVersion'])) {
455
+                        $value = $data['encryptedVersion'];
456
+                    } else {
457
+                        // Boolean to integer conversion
458
+                        $value = $value ? 1 : 0;
459
+                    }
460
+                }
461
+                $params[$name] = $value;
462
+            }
463
+            if (array_search($name, $extensionFields) !== false) {
464
+                $extensionParams[$name] = $value;
465
+            }
466
+        }
467
+        return [$params, array_filter($extensionParams)];
468
+    }
469
+
470
+    /**
471
+     * get the file id for a file
472
+     *
473
+     * A file id is a numeric id for a file or folder that's unique within an owncloud instance which stays the same for the lifetime of a file
474
+     *
475
+     * File ids are easiest way for apps to store references to a file since unlike paths they are not affected by renames or sharing
476
+     *
477
+     * @param string $file
478
+     * @return int
479
+     */
480
+    public function getId($file) {
481
+        // normalize file
482
+        $file = $this->normalize($file);
483
+
484
+        $query = $this->getQueryBuilder();
485
+        $query->select('fileid')
486
+            ->from('filecache')
487
+            ->whereStorageId($this->getNumericStorageId())
488
+            ->wherePath($file);
489
+
490
+        $result = $query->execute();
491
+        $id = $result->fetchOne();
492
+        $result->closeCursor();
493
+
494
+        return $id === false ? -1 : (int)$id;
495
+    }
496
+
497
+    /**
498
+     * get the id of the parent folder of a file
499
+     *
500
+     * @param string $file
501
+     * @return int
502
+     */
503
+    public function getParentId($file) {
504
+        if ($file === '') {
505
+            return -1;
506
+        } else {
507
+            $parent = $this->getParentPath($file);
508
+            return (int)$this->getId($parent);
509
+        }
510
+    }
511
+
512
+    private function getParentPath($path) {
513
+        $parent = dirname($path);
514
+        if ($parent === '.') {
515
+            $parent = '';
516
+        }
517
+        return $parent;
518
+    }
519
+
520
+    /**
521
+     * check if a file is available in the cache
522
+     *
523
+     * @param string $file
524
+     * @return bool
525
+     */
526
+    public function inCache($file) {
527
+        return $this->getId($file) != -1;
528
+    }
529
+
530
+    /**
531
+     * remove a file or folder from the cache
532
+     *
533
+     * when removing a folder from the cache all files and folders inside the folder will be removed as well
534
+     *
535
+     * @param string $file
536
+     */
537
+    public function remove($file) {
538
+        $entry = $this->get($file);
539
+
540
+        if ($entry) {
541
+            $query = $this->getQueryBuilder();
542
+            $query->delete('filecache')
543
+                ->whereFileId($entry->getId());
544
+            $query->execute();
545
+
546
+            $query = $this->getQueryBuilder();
547
+            $query->delete('filecache_extended')
548
+                ->whereFileId($entry->getId());
549
+            $query->execute();
550
+
551
+            if ($entry->getMimeType() == FileInfo::MIMETYPE_FOLDER) {
552
+                $this->removeChildren($entry);
553
+            }
554
+
555
+            $this->eventDispatcher->dispatchTyped(new CacheEntryRemovedEvent($this->storage, $entry->getPath(), $entry->getId(), $this->getNumericStorageId()));
556
+        }
557
+    }
558
+
559
+    /**
560
+     * Get all sub folders of a folder
561
+     *
562
+     * @param ICacheEntry $entry the cache entry of the folder to get the subfolders for
563
+     * @return ICacheEntry[] the cache entries for the subfolders
564
+     */
565
+    private function getSubFolders(ICacheEntry $entry) {
566
+        $children = $this->getFolderContentsById($entry->getId());
567
+        return array_filter($children, function ($child) {
568
+            return $child->getMimeType() == FileInfo::MIMETYPE_FOLDER;
569
+        });
570
+    }
571
+
572
+    /**
573
+     * Recursively remove all children of a folder
574
+     *
575
+     * @param ICacheEntry $entry the cache entry of the folder to remove the children of
576
+     * @throws \OC\DatabaseException
577
+     */
578
+    private function removeChildren(ICacheEntry $entry) {
579
+        $parentIds = [$entry->getId()];
580
+        $queue = [$entry->getId()];
581
+
582
+        // we walk depth first trough the file tree, removing all filecache_extended attributes while we walk
583
+        // and collecting all folder ids to later use to delete the filecache entries
584
+        while ($entryId = array_pop($queue)) {
585
+            $children = $this->getFolderContentsById($entryId);
586
+            $childIds = array_map(function (ICacheEntry $cacheEntry) {
587
+                return $cacheEntry->getId();
588
+            }, $children);
589
+
590
+            $query = $this->getQueryBuilder();
591
+            $query->delete('filecache_extended')
592
+                ->where($query->expr()->in('fileid', $query->createNamedParameter($childIds, IQueryBuilder::PARAM_INT_ARRAY)));
593
+            $query->execute();
594
+
595
+            /** @var ICacheEntry[] $childFolders */
596
+            $childFolders = array_filter($children, function ($child) {
597
+                return $child->getMimeType() == FileInfo::MIMETYPE_FOLDER;
598
+            });
599
+            foreach ($childFolders as $folder) {
600
+                $parentIds[] = $folder->getId();
601
+                $queue[] = $folder->getId();
602
+            }
603
+        }
604
+
605
+        $query = $this->getQueryBuilder();
606
+        $query->delete('filecache')
607
+            ->whereParentIn($parentIds);
608
+        $query->execute();
609
+    }
610
+
611
+    /**
612
+     * Move a file or folder in the cache
613
+     *
614
+     * @param string $source
615
+     * @param string $target
616
+     */
617
+    public function move($source, $target) {
618
+        $this->moveFromCache($this, $source, $target);
619
+    }
620
+
621
+    /**
622
+     * Get the storage id and path needed for a move
623
+     *
624
+     * @param string $path
625
+     * @return array [$storageId, $internalPath]
626
+     */
627
+    protected function getMoveInfo($path) {
628
+        return [$this->getNumericStorageId(), $path];
629
+    }
630
+
631
+    /**
632
+     * Move a file or folder in the cache
633
+     *
634
+     * @param ICache $sourceCache
635
+     * @param string $sourcePath
636
+     * @param string $targetPath
637
+     * @throws \OC\DatabaseException
638
+     * @throws \Exception if the given storages have an invalid id
639
+     */
640
+    public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
641
+        if ($sourceCache instanceof Cache) {
642
+            // normalize source and target
643
+            $sourcePath = $this->normalize($sourcePath);
644
+            $targetPath = $this->normalize($targetPath);
645
+
646
+            $sourceData = $sourceCache->get($sourcePath);
647
+            if ($sourceData === false) {
648
+                throw new \Exception('Invalid source storage path: ' . $sourcePath);
649
+            }
650
+
651
+            $sourceId = $sourceData['fileid'];
652
+            $newParentId = $this->getParentId($targetPath);
653
+
654
+            [$sourceStorageId, $sourcePath] = $sourceCache->getMoveInfo($sourcePath);
655
+            [$targetStorageId, $targetPath] = $this->getMoveInfo($targetPath);
656
+
657
+            if (is_null($sourceStorageId) || $sourceStorageId === false) {
658
+                throw new \Exception('Invalid source storage id: ' . $sourceStorageId);
659
+            }
660
+            if (is_null($targetStorageId) || $targetStorageId === false) {
661
+                throw new \Exception('Invalid target storage id: ' . $targetStorageId);
662
+            }
663
+
664
+            $this->connection->beginTransaction();
665
+            if ($sourceData['mimetype'] === 'httpd/unix-directory') {
666
+                //update all child entries
667
+                $sourceLength = mb_strlen($sourcePath);
668
+                $query = $this->connection->getQueryBuilder();
669
+
670
+                $fun = $query->func();
671
+                $newPathFunction = $fun->concat(
672
+                    $query->createNamedParameter($targetPath),
673
+                    $fun->substring('path', $query->createNamedParameter($sourceLength + 1, IQueryBuilder::PARAM_INT))// +1 for the leading slash
674
+                );
675
+                $query->update('filecache')
676
+                    ->set('storage', $query->createNamedParameter($targetStorageId, IQueryBuilder::PARAM_INT))
677
+                    ->set('path_hash', $fun->md5($newPathFunction))
678
+                    ->set('path', $newPathFunction)
679
+                    ->where($query->expr()->eq('storage', $query->createNamedParameter($sourceStorageId, IQueryBuilder::PARAM_INT)))
680
+                    ->andWhere($query->expr()->like('path', $query->createNamedParameter($this->connection->escapeLikeParameter($sourcePath) . '/%')));
681
+
682
+                try {
683
+                    $query->execute();
684
+                } catch (\OC\DatabaseException $e) {
685
+                    $this->connection->rollBack();
686
+                    throw $e;
687
+                }
688
+            }
689
+
690
+            $query = $this->getQueryBuilder();
691
+            $query->update('filecache')
692
+                ->set('storage', $query->createNamedParameter($targetStorageId))
693
+                ->set('path', $query->createNamedParameter($targetPath))
694
+                ->set('path_hash', $query->createNamedParameter(md5($targetPath)))
695
+                ->set('name', $query->createNamedParameter(basename($targetPath)))
696
+                ->set('parent', $query->createNamedParameter($newParentId, IQueryBuilder::PARAM_INT))
697
+                ->whereFileId($sourceId);
698
+            $query->execute();
699
+
700
+            $this->connection->commit();
701
+
702
+            if ($sourceCache->getNumericStorageId() !== $this->getNumericStorageId()) {
703
+                $this->eventDispatcher->dispatchTyped(new CacheEntryRemovedEvent($this->storage, $sourcePath, $sourceId, $sourceCache->getNumericStorageId()));
704
+                $event = new CacheEntryInsertedEvent($this->storage, $targetPath, $sourceId, $this->getNumericStorageId());
705
+                $this->eventDispatcher->dispatch(CacheInsertEvent::class, $event);
706
+                $this->eventDispatcher->dispatchTyped($event);
707
+            } else {
708
+                $event = new CacheEntryUpdatedEvent($this->storage, $targetPath, $sourceId, $this->getNumericStorageId());
709
+                $this->eventDispatcher->dispatch(CacheUpdateEvent::class, $event);
710
+                $this->eventDispatcher->dispatchTyped($event);
711
+            }
712
+        } else {
713
+            $this->moveFromCacheFallback($sourceCache, $sourcePath, $targetPath);
714
+        }
715
+    }
716
+
717
+    /**
718
+     * remove all entries for files that are stored on the storage from the cache
719
+     */
720
+    public function clear() {
721
+        $query = $this->getQueryBuilder();
722
+        $query->delete('filecache')
723
+            ->whereStorageId($this->getNumericStorageId());
724
+        $query->execute();
725
+
726
+        $query = $this->connection->getQueryBuilder();
727
+        $query->delete('storages')
728
+            ->where($query->expr()->eq('id', $query->createNamedParameter($this->storageId)));
729
+        $query->execute();
730
+    }
731
+
732
+    /**
733
+     * Get the scan status of a file
734
+     *
735
+     * - Cache::NOT_FOUND: File is not in the cache
736
+     * - Cache::PARTIAL: File is not stored in the cache but some incomplete data is known
737
+     * - Cache::SHALLOW: The folder and it's direct children are in the cache but not all sub folders are fully scanned
738
+     * - Cache::COMPLETE: The file or folder, with all it's children) are fully scanned
739
+     *
740
+     * @param string $file
741
+     *
742
+     * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
743
+     */
744
+    public function getStatus($file) {
745
+        // normalize file
746
+        $file = $this->normalize($file);
747
+
748
+        $query = $this->getQueryBuilder();
749
+        $query->select('size')
750
+            ->from('filecache')
751
+            ->whereStorageId($this->getNumericStorageId())
752
+            ->wherePath($file);
753
+
754
+        $result = $query->execute();
755
+        $size = $result->fetchOne();
756
+        $result->closeCursor();
757
+
758
+        if ($size !== false) {
759
+            if ((int)$size === -1) {
760
+                return self::SHALLOW;
761
+            } else {
762
+                return self::COMPLETE;
763
+            }
764
+        } else {
765
+            if (isset($this->partial[$file])) {
766
+                return self::PARTIAL;
767
+            } else {
768
+                return self::NOT_FOUND;
769
+            }
770
+        }
771
+    }
772
+
773
+    /**
774
+     * search for files matching $pattern
775
+     *
776
+     * @param string $pattern the search pattern using SQL search syntax (e.g. '%searchstring%')
777
+     * @return ICacheEntry[] an array of cache entries where the name matches the search pattern
778
+     */
779
+    public function search($pattern) {
780
+        $operator = new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', $pattern);
781
+        return $this->searchQuery(new SearchQuery($operator, 0, 0, [], null));
782
+    }
783
+
784
+    /**
785
+     * search for files by mimetype
786
+     *
787
+     * @param string $mimetype either a full mimetype to search ('text/plain') or only the first part of a mimetype ('image')
788
+     *        where it will search for all mimetypes in the group ('image/*')
789
+     * @return ICacheEntry[] an array of cache entries where the mimetype matches the search
790
+     */
791
+    public function searchByMime($mimetype) {
792
+        if (strpos($mimetype, '/') === false) {
793
+            $operator = new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype . '/%');
794
+        } else {
795
+            $operator = new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $mimetype);
796
+        }
797
+        return $this->searchQuery(new SearchQuery($operator, 0, 0, [], null));
798
+    }
799
+
800
+    public function searchQuery(ISearchQuery $searchQuery) {
801
+        return current($this->querySearchHelper->searchInCaches($searchQuery, [$this]));
802
+    }
803
+
804
+    /**
805
+     * Re-calculate the folder size and the size of all parent folders
806
+     *
807
+     * @param string|boolean $path
808
+     * @param array $data (optional) meta data of the folder
809
+     */
810
+    public function correctFolderSize($path, $data = null, $isBackgroundScan = false) {
811
+        $this->calculateFolderSize($path, $data);
812
+        if ($path !== '') {
813
+            $parent = dirname($path);
814
+            if ($parent === '.' or $parent === '/') {
815
+                $parent = '';
816
+            }
817
+            if ($isBackgroundScan) {
818
+                $parentData = $this->get($parent);
819
+                if ($parentData['size'] !== -1 && $this->getIncompleteChildrenCount($parentData['fileid']) === 0) {
820
+                    $this->correctFolderSize($parent, $parentData, $isBackgroundScan);
821
+                }
822
+            } else {
823
+                $this->correctFolderSize($parent);
824
+            }
825
+        }
826
+    }
827
+
828
+    /**
829
+     * get the incomplete count that shares parent $folder
830
+     *
831
+     * @param int $fileId the file id of the folder
832
+     * @return int
833
+     */
834
+    public function getIncompleteChildrenCount($fileId) {
835
+        if ($fileId > -1) {
836
+            $query = $this->getQueryBuilder();
837
+            $query->select($query->func()->count())
838
+                ->from('filecache')
839
+                ->whereParent($fileId)
840
+                ->andWhere($query->expr()->lt('size', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
841
+
842
+            $result = $query->execute();
843
+            $size = (int)$result->fetchOne();
844
+            $result->closeCursor();
845
+
846
+            return $size;
847
+        }
848
+        return -1;
849
+    }
850
+
851
+    /**
852
+     * calculate the size of a folder and set it in the cache
853
+     *
854
+     * @param string $path
855
+     * @param array $entry (optional) meta data of the folder
856
+     * @return int
857
+     */
858
+    public function calculateFolderSize($path, $entry = null) {
859
+        $totalSize = 0;
860
+        if (is_null($entry) or !isset($entry['fileid'])) {
861
+            $entry = $this->get($path);
862
+        }
863
+        if (isset($entry['mimetype']) && $entry['mimetype'] === FileInfo::MIMETYPE_FOLDER) {
864
+            $id = $entry['fileid'];
865
+
866
+            $query = $this->getQueryBuilder();
867
+            $query->selectAlias($query->func()->sum('size'), 'f1')
868
+                ->selectAlias($query->func()->min('size'), 'f2')
869
+                ->from('filecache')
870
+                ->whereStorageId($this->getNumericStorageId())
871
+                ->whereParent($id);
872
+
873
+            $result = $query->execute();
874
+            $row = $result->fetch();
875
+            $result->closeCursor();
876
+
877
+            if ($row) {
878
+                [$sum, $min] = array_values($row);
879
+                $sum = 0 + $sum;
880
+                $min = 0 + $min;
881
+                if ($min === -1) {
882
+                    $totalSize = $min;
883
+                } else {
884
+                    $totalSize = $sum;
885
+                }
886
+                if ($entry['size'] !== $totalSize) {
887
+                    $this->update($id, ['size' => $totalSize]);
888
+                }
889
+            }
890
+        }
891
+        return $totalSize;
892
+    }
893
+
894
+    /**
895
+     * get all file ids on the files on the storage
896
+     *
897
+     * @return int[]
898
+     */
899
+    public function getAll() {
900
+        $query = $this->getQueryBuilder();
901
+        $query->select('fileid')
902
+            ->from('filecache')
903
+            ->whereStorageId($this->getNumericStorageId());
904
+
905
+        $result = $query->execute();
906
+        $files = $result->fetchAll(\PDO::FETCH_COLUMN);
907
+        $result->closeCursor();
908
+
909
+        return array_map(function ($id) {
910
+            return (int)$id;
911
+        }, $files);
912
+    }
913
+
914
+    /**
915
+     * find a folder in the cache which has not been fully scanned
916
+     *
917
+     * If multiple incomplete folders are in the cache, the one with the highest id will be returned,
918
+     * use the one with the highest id gives the best result with the background scanner, since that is most
919
+     * likely the folder where we stopped scanning previously
920
+     *
921
+     * @return string|bool the path of the folder or false when no folder matched
922
+     */
923
+    public function getIncomplete() {
924
+        $query = $this->getQueryBuilder();
925
+        $query->select('path')
926
+            ->from('filecache')
927
+            ->whereStorageId($this->getNumericStorageId())
928
+            ->andWhere($query->expr()->lt('size', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
929
+            ->orderBy('fileid', 'DESC')
930
+            ->setMaxResults(1);
931
+
932
+        $result = $query->execute();
933
+        $path = $result->fetchOne();
934
+        $result->closeCursor();
935
+
936
+        return $path;
937
+    }
938
+
939
+    /**
940
+     * get the path of a file on this storage by it's file id
941
+     *
942
+     * @param int $id the file id of the file or folder to search
943
+     * @return string|null the path of the file (relative to the storage) or null if a file with the given id does not exists within this cache
944
+     */
945
+    public function getPathById($id) {
946
+        $query = $this->getQueryBuilder();
947
+        $query->select('path')
948
+            ->from('filecache')
949
+            ->whereStorageId($this->getNumericStorageId())
950
+            ->whereFileId($id);
951
+
952
+        $result = $query->execute();
953
+        $path = $result->fetchOne();
954
+        $result->closeCursor();
955
+
956
+        if ($path === false) {
957
+            return null;
958
+        }
959
+
960
+        return (string)$path;
961
+    }
962
+
963
+    /**
964
+     * get the storage id of the storage for a file and the internal path of the file
965
+     * unlike getPathById this does not limit the search to files on this storage and
966
+     * instead does a global search in the cache table
967
+     *
968
+     * @param int $id
969
+     * @return array first element holding the storage id, second the path
970
+     * @deprecated use getPathById() instead
971
+     */
972
+    public static function getById($id) {
973
+        $query = \OC::$server->getDatabaseConnection()->getQueryBuilder();
974
+        $query->select('path', 'storage')
975
+            ->from('filecache')
976
+            ->where($query->expr()->eq('fileid', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
977
+
978
+        $result = $query->execute();
979
+        $row = $result->fetch();
980
+        $result->closeCursor();
981
+
982
+        if ($row) {
983
+            $numericId = $row['storage'];
984
+            $path = $row['path'];
985
+        } else {
986
+            return null;
987
+        }
988
+
989
+        if ($id = Storage::getStorageId($numericId)) {
990
+            return [$id, $path];
991
+        } else {
992
+            return null;
993
+        }
994
+    }
995
+
996
+    /**
997
+     * normalize the given path
998
+     *
999
+     * @param string $path
1000
+     * @return string
1001
+     */
1002
+    public function normalize($path) {
1003
+        return trim(\OC_Util::normalizeUnicode($path), '/');
1004
+    }
1005
+
1006
+    /**
1007
+     * Copy a file or folder in the cache
1008
+     *
1009
+     * @param ICache $sourceCache
1010
+     * @param ICacheEntry $sourceEntry
1011
+     * @param string $targetPath
1012
+     * @return int fileid of copied entry
1013
+     */
1014
+    public function copyFromCache(ICache $sourceCache, ICacheEntry $sourceEntry, string $targetPath): int {
1015
+        if ($sourceEntry->getId() < 0) {
1016
+            throw new \RuntimeException("Invalid source cache entry on copyFromCache");
1017
+        }
1018
+        $data = $this->cacheEntryToArray($sourceEntry);
1019
+        $fileId = $this->put($targetPath, $data);
1020
+        if ($fileId <= 0) {
1021
+            throw new \RuntimeException("Failed to copy to " . $targetPath . " from cache with source data " . json_encode($data) . " ");
1022
+        }
1023
+        if ($sourceEntry->getMimeType() === ICacheEntry::DIRECTORY_MIMETYPE) {
1024
+            $folderContent = $sourceCache->getFolderContentsById($sourceEntry->getId());
1025
+            foreach ($folderContent as $subEntry) {
1026
+                $subTargetPath = $targetPath . '/' . $subEntry->getName();
1027
+                $this->copyFromCache($sourceCache, $subEntry, $subTargetPath);
1028
+            }
1029
+        }
1030
+        return $fileId;
1031
+    }
1032
+
1033
+    private function cacheEntryToArray(ICacheEntry $entry): array {
1034
+        return [
1035
+            'size' => $entry->getSize(),
1036
+            'mtime' => $entry->getMTime(),
1037
+            'storage_mtime' => $entry->getStorageMTime(),
1038
+            'mimetype' => $entry->getMimeType(),
1039
+            'mimepart' => $entry->getMimePart(),
1040
+            'etag' => $entry->getEtag(),
1041
+            'permissions' => $entry->getPermissions(),
1042
+            'encrypted' => $entry->isEncrypted(),
1043
+            'creation_time' => $entry->getCreationTime(),
1044
+            'upload_time' => $entry->getUploadTime(),
1045
+            'metadata_etag' => $entry->getMetadataEtag(),
1046
+        ];
1047
+    }
1048
+
1049
+    public function getQueryFilterForStorage(): ISearchOperator {
1050
+        return new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', $this->getNumericStorageId());
1051
+    }
1052
+
1053
+    public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {
1054
+        if ($rawEntry->getStorageId() === $this->getNumericStorageId()) {
1055
+            return $rawEntry;
1056
+        } else {
1057
+            return null;
1058
+        }
1059
+    }
1060 1060
 }
Please login to merge, or discard this patch.
Spacing   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -184,26 +184,26 @@  discard block
 block discarded – undo
184 184
 	 */
185 185
 	public static function cacheEntryFromData($data, IMimeTypeLoader $mimetypeLoader) {
186 186
 		//fix types
187
-		$data['fileid'] = (int)$data['fileid'];
188
-		$data['parent'] = (int)$data['parent'];
187
+		$data['fileid'] = (int) $data['fileid'];
188
+		$data['parent'] = (int) $data['parent'];
189 189
 		$data['size'] = 0 + $data['size'];
190
-		$data['mtime'] = (int)$data['mtime'];
191
-		$data['storage_mtime'] = (int)$data['storage_mtime'];
192
-		$data['encryptedVersion'] = (int)$data['encrypted'];
193
-		$data['encrypted'] = (bool)$data['encrypted'];
190
+		$data['mtime'] = (int) $data['mtime'];
191
+		$data['storage_mtime'] = (int) $data['storage_mtime'];
192
+		$data['encryptedVersion'] = (int) $data['encrypted'];
193
+		$data['encrypted'] = (bool) $data['encrypted'];
194 194
 		$data['storage_id'] = $data['storage'];
195
-		$data['storage'] = (int)$data['storage'];
195
+		$data['storage'] = (int) $data['storage'];
196 196
 		$data['mimetype'] = $mimetypeLoader->getMimetypeById($data['mimetype']);
197 197
 		$data['mimepart'] = $mimetypeLoader->getMimetypeById($data['mimepart']);
198 198
 		if ($data['storage_mtime'] == 0) {
199 199
 			$data['storage_mtime'] = $data['mtime'];
200 200
 		}
201
-		$data['permissions'] = (int)$data['permissions'];
201
+		$data['permissions'] = (int) $data['permissions'];
202 202
 		if (isset($data['creation_time'])) {
203
-			$data['creation_time'] = (int)$data['creation_time'];
203
+			$data['creation_time'] = (int) $data['creation_time'];
204 204
 		}
205 205
 		if (isset($data['upload_time'])) {
206
-			$data['upload_time'] = (int)$data['upload_time'];
206
+			$data['upload_time'] = (int) $data['upload_time'];
207 207
 		}
208 208
 		return new CacheEntry($data);
209 209
 	}
@@ -236,7 +236,7 @@  discard block
 block discarded – undo
236 236
 			$files = $result->fetchAll();
237 237
 			$result->closeCursor();
238 238
 
239
-			return array_map(function (array $data) {
239
+			return array_map(function(array $data) {
240 240
 				return self::cacheEntryFromData($data, $this->mimetypeLoader);
241 241
 			}, $files);
242 242
 		}
@@ -365,7 +365,7 @@  discard block
 block discarded – undo
365 365
 
366 366
 			$query->update('filecache')
367 367
 				->whereFileId($id)
368
-				->andWhere($query->expr()->orX(...array_map(function ($key, $value) use ($query) {
368
+				->andWhere($query->expr()->orX(...array_map(function($key, $value) use ($query) {
369 369
 					return $query->expr()->orX(
370 370
 						$query->expr()->neq($key, $query->createNamedParameter($value)),
371 371
 						$query->expr()->isNull($key)
@@ -394,7 +394,7 @@  discard block
 block discarded – undo
394 394
 				$query = $this->getQueryBuilder();
395 395
 				$query->update('filecache_extended')
396 396
 					->whereFileId($id)
397
-					->andWhere($query->expr()->orX(...array_map(function ($key, $value) use ($query) {
397
+					->andWhere($query->expr()->orX(...array_map(function($key, $value) use ($query) {
398 398
 						return $query->expr()->orX(
399 399
 							$query->expr()->neq($key, $query->createNamedParameter($value)),
400 400
 							$query->expr()->isNull($key)
@@ -491,7 +491,7 @@  discard block
 block discarded – undo
491 491
 		$id = $result->fetchOne();
492 492
 		$result->closeCursor();
493 493
 
494
-		return $id === false ? -1 : (int)$id;
494
+		return $id === false ? -1 : (int) $id;
495 495
 	}
496 496
 
497 497
 	/**
@@ -505,7 +505,7 @@  discard block
 block discarded – undo
505 505
 			return -1;
506 506
 		} else {
507 507
 			$parent = $this->getParentPath($file);
508
-			return (int)$this->getId($parent);
508
+			return (int) $this->getId($parent);
509 509
 		}
510 510
 	}
511 511
 
@@ -564,7 +564,7 @@  discard block
 block discarded – undo
564 564
 	 */
565 565
 	private function getSubFolders(ICacheEntry $entry) {
566 566
 		$children = $this->getFolderContentsById($entry->getId());
567
-		return array_filter($children, function ($child) {
567
+		return array_filter($children, function($child) {
568 568
 			return $child->getMimeType() == FileInfo::MIMETYPE_FOLDER;
569 569
 		});
570 570
 	}
@@ -583,7 +583,7 @@  discard block
 block discarded – undo
583 583
 		// and collecting all folder ids to later use to delete the filecache entries
584 584
 		while ($entryId = array_pop($queue)) {
585 585
 			$children = $this->getFolderContentsById($entryId);
586
-			$childIds = array_map(function (ICacheEntry $cacheEntry) {
586
+			$childIds = array_map(function(ICacheEntry $cacheEntry) {
587 587
 				return $cacheEntry->getId();
588 588
 			}, $children);
589 589
 
@@ -593,7 +593,7 @@  discard block
 block discarded – undo
593 593
 			$query->execute();
594 594
 
595 595
 			/** @var ICacheEntry[] $childFolders */
596
-			$childFolders = array_filter($children, function ($child) {
596
+			$childFolders = array_filter($children, function($child) {
597 597
 				return $child->getMimeType() == FileInfo::MIMETYPE_FOLDER;
598 598
 			});
599 599
 			foreach ($childFolders as $folder) {
@@ -645,7 +645,7 @@  discard block
 block discarded – undo
645 645
 
646 646
 			$sourceData = $sourceCache->get($sourcePath);
647 647
 			if ($sourceData === false) {
648
-				throw new \Exception('Invalid source storage path: ' . $sourcePath);
648
+				throw new \Exception('Invalid source storage path: '.$sourcePath);
649 649
 			}
650 650
 
651 651
 			$sourceId = $sourceData['fileid'];
@@ -655,10 +655,10 @@  discard block
 block discarded – undo
655 655
 			[$targetStorageId, $targetPath] = $this->getMoveInfo($targetPath);
656 656
 
657 657
 			if (is_null($sourceStorageId) || $sourceStorageId === false) {
658
-				throw new \Exception('Invalid source storage id: ' . $sourceStorageId);
658
+				throw new \Exception('Invalid source storage id: '.$sourceStorageId);
659 659
 			}
660 660
 			if (is_null($targetStorageId) || $targetStorageId === false) {
661
-				throw new \Exception('Invalid target storage id: ' . $targetStorageId);
661
+				throw new \Exception('Invalid target storage id: '.$targetStorageId);
662 662
 			}
663 663
 
664 664
 			$this->connection->beginTransaction();
@@ -677,7 +677,7 @@  discard block
 block discarded – undo
677 677
 					->set('path_hash', $fun->md5($newPathFunction))
678 678
 					->set('path', $newPathFunction)
679 679
 					->where($query->expr()->eq('storage', $query->createNamedParameter($sourceStorageId, IQueryBuilder::PARAM_INT)))
680
-					->andWhere($query->expr()->like('path', $query->createNamedParameter($this->connection->escapeLikeParameter($sourcePath) . '/%')));
680
+					->andWhere($query->expr()->like('path', $query->createNamedParameter($this->connection->escapeLikeParameter($sourcePath).'/%')));
681 681
 
682 682
 				try {
683 683
 					$query->execute();
@@ -756,7 +756,7 @@  discard block
 block discarded – undo
756 756
 		$result->closeCursor();
757 757
 
758 758
 		if ($size !== false) {
759
-			if ((int)$size === -1) {
759
+			if ((int) $size === -1) {
760 760
 				return self::SHALLOW;
761 761
 			} else {
762 762
 				return self::COMPLETE;
@@ -790,7 +790,7 @@  discard block
 block discarded – undo
790 790
 	 */
791 791
 	public function searchByMime($mimetype) {
792 792
 		if (strpos($mimetype, '/') === false) {
793
-			$operator = new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype . '/%');
793
+			$operator = new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype.'/%');
794 794
 		} else {
795 795
 			$operator = new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $mimetype);
796 796
 		}
@@ -840,7 +840,7 @@  discard block
 block discarded – undo
840 840
 				->andWhere($query->expr()->lt('size', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
841 841
 
842 842
 			$result = $query->execute();
843
-			$size = (int)$result->fetchOne();
843
+			$size = (int) $result->fetchOne();
844 844
 			$result->closeCursor();
845 845
 
846 846
 			return $size;
@@ -906,8 +906,8 @@  discard block
 block discarded – undo
906 906
 		$files = $result->fetchAll(\PDO::FETCH_COLUMN);
907 907
 		$result->closeCursor();
908 908
 
909
-		return array_map(function ($id) {
910
-			return (int)$id;
909
+		return array_map(function($id) {
910
+			return (int) $id;
911 911
 		}, $files);
912 912
 	}
913 913
 
@@ -957,7 +957,7 @@  discard block
 block discarded – undo
957 957
 			return null;
958 958
 		}
959 959
 
960
-		return (string)$path;
960
+		return (string) $path;
961 961
 	}
962 962
 
963 963
 	/**
@@ -1018,12 +1018,12 @@  discard block
 block discarded – undo
1018 1018
 		$data = $this->cacheEntryToArray($sourceEntry);
1019 1019
 		$fileId = $this->put($targetPath, $data);
1020 1020
 		if ($fileId <= 0) {
1021
-			throw new \RuntimeException("Failed to copy to " . $targetPath . " from cache with source data " . json_encode($data) . " ");
1021
+			throw new \RuntimeException("Failed to copy to ".$targetPath." from cache with source data ".json_encode($data)." ");
1022 1022
 		}
1023 1023
 		if ($sourceEntry->getMimeType() === ICacheEntry::DIRECTORY_MIMETYPE) {
1024 1024
 			$folderContent = $sourceCache->getFolderContentsById($sourceEntry->getId());
1025 1025
 			foreach ($folderContent as $subEntry) {
1026
-				$subTargetPath = $targetPath . '/' . $subEntry->getName();
1026
+				$subTargetPath = $targetPath.'/'.$subEntry->getName();
1027 1027
 				$this->copyFromCache($sourceCache, $subEntry, $subTargetPath);
1028 1028
 			}
1029 1029
 		}
Please login to merge, or discard this patch.
lib/private/Files/Cache/QuerySearchHelper.php 2 patches
Indentation   +119 added lines, -119 removed lines patch added patch discarded remove patch
@@ -37,123 +37,123 @@
 block discarded – undo
37 37
 
38 38
 class QuerySearchHelper {
39 39
 
40
-	/** @var IMimeTypeLoader */
41
-	private $mimetypeLoader;
42
-	/** @var IDBConnection */
43
-	private $connection;
44
-	/** @var SystemConfig */
45
-	private $systemConfig;
46
-	/** @var ILogger */
47
-	private $logger;
48
-	/** @var SearchBuilder */
49
-	private $searchBuilder;
50
-
51
-	public function __construct(
52
-		IMimeTypeLoader $mimetypeLoader,
53
-		IDBConnection $connection,
54
-		SystemConfig $systemConfig,
55
-		ILogger $logger,
56
-		SearchBuilder $searchBuilder
57
-	) {
58
-		$this->mimetypeLoader = $mimetypeLoader;
59
-		$this->connection = $connection;
60
-		$this->systemConfig = $systemConfig;
61
-		$this->logger = $logger;
62
-		$this->searchBuilder = $searchBuilder;
63
-	}
64
-
65
-	protected function getQueryBuilder() {
66
-		return new CacheQueryBuilder(
67
-			$this->connection,
68
-			$this->systemConfig,
69
-			$this->logger
70
-		);
71
-	}
72
-
73
-	/**
74
-	 * Perform a file system search in multiple caches
75
-	 *
76
-	 * the results will be grouped by the same array keys as the $caches argument to allow
77
-	 * post-processing based on which cache the result came from
78
-	 *
79
-	 * @template T of array-key
80
-	 * @param ISearchQuery $searchQuery
81
-	 * @param array<T, ICache> $caches
82
-	 * @return array<T, ICacheEntry[]>
83
-	 */
84
-	public function searchInCaches(ISearchQuery $searchQuery, array $caches): array {
85
-		// search in multiple caches at once by creating one query in the following format
86
-		// SELECT ... FROM oc_filecache WHERE
87
-		//     <filter expressions from the search query>
88
-		// AND (
89
-		//     <filter expression for storage1> OR
90
-		//     <filter expression for storage2> OR
91
-		//     ...
92
-		// );
93
-		//
94
-		// This gives us all the files matching the search query from all caches
95
-		//
96
-		// while the resulting rows don't have a way to tell what storage they came from (multiple storages/caches can share storage_id)
97
-		// we can just ask every cache if the row belongs to them and give them the cache to do any post processing on the result.
98
-
99
-		$builder = $this->getQueryBuilder();
100
-
101
-		$query = $builder->selectFileCache('file');
102
-
103
-		if ($this->searchBuilder->shouldJoinTags($searchQuery->getSearchOperation())) {
104
-			$user = $searchQuery->getUser();
105
-			if ($user === null) {
106
-				throw new \InvalidArgumentException("Searching by tag requires the user to be set in the query");
107
-			}
108
-			$query
109
-				->innerJoin('file', 'vcategory_to_object', 'tagmap', $builder->expr()->eq('file.fileid', 'tagmap.objid'))
110
-				->innerJoin('tagmap', 'vcategory', 'tag', $builder->expr()->andX(
111
-					$builder->expr()->eq('tagmap.type', 'tag.type'),
112
-					$builder->expr()->eq('tagmap.categoryid', 'tag.id')
113
-				))
114
-				->andWhere($builder->expr()->eq('tag.type', $builder->createNamedParameter('files')))
115
-				->andWhere($builder->expr()->eq('tag.uid', $builder->createNamedParameter($user->getUID())));
116
-		}
117
-
118
-		$searchExpr = $this->searchBuilder->searchOperatorToDBExpr($builder, $searchQuery->getSearchOperation());
119
-		if ($searchExpr) {
120
-			$query->andWhere($searchExpr);
121
-		}
122
-
123
-		$storageFilters = array_values(array_map(function (ICache $cache) {
124
-			return $cache->getQueryFilterForStorage();
125
-		}, $caches));
126
-		$query->andWhere($this->searchBuilder->searchOperatorToDBExpr($builder, new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $storageFilters)));
127
-
128
-		$this->searchBuilder->addSearchOrdersToQuery($query, $searchQuery->getOrder());
129
-
130
-		if ($searchQuery->getLimit()) {
131
-			$query->setMaxResults($searchQuery->getLimit());
132
-		}
133
-		if ($searchQuery->getOffset()) {
134
-			$query->setFirstResult($searchQuery->getOffset());
135
-		}
136
-
137
-		$result = $query->execute();
138
-		$files = $result->fetchAll();
139
-
140
-		$rawEntries = array_map(function (array $data) {
141
-			return Cache::cacheEntryFromData($data, $this->mimetypeLoader);
142
-		}, $files);
143
-
144
-		$result->closeCursor();
145
-
146
-		// loop trough all caches for each result to see if the result matches that storage
147
-		// results are grouped by the same array keys as the caches argument to allow the caller to distringuish the source of the results
148
-		$results = array_fill_keys(array_keys($caches), []);
149
-		foreach ($rawEntries as $rawEntry) {
150
-			foreach ($caches as $cacheKey => $cache) {
151
-				$entry = $cache->getCacheEntryFromSearchResult($rawEntry);
152
-				if ($entry) {
153
-					$results[$cacheKey][] = $entry;
154
-				}
155
-			}
156
-		}
157
-		return $results;
158
-	}
40
+    /** @var IMimeTypeLoader */
41
+    private $mimetypeLoader;
42
+    /** @var IDBConnection */
43
+    private $connection;
44
+    /** @var SystemConfig */
45
+    private $systemConfig;
46
+    /** @var ILogger */
47
+    private $logger;
48
+    /** @var SearchBuilder */
49
+    private $searchBuilder;
50
+
51
+    public function __construct(
52
+        IMimeTypeLoader $mimetypeLoader,
53
+        IDBConnection $connection,
54
+        SystemConfig $systemConfig,
55
+        ILogger $logger,
56
+        SearchBuilder $searchBuilder
57
+    ) {
58
+        $this->mimetypeLoader = $mimetypeLoader;
59
+        $this->connection = $connection;
60
+        $this->systemConfig = $systemConfig;
61
+        $this->logger = $logger;
62
+        $this->searchBuilder = $searchBuilder;
63
+    }
64
+
65
+    protected function getQueryBuilder() {
66
+        return new CacheQueryBuilder(
67
+            $this->connection,
68
+            $this->systemConfig,
69
+            $this->logger
70
+        );
71
+    }
72
+
73
+    /**
74
+     * Perform a file system search in multiple caches
75
+     *
76
+     * the results will be grouped by the same array keys as the $caches argument to allow
77
+     * post-processing based on which cache the result came from
78
+     *
79
+     * @template T of array-key
80
+     * @param ISearchQuery $searchQuery
81
+     * @param array<T, ICache> $caches
82
+     * @return array<T, ICacheEntry[]>
83
+     */
84
+    public function searchInCaches(ISearchQuery $searchQuery, array $caches): array {
85
+        // search in multiple caches at once by creating one query in the following format
86
+        // SELECT ... FROM oc_filecache WHERE
87
+        //     <filter expressions from the search query>
88
+        // AND (
89
+        //     <filter expression for storage1> OR
90
+        //     <filter expression for storage2> OR
91
+        //     ...
92
+        // );
93
+        //
94
+        // This gives us all the files matching the search query from all caches
95
+        //
96
+        // while the resulting rows don't have a way to tell what storage they came from (multiple storages/caches can share storage_id)
97
+        // we can just ask every cache if the row belongs to them and give them the cache to do any post processing on the result.
98
+
99
+        $builder = $this->getQueryBuilder();
100
+
101
+        $query = $builder->selectFileCache('file');
102
+
103
+        if ($this->searchBuilder->shouldJoinTags($searchQuery->getSearchOperation())) {
104
+            $user = $searchQuery->getUser();
105
+            if ($user === null) {
106
+                throw new \InvalidArgumentException("Searching by tag requires the user to be set in the query");
107
+            }
108
+            $query
109
+                ->innerJoin('file', 'vcategory_to_object', 'tagmap', $builder->expr()->eq('file.fileid', 'tagmap.objid'))
110
+                ->innerJoin('tagmap', 'vcategory', 'tag', $builder->expr()->andX(
111
+                    $builder->expr()->eq('tagmap.type', 'tag.type'),
112
+                    $builder->expr()->eq('tagmap.categoryid', 'tag.id')
113
+                ))
114
+                ->andWhere($builder->expr()->eq('tag.type', $builder->createNamedParameter('files')))
115
+                ->andWhere($builder->expr()->eq('tag.uid', $builder->createNamedParameter($user->getUID())));
116
+        }
117
+
118
+        $searchExpr = $this->searchBuilder->searchOperatorToDBExpr($builder, $searchQuery->getSearchOperation());
119
+        if ($searchExpr) {
120
+            $query->andWhere($searchExpr);
121
+        }
122
+
123
+        $storageFilters = array_values(array_map(function (ICache $cache) {
124
+            return $cache->getQueryFilterForStorage();
125
+        }, $caches));
126
+        $query->andWhere($this->searchBuilder->searchOperatorToDBExpr($builder, new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $storageFilters)));
127
+
128
+        $this->searchBuilder->addSearchOrdersToQuery($query, $searchQuery->getOrder());
129
+
130
+        if ($searchQuery->getLimit()) {
131
+            $query->setMaxResults($searchQuery->getLimit());
132
+        }
133
+        if ($searchQuery->getOffset()) {
134
+            $query->setFirstResult($searchQuery->getOffset());
135
+        }
136
+
137
+        $result = $query->execute();
138
+        $files = $result->fetchAll();
139
+
140
+        $rawEntries = array_map(function (array $data) {
141
+            return Cache::cacheEntryFromData($data, $this->mimetypeLoader);
142
+        }, $files);
143
+
144
+        $result->closeCursor();
145
+
146
+        // loop trough all caches for each result to see if the result matches that storage
147
+        // results are grouped by the same array keys as the caches argument to allow the caller to distringuish the source of the results
148
+        $results = array_fill_keys(array_keys($caches), []);
149
+        foreach ($rawEntries as $rawEntry) {
150
+            foreach ($caches as $cacheKey => $cache) {
151
+                $entry = $cache->getCacheEntryFromSearchResult($rawEntry);
152
+                if ($entry) {
153
+                    $results[$cacheKey][] = $entry;
154
+                }
155
+            }
156
+        }
157
+        return $results;
158
+    }
159 159
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -120,7 +120,7 @@  discard block
 block discarded – undo
120 120
 			$query->andWhere($searchExpr);
121 121
 		}
122 122
 
123
-		$storageFilters = array_values(array_map(function (ICache $cache) {
123
+		$storageFilters = array_values(array_map(function(ICache $cache) {
124 124
 			return $cache->getQueryFilterForStorage();
125 125
 		}, $caches));
126 126
 		$query->andWhere($this->searchBuilder->searchOperatorToDBExpr($builder, new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $storageFilters)));
@@ -137,7 +137,7 @@  discard block
 block discarded – undo
137 137
 		$result = $query->execute();
138 138
 		$files = $result->fetchAll();
139 139
 
140
-		$rawEntries = array_map(function (array $data) {
140
+		$rawEntries = array_map(function(array $data) {
141 141
 			return Cache::cacheEntryFromData($data, $this->mimetypeLoader);
142 142
 		}, $files);
143 143
 
Please login to merge, or discard this patch.
lib/private/Files/Cache/FailedCache.php 1 patch
Indentation   +116 added lines, -116 removed lines patch added patch discarded remove patch
@@ -33,120 +33,120 @@
 block discarded – undo
33 33
  * Storage placeholder to represent a missing precondition, storage unavailable
34 34
  */
35 35
 class FailedCache implements ICache {
36
-	/** @var bool whether to show the failed storage in the ui */
37
-	private $visible;
38
-
39
-	/**
40
-	 * FailedCache constructor.
41
-	 *
42
-	 * @param bool $visible
43
-	 */
44
-	public function __construct($visible = true) {
45
-		$this->visible = $visible;
46
-	}
47
-
48
-
49
-	public function getNumericStorageId() {
50
-		return -1;
51
-	}
52
-
53
-	public function get($file) {
54
-		if ($file === '') {
55
-			return new CacheEntry([
56
-				'fileid' => -1,
57
-				'size' => 0,
58
-				'mimetype' => 'httpd/unix-directory',
59
-				'mimepart' => 'httpd',
60
-				'permissions' => $this->visible ? Constants::PERMISSION_READ : 0,
61
-				'mtime' => time()
62
-			]);
63
-		} else {
64
-			return false;
65
-		}
66
-	}
67
-
68
-	public function getFolderContents($folder) {
69
-		return [];
70
-	}
71
-
72
-	public function getFolderContentsById($fileId) {
73
-		return [];
74
-	}
75
-
76
-	public function put($file, array $data) {
77
-	}
78
-
79
-	public function insert($file, array $data) {
80
-	}
81
-
82
-	public function update($id, array $data) {
83
-	}
84
-
85
-	public function getId($file) {
86
-		return -1;
87
-	}
88
-
89
-	public function getParentId($file) {
90
-		return -1;
91
-	}
92
-
93
-	public function inCache($file) {
94
-		return false;
95
-	}
96
-
97
-	public function remove($file) {
98
-	}
99
-
100
-	public function move($source, $target) {
101
-	}
102
-
103
-	public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
104
-	}
105
-
106
-	public function clear() {
107
-	}
108
-
109
-	public function getStatus($file) {
110
-		return ICache::NOT_FOUND;
111
-	}
112
-
113
-	public function search($pattern) {
114
-		return [];
115
-	}
116
-
117
-	public function searchByMime($mimetype) {
118
-		return [];
119
-	}
120
-
121
-	public function searchQuery(ISearchQuery $query) {
122
-		return [];
123
-	}
124
-
125
-	public function getAll() {
126
-		return [];
127
-	}
128
-
129
-	public function getIncomplete() {
130
-		return [];
131
-	}
132
-
133
-	public function getPathById($id) {
134
-		return null;
135
-	}
136
-
137
-	public function normalize($path) {
138
-		return $path;
139
-	}
140
-
141
-	public function copyFromCache(ICache $sourceCache, ICacheEntry $sourceEntry, string $targetPath): int {
142
-		throw new \Exception("Invalid cache");
143
-	}
144
-
145
-	public function getQueryFilterForStorage(): ISearchOperator {
146
-		return new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', -1);
147
-	}
148
-
149
-	public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {
150
-		return null;
151
-	}
36
+    /** @var bool whether to show the failed storage in the ui */
37
+    private $visible;
38
+
39
+    /**
40
+     * FailedCache constructor.
41
+     *
42
+     * @param bool $visible
43
+     */
44
+    public function __construct($visible = true) {
45
+        $this->visible = $visible;
46
+    }
47
+
48
+
49
+    public function getNumericStorageId() {
50
+        return -1;
51
+    }
52
+
53
+    public function get($file) {
54
+        if ($file === '') {
55
+            return new CacheEntry([
56
+                'fileid' => -1,
57
+                'size' => 0,
58
+                'mimetype' => 'httpd/unix-directory',
59
+                'mimepart' => 'httpd',
60
+                'permissions' => $this->visible ? Constants::PERMISSION_READ : 0,
61
+                'mtime' => time()
62
+            ]);
63
+        } else {
64
+            return false;
65
+        }
66
+    }
67
+
68
+    public function getFolderContents($folder) {
69
+        return [];
70
+    }
71
+
72
+    public function getFolderContentsById($fileId) {
73
+        return [];
74
+    }
75
+
76
+    public function put($file, array $data) {
77
+    }
78
+
79
+    public function insert($file, array $data) {
80
+    }
81
+
82
+    public function update($id, array $data) {
83
+    }
84
+
85
+    public function getId($file) {
86
+        return -1;
87
+    }
88
+
89
+    public function getParentId($file) {
90
+        return -1;
91
+    }
92
+
93
+    public function inCache($file) {
94
+        return false;
95
+    }
96
+
97
+    public function remove($file) {
98
+    }
99
+
100
+    public function move($source, $target) {
101
+    }
102
+
103
+    public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
104
+    }
105
+
106
+    public function clear() {
107
+    }
108
+
109
+    public function getStatus($file) {
110
+        return ICache::NOT_FOUND;
111
+    }
112
+
113
+    public function search($pattern) {
114
+        return [];
115
+    }
116
+
117
+    public function searchByMime($mimetype) {
118
+        return [];
119
+    }
120
+
121
+    public function searchQuery(ISearchQuery $query) {
122
+        return [];
123
+    }
124
+
125
+    public function getAll() {
126
+        return [];
127
+    }
128
+
129
+    public function getIncomplete() {
130
+        return [];
131
+    }
132
+
133
+    public function getPathById($id) {
134
+        return null;
135
+    }
136
+
137
+    public function normalize($path) {
138
+        return $path;
139
+    }
140
+
141
+    public function copyFromCache(ICache $sourceCache, ICacheEntry $sourceEntry, string $targetPath): int {
142
+        throw new \Exception("Invalid cache");
143
+    }
144
+
145
+    public function getQueryFilterForStorage(): ISearchOperator {
146
+        return new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', -1);
147
+    }
148
+
149
+    public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {
150
+        return null;
151
+    }
152 152
 }
Please login to merge, or discard this patch.
lib/private/Files/Cache/CacheQueryBuilder.php 1 patch
Indentation   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -35,72 +35,72 @@
 block discarded – undo
35 35
  * Query builder with commonly used helpers for filecache queries
36 36
  */
37 37
 class CacheQueryBuilder extends QueryBuilder {
38
-	private $alias = null;
38
+    private $alias = null;
39 39
 
40
-	public function __construct(IDBConnection $connection, SystemConfig $systemConfig, ILogger $logger) {
41
-		parent::__construct($connection, $systemConfig, $logger);
42
-	}
40
+    public function __construct(IDBConnection $connection, SystemConfig $systemConfig, ILogger $logger) {
41
+        parent::__construct($connection, $systemConfig, $logger);
42
+    }
43 43
 
44
-	public function selectFileCache(string $alias = null) {
45
-		$name = $alias ? $alias : 'filecache';
46
-		$this->select("$name.fileid", 'storage', 'path', 'path_hash', "$name.parent", 'name', 'mimetype', 'mimepart', 'size', 'mtime',
47
-			'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum', 'metadata_etag', 'creation_time', 'upload_time')
48
-			->from('filecache', $name)
49
-			->leftJoin($name, 'filecache_extended', 'fe', $this->expr()->eq("$name.fileid", 'fe.fileid'));
44
+    public function selectFileCache(string $alias = null) {
45
+        $name = $alias ? $alias : 'filecache';
46
+        $this->select("$name.fileid", 'storage', 'path', 'path_hash', "$name.parent", 'name', 'mimetype', 'mimepart', 'size', 'mtime',
47
+            'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum', 'metadata_etag', 'creation_time', 'upload_time')
48
+            ->from('filecache', $name)
49
+            ->leftJoin($name, 'filecache_extended', 'fe', $this->expr()->eq("$name.fileid", 'fe.fileid'));
50 50
 
51
-		$this->alias = $name;
51
+        $this->alias = $name;
52 52
 
53
-		return $this;
54
-	}
53
+        return $this;
54
+    }
55 55
 
56
-	public function whereStorageId(int $storageId) {
57
-		$this->andWhere($this->expr()->eq('storage', $this->createNamedParameter($storageId, IQueryBuilder::PARAM_INT)));
56
+    public function whereStorageId(int $storageId) {
57
+        $this->andWhere($this->expr()->eq('storage', $this->createNamedParameter($storageId, IQueryBuilder::PARAM_INT)));
58 58
 
59
-		return $this;
60
-	}
59
+        return $this;
60
+    }
61 61
 
62
-	public function whereFileId(int $fileId) {
63
-		$alias = $this->alias;
64
-		if ($alias) {
65
-			$alias .= '.';
66
-		} else {
67
-			$alias = '';
68
-		}
62
+    public function whereFileId(int $fileId) {
63
+        $alias = $this->alias;
64
+        if ($alias) {
65
+            $alias .= '.';
66
+        } else {
67
+            $alias = '';
68
+        }
69 69
 
70
-		$this->andWhere($this->expr()->eq("{$alias}fileid", $this->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
70
+        $this->andWhere($this->expr()->eq("{$alias}fileid", $this->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
71 71
 
72
-		return $this;
73
-	}
72
+        return $this;
73
+    }
74 74
 
75
-	public function wherePath(string $path) {
76
-		$this->andWhere($this->expr()->eq('path_hash', $this->createNamedParameter(md5($path))));
75
+    public function wherePath(string $path) {
76
+        $this->andWhere($this->expr()->eq('path_hash', $this->createNamedParameter(md5($path))));
77 77
 
78
-		return $this;
79
-	}
78
+        return $this;
79
+    }
80 80
 
81
-	public function whereParent(int $parent) {
82
-		$alias = $this->alias;
83
-		if ($alias) {
84
-			$alias .= '.';
85
-		} else {
86
-			$alias = '';
87
-		}
81
+    public function whereParent(int $parent) {
82
+        $alias = $this->alias;
83
+        if ($alias) {
84
+            $alias .= '.';
85
+        } else {
86
+            $alias = '';
87
+        }
88 88
 
89
-		$this->andWhere($this->expr()->eq("{$alias}parent", $this->createNamedParameter($parent, IQueryBuilder::PARAM_INT)));
89
+        $this->andWhere($this->expr()->eq("{$alias}parent", $this->createNamedParameter($parent, IQueryBuilder::PARAM_INT)));
90 90
 
91
-		return $this;
92
-	}
91
+        return $this;
92
+    }
93 93
 
94
-	public function whereParentIn(array $parents) {
95
-		$alias = $this->alias;
96
-		if ($alias) {
97
-			$alias .= '.';
98
-		} else {
99
-			$alias = '';
100
-		}
94
+    public function whereParentIn(array $parents) {
95
+        $alias = $this->alias;
96
+        if ($alias) {
97
+            $alias .= '.';
98
+        } else {
99
+            $alias = '';
100
+        }
101 101
 
102
-		$this->andWhere($this->expr()->in("{$alias}parent", $this->createNamedParameter($parents, IQueryBuilder::PARAM_INT_ARRAY)));
102
+        $this->andWhere($this->expr()->in("{$alias}parent", $this->createNamedParameter($parents, IQueryBuilder::PARAM_INT_ARRAY)));
103 103
 
104
-		return $this;
105
-	}
104
+        return $this;
105
+    }
106 106
 }
Please login to merge, or discard this patch.
lib/private/Files/Cache/Wrapper/CacheWrapper.php 1 patch
Indentation   +250 added lines, -250 removed lines patch added patch discarded remove patch
@@ -37,283 +37,283 @@
 block discarded – undo
37 37
 use OCP\Files\Search\ISearchQuery;
38 38
 
39 39
 class CacheWrapper extends Cache {
40
-	/**
41
-	 * @var \OCP\Files\Cache\ICache
42
-	 */
43
-	protected $cache;
40
+    /**
41
+     * @var \OCP\Files\Cache\ICache
42
+     */
43
+    protected $cache;
44 44
 
45
-	/**
46
-	 * @param \OCP\Files\Cache\ICache $cache
47
-	 */
48
-	public function __construct($cache) {
49
-		$this->cache = $cache;
50
-		$this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
51
-		$this->connection = \OC::$server->getDatabaseConnection();
52
-		$this->querySearchHelper = \OC::$server->get(QuerySearchHelper::class);
53
-	}
45
+    /**
46
+     * @param \OCP\Files\Cache\ICache $cache
47
+     */
48
+    public function __construct($cache) {
49
+        $this->cache = $cache;
50
+        $this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
51
+        $this->connection = \OC::$server->getDatabaseConnection();
52
+        $this->querySearchHelper = \OC::$server->get(QuerySearchHelper::class);
53
+    }
54 54
 
55
-	protected function getCache() {
56
-		return $this->cache;
57
-	}
55
+    protected function getCache() {
56
+        return $this->cache;
57
+    }
58 58
 
59
-	/**
60
-	 * Make it easy for wrappers to modify every returned cache entry
61
-	 *
62
-	 * @param ICacheEntry $entry
63
-	 * @return ICacheEntry
64
-	 */
65
-	protected function formatCacheEntry($entry) {
66
-		return $entry;
67
-	}
59
+    /**
60
+     * Make it easy for wrappers to modify every returned cache entry
61
+     *
62
+     * @param ICacheEntry $entry
63
+     * @return ICacheEntry
64
+     */
65
+    protected function formatCacheEntry($entry) {
66
+        return $entry;
67
+    }
68 68
 
69
-	/**
70
-	 * get the stored metadata of a file or folder
71
-	 *
72
-	 * @param string|int $file
73
-	 * @return ICacheEntry|false
74
-	 */
75
-	public function get($file) {
76
-		$result = $this->getCache()->get($file);
77
-		if ($result) {
78
-			$result = $this->formatCacheEntry($result);
79
-		}
80
-		return $result;
81
-	}
69
+    /**
70
+     * get the stored metadata of a file or folder
71
+     *
72
+     * @param string|int $file
73
+     * @return ICacheEntry|false
74
+     */
75
+    public function get($file) {
76
+        $result = $this->getCache()->get($file);
77
+        if ($result) {
78
+            $result = $this->formatCacheEntry($result);
79
+        }
80
+        return $result;
81
+    }
82 82
 
83
-	/**
84
-	 * get the metadata of all files stored in $folder
85
-	 *
86
-	 * @param string $folder
87
-	 * @return ICacheEntry[]
88
-	 */
89
-	public function getFolderContents($folder) {
90
-		// can't do a simple $this->getCache()->.... call here since getFolderContentsById needs to be called on this
91
-		// and not the wrapped cache
92
-		$fileId = $this->getId($folder);
93
-		return $this->getFolderContentsById($fileId);
94
-	}
83
+    /**
84
+     * get the metadata of all files stored in $folder
85
+     *
86
+     * @param string $folder
87
+     * @return ICacheEntry[]
88
+     */
89
+    public function getFolderContents($folder) {
90
+        // can't do a simple $this->getCache()->.... call here since getFolderContentsById needs to be called on this
91
+        // and not the wrapped cache
92
+        $fileId = $this->getId($folder);
93
+        return $this->getFolderContentsById($fileId);
94
+    }
95 95
 
96
-	/**
97
-	 * get the metadata of all files stored in $folder
98
-	 *
99
-	 * @param int $fileId the file id of the folder
100
-	 * @return array
101
-	 */
102
-	public function getFolderContentsById($fileId) {
103
-		$results = $this->getCache()->getFolderContentsById($fileId);
104
-		return array_map([$this, 'formatCacheEntry'], $results);
105
-	}
96
+    /**
97
+     * get the metadata of all files stored in $folder
98
+     *
99
+     * @param int $fileId the file id of the folder
100
+     * @return array
101
+     */
102
+    public function getFolderContentsById($fileId) {
103
+        $results = $this->getCache()->getFolderContentsById($fileId);
104
+        return array_map([$this, 'formatCacheEntry'], $results);
105
+    }
106 106
 
107
-	/**
108
-	 * insert or update meta data for a file or folder
109
-	 *
110
-	 * @param string $file
111
-	 * @param array $data
112
-	 *
113
-	 * @return int file id
114
-	 * @throws \RuntimeException
115
-	 */
116
-	public function put($file, array $data) {
117
-		if (($id = $this->getId($file)) > -1) {
118
-			$this->update($id, $data);
119
-			return $id;
120
-		} else {
121
-			return $this->insert($file, $data);
122
-		}
123
-	}
107
+    /**
108
+     * insert or update meta data for a file or folder
109
+     *
110
+     * @param string $file
111
+     * @param array $data
112
+     *
113
+     * @return int file id
114
+     * @throws \RuntimeException
115
+     */
116
+    public function put($file, array $data) {
117
+        if (($id = $this->getId($file)) > -1) {
118
+            $this->update($id, $data);
119
+            return $id;
120
+        } else {
121
+            return $this->insert($file, $data);
122
+        }
123
+    }
124 124
 
125
-	/**
126
-	 * insert meta data for a new file or folder
127
-	 *
128
-	 * @param string $file
129
-	 * @param array $data
130
-	 *
131
-	 * @return int file id
132
-	 * @throws \RuntimeException
133
-	 */
134
-	public function insert($file, array $data) {
135
-		return $this->getCache()->insert($file, $data);
136
-	}
125
+    /**
126
+     * insert meta data for a new file or folder
127
+     *
128
+     * @param string $file
129
+     * @param array $data
130
+     *
131
+     * @return int file id
132
+     * @throws \RuntimeException
133
+     */
134
+    public function insert($file, array $data) {
135
+        return $this->getCache()->insert($file, $data);
136
+    }
137 137
 
138
-	/**
139
-	 * update the metadata in the cache
140
-	 *
141
-	 * @param int $id
142
-	 * @param array $data
143
-	 */
144
-	public function update($id, array $data) {
145
-		$this->getCache()->update($id, $data);
146
-	}
138
+    /**
139
+     * update the metadata in the cache
140
+     *
141
+     * @param int $id
142
+     * @param array $data
143
+     */
144
+    public function update($id, array $data) {
145
+        $this->getCache()->update($id, $data);
146
+    }
147 147
 
148
-	/**
149
-	 * get the file id for a file
150
-	 *
151
-	 * @param string $file
152
-	 * @return int
153
-	 */
154
-	public function getId($file) {
155
-		return $this->getCache()->getId($file);
156
-	}
148
+    /**
149
+     * get the file id for a file
150
+     *
151
+     * @param string $file
152
+     * @return int
153
+     */
154
+    public function getId($file) {
155
+        return $this->getCache()->getId($file);
156
+    }
157 157
 
158
-	/**
159
-	 * get the id of the parent folder of a file
160
-	 *
161
-	 * @param string $file
162
-	 * @return int
163
-	 */
164
-	public function getParentId($file) {
165
-		return $this->getCache()->getParentId($file);
166
-	}
158
+    /**
159
+     * get the id of the parent folder of a file
160
+     *
161
+     * @param string $file
162
+     * @return int
163
+     */
164
+    public function getParentId($file) {
165
+        return $this->getCache()->getParentId($file);
166
+    }
167 167
 
168
-	/**
169
-	 * check if a file is available in the cache
170
-	 *
171
-	 * @param string $file
172
-	 * @return bool
173
-	 */
174
-	public function inCache($file) {
175
-		return $this->getCache()->inCache($file);
176
-	}
168
+    /**
169
+     * check if a file is available in the cache
170
+     *
171
+     * @param string $file
172
+     * @return bool
173
+     */
174
+    public function inCache($file) {
175
+        return $this->getCache()->inCache($file);
176
+    }
177 177
 
178
-	/**
179
-	 * remove a file or folder from the cache
180
-	 *
181
-	 * @param string $file
182
-	 */
183
-	public function remove($file) {
184
-		$this->getCache()->remove($file);
185
-	}
178
+    /**
179
+     * remove a file or folder from the cache
180
+     *
181
+     * @param string $file
182
+     */
183
+    public function remove($file) {
184
+        $this->getCache()->remove($file);
185
+    }
186 186
 
187
-	/**
188
-	 * Move a file or folder in the cache
189
-	 *
190
-	 * @param string $source
191
-	 * @param string $target
192
-	 */
193
-	public function move($source, $target) {
194
-		$this->getCache()->move($source, $target);
195
-	}
187
+    /**
188
+     * Move a file or folder in the cache
189
+     *
190
+     * @param string $source
191
+     * @param string $target
192
+     */
193
+    public function move($source, $target) {
194
+        $this->getCache()->move($source, $target);
195
+    }
196 196
 
197
-	protected function getMoveInfo($path) {
198
-		/** @var Cache $cache */
199
-		$cache = $this->getCache();
200
-		return $cache->getMoveInfo($path);
201
-	}
197
+    protected function getMoveInfo($path) {
198
+        /** @var Cache $cache */
199
+        $cache = $this->getCache();
200
+        return $cache->getMoveInfo($path);
201
+    }
202 202
 
203
-	public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
204
-		$this->getCache()->moveFromCache($sourceCache, $sourcePath, $targetPath);
205
-	}
203
+    public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
204
+        $this->getCache()->moveFromCache($sourceCache, $sourcePath, $targetPath);
205
+    }
206 206
 
207
-	/**
208
-	 * remove all entries for files that are stored on the storage from the cache
209
-	 */
210
-	public function clear() {
211
-		$this->getCache()->clear();
212
-	}
207
+    /**
208
+     * remove all entries for files that are stored on the storage from the cache
209
+     */
210
+    public function clear() {
211
+        $this->getCache()->clear();
212
+    }
213 213
 
214
-	/**
215
-	 * @param string $file
216
-	 *
217
-	 * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
218
-	 */
219
-	public function getStatus($file) {
220
-		return $this->getCache()->getStatus($file);
221
-	}
214
+    /**
215
+     * @param string $file
216
+     *
217
+     * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
218
+     */
219
+    public function getStatus($file) {
220
+        return $this->getCache()->getStatus($file);
221
+    }
222 222
 
223
-	public function searchQuery(ISearchQuery $searchQuery) {
224
-		return current($this->querySearchHelper->searchInCaches($searchQuery, [$this]));
225
-	}
223
+    public function searchQuery(ISearchQuery $searchQuery) {
224
+        return current($this->querySearchHelper->searchInCaches($searchQuery, [$this]));
225
+    }
226 226
 
227
-	/**
228
-	 * update the folder size and the size of all parent folders
229
-	 *
230
-	 * @param string|boolean $path
231
-	 * @param array $data (optional) meta data of the folder
232
-	 */
233
-	public function correctFolderSize($path, $data = null, $isBackgroundScan = false) {
234
-		if ($this->getCache() instanceof Cache) {
235
-			$this->getCache()->correctFolderSize($path, $data, $isBackgroundScan);
236
-		}
237
-	}
227
+    /**
228
+     * update the folder size and the size of all parent folders
229
+     *
230
+     * @param string|boolean $path
231
+     * @param array $data (optional) meta data of the folder
232
+     */
233
+    public function correctFolderSize($path, $data = null, $isBackgroundScan = false) {
234
+        if ($this->getCache() instanceof Cache) {
235
+            $this->getCache()->correctFolderSize($path, $data, $isBackgroundScan);
236
+        }
237
+    }
238 238
 
239
-	/**
240
-	 * get the size of a folder and set it in the cache
241
-	 *
242
-	 * @param string $path
243
-	 * @param array $entry (optional) meta data of the folder
244
-	 * @return int
245
-	 */
246
-	public function calculateFolderSize($path, $entry = null) {
247
-		if ($this->getCache() instanceof Cache) {
248
-			return $this->getCache()->calculateFolderSize($path, $entry);
249
-		} else {
250
-			return 0;
251
-		}
252
-	}
239
+    /**
240
+     * get the size of a folder and set it in the cache
241
+     *
242
+     * @param string $path
243
+     * @param array $entry (optional) meta data of the folder
244
+     * @return int
245
+     */
246
+    public function calculateFolderSize($path, $entry = null) {
247
+        if ($this->getCache() instanceof Cache) {
248
+            return $this->getCache()->calculateFolderSize($path, $entry);
249
+        } else {
250
+            return 0;
251
+        }
252
+    }
253 253
 
254
-	/**
255
-	 * get all file ids on the files on the storage
256
-	 *
257
-	 * @return int[]
258
-	 */
259
-	public function getAll() {
260
-		return $this->getCache()->getAll();
261
-	}
254
+    /**
255
+     * get all file ids on the files on the storage
256
+     *
257
+     * @return int[]
258
+     */
259
+    public function getAll() {
260
+        return $this->getCache()->getAll();
261
+    }
262 262
 
263
-	/**
264
-	 * find a folder in the cache which has not been fully scanned
265
-	 *
266
-	 * If multiple incomplete folders are in the cache, the one with the highest id will be returned,
267
-	 * use the one with the highest id gives the best result with the background scanner, since that is most
268
-	 * likely the folder where we stopped scanning previously
269
-	 *
270
-	 * @return string|bool the path of the folder or false when no folder matched
271
-	 */
272
-	public function getIncomplete() {
273
-		return $this->getCache()->getIncomplete();
274
-	}
263
+    /**
264
+     * find a folder in the cache which has not been fully scanned
265
+     *
266
+     * If multiple incomplete folders are in the cache, the one with the highest id will be returned,
267
+     * use the one with the highest id gives the best result with the background scanner, since that is most
268
+     * likely the folder where we stopped scanning previously
269
+     *
270
+     * @return string|bool the path of the folder or false when no folder matched
271
+     */
272
+    public function getIncomplete() {
273
+        return $this->getCache()->getIncomplete();
274
+    }
275 275
 
276
-	/**
277
-	 * get the path of a file on this storage by it's id
278
-	 *
279
-	 * @param int $id
280
-	 * @return string|null
281
-	 */
282
-	public function getPathById($id) {
283
-		return $this->getCache()->getPathById($id);
284
-	}
276
+    /**
277
+     * get the path of a file on this storage by it's id
278
+     *
279
+     * @param int $id
280
+     * @return string|null
281
+     */
282
+    public function getPathById($id) {
283
+        return $this->getCache()->getPathById($id);
284
+    }
285 285
 
286
-	/**
287
-	 * Returns the numeric storage id
288
-	 *
289
-	 * @return int
290
-	 */
291
-	public function getNumericStorageId() {
292
-		return $this->getCache()->getNumericStorageId();
293
-	}
286
+    /**
287
+     * Returns the numeric storage id
288
+     *
289
+     * @return int
290
+     */
291
+    public function getNumericStorageId() {
292
+        return $this->getCache()->getNumericStorageId();
293
+    }
294 294
 
295
-	/**
296
-	 * get the storage id of the storage for a file and the internal path of the file
297
-	 * unlike getPathById this does not limit the search to files on this storage and
298
-	 * instead does a global search in the cache table
299
-	 *
300
-	 * @param int $id
301
-	 * @return array first element holding the storage id, second the path
302
-	 */
303
-	public static function getById($id) {
304
-		return parent::getById($id);
305
-	}
295
+    /**
296
+     * get the storage id of the storage for a file and the internal path of the file
297
+     * unlike getPathById this does not limit the search to files on this storage and
298
+     * instead does a global search in the cache table
299
+     *
300
+     * @param int $id
301
+     * @return array first element holding the storage id, second the path
302
+     */
303
+    public static function getById($id) {
304
+        return parent::getById($id);
305
+    }
306 306
 
307
-	public function getQueryFilterForStorage(): ISearchOperator {
308
-		return $this->getCache()->getQueryFilterForStorage();
309
-	}
307
+    public function getQueryFilterForStorage(): ISearchOperator {
308
+        return $this->getCache()->getQueryFilterForStorage();
309
+    }
310 310
 
311
-	public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {
312
-		$rawEntry = $this->getCache()->getCacheEntryFromSearchResult($rawEntry);
313
-		if ($rawEntry) {
314
-			return $this->formatCacheEntry(clone $rawEntry);
315
-		}
311
+    public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {
312
+        $rawEntry = $this->getCache()->getCacheEntryFromSearchResult($rawEntry);
313
+        if ($rawEntry) {
314
+            return $this->formatCacheEntry(clone $rawEntry);
315
+        }
316 316
 
317
-		return null;
318
-	}
317
+        return null;
318
+    }
319 319
 }
Please login to merge, or discard this patch.
lib/private/Files/Cache/Wrapper/CacheJail.php 2 patches
Indentation   +263 added lines, -263 removed lines patch added patch discarded remove patch
@@ -39,295 +39,295 @@
 block discarded – undo
39 39
  * Jail to a subdirectory of the wrapped cache
40 40
  */
41 41
 class CacheJail extends CacheWrapper {
42
-	/**
43
-	 * @var string
44
-	 */
45
-	protected $root;
46
-	protected $unjailedRoot;
42
+    /**
43
+     * @var string
44
+     */
45
+    protected $root;
46
+    protected $unjailedRoot;
47 47
 
48
-	/**
49
-	 * @param \OCP\Files\Cache\ICache $cache
50
-	 * @param string $root
51
-	 */
52
-	public function __construct($cache, $root) {
53
-		parent::__construct($cache);
54
-		$this->root = $root;
55
-		$this->connection = \OC::$server->getDatabaseConnection();
56
-		$this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
48
+    /**
49
+     * @param \OCP\Files\Cache\ICache $cache
50
+     * @param string $root
51
+     */
52
+    public function __construct($cache, $root) {
53
+        parent::__construct($cache);
54
+        $this->root = $root;
55
+        $this->connection = \OC::$server->getDatabaseConnection();
56
+        $this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
57 57
 
58
-		if ($cache instanceof CacheJail) {
59
-			$this->unjailedRoot = $cache->getSourcePath($root);
60
-		} else {
61
-			$this->unjailedRoot = $root;
62
-		}
63
-	}
58
+        if ($cache instanceof CacheJail) {
59
+            $this->unjailedRoot = $cache->getSourcePath($root);
60
+        } else {
61
+            $this->unjailedRoot = $root;
62
+        }
63
+    }
64 64
 
65
-	protected function getRoot() {
66
-		return $this->root;
67
-	}
65
+    protected function getRoot() {
66
+        return $this->root;
67
+    }
68 68
 
69
-	/**
70
-	 * Get the root path with any nested jails resolved
71
-	 *
72
-	 * @return string
73
-	 */
74
-	protected function getGetUnjailedRoot() {
75
-		return $this->unjailedRoot;
76
-	}
69
+    /**
70
+     * Get the root path with any nested jails resolved
71
+     *
72
+     * @return string
73
+     */
74
+    protected function getGetUnjailedRoot() {
75
+        return $this->unjailedRoot;
76
+    }
77 77
 
78
-	protected function getSourcePath($path) {
79
-		if ($path === '') {
80
-			return $this->getRoot();
81
-		} else {
82
-			return $this->getRoot() . '/' . ltrim($path, '/');
83
-		}
84
-	}
78
+    protected function getSourcePath($path) {
79
+        if ($path === '') {
80
+            return $this->getRoot();
81
+        } else {
82
+            return $this->getRoot() . '/' . ltrim($path, '/');
83
+        }
84
+    }
85 85
 
86
-	/**
87
-	 * @param string $path
88
-	 * @param null|string $root
89
-	 * @return null|string the jailed path or null if the path is outside the jail
90
-	 */
91
-	protected function getJailedPath(string $path, string $root = null) {
92
-		if ($root === null) {
93
-			$root = $this->getRoot();
94
-		}
95
-		if ($root === '') {
96
-			return $path;
97
-		}
98
-		$rootLength = strlen($root) + 1;
99
-		if ($path === $root) {
100
-			return '';
101
-		} elseif (substr($path, 0, $rootLength) === $root . '/') {
102
-			return substr($path, $rootLength);
103
-		} else {
104
-			return null;
105
-		}
106
-	}
86
+    /**
87
+     * @param string $path
88
+     * @param null|string $root
89
+     * @return null|string the jailed path or null if the path is outside the jail
90
+     */
91
+    protected function getJailedPath(string $path, string $root = null) {
92
+        if ($root === null) {
93
+            $root = $this->getRoot();
94
+        }
95
+        if ($root === '') {
96
+            return $path;
97
+        }
98
+        $rootLength = strlen($root) + 1;
99
+        if ($path === $root) {
100
+            return '';
101
+        } elseif (substr($path, 0, $rootLength) === $root . '/') {
102
+            return substr($path, $rootLength);
103
+        } else {
104
+            return null;
105
+        }
106
+    }
107 107
 
108
-	protected function formatCacheEntry($entry) {
109
-		if (isset($entry['path'])) {
110
-			$entry['path'] = $this->getJailedPath($entry['path']);
111
-		}
112
-		return $entry;
113
-	}
108
+    protected function formatCacheEntry($entry) {
109
+        if (isset($entry['path'])) {
110
+            $entry['path'] = $this->getJailedPath($entry['path']);
111
+        }
112
+        return $entry;
113
+    }
114 114
 
115
-	/**
116
-	 * get the stored metadata of a file or folder
117
-	 *
118
-	 * @param string /int $file
119
-	 * @return ICacheEntry|false
120
-	 */
121
-	public function get($file) {
122
-		if (is_string($file) or $file == '') {
123
-			$file = $this->getSourcePath($file);
124
-		}
125
-		return parent::get($file);
126
-	}
115
+    /**
116
+     * get the stored metadata of a file or folder
117
+     *
118
+     * @param string /int $file
119
+     * @return ICacheEntry|false
120
+     */
121
+    public function get($file) {
122
+        if (is_string($file) or $file == '') {
123
+            $file = $this->getSourcePath($file);
124
+        }
125
+        return parent::get($file);
126
+    }
127 127
 
128
-	/**
129
-	 * insert meta data for a new file or folder
130
-	 *
131
-	 * @param string $file
132
-	 * @param array $data
133
-	 *
134
-	 * @return int file id
135
-	 * @throws \RuntimeException
136
-	 */
137
-	public function insert($file, array $data) {
138
-		return $this->getCache()->insert($this->getSourcePath($file), $data);
139
-	}
128
+    /**
129
+     * insert meta data for a new file or folder
130
+     *
131
+     * @param string $file
132
+     * @param array $data
133
+     *
134
+     * @return int file id
135
+     * @throws \RuntimeException
136
+     */
137
+    public function insert($file, array $data) {
138
+        return $this->getCache()->insert($this->getSourcePath($file), $data);
139
+    }
140 140
 
141
-	/**
142
-	 * update the metadata in the cache
143
-	 *
144
-	 * @param int $id
145
-	 * @param array $data
146
-	 */
147
-	public function update($id, array $data) {
148
-		$this->getCache()->update($id, $data);
149
-	}
141
+    /**
142
+     * update the metadata in the cache
143
+     *
144
+     * @param int $id
145
+     * @param array $data
146
+     */
147
+    public function update($id, array $data) {
148
+        $this->getCache()->update($id, $data);
149
+    }
150 150
 
151
-	/**
152
-	 * get the file id for a file
153
-	 *
154
-	 * @param string $file
155
-	 * @return int
156
-	 */
157
-	public function getId($file) {
158
-		return $this->getCache()->getId($this->getSourcePath($file));
159
-	}
151
+    /**
152
+     * get the file id for a file
153
+     *
154
+     * @param string $file
155
+     * @return int
156
+     */
157
+    public function getId($file) {
158
+        return $this->getCache()->getId($this->getSourcePath($file));
159
+    }
160 160
 
161
-	/**
162
-	 * get the id of the parent folder of a file
163
-	 *
164
-	 * @param string $file
165
-	 * @return int
166
-	 */
167
-	public function getParentId($file) {
168
-		return $this->getCache()->getParentId($this->getSourcePath($file));
169
-	}
161
+    /**
162
+     * get the id of the parent folder of a file
163
+     *
164
+     * @param string $file
165
+     * @return int
166
+     */
167
+    public function getParentId($file) {
168
+        return $this->getCache()->getParentId($this->getSourcePath($file));
169
+    }
170 170
 
171
-	/**
172
-	 * check if a file is available in the cache
173
-	 *
174
-	 * @param string $file
175
-	 * @return bool
176
-	 */
177
-	public function inCache($file) {
178
-		return $this->getCache()->inCache($this->getSourcePath($file));
179
-	}
171
+    /**
172
+     * check if a file is available in the cache
173
+     *
174
+     * @param string $file
175
+     * @return bool
176
+     */
177
+    public function inCache($file) {
178
+        return $this->getCache()->inCache($this->getSourcePath($file));
179
+    }
180 180
 
181
-	/**
182
-	 * remove a file or folder from the cache
183
-	 *
184
-	 * @param string $file
185
-	 */
186
-	public function remove($file) {
187
-		$this->getCache()->remove($this->getSourcePath($file));
188
-	}
181
+    /**
182
+     * remove a file or folder from the cache
183
+     *
184
+     * @param string $file
185
+     */
186
+    public function remove($file) {
187
+        $this->getCache()->remove($this->getSourcePath($file));
188
+    }
189 189
 
190
-	/**
191
-	 * Move a file or folder in the cache
192
-	 *
193
-	 * @param string $source
194
-	 * @param string $target
195
-	 */
196
-	public function move($source, $target) {
197
-		$this->getCache()->move($this->getSourcePath($source), $this->getSourcePath($target));
198
-	}
190
+    /**
191
+     * Move a file or folder in the cache
192
+     *
193
+     * @param string $source
194
+     * @param string $target
195
+     */
196
+    public function move($source, $target) {
197
+        $this->getCache()->move($this->getSourcePath($source), $this->getSourcePath($target));
198
+    }
199 199
 
200
-	/**
201
-	 * Get the storage id and path needed for a move
202
-	 *
203
-	 * @param string $path
204
-	 * @return array [$storageId, $internalPath]
205
-	 */
206
-	protected function getMoveInfo($path) {
207
-		return [$this->getNumericStorageId(), $this->getSourcePath($path)];
208
-	}
200
+    /**
201
+     * Get the storage id and path needed for a move
202
+     *
203
+     * @param string $path
204
+     * @return array [$storageId, $internalPath]
205
+     */
206
+    protected function getMoveInfo($path) {
207
+        return [$this->getNumericStorageId(), $this->getSourcePath($path)];
208
+    }
209 209
 
210
-	/**
211
-	 * remove all entries for files that are stored on the storage from the cache
212
-	 */
213
-	public function clear() {
214
-		$this->getCache()->remove($this->getRoot());
215
-	}
210
+    /**
211
+     * remove all entries for files that are stored on the storage from the cache
212
+     */
213
+    public function clear() {
214
+        $this->getCache()->remove($this->getRoot());
215
+    }
216 216
 
217
-	/**
218
-	 * @param string $file
219
-	 *
220
-	 * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
221
-	 */
222
-	public function getStatus($file) {
223
-		return $this->getCache()->getStatus($this->getSourcePath($file));
224
-	}
217
+    /**
218
+     * @param string $file
219
+     *
220
+     * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
221
+     */
222
+    public function getStatus($file) {
223
+        return $this->getCache()->getStatus($this->getSourcePath($file));
224
+    }
225 225
 
226
-	/**
227
-	 * update the folder size and the size of all parent folders
228
-	 *
229
-	 * @param string|boolean $path
230
-	 * @param array $data (optional) meta data of the folder
231
-	 */
232
-	public function correctFolderSize($path, $data = null, $isBackgroundScan = false) {
233
-		if ($this->getCache() instanceof Cache) {
234
-			$this->getCache()->correctFolderSize($this->getSourcePath($path), $data, $isBackgroundScan);
235
-		}
236
-	}
226
+    /**
227
+     * update the folder size and the size of all parent folders
228
+     *
229
+     * @param string|boolean $path
230
+     * @param array $data (optional) meta data of the folder
231
+     */
232
+    public function correctFolderSize($path, $data = null, $isBackgroundScan = false) {
233
+        if ($this->getCache() instanceof Cache) {
234
+            $this->getCache()->correctFolderSize($this->getSourcePath($path), $data, $isBackgroundScan);
235
+        }
236
+    }
237 237
 
238
-	/**
239
-	 * get the size of a folder and set it in the cache
240
-	 *
241
-	 * @param string $path
242
-	 * @param array $entry (optional) meta data of the folder
243
-	 * @return int
244
-	 */
245
-	public function calculateFolderSize($path, $entry = null) {
246
-		if ($this->getCache() instanceof Cache) {
247
-			return $this->getCache()->calculateFolderSize($this->getSourcePath($path), $entry);
248
-		} else {
249
-			return 0;
250
-		}
251
-	}
238
+    /**
239
+     * get the size of a folder and set it in the cache
240
+     *
241
+     * @param string $path
242
+     * @param array $entry (optional) meta data of the folder
243
+     * @return int
244
+     */
245
+    public function calculateFolderSize($path, $entry = null) {
246
+        if ($this->getCache() instanceof Cache) {
247
+            return $this->getCache()->calculateFolderSize($this->getSourcePath($path), $entry);
248
+        } else {
249
+            return 0;
250
+        }
251
+    }
252 252
 
253
-	/**
254
-	 * get all file ids on the files on the storage
255
-	 *
256
-	 * @return int[]
257
-	 */
258
-	public function getAll() {
259
-		// not supported
260
-		return [];
261
-	}
253
+    /**
254
+     * get all file ids on the files on the storage
255
+     *
256
+     * @return int[]
257
+     */
258
+    public function getAll() {
259
+        // not supported
260
+        return [];
261
+    }
262 262
 
263
-	/**
264
-	 * find a folder in the cache which has not been fully scanned
265
-	 *
266
-	 * If multiply incomplete folders are in the cache, the one with the highest id will be returned,
267
-	 * use the one with the highest id gives the best result with the background scanner, since that is most
268
-	 * likely the folder where we stopped scanning previously
269
-	 *
270
-	 * @return string|bool the path of the folder or false when no folder matched
271
-	 */
272
-	public function getIncomplete() {
273
-		// not supported
274
-		return false;
275
-	}
263
+    /**
264
+     * find a folder in the cache which has not been fully scanned
265
+     *
266
+     * If multiply incomplete folders are in the cache, the one with the highest id will be returned,
267
+     * use the one with the highest id gives the best result with the background scanner, since that is most
268
+     * likely the folder where we stopped scanning previously
269
+     *
270
+     * @return string|bool the path of the folder or false when no folder matched
271
+     */
272
+    public function getIncomplete() {
273
+        // not supported
274
+        return false;
275
+    }
276 276
 
277
-	/**
278
-	 * get the path of a file on this storage by it's id
279
-	 *
280
-	 * @param int $id
281
-	 * @return string|null
282
-	 */
283
-	public function getPathById($id) {
284
-		$path = $this->getCache()->getPathById($id);
285
-		if ($path === null) {
286
-			return null;
287
-		}
277
+    /**
278
+     * get the path of a file on this storage by it's id
279
+     *
280
+     * @param int $id
281
+     * @return string|null
282
+     */
283
+    public function getPathById($id) {
284
+        $path = $this->getCache()->getPathById($id);
285
+        if ($path === null) {
286
+            return null;
287
+        }
288 288
 
289
-		return $this->getJailedPath($path);
290
-	}
289
+        return $this->getJailedPath($path);
290
+    }
291 291
 
292
-	/**
293
-	 * Move a file or folder in the cache
294
-	 *
295
-	 * Note that this should make sure the entries are removed from the source cache
296
-	 *
297
-	 * @param \OCP\Files\Cache\ICache $sourceCache
298
-	 * @param string $sourcePath
299
-	 * @param string $targetPath
300
-	 */
301
-	public function moveFromCache(\OCP\Files\Cache\ICache $sourceCache, $sourcePath, $targetPath) {
302
-		if ($sourceCache === $this) {
303
-			return $this->move($sourcePath, $targetPath);
304
-		}
305
-		return $this->getCache()->moveFromCache($sourceCache, $sourcePath, $this->getSourcePath($targetPath));
306
-	}
292
+    /**
293
+     * Move a file or folder in the cache
294
+     *
295
+     * Note that this should make sure the entries are removed from the source cache
296
+     *
297
+     * @param \OCP\Files\Cache\ICache $sourceCache
298
+     * @param string $sourcePath
299
+     * @param string $targetPath
300
+     */
301
+    public function moveFromCache(\OCP\Files\Cache\ICache $sourceCache, $sourcePath, $targetPath) {
302
+        if ($sourceCache === $this) {
303
+            return $this->move($sourcePath, $targetPath);
304
+        }
305
+        return $this->getCache()->moveFromCache($sourceCache, $sourcePath, $this->getSourcePath($targetPath));
306
+    }
307 307
 
308
-	public function getQueryFilterForStorage(): ISearchOperator {
309
-		return new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND,
310
-			[
311
-				$this->getCache()->getQueryFilterForStorage(),
312
-				new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR,
313
-					[
314
-						new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', $this->getGetUnjailedRoot()),
315
-						new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', $this->getGetUnjailedRoot() . '/%'),
316
-					],
317
-				)
318
-			]
319
-		);
320
-	}
308
+    public function getQueryFilterForStorage(): ISearchOperator {
309
+        return new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND,
310
+            [
311
+                $this->getCache()->getQueryFilterForStorage(),
312
+                new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR,
313
+                    [
314
+                        new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', $this->getGetUnjailedRoot()),
315
+                        new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', $this->getGetUnjailedRoot() . '/%'),
316
+                    ],
317
+                )
318
+            ]
319
+        );
320
+    }
321 321
 
322
-	public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {
323
-		$rawEntry = $this->getCache()->getCacheEntryFromSearchResult($rawEntry);
324
-		if ($rawEntry) {
325
-			$jailedPath = $this->getJailedPath($rawEntry->getPath());
326
-			if ($jailedPath !== null) {
327
-				return $this->formatCacheEntry(clone $rawEntry);
328
-			}
329
-		}
322
+    public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {
323
+        $rawEntry = $this->getCache()->getCacheEntryFromSearchResult($rawEntry);
324
+        if ($rawEntry) {
325
+            $jailedPath = $this->getJailedPath($rawEntry->getPath());
326
+            if ($jailedPath !== null) {
327
+                return $this->formatCacheEntry(clone $rawEntry);
328
+            }
329
+        }
330 330
 
331
-		return null;
332
-	}
331
+        return null;
332
+    }
333 333
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -79,7 +79,7 @@  discard block
 block discarded – undo
79 79
 		if ($path === '') {
80 80
 			return $this->getRoot();
81 81
 		} else {
82
-			return $this->getRoot() . '/' . ltrim($path, '/');
82
+			return $this->getRoot().'/'.ltrim($path, '/');
83 83
 		}
84 84
 	}
85 85
 
@@ -98,7 +98,7 @@  discard block
 block discarded – undo
98 98
 		$rootLength = strlen($root) + 1;
99 99
 		if ($path === $root) {
100 100
 			return '';
101
-		} elseif (substr($path, 0, $rootLength) === $root . '/') {
101
+		} elseif (substr($path, 0, $rootLength) === $root.'/') {
102 102
 			return substr($path, $rootLength);
103 103
 		} else {
104 104
 			return null;
@@ -312,7 +312,7 @@  discard block
 block discarded – undo
312 312
 				new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR,
313 313
 					[
314 314
 						new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', $this->getGetUnjailedRoot()),
315
-						new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', $this->getGetUnjailedRoot() . '/%'),
315
+						new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', $this->getGetUnjailedRoot().'/%'),
316 316
 					],
317 317
 				)
318 318
 			]
Please login to merge, or discard this patch.
lib/private/Files/Cache/CacheEntry.php 1 patch
Indentation   +74 added lines, -74 removed lines patch added patch discarded remove patch
@@ -28,104 +28,104 @@
 block discarded – undo
28 28
  * meta data for a file or folder
29 29
  */
30 30
 class CacheEntry implements ICacheEntry {
31
-	/**
32
-	 * @var array
33
-	 */
34
-	private $data;
31
+    /**
32
+     * @var array
33
+     */
34
+    private $data;
35 35
 
36
-	public function __construct(array $data) {
37
-		$this->data = $data;
38
-	}
36
+    public function __construct(array $data) {
37
+        $this->data = $data;
38
+    }
39 39
 
40
-	public function offsetSet($offset, $value) {
41
-		$this->data[$offset] = $value;
42
-	}
40
+    public function offsetSet($offset, $value) {
41
+        $this->data[$offset] = $value;
42
+    }
43 43
 
44
-	public function offsetExists($offset) {
45
-		return isset($this->data[$offset]);
46
-	}
44
+    public function offsetExists($offset) {
45
+        return isset($this->data[$offset]);
46
+    }
47 47
 
48
-	public function offsetUnset($offset) {
49
-		unset($this->data[$offset]);
50
-	}
48
+    public function offsetUnset($offset) {
49
+        unset($this->data[$offset]);
50
+    }
51 51
 
52
-	public function offsetGet($offset) {
53
-		if (isset($this->data[$offset])) {
54
-			return $this->data[$offset];
55
-		} else {
56
-			return null;
57
-		}
58
-	}
52
+    public function offsetGet($offset) {
53
+        if (isset($this->data[$offset])) {
54
+            return $this->data[$offset];
55
+        } else {
56
+            return null;
57
+        }
58
+    }
59 59
 
60
-	public function getId() {
61
-		return (int)$this->data['fileid'];
62
-	}
60
+    public function getId() {
61
+        return (int)$this->data['fileid'];
62
+    }
63 63
 
64
-	public function getStorageId() {
65
-		return $this->data['storage'];
66
-	}
64
+    public function getStorageId() {
65
+        return $this->data['storage'];
66
+    }
67 67
 
68 68
 
69
-	public function getPath() {
70
-		return (string)$this->data['path'];
71
-	}
69
+    public function getPath() {
70
+        return (string)$this->data['path'];
71
+    }
72 72
 
73 73
 
74
-	public function getName() {
75
-		return $this->data['name'];
76
-	}
74
+    public function getName() {
75
+        return $this->data['name'];
76
+    }
77 77
 
78 78
 
79
-	public function getMimeType() {
80
-		return $this->data['mimetype'];
81
-	}
79
+    public function getMimeType() {
80
+        return $this->data['mimetype'];
81
+    }
82 82
 
83 83
 
84
-	public function getMimePart() {
85
-		return $this->data['mimepart'];
86
-	}
84
+    public function getMimePart() {
85
+        return $this->data['mimepart'];
86
+    }
87 87
 
88
-	public function getSize() {
89
-		return $this->data['size'];
90
-	}
88
+    public function getSize() {
89
+        return $this->data['size'];
90
+    }
91 91
 
92
-	public function getMTime() {
93
-		return $this->data['mtime'];
94
-	}
92
+    public function getMTime() {
93
+        return $this->data['mtime'];
94
+    }
95 95
 
96
-	public function getStorageMTime() {
97
-		return $this->data['storage_mtime'];
98
-	}
96
+    public function getStorageMTime() {
97
+        return $this->data['storage_mtime'];
98
+    }
99 99
 
100
-	public function getEtag() {
101
-		return $this->data['etag'];
102
-	}
100
+    public function getEtag() {
101
+        return $this->data['etag'];
102
+    }
103 103
 
104
-	public function getPermissions() {
105
-		return $this->data['permissions'];
106
-	}
104
+    public function getPermissions() {
105
+        return $this->data['permissions'];
106
+    }
107 107
 
108
-	public function isEncrypted() {
109
-		return isset($this->data['encrypted']) && $this->data['encrypted'];
110
-	}
108
+    public function isEncrypted() {
109
+        return isset($this->data['encrypted']) && $this->data['encrypted'];
110
+    }
111 111
 
112
-	public function getMetadataEtag(): ?string {
113
-		return $this->data['metadata_etag'];
114
-	}
112
+    public function getMetadataEtag(): ?string {
113
+        return $this->data['metadata_etag'];
114
+    }
115 115
 
116
-	public function getCreationTime(): ?int {
117
-		return $this->data['creation_time'];
118
-	}
116
+    public function getCreationTime(): ?int {
117
+        return $this->data['creation_time'];
118
+    }
119 119
 
120
-	public function getUploadTime(): ?int {
121
-		return $this->data['upload_time'];
122
-	}
120
+    public function getUploadTime(): ?int {
121
+        return $this->data['upload_time'];
122
+    }
123 123
 
124
-	public function getData() {
125
-		return $this->data;
126
-	}
124
+    public function getData() {
125
+        return $this->data;
126
+    }
127 127
 
128
-	public function __clone() {
129
-		$this->data = array_merge([], $this->data);
130
-	}
128
+    public function __clone() {
129
+        $this->data = array_merge([], $this->data);
130
+    }
131 131
 }
Please login to merge, or discard this patch.
lib/private/Files/Node/Folder.php 2 patches
Indentation   +447 added lines, -447 removed lines patch added patch discarded remove patch
@@ -50,451 +50,451 @@
 block discarded – undo
50 50
 use OCP\IUserManager;
51 51
 
52 52
 class Folder extends Node implements \OCP\Files\Folder {
53
-	/**
54
-	 * Creates a Folder that represents a non-existing path
55
-	 *
56
-	 * @param string $path path
57
-	 * @return string non-existing node class
58
-	 */
59
-	protected function createNonExistingNode($path) {
60
-		return new NonExistingFolder($this->root, $this->view, $path);
61
-	}
62
-
63
-	/**
64
-	 * @param string $path path relative to the folder
65
-	 * @return string
66
-	 * @throws \OCP\Files\NotPermittedException
67
-	 */
68
-	public function getFullPath($path) {
69
-		if (!$this->isValidPath($path)) {
70
-			throw new NotPermittedException('Invalid path');
71
-		}
72
-		return $this->path . $this->normalizePath($path);
73
-	}
74
-
75
-	/**
76
-	 * @param string $path
77
-	 * @return string|null
78
-	 */
79
-	public function getRelativePath($path) {
80
-		if ($this->path === '' or $this->path === '/') {
81
-			return $this->normalizePath($path);
82
-		}
83
-		if ($path === $this->path) {
84
-			return '/';
85
-		} elseif (strpos($path, $this->path . '/') !== 0) {
86
-			return null;
87
-		} else {
88
-			$path = substr($path, strlen($this->path));
89
-			return $this->normalizePath($path);
90
-		}
91
-	}
92
-
93
-	/**
94
-	 * check if a node is a (grand-)child of the folder
95
-	 *
96
-	 * @param \OC\Files\Node\Node $node
97
-	 * @return bool
98
-	 */
99
-	public function isSubNode($node) {
100
-		return strpos($node->getPath(), $this->path . '/') === 0;
101
-	}
102
-
103
-	/**
104
-	 * get the content of this directory
105
-	 *
106
-	 * @return Node[]
107
-	 * @throws \OCP\Files\NotFoundException
108
-	 */
109
-	public function getDirectoryListing() {
110
-		$folderContent = $this->view->getDirectoryContent($this->path);
111
-
112
-		return array_map(function (FileInfo $info) {
113
-			if ($info->getMimetype() === 'httpd/unix-directory') {
114
-				return new Folder($this->root, $this->view, $info->getPath(), $info);
115
-			} else {
116
-				return new File($this->root, $this->view, $info->getPath(), $info);
117
-			}
118
-		}, $folderContent);
119
-	}
120
-
121
-	/**
122
-	 * @param string $path
123
-	 * @param FileInfo $info
124
-	 * @return File|Folder
125
-	 */
126
-	protected function createNode($path, FileInfo $info = null) {
127
-		if (is_null($info)) {
128
-			$isDir = $this->view->is_dir($path);
129
-		} else {
130
-			$isDir = $info->getType() === FileInfo::TYPE_FOLDER;
131
-		}
132
-		if ($isDir) {
133
-			return new Folder($this->root, $this->view, $path, $info);
134
-		} else {
135
-			return new File($this->root, $this->view, $path, $info);
136
-		}
137
-	}
138
-
139
-	/**
140
-	 * Get the node at $path
141
-	 *
142
-	 * @param string $path
143
-	 * @return \OC\Files\Node\Node
144
-	 * @throws \OCP\Files\NotFoundException
145
-	 */
146
-	public function get($path) {
147
-		return $this->root->get($this->getFullPath($path));
148
-	}
149
-
150
-	/**
151
-	 * @param string $path
152
-	 * @return bool
153
-	 */
154
-	public function nodeExists($path) {
155
-		try {
156
-			$this->get($path);
157
-			return true;
158
-		} catch (NotFoundException $e) {
159
-			return false;
160
-		}
161
-	}
162
-
163
-	/**
164
-	 * @param string $path
165
-	 * @return \OC\Files\Node\Folder
166
-	 * @throws \OCP\Files\NotPermittedException
167
-	 */
168
-	public function newFolder($path) {
169
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
170
-			$fullPath = $this->getFullPath($path);
171
-			$nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath);
172
-			$this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
173
-			if (!$this->view->mkdir($fullPath)) {
174
-				throw new NotPermittedException('Could not create folder');
175
-			}
176
-			$node = new Folder($this->root, $this->view, $fullPath);
177
-			$this->sendHooks(['postWrite', 'postCreate'], [$node]);
178
-			return $node;
179
-		} else {
180
-			throw new NotPermittedException('No create permission for folder');
181
-		}
182
-	}
183
-
184
-	/**
185
-	 * @param string $path
186
-	 * @param string | resource | null $content
187
-	 * @return \OC\Files\Node\File
188
-	 * @throws \OCP\Files\NotPermittedException
189
-	 */
190
-	public function newFile($path, $content = null) {
191
-		if (empty($path)) {
192
-			throw new NotPermittedException('Could not create as provided path is empty');
193
-		}
194
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
195
-			$fullPath = $this->getFullPath($path);
196
-			$nonExisting = new NonExistingFile($this->root, $this->view, $fullPath);
197
-			$this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
198
-			if ($content !== null) {
199
-				$result = $this->view->file_put_contents($fullPath, $content);
200
-			} else {
201
-				$result = $this->view->touch($fullPath);
202
-			}
203
-			if ($result === false) {
204
-				throw new NotPermittedException('Could not create path');
205
-			}
206
-			$node = new File($this->root, $this->view, $fullPath);
207
-			$this->sendHooks(['postWrite', 'postCreate'], [$node]);
208
-			return $node;
209
-		}
210
-		throw new NotPermittedException('No create permission for path');
211
-	}
212
-
213
-	private function queryFromOperator(ISearchOperator $operator, string $uid = null): ISearchQuery {
214
-		if ($uid === null) {
215
-			$user = null;
216
-		} else {
217
-			/** @var IUserManager $userManager */
218
-			$userManager = \OC::$server->query(IUserManager::class);
219
-			$user = $userManager->get($uid);
220
-		}
221
-		return new SearchQuery($operator, 0, 0, [], $user);
222
-	}
223
-
224
-	/**
225
-	 * search for files with the name matching $query
226
-	 *
227
-	 * @param string|ISearchQuery $query
228
-	 * @return \OC\Files\Node\Node[]
229
-	 */
230
-	public function search($query) {
231
-		if (is_string($query)) {
232
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $query . '%'));
233
-		}
234
-
235
-		// search is handled by a single query covering all caches that this folder contains
236
-		// this is done by collect
237
-
238
-		$limitToHome = $query->limitToHome();
239
-		if ($limitToHome && count(explode('/', $this->path)) !== 3) {
240
-			throw new \InvalidArgumentException('searching by owner is only allows on the users home folder');
241
-		}
242
-
243
-		$rootLength = strlen($this->path);
244
-		$mount = $this->root->getMount($this->path);
245
-		$storage = $mount->getStorage();
246
-		$internalPath = $mount->getInternalPath($this->path);
247
-
248
-		// collect all caches for this folder, indexed by their mountpoint relative to this folder
249
-		// and save the mount which is needed later to construct the FileInfo objects
250
-
251
-		if ($internalPath !== '') {
252
-			// a temporary CacheJail is used to handle filtering down the results to within this folder
253
-			$caches = ['' => new CacheJail($storage->getCache(''), $internalPath)];
254
-		} else {
255
-			$caches = ['' => $storage->getCache('')];
256
-		}
257
-		$mountByMountPoint = ['' => $mount];
258
-
259
-		if (!$limitToHome) {
260
-			$mounts = $this->root->getMountsIn($this->path);
261
-			foreach ($mounts as $mount) {
262
-				$storage = $mount->getStorage();
263
-				if ($storage) {
264
-					$relativeMountPoint = ltrim(substr($mount->getMountPoint(), $rootLength), '/');
265
-					$caches[$relativeMountPoint] = $storage->getCache('');
266
-					$mountByMountPoint[$relativeMountPoint] = $mount;
267
-				}
268
-			}
269
-		}
270
-
271
-		/** @var QuerySearchHelper $searchHelper */
272
-		$searchHelper = \OC::$server->get(QuerySearchHelper::class);
273
-		$resultsPerCache = $searchHelper->searchInCaches($query, $caches);
274
-
275
-		// loop trough all results per-cache, constructing the FileInfo object from the CacheEntry and merge them all
276
-		$files = array_merge(...array_map(function (array $results, $relativeMountPoint) use ($mountByMountPoint) {
277
-			$mount = $mountByMountPoint[$relativeMountPoint];
278
-			return array_map(function (ICacheEntry $result) use ($relativeMountPoint, $mount) {
279
-				return $this->cacheEntryToFileInfo($mount, $relativeMountPoint, $result);
280
-			}, $results);
281
-		}, array_values($resultsPerCache), array_keys($resultsPerCache)));
282
-
283
-		// since results were returned per-cache, they are no longer fully sorted
284
-		$order = $query->getOrder();
285
-		if ($order) {
286
-			usort($files, function (FileInfo $a, FileInfo $b) use ($order) {
287
-				foreach ($order as $orderField) {
288
-					$cmp = $orderField->sortFileInfo($a, $b);
289
-					if ($cmp !== 0) {
290
-						return $cmp;
291
-					}
292
-				}
293
-				return 0;
294
-			});
295
-		}
296
-
297
-		return array_map(function (FileInfo $file) {
298
-			return $this->createNode($file->getPath(), $file);
299
-		}, $files);
300
-	}
301
-
302
-	private function cacheEntryToFileInfo(IMountPoint $mount, string $appendRoot, ICacheEntry $cacheEntry): FileInfo {
303
-		$cacheEntry['internalPath'] = $cacheEntry['path'];
304
-		$cacheEntry['path'] = $appendRoot . $cacheEntry->getPath();
305
-		return new \OC\Files\FileInfo($this->path . '/' . $cacheEntry['path'], $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
306
-	}
307
-
308
-	/**
309
-	 * search for files by mimetype
310
-	 *
311
-	 * @param string $mimetype
312
-	 * @return Node[]
313
-	 */
314
-	public function searchByMime($mimetype) {
315
-		if (strpos($mimetype, '/') === false) {
316
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype . '/%'));
317
-		} else {
318
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $mimetype));
319
-		}
320
-		return $this->search($query);
321
-	}
322
-
323
-	/**
324
-	 * search for files by tag
325
-	 *
326
-	 * @param string|int $tag name or tag id
327
-	 * @param string $userId owner of the tags
328
-	 * @return Node[]
329
-	 */
330
-	public function searchByTag($tag, $userId) {
331
-		$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'tagname', $tag), $userId);
332
-		return $this->search($query);
333
-	}
334
-
335
-	/**
336
-	 * @param int $id
337
-	 * @return \OC\Files\Node\Node[]
338
-	 */
339
-	public function getById($id) {
340
-		$mountCache = $this->root->getUserMountCache();
341
-		if (strpos($this->getPath(), '/', 1) > 0) {
342
-			[, $user] = explode('/', $this->getPath());
343
-		} else {
344
-			$user = null;
345
-		}
346
-		$mountsContainingFile = $mountCache->getMountsForFileId((int)$id, $user);
347
-		$mounts = $this->root->getMountsIn($this->path);
348
-		$mounts[] = $this->root->getMount($this->path);
349
-		/** @var IMountPoint[] $folderMounts */
350
-		$folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) {
351
-			return $mountPoint->getMountPoint();
352
-		}, $mounts), $mounts);
353
-
354
-		/** @var ICachedMountInfo[] $mountsContainingFile */
355
-		$mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
356
-			return isset($folderMounts[$cachedMountInfo->getMountPoint()]);
357
-		}));
358
-
359
-		if (count($mountsContainingFile) === 0) {
360
-			if ($user === $this->getAppDataDirectoryName()) {
361
-				return $this->getByIdInRootMount((int)$id);
362
-			}
363
-			return [];
364
-		}
365
-
366
-		$nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($folderMounts, $id) {
367
-			$mount = $folderMounts[$cachedMountInfo->getMountPoint()];
368
-			$cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
369
-			if (!$cacheEntry) {
370
-				return null;
371
-			}
372
-
373
-			// cache jails will hide the "true" internal path
374
-			$internalPath = ltrim($cachedMountInfo->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
375
-			$pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
376
-			$pathRelativeToMount = ltrim($pathRelativeToMount, '/');
377
-			$absolutePath = rtrim($cachedMountInfo->getMountPoint() . $pathRelativeToMount, '/');
378
-			return $this->root->createNode($absolutePath, new \OC\Files\FileInfo(
379
-				$absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount,
380
-				\OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount))
381
-			));
382
-		}, $mountsContainingFile);
383
-
384
-		$nodes = array_filter($nodes);
385
-
386
-		return array_filter($nodes, function (Node $node) {
387
-			return $this->getRelativePath($node->getPath());
388
-		});
389
-	}
390
-
391
-	protected function getAppDataDirectoryName(): string {
392
-		$instanceId = \OC::$server->getConfig()->getSystemValueString('instanceid');
393
-		return 'appdata_' . $instanceId;
394
-	}
395
-
396
-	/**
397
-	 * In case the path we are currently in is inside the appdata_* folder,
398
-	 * the original getById method does not work, because it can only look inside
399
-	 * the user's mount points. But the user has no mount point for the root storage.
400
-	 *
401
-	 * So in that case we directly check the mount of the root if it contains
402
-	 * the id. If it does we check if the path is inside the path we are working
403
-	 * in.
404
-	 *
405
-	 * @param int $id
406
-	 * @return array
407
-	 */
408
-	protected function getByIdInRootMount(int $id): array {
409
-		$mount = $this->root->getMount('');
410
-		$cacheEntry = $mount->getStorage()->getCache($this->path)->get($id);
411
-		if (!$cacheEntry) {
412
-			return [];
413
-		}
414
-
415
-		$absolutePath = '/' . ltrim($cacheEntry->getPath(), '/');
416
-		$currentPath = rtrim($this->path, '/') . '/';
417
-
418
-		if (strpos($absolutePath, $currentPath) !== 0) {
419
-			return [];
420
-		}
421
-
422
-		return [$this->root->createNode(
423
-			$absolutePath, new \OC\Files\FileInfo(
424
-			$absolutePath,
425
-			$mount->getStorage(),
426
-			$cacheEntry->getPath(),
427
-			$cacheEntry,
428
-			$mount
429
-		))];
430
-	}
431
-
432
-	public function getFreeSpace() {
433
-		return $this->view->free_space($this->path);
434
-	}
435
-
436
-	public function delete() {
437
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
438
-			$this->sendHooks(['preDelete']);
439
-			$fileInfo = $this->getFileInfo();
440
-			$this->view->rmdir($this->path);
441
-			$nonExisting = new NonExistingFolder($this->root, $this->view, $this->path, $fileInfo);
442
-			$this->sendHooks(['postDelete'], [$nonExisting]);
443
-			$this->exists = false;
444
-		} else {
445
-			throw new NotPermittedException('No delete permission for path');
446
-		}
447
-	}
448
-
449
-	/**
450
-	 * Add a suffix to the name in case the file exists
451
-	 *
452
-	 * @param string $name
453
-	 * @return string
454
-	 * @throws NotPermittedException
455
-	 */
456
-	public function getNonExistingName($name) {
457
-		$uniqueName = \OC_Helper::buildNotExistingFileNameForView($this->getPath(), $name, $this->view);
458
-		return trim($this->getRelativePath($uniqueName), '/');
459
-	}
460
-
461
-	/**
462
-	 * @param int $limit
463
-	 * @param int $offset
464
-	 * @return \OCP\Files\Node[]
465
-	 */
466
-	public function getRecent($limit, $offset = 0) {
467
-		$query = new SearchQuery(
468
-			new SearchBinaryOperator(
469
-				// filter out non empty folders
470
-				ISearchBinaryOperator::OPERATOR_OR,
471
-				[
472
-					new SearchBinaryOperator(
473
-						ISearchBinaryOperator::OPERATOR_NOT,
474
-						[
475
-							new SearchComparison(
476
-								ISearchComparison::COMPARE_EQUAL,
477
-								'mimetype',
478
-								FileInfo::MIMETYPE_FOLDER
479
-							),
480
-						]
481
-					),
482
-					new SearchComparison(
483
-						ISearchComparison::COMPARE_EQUAL,
484
-						'size',
485
-						0
486
-					),
487
-				]
488
-			),
489
-			$limit,
490
-			$offset,
491
-			[
492
-				new SearchOrder(
493
-					ISearchOrder::DIRECTION_DESCENDING,
494
-					'mtime'
495
-				),
496
-			]
497
-		);
498
-		return $this->search($query);
499
-	}
53
+    /**
54
+     * Creates a Folder that represents a non-existing path
55
+     *
56
+     * @param string $path path
57
+     * @return string non-existing node class
58
+     */
59
+    protected function createNonExistingNode($path) {
60
+        return new NonExistingFolder($this->root, $this->view, $path);
61
+    }
62
+
63
+    /**
64
+     * @param string $path path relative to the folder
65
+     * @return string
66
+     * @throws \OCP\Files\NotPermittedException
67
+     */
68
+    public function getFullPath($path) {
69
+        if (!$this->isValidPath($path)) {
70
+            throw new NotPermittedException('Invalid path');
71
+        }
72
+        return $this->path . $this->normalizePath($path);
73
+    }
74
+
75
+    /**
76
+     * @param string $path
77
+     * @return string|null
78
+     */
79
+    public function getRelativePath($path) {
80
+        if ($this->path === '' or $this->path === '/') {
81
+            return $this->normalizePath($path);
82
+        }
83
+        if ($path === $this->path) {
84
+            return '/';
85
+        } elseif (strpos($path, $this->path . '/') !== 0) {
86
+            return null;
87
+        } else {
88
+            $path = substr($path, strlen($this->path));
89
+            return $this->normalizePath($path);
90
+        }
91
+    }
92
+
93
+    /**
94
+     * check if a node is a (grand-)child of the folder
95
+     *
96
+     * @param \OC\Files\Node\Node $node
97
+     * @return bool
98
+     */
99
+    public function isSubNode($node) {
100
+        return strpos($node->getPath(), $this->path . '/') === 0;
101
+    }
102
+
103
+    /**
104
+     * get the content of this directory
105
+     *
106
+     * @return Node[]
107
+     * @throws \OCP\Files\NotFoundException
108
+     */
109
+    public function getDirectoryListing() {
110
+        $folderContent = $this->view->getDirectoryContent($this->path);
111
+
112
+        return array_map(function (FileInfo $info) {
113
+            if ($info->getMimetype() === 'httpd/unix-directory') {
114
+                return new Folder($this->root, $this->view, $info->getPath(), $info);
115
+            } else {
116
+                return new File($this->root, $this->view, $info->getPath(), $info);
117
+            }
118
+        }, $folderContent);
119
+    }
120
+
121
+    /**
122
+     * @param string $path
123
+     * @param FileInfo $info
124
+     * @return File|Folder
125
+     */
126
+    protected function createNode($path, FileInfo $info = null) {
127
+        if (is_null($info)) {
128
+            $isDir = $this->view->is_dir($path);
129
+        } else {
130
+            $isDir = $info->getType() === FileInfo::TYPE_FOLDER;
131
+        }
132
+        if ($isDir) {
133
+            return new Folder($this->root, $this->view, $path, $info);
134
+        } else {
135
+            return new File($this->root, $this->view, $path, $info);
136
+        }
137
+    }
138
+
139
+    /**
140
+     * Get the node at $path
141
+     *
142
+     * @param string $path
143
+     * @return \OC\Files\Node\Node
144
+     * @throws \OCP\Files\NotFoundException
145
+     */
146
+    public function get($path) {
147
+        return $this->root->get($this->getFullPath($path));
148
+    }
149
+
150
+    /**
151
+     * @param string $path
152
+     * @return bool
153
+     */
154
+    public function nodeExists($path) {
155
+        try {
156
+            $this->get($path);
157
+            return true;
158
+        } catch (NotFoundException $e) {
159
+            return false;
160
+        }
161
+    }
162
+
163
+    /**
164
+     * @param string $path
165
+     * @return \OC\Files\Node\Folder
166
+     * @throws \OCP\Files\NotPermittedException
167
+     */
168
+    public function newFolder($path) {
169
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
170
+            $fullPath = $this->getFullPath($path);
171
+            $nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath);
172
+            $this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
173
+            if (!$this->view->mkdir($fullPath)) {
174
+                throw new NotPermittedException('Could not create folder');
175
+            }
176
+            $node = new Folder($this->root, $this->view, $fullPath);
177
+            $this->sendHooks(['postWrite', 'postCreate'], [$node]);
178
+            return $node;
179
+        } else {
180
+            throw new NotPermittedException('No create permission for folder');
181
+        }
182
+    }
183
+
184
+    /**
185
+     * @param string $path
186
+     * @param string | resource | null $content
187
+     * @return \OC\Files\Node\File
188
+     * @throws \OCP\Files\NotPermittedException
189
+     */
190
+    public function newFile($path, $content = null) {
191
+        if (empty($path)) {
192
+            throw new NotPermittedException('Could not create as provided path is empty');
193
+        }
194
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
195
+            $fullPath = $this->getFullPath($path);
196
+            $nonExisting = new NonExistingFile($this->root, $this->view, $fullPath);
197
+            $this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
198
+            if ($content !== null) {
199
+                $result = $this->view->file_put_contents($fullPath, $content);
200
+            } else {
201
+                $result = $this->view->touch($fullPath);
202
+            }
203
+            if ($result === false) {
204
+                throw new NotPermittedException('Could not create path');
205
+            }
206
+            $node = new File($this->root, $this->view, $fullPath);
207
+            $this->sendHooks(['postWrite', 'postCreate'], [$node]);
208
+            return $node;
209
+        }
210
+        throw new NotPermittedException('No create permission for path');
211
+    }
212
+
213
+    private function queryFromOperator(ISearchOperator $operator, string $uid = null): ISearchQuery {
214
+        if ($uid === null) {
215
+            $user = null;
216
+        } else {
217
+            /** @var IUserManager $userManager */
218
+            $userManager = \OC::$server->query(IUserManager::class);
219
+            $user = $userManager->get($uid);
220
+        }
221
+        return new SearchQuery($operator, 0, 0, [], $user);
222
+    }
223
+
224
+    /**
225
+     * search for files with the name matching $query
226
+     *
227
+     * @param string|ISearchQuery $query
228
+     * @return \OC\Files\Node\Node[]
229
+     */
230
+    public function search($query) {
231
+        if (is_string($query)) {
232
+            $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $query . '%'));
233
+        }
234
+
235
+        // search is handled by a single query covering all caches that this folder contains
236
+        // this is done by collect
237
+
238
+        $limitToHome = $query->limitToHome();
239
+        if ($limitToHome && count(explode('/', $this->path)) !== 3) {
240
+            throw new \InvalidArgumentException('searching by owner is only allows on the users home folder');
241
+        }
242
+
243
+        $rootLength = strlen($this->path);
244
+        $mount = $this->root->getMount($this->path);
245
+        $storage = $mount->getStorage();
246
+        $internalPath = $mount->getInternalPath($this->path);
247
+
248
+        // collect all caches for this folder, indexed by their mountpoint relative to this folder
249
+        // and save the mount which is needed later to construct the FileInfo objects
250
+
251
+        if ($internalPath !== '') {
252
+            // a temporary CacheJail is used to handle filtering down the results to within this folder
253
+            $caches = ['' => new CacheJail($storage->getCache(''), $internalPath)];
254
+        } else {
255
+            $caches = ['' => $storage->getCache('')];
256
+        }
257
+        $mountByMountPoint = ['' => $mount];
258
+
259
+        if (!$limitToHome) {
260
+            $mounts = $this->root->getMountsIn($this->path);
261
+            foreach ($mounts as $mount) {
262
+                $storage = $mount->getStorage();
263
+                if ($storage) {
264
+                    $relativeMountPoint = ltrim(substr($mount->getMountPoint(), $rootLength), '/');
265
+                    $caches[$relativeMountPoint] = $storage->getCache('');
266
+                    $mountByMountPoint[$relativeMountPoint] = $mount;
267
+                }
268
+            }
269
+        }
270
+
271
+        /** @var QuerySearchHelper $searchHelper */
272
+        $searchHelper = \OC::$server->get(QuerySearchHelper::class);
273
+        $resultsPerCache = $searchHelper->searchInCaches($query, $caches);
274
+
275
+        // loop trough all results per-cache, constructing the FileInfo object from the CacheEntry and merge them all
276
+        $files = array_merge(...array_map(function (array $results, $relativeMountPoint) use ($mountByMountPoint) {
277
+            $mount = $mountByMountPoint[$relativeMountPoint];
278
+            return array_map(function (ICacheEntry $result) use ($relativeMountPoint, $mount) {
279
+                return $this->cacheEntryToFileInfo($mount, $relativeMountPoint, $result);
280
+            }, $results);
281
+        }, array_values($resultsPerCache), array_keys($resultsPerCache)));
282
+
283
+        // since results were returned per-cache, they are no longer fully sorted
284
+        $order = $query->getOrder();
285
+        if ($order) {
286
+            usort($files, function (FileInfo $a, FileInfo $b) use ($order) {
287
+                foreach ($order as $orderField) {
288
+                    $cmp = $orderField->sortFileInfo($a, $b);
289
+                    if ($cmp !== 0) {
290
+                        return $cmp;
291
+                    }
292
+                }
293
+                return 0;
294
+            });
295
+        }
296
+
297
+        return array_map(function (FileInfo $file) {
298
+            return $this->createNode($file->getPath(), $file);
299
+        }, $files);
300
+    }
301
+
302
+    private function cacheEntryToFileInfo(IMountPoint $mount, string $appendRoot, ICacheEntry $cacheEntry): FileInfo {
303
+        $cacheEntry['internalPath'] = $cacheEntry['path'];
304
+        $cacheEntry['path'] = $appendRoot . $cacheEntry->getPath();
305
+        return new \OC\Files\FileInfo($this->path . '/' . $cacheEntry['path'], $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
306
+    }
307
+
308
+    /**
309
+     * search for files by mimetype
310
+     *
311
+     * @param string $mimetype
312
+     * @return Node[]
313
+     */
314
+    public function searchByMime($mimetype) {
315
+        if (strpos($mimetype, '/') === false) {
316
+            $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype . '/%'));
317
+        } else {
318
+            $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $mimetype));
319
+        }
320
+        return $this->search($query);
321
+    }
322
+
323
+    /**
324
+     * search for files by tag
325
+     *
326
+     * @param string|int $tag name or tag id
327
+     * @param string $userId owner of the tags
328
+     * @return Node[]
329
+     */
330
+    public function searchByTag($tag, $userId) {
331
+        $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'tagname', $tag), $userId);
332
+        return $this->search($query);
333
+    }
334
+
335
+    /**
336
+     * @param int $id
337
+     * @return \OC\Files\Node\Node[]
338
+     */
339
+    public function getById($id) {
340
+        $mountCache = $this->root->getUserMountCache();
341
+        if (strpos($this->getPath(), '/', 1) > 0) {
342
+            [, $user] = explode('/', $this->getPath());
343
+        } else {
344
+            $user = null;
345
+        }
346
+        $mountsContainingFile = $mountCache->getMountsForFileId((int)$id, $user);
347
+        $mounts = $this->root->getMountsIn($this->path);
348
+        $mounts[] = $this->root->getMount($this->path);
349
+        /** @var IMountPoint[] $folderMounts */
350
+        $folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) {
351
+            return $mountPoint->getMountPoint();
352
+        }, $mounts), $mounts);
353
+
354
+        /** @var ICachedMountInfo[] $mountsContainingFile */
355
+        $mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
356
+            return isset($folderMounts[$cachedMountInfo->getMountPoint()]);
357
+        }));
358
+
359
+        if (count($mountsContainingFile) === 0) {
360
+            if ($user === $this->getAppDataDirectoryName()) {
361
+                return $this->getByIdInRootMount((int)$id);
362
+            }
363
+            return [];
364
+        }
365
+
366
+        $nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($folderMounts, $id) {
367
+            $mount = $folderMounts[$cachedMountInfo->getMountPoint()];
368
+            $cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
369
+            if (!$cacheEntry) {
370
+                return null;
371
+            }
372
+
373
+            // cache jails will hide the "true" internal path
374
+            $internalPath = ltrim($cachedMountInfo->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
375
+            $pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
376
+            $pathRelativeToMount = ltrim($pathRelativeToMount, '/');
377
+            $absolutePath = rtrim($cachedMountInfo->getMountPoint() . $pathRelativeToMount, '/');
378
+            return $this->root->createNode($absolutePath, new \OC\Files\FileInfo(
379
+                $absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount,
380
+                \OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount))
381
+            ));
382
+        }, $mountsContainingFile);
383
+
384
+        $nodes = array_filter($nodes);
385
+
386
+        return array_filter($nodes, function (Node $node) {
387
+            return $this->getRelativePath($node->getPath());
388
+        });
389
+    }
390
+
391
+    protected function getAppDataDirectoryName(): string {
392
+        $instanceId = \OC::$server->getConfig()->getSystemValueString('instanceid');
393
+        return 'appdata_' . $instanceId;
394
+    }
395
+
396
+    /**
397
+     * In case the path we are currently in is inside the appdata_* folder,
398
+     * the original getById method does not work, because it can only look inside
399
+     * the user's mount points. But the user has no mount point for the root storage.
400
+     *
401
+     * So in that case we directly check the mount of the root if it contains
402
+     * the id. If it does we check if the path is inside the path we are working
403
+     * in.
404
+     *
405
+     * @param int $id
406
+     * @return array
407
+     */
408
+    protected function getByIdInRootMount(int $id): array {
409
+        $mount = $this->root->getMount('');
410
+        $cacheEntry = $mount->getStorage()->getCache($this->path)->get($id);
411
+        if (!$cacheEntry) {
412
+            return [];
413
+        }
414
+
415
+        $absolutePath = '/' . ltrim($cacheEntry->getPath(), '/');
416
+        $currentPath = rtrim($this->path, '/') . '/';
417
+
418
+        if (strpos($absolutePath, $currentPath) !== 0) {
419
+            return [];
420
+        }
421
+
422
+        return [$this->root->createNode(
423
+            $absolutePath, new \OC\Files\FileInfo(
424
+            $absolutePath,
425
+            $mount->getStorage(),
426
+            $cacheEntry->getPath(),
427
+            $cacheEntry,
428
+            $mount
429
+        ))];
430
+    }
431
+
432
+    public function getFreeSpace() {
433
+        return $this->view->free_space($this->path);
434
+    }
435
+
436
+    public function delete() {
437
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
438
+            $this->sendHooks(['preDelete']);
439
+            $fileInfo = $this->getFileInfo();
440
+            $this->view->rmdir($this->path);
441
+            $nonExisting = new NonExistingFolder($this->root, $this->view, $this->path, $fileInfo);
442
+            $this->sendHooks(['postDelete'], [$nonExisting]);
443
+            $this->exists = false;
444
+        } else {
445
+            throw new NotPermittedException('No delete permission for path');
446
+        }
447
+    }
448
+
449
+    /**
450
+     * Add a suffix to the name in case the file exists
451
+     *
452
+     * @param string $name
453
+     * @return string
454
+     * @throws NotPermittedException
455
+     */
456
+    public function getNonExistingName($name) {
457
+        $uniqueName = \OC_Helper::buildNotExistingFileNameForView($this->getPath(), $name, $this->view);
458
+        return trim($this->getRelativePath($uniqueName), '/');
459
+    }
460
+
461
+    /**
462
+     * @param int $limit
463
+     * @param int $offset
464
+     * @return \OCP\Files\Node[]
465
+     */
466
+    public function getRecent($limit, $offset = 0) {
467
+        $query = new SearchQuery(
468
+            new SearchBinaryOperator(
469
+                // filter out non empty folders
470
+                ISearchBinaryOperator::OPERATOR_OR,
471
+                [
472
+                    new SearchBinaryOperator(
473
+                        ISearchBinaryOperator::OPERATOR_NOT,
474
+                        [
475
+                            new SearchComparison(
476
+                                ISearchComparison::COMPARE_EQUAL,
477
+                                'mimetype',
478
+                                FileInfo::MIMETYPE_FOLDER
479
+                            ),
480
+                        ]
481
+                    ),
482
+                    new SearchComparison(
483
+                        ISearchComparison::COMPARE_EQUAL,
484
+                        'size',
485
+                        0
486
+                    ),
487
+                ]
488
+            ),
489
+            $limit,
490
+            $offset,
491
+            [
492
+                new SearchOrder(
493
+                    ISearchOrder::DIRECTION_DESCENDING,
494
+                    'mtime'
495
+                ),
496
+            ]
497
+        );
498
+        return $this->search($query);
499
+    }
500 500
 }
Please login to merge, or discard this patch.
Spacing   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -69,7 +69,7 @@  discard block
 block discarded – undo
69 69
 		if (!$this->isValidPath($path)) {
70 70
 			throw new NotPermittedException('Invalid path');
71 71
 		}
72
-		return $this->path . $this->normalizePath($path);
72
+		return $this->path.$this->normalizePath($path);
73 73
 	}
74 74
 
75 75
 	/**
@@ -82,7 +82,7 @@  discard block
 block discarded – undo
82 82
 		}
83 83
 		if ($path === $this->path) {
84 84
 			return '/';
85
-		} elseif (strpos($path, $this->path . '/') !== 0) {
85
+		} elseif (strpos($path, $this->path.'/') !== 0) {
86 86
 			return null;
87 87
 		} else {
88 88
 			$path = substr($path, strlen($this->path));
@@ -97,7 +97,7 @@  discard block
 block discarded – undo
97 97
 	 * @return bool
98 98
 	 */
99 99
 	public function isSubNode($node) {
100
-		return strpos($node->getPath(), $this->path . '/') === 0;
100
+		return strpos($node->getPath(), $this->path.'/') === 0;
101 101
 	}
102 102
 
103 103
 	/**
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
 	public function getDirectoryListing() {
110 110
 		$folderContent = $this->view->getDirectoryContent($this->path);
111 111
 
112
-		return array_map(function (FileInfo $info) {
112
+		return array_map(function(FileInfo $info) {
113 113
 			if ($info->getMimetype() === 'httpd/unix-directory') {
114 114
 				return new Folder($this->root, $this->view, $info->getPath(), $info);
115 115
 			} else {
@@ -229,7 +229,7 @@  discard block
 block discarded – undo
229 229
 	 */
230 230
 	public function search($query) {
231 231
 		if (is_string($query)) {
232
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $query . '%'));
232
+			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%'.$query.'%'));
233 233
 		}
234 234
 
235 235
 		// search is handled by a single query covering all caches that this folder contains
@@ -273,9 +273,9 @@  discard block
 block discarded – undo
273 273
 		$resultsPerCache = $searchHelper->searchInCaches($query, $caches);
274 274
 
275 275
 		// loop trough all results per-cache, constructing the FileInfo object from the CacheEntry and merge them all
276
-		$files = array_merge(...array_map(function (array $results, $relativeMountPoint) use ($mountByMountPoint) {
276
+		$files = array_merge(...array_map(function(array $results, $relativeMountPoint) use ($mountByMountPoint) {
277 277
 			$mount = $mountByMountPoint[$relativeMountPoint];
278
-			return array_map(function (ICacheEntry $result) use ($relativeMountPoint, $mount) {
278
+			return array_map(function(ICacheEntry $result) use ($relativeMountPoint, $mount) {
279 279
 				return $this->cacheEntryToFileInfo($mount, $relativeMountPoint, $result);
280 280
 			}, $results);
281 281
 		}, array_values($resultsPerCache), array_keys($resultsPerCache)));
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
 		// since results were returned per-cache, they are no longer fully sorted
284 284
 		$order = $query->getOrder();
285 285
 		if ($order) {
286
-			usort($files, function (FileInfo $a, FileInfo $b) use ($order) {
286
+			usort($files, function(FileInfo $a, FileInfo $b) use ($order) {
287 287
 				foreach ($order as $orderField) {
288 288
 					$cmp = $orderField->sortFileInfo($a, $b);
289 289
 					if ($cmp !== 0) {
@@ -294,15 +294,15 @@  discard block
 block discarded – undo
294 294
 			});
295 295
 		}
296 296
 
297
-		return array_map(function (FileInfo $file) {
297
+		return array_map(function(FileInfo $file) {
298 298
 			return $this->createNode($file->getPath(), $file);
299 299
 		}, $files);
300 300
 	}
301 301
 
302 302
 	private function cacheEntryToFileInfo(IMountPoint $mount, string $appendRoot, ICacheEntry $cacheEntry): FileInfo {
303 303
 		$cacheEntry['internalPath'] = $cacheEntry['path'];
304
-		$cacheEntry['path'] = $appendRoot . $cacheEntry->getPath();
305
-		return new \OC\Files\FileInfo($this->path . '/' . $cacheEntry['path'], $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
304
+		$cacheEntry['path'] = $appendRoot.$cacheEntry->getPath();
305
+		return new \OC\Files\FileInfo($this->path.'/'.$cacheEntry['path'], $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
306 306
 	}
307 307
 
308 308
 	/**
@@ -313,7 +313,7 @@  discard block
 block discarded – undo
313 313
 	 */
314 314
 	public function searchByMime($mimetype) {
315 315
 		if (strpos($mimetype, '/') === false) {
316
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype . '/%'));
316
+			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype.'/%'));
317 317
 		} else {
318 318
 			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $mimetype));
319 319
 		}
@@ -343,38 +343,38 @@  discard block
 block discarded – undo
343 343
 		} else {
344 344
 			$user = null;
345 345
 		}
346
-		$mountsContainingFile = $mountCache->getMountsForFileId((int)$id, $user);
346
+		$mountsContainingFile = $mountCache->getMountsForFileId((int) $id, $user);
347 347
 		$mounts = $this->root->getMountsIn($this->path);
348 348
 		$mounts[] = $this->root->getMount($this->path);
349 349
 		/** @var IMountPoint[] $folderMounts */
350
-		$folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) {
350
+		$folderMounts = array_combine(array_map(function(IMountPoint $mountPoint) {
351 351
 			return $mountPoint->getMountPoint();
352 352
 		}, $mounts), $mounts);
353 353
 
354 354
 		/** @var ICachedMountInfo[] $mountsContainingFile */
355
-		$mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
355
+		$mountsContainingFile = array_values(array_filter($mountsContainingFile, function(ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
356 356
 			return isset($folderMounts[$cachedMountInfo->getMountPoint()]);
357 357
 		}));
358 358
 
359 359
 		if (count($mountsContainingFile) === 0) {
360 360
 			if ($user === $this->getAppDataDirectoryName()) {
361
-				return $this->getByIdInRootMount((int)$id);
361
+				return $this->getByIdInRootMount((int) $id);
362 362
 			}
363 363
 			return [];
364 364
 		}
365 365
 
366
-		$nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($folderMounts, $id) {
366
+		$nodes = array_map(function(ICachedMountInfo $cachedMountInfo) use ($folderMounts, $id) {
367 367
 			$mount = $folderMounts[$cachedMountInfo->getMountPoint()];
368
-			$cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
368
+			$cacheEntry = $mount->getStorage()->getCache()->get((int) $id);
369 369
 			if (!$cacheEntry) {
370 370
 				return null;
371 371
 			}
372 372
 
373 373
 			// cache jails will hide the "true" internal path
374
-			$internalPath = ltrim($cachedMountInfo->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
374
+			$internalPath = ltrim($cachedMountInfo->getRootInternalPath().'/'.$cacheEntry->getPath(), '/');
375 375
 			$pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
376 376
 			$pathRelativeToMount = ltrim($pathRelativeToMount, '/');
377
-			$absolutePath = rtrim($cachedMountInfo->getMountPoint() . $pathRelativeToMount, '/');
377
+			$absolutePath = rtrim($cachedMountInfo->getMountPoint().$pathRelativeToMount, '/');
378 378
 			return $this->root->createNode($absolutePath, new \OC\Files\FileInfo(
379 379
 				$absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount,
380 380
 				\OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount))
@@ -383,14 +383,14 @@  discard block
 block discarded – undo
383 383
 
384 384
 		$nodes = array_filter($nodes);
385 385
 
386
-		return array_filter($nodes, function (Node $node) {
386
+		return array_filter($nodes, function(Node $node) {
387 387
 			return $this->getRelativePath($node->getPath());
388 388
 		});
389 389
 	}
390 390
 
391 391
 	protected function getAppDataDirectoryName(): string {
392 392
 		$instanceId = \OC::$server->getConfig()->getSystemValueString('instanceid');
393
-		return 'appdata_' . $instanceId;
393
+		return 'appdata_'.$instanceId;
394 394
 	}
395 395
 
396 396
 	/**
@@ -412,8 +412,8 @@  discard block
 block discarded – undo
412 412
 			return [];
413 413
 		}
414 414
 
415
-		$absolutePath = '/' . ltrim($cacheEntry->getPath(), '/');
416
-		$currentPath = rtrim($this->path, '/') . '/';
415
+		$absolutePath = '/'.ltrim($cacheEntry->getPath(), '/');
416
+		$currentPath = rtrim($this->path, '/').'/';
417 417
 
418 418
 		if (strpos($absolutePath, $currentPath) !== 0) {
419 419
 			return [];
Please login to merge, or discard this patch.