Passed
Push — master ( 62403d...0c3e2f )
by Joas
14:50 queued 14s
created
lib/private/TagManager.php 1 patch
Indentation   +44 added lines, -44 removed lines patch added patch discarded remove patch
@@ -40,53 +40,53 @@
 block discarded – undo
40 40
 
41 41
 class TagManager implements \OCP\ITagManager {
42 42
 
43
-	/**
44
-	 * User session
45
-	 *
46
-	 * @var \OCP\IUserSession
47
-	 */
48
-	private $userSession;
43
+    /**
44
+     * User session
45
+     *
46
+     * @var \OCP\IUserSession
47
+     */
48
+    private $userSession;
49 49
 
50
-	/**
51
-	 * TagMapper
52
-	 *
53
-	 * @var TagMapper
54
-	 */
55
-	private $mapper;
50
+    /**
51
+     * TagMapper
52
+     *
53
+     * @var TagMapper
54
+     */
55
+    private $mapper;
56 56
 
57
-	/**
58
-	* Constructor.
59
-	*
60
-	* @param TagMapper $mapper Instance of the TagMapper abstraction layer.
61
-	* @param \OCP\IUserSession $userSession the user session
62
-	*/
63
-	public function __construct(TagMapper $mapper, \OCP\IUserSession $userSession) {
64
-		$this->mapper = $mapper;
65
-		$this->userSession = $userSession;
57
+    /**
58
+     * Constructor.
59
+     *
60
+     * @param TagMapper $mapper Instance of the TagMapper abstraction layer.
61
+     * @param \OCP\IUserSession $userSession the user session
62
+     */
63
+    public function __construct(TagMapper $mapper, \OCP\IUserSession $userSession) {
64
+        $this->mapper = $mapper;
65
+        $this->userSession = $userSession;
66 66
 
67
-	}
67
+    }
68 68
 
69
-	/**
70
-	* Create a new \OCP\ITags instance and load tags from db.
71
-	*
72
-	* @see \OCP\ITags
73
-	* @param string $type The type identifier e.g. 'contact' or 'event'.
74
-	* @param array $defaultTags An array of default tags to be used if none are stored.
75
-	* @param boolean $includeShared Whether to include tags for items shared with this user by others.
76
-	* @param string $userId user for which to retrieve the tags, defaults to the currently
77
-	* logged in user
78
-	* @return \OCP\ITags
79
-	*/
80
-	public function load($type, $defaultTags = [], $includeShared = false, $userId = null) {
81
-		if (is_null($userId)) {
82
-			$user = $this->userSession->getUser();
83
-			if ($user === null) {
84
-				// nothing we can do without a user
85
-				return null;
86
-			}
87
-			$userId = $this->userSession->getUser()->getUId();
88
-		}
89
-		return new Tags($this->mapper, $userId, $type, $defaultTags, $includeShared);
90
-	}
69
+    /**
70
+     * Create a new \OCP\ITags instance and load tags from db.
71
+     *
72
+     * @see \OCP\ITags
73
+     * @param string $type The type identifier e.g. 'contact' or 'event'.
74
+     * @param array $defaultTags An array of default tags to be used if none are stored.
75
+     * @param boolean $includeShared Whether to include tags for items shared with this user by others.
76
+     * @param string $userId user for which to retrieve the tags, defaults to the currently
77
+     * logged in user
78
+     * @return \OCP\ITags
79
+     */
80
+    public function load($type, $defaultTags = [], $includeShared = false, $userId = null) {
81
+        if (is_null($userId)) {
82
+            $user = $this->userSession->getUser();
83
+            if ($user === null) {
84
+                // nothing we can do without a user
85
+                return null;
86
+            }
87
+            $userId = $this->userSession->getUser()->getUId();
88
+        }
89
+        return new Tags($this->mapper, $userId, $type, $defaultTags, $includeShared);
90
+    }
91 91
 
92 92
 }
Please login to merge, or discard this patch.
lib/private/LargeFileHelper.php 1 patch
Indentation   +165 added lines, -165 removed lines patch added patch discarded remove patch
@@ -32,180 +32,180 @@
 block discarded – undo
32 32
  * Helper class for large files on 32-bit platforms.
33 33
  */
34 34
 class LargeFileHelper {
35
-	/**
36
-	* pow(2, 53) as a base-10 string.
37
-	* @var string
38
-	*/
39
-	const POW_2_53 = '9007199254740992';
35
+    /**
36
+     * pow(2, 53) as a base-10 string.
37
+     * @var string
38
+     */
39
+    const POW_2_53 = '9007199254740992';
40 40
 
41
-	/**
42
-	* pow(2, 53) - 1 as a base-10 string.
43
-	* @var string
44
-	*/
45
-	const POW_2_53_MINUS_1 = '9007199254740991';
41
+    /**
42
+     * pow(2, 53) - 1 as a base-10 string.
43
+     * @var string
44
+     */
45
+    const POW_2_53_MINUS_1 = '9007199254740991';
46 46
 
47
-	/**
48
-	* @brief Checks whether our assumptions hold on the PHP platform we are on.
49
-	*
50
-	* @throws \RunTimeException if our assumptions do not hold on the current
51
-	*                           PHP platform.
52
-	*/
53
-	public function __construct() {
54
-		$pow_2_53 = (float)self::POW_2_53_MINUS_1 + 1.0;
55
-		if ($this->formatUnsignedInteger($pow_2_53) !== self::POW_2_53) {
56
-			throw new \RuntimeException(
57
-				'This class assumes floats to be double precision or "better".'
58
-			);
59
-		}
60
-	}
47
+    /**
48
+     * @brief Checks whether our assumptions hold on the PHP platform we are on.
49
+     *
50
+     * @throws \RunTimeException if our assumptions do not hold on the current
51
+     *                           PHP platform.
52
+     */
53
+    public function __construct() {
54
+        $pow_2_53 = (float)self::POW_2_53_MINUS_1 + 1.0;
55
+        if ($this->formatUnsignedInteger($pow_2_53) !== self::POW_2_53) {
56
+            throw new \RuntimeException(
57
+                'This class assumes floats to be double precision or "better".'
58
+            );
59
+        }
60
+    }
61 61
 
62
-	/**
63
-	* @brief Formats a signed integer or float as an unsigned integer base-10
64
-	*        string. Passed strings will be checked for being base-10.
65
-	*
66
-	* @param int|float|string $number Number containing unsigned integer data
67
-	*
68
-	* @throws \UnexpectedValueException if $number is not a float, not an int
69
-	*                                   and not a base-10 string.
70
-	*
71
-	* @return string Unsigned integer base-10 string
72
-	*/
73
-	public function formatUnsignedInteger($number) {
74
-		if (is_float($number)) {
75
-			// Undo the effect of the php.ini setting 'precision'.
76
-			return number_format($number, 0, '', '');
77
-		} else if (is_string($number) && ctype_digit($number)) {
78
-			return $number;
79
-		} else if (is_int($number)) {
80
-			// Interpret signed integer as unsigned integer.
81
-			return sprintf('%u', $number);
82
-		} else {
83
-			throw new \UnexpectedValueException(
84
-				'Expected int, float or base-10 string'
85
-			);
86
-		}
87
-	}
62
+    /**
63
+     * @brief Formats a signed integer or float as an unsigned integer base-10
64
+     *        string. Passed strings will be checked for being base-10.
65
+     *
66
+     * @param int|float|string $number Number containing unsigned integer data
67
+     *
68
+     * @throws \UnexpectedValueException if $number is not a float, not an int
69
+     *                                   and not a base-10 string.
70
+     *
71
+     * @return string Unsigned integer base-10 string
72
+     */
73
+    public function formatUnsignedInteger($number) {
74
+        if (is_float($number)) {
75
+            // Undo the effect of the php.ini setting 'precision'.
76
+            return number_format($number, 0, '', '');
77
+        } else if (is_string($number) && ctype_digit($number)) {
78
+            return $number;
79
+        } else if (is_int($number)) {
80
+            // Interpret signed integer as unsigned integer.
81
+            return sprintf('%u', $number);
82
+        } else {
83
+            throw new \UnexpectedValueException(
84
+                'Expected int, float or base-10 string'
85
+            );
86
+        }
87
+    }
88 88
 
89
-	/**
90
-	* @brief Tries to get the size of a file via various workarounds that
91
-	*        even work for large files on 32-bit platforms.
92
-	*
93
-	* @param string $filename Path to the file.
94
-	*
95
-	* @return null|int|float Number of bytes as number (float or int) or
96
-	*                        null on failure.
97
-	*/
98
-	public function getFileSize($filename) {
99
-		$fileSize = $this->getFileSizeViaCurl($filename);
100
-		if (!is_null($fileSize)) {
101
-			return $fileSize;
102
-		}
103
-		$fileSize = $this->getFileSizeViaExec($filename);
104
-		if (!is_null($fileSize)) {
105
-			return $fileSize;
106
-		}
107
-		return $this->getFileSizeNative($filename);
108
-	}
89
+    /**
90
+     * @brief Tries to get the size of a file via various workarounds that
91
+     *        even work for large files on 32-bit platforms.
92
+     *
93
+     * @param string $filename Path to the file.
94
+     *
95
+     * @return null|int|float Number of bytes as number (float or int) or
96
+     *                        null on failure.
97
+     */
98
+    public function getFileSize($filename) {
99
+        $fileSize = $this->getFileSizeViaCurl($filename);
100
+        if (!is_null($fileSize)) {
101
+            return $fileSize;
102
+        }
103
+        $fileSize = $this->getFileSizeViaExec($filename);
104
+        if (!is_null($fileSize)) {
105
+            return $fileSize;
106
+        }
107
+        return $this->getFileSizeNative($filename);
108
+    }
109 109
 
110
-	/**
111
-	* @brief Tries to get the size of a file via a CURL HEAD request.
112
-	*
113
-	* @param string $fileName Path to the file.
114
-	*
115
-	* @return null|int|float Number of bytes as number (float or int) or
116
-	*                        null on failure.
117
-	*/
118
-	public function getFileSizeViaCurl($fileName) {
119
-		if (\OC::$server->getIniWrapper()->getString('open_basedir') === '') {
120
-			$encodedFileName = rawurlencode($fileName);
121
-			$ch = curl_init("file:///$encodedFileName");
122
-			curl_setopt($ch, CURLOPT_NOBODY, true);
123
-			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
124
-			curl_setopt($ch, CURLOPT_HEADER, true);
125
-			$data = curl_exec($ch);
126
-			curl_close($ch);
127
-			if ($data !== false) {
128
-				$matches = [];
129
-				preg_match('/Content-Length: (\d+)/', $data, $matches);
130
-				if (isset($matches[1])) {
131
-					return 0 + $matches[1];
132
-				}
133
-			}
134
-		}
135
-		return null;
136
-	}
110
+    /**
111
+     * @brief Tries to get the size of a file via a CURL HEAD request.
112
+     *
113
+     * @param string $fileName Path to the file.
114
+     *
115
+     * @return null|int|float Number of bytes as number (float or int) or
116
+     *                        null on failure.
117
+     */
118
+    public function getFileSizeViaCurl($fileName) {
119
+        if (\OC::$server->getIniWrapper()->getString('open_basedir') === '') {
120
+            $encodedFileName = rawurlencode($fileName);
121
+            $ch = curl_init("file:///$encodedFileName");
122
+            curl_setopt($ch, CURLOPT_NOBODY, true);
123
+            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
124
+            curl_setopt($ch, CURLOPT_HEADER, true);
125
+            $data = curl_exec($ch);
126
+            curl_close($ch);
127
+            if ($data !== false) {
128
+                $matches = [];
129
+                preg_match('/Content-Length: (\d+)/', $data, $matches);
130
+                if (isset($matches[1])) {
131
+                    return 0 + $matches[1];
132
+                }
133
+            }
134
+        }
135
+        return null;
136
+    }
137 137
 
138
-	/**
139
-	* @brief Tries to get the size of a file via an exec() call.
140
-	*
141
-	* @param string $filename Path to the file.
142
-	*
143
-	* @return null|int|float Number of bytes as number (float or int) or
144
-	*                        null on failure.
145
-	*/
146
-	public function getFileSizeViaExec($filename) {
147
-		if (\OC_Helper::is_function_enabled('exec')) {
148
-			$os = strtolower(php_uname('s'));
149
-			$arg = escapeshellarg($filename);
150
-			$result = null;
151
-			if (strpos($os, 'linux') !== false) {
152
-				$result = $this->exec("stat -c %s $arg");
153
-			} else if (strpos($os, 'bsd') !== false || strpos($os, 'darwin') !== false) {
154
-				$result = $this->exec("stat -f %z $arg");
155
-			}
156
-			return $result;
157
-		}
158
-		return null;
159
-	}
138
+    /**
139
+     * @brief Tries to get the size of a file via an exec() call.
140
+     *
141
+     * @param string $filename Path to the file.
142
+     *
143
+     * @return null|int|float Number of bytes as number (float or int) or
144
+     *                        null on failure.
145
+     */
146
+    public function getFileSizeViaExec($filename) {
147
+        if (\OC_Helper::is_function_enabled('exec')) {
148
+            $os = strtolower(php_uname('s'));
149
+            $arg = escapeshellarg($filename);
150
+            $result = null;
151
+            if (strpos($os, 'linux') !== false) {
152
+                $result = $this->exec("stat -c %s $arg");
153
+            } else if (strpos($os, 'bsd') !== false || strpos($os, 'darwin') !== false) {
154
+                $result = $this->exec("stat -f %z $arg");
155
+            }
156
+            return $result;
157
+        }
158
+        return null;
159
+    }
160 160
 
161
-	/**
162
-	* @brief Gets the size of a file via a filesize() call and converts
163
-	*        negative signed int to positive float. As the result of filesize()
164
-	*        will wrap around after a file size of 2^32 bytes = 4 GiB, this
165
-	*        should only be used as a last resort.
166
-	*
167
-	* @param string $filename Path to the file.
168
-	*
169
-	* @return int|float Number of bytes as number (float or int).
170
-	*/
171
-	public function getFileSizeNative($filename) {
172
-		$result = filesize($filename);
173
-		if ($result < 0) {
174
-			// For file sizes between 2 GiB and 4 GiB, filesize() will return a
175
-			// negative int, as the PHP data type int is signed. Interpret the
176
-			// returned int as an unsigned integer and put it into a float.
177
-			return (float) sprintf('%u', $result);
178
-		}
179
-		return $result;
180
-	}
161
+    /**
162
+     * @brief Gets the size of a file via a filesize() call and converts
163
+     *        negative signed int to positive float. As the result of filesize()
164
+     *        will wrap around after a file size of 2^32 bytes = 4 GiB, this
165
+     *        should only be used as a last resort.
166
+     *
167
+     * @param string $filename Path to the file.
168
+     *
169
+     * @return int|float Number of bytes as number (float or int).
170
+     */
171
+    public function getFileSizeNative($filename) {
172
+        $result = filesize($filename);
173
+        if ($result < 0) {
174
+            // For file sizes between 2 GiB and 4 GiB, filesize() will return a
175
+            // negative int, as the PHP data type int is signed. Interpret the
176
+            // returned int as an unsigned integer and put it into a float.
177
+            return (float) sprintf('%u', $result);
178
+        }
179
+        return $result;
180
+    }
181 181
 
182
-	/**
183
-	 * Returns the current mtime for $fullPath
184
-	 *
185
-	 * @param string $fullPath
186
-	 * @return int
187
-	 */
188
-	public function getFileMtime($fullPath) {
189
-		try {
190
-			$result = filemtime($fullPath);
191
-		} catch (\Exception $e) {
192
-			$result =- 1;
193
-		}
194
-		if ($result < 0) {
195
-			if (\OC_Helper::is_function_enabled('exec')) {
196
-				$os = strtolower(php_uname('s'));
197
-				if (strpos($os, 'linux') !== false) {
198
-					return $this->exec('stat -c %Y ' . escapeshellarg($fullPath));
199
-				}
200
-			}
201
-		}
202
-		return $result;
182
+    /**
183
+     * Returns the current mtime for $fullPath
184
+     *
185
+     * @param string $fullPath
186
+     * @return int
187
+     */
188
+    public function getFileMtime($fullPath) {
189
+        try {
190
+            $result = filemtime($fullPath);
191
+        } catch (\Exception $e) {
192
+            $result =- 1;
193
+        }
194
+        if ($result < 0) {
195
+            if (\OC_Helper::is_function_enabled('exec')) {
196
+                $os = strtolower(php_uname('s'));
197
+                if (strpos($os, 'linux') !== false) {
198
+                    return $this->exec('stat -c %Y ' . escapeshellarg($fullPath));
199
+                }
200
+            }
201
+        }
202
+        return $result;
203 203
 
204 204
 
205
-	}
205
+    }
206 206
 
207
-	protected function exec($cmd) {
208
-		$result = trim(exec($cmd));
209
-		return ctype_digit($result) ? 0 + $result : null;
210
-	}
207
+    protected function exec($cmd) {
208
+        $result = trim(exec($cmd));
209
+        return ctype_digit($result) ? 0 + $result : null;
210
+    }
211 211
 }
Please login to merge, or discard this patch.
lib/private/Route/Route.php 1 patch
Indentation   +115 added lines, -115 removed lines patch added patch discarded remove patch
@@ -32,128 +32,128 @@
 block discarded – undo
32 32
 use Symfony\Component\Routing\Route as SymfonyRoute;
33 33
 
34 34
 class Route extends SymfonyRoute implements IRoute {
35
-	/**
36
-	 * Specify the method when this route is to be used
37
-	 *
38
-	 * @param string $method HTTP method (uppercase)
39
-	 * @return \OC\Route\Route
40
-	 */
41
-	public function method($method) {
42
-		$this->setMethods($method);
43
-		return $this;
44
-	}
35
+    /**
36
+     * Specify the method when this route is to be used
37
+     *
38
+     * @param string $method HTTP method (uppercase)
39
+     * @return \OC\Route\Route
40
+     */
41
+    public function method($method) {
42
+        $this->setMethods($method);
43
+        return $this;
44
+    }
45 45
 
46
-	/**
47
-	 * Specify POST as the method to use with this route
48
-	 * @return \OC\Route\Route
49
-	 */
50
-	public function post() {
51
-		$this->method('POST');
52
-		return $this;
53
-	}
46
+    /**
47
+     * Specify POST as the method to use with this route
48
+     * @return \OC\Route\Route
49
+     */
50
+    public function post() {
51
+        $this->method('POST');
52
+        return $this;
53
+    }
54 54
 
55
-	/**
56
-	 * Specify GET as the method to use with this route
57
-	 * @return \OC\Route\Route
58
-	 */
59
-	public function get() {
60
-		$this->method('GET');
61
-		return $this;
62
-	}
55
+    /**
56
+     * Specify GET as the method to use with this route
57
+     * @return \OC\Route\Route
58
+     */
59
+    public function get() {
60
+        $this->method('GET');
61
+        return $this;
62
+    }
63 63
 
64
-	/**
65
-	 * Specify PUT as the method to use with this route
66
-	 * @return \OC\Route\Route
67
-	 */
68
-	public function put() {
69
-		$this->method('PUT');
70
-		return $this;
71
-	}
64
+    /**
65
+     * Specify PUT as the method to use with this route
66
+     * @return \OC\Route\Route
67
+     */
68
+    public function put() {
69
+        $this->method('PUT');
70
+        return $this;
71
+    }
72 72
 
73
-	/**
74
-	 * Specify DELETE as the method to use with this route
75
-	 * @return \OC\Route\Route
76
-	 */
77
-	public function delete() {
78
-		$this->method('DELETE');
79
-		return $this;
80
-	}
73
+    /**
74
+     * Specify DELETE as the method to use with this route
75
+     * @return \OC\Route\Route
76
+     */
77
+    public function delete() {
78
+        $this->method('DELETE');
79
+        return $this;
80
+    }
81 81
 
82
-	/**
83
-	 * Specify PATCH as the method to use with this route
84
-	 * @return \OC\Route\Route
85
-	 */
86
-	public function patch() {
87
-		$this->method('PATCH');
88
-		return $this;
89
-	}
82
+    /**
83
+     * Specify PATCH as the method to use with this route
84
+     * @return \OC\Route\Route
85
+     */
86
+    public function patch() {
87
+        $this->method('PATCH');
88
+        return $this;
89
+    }
90 90
 
91
-	/**
92
-	 * Defaults to use for this route
93
-	 *
94
-	 * @param array $defaults The defaults
95
-	 * @return \OC\Route\Route
96
-	 */
97
-	public function defaults($defaults) {
98
-		$action = $this->getDefault('action');
99
-		$this->setDefaults($defaults);
100
-		if (isset($defaults['action'])) {
101
-			$action = $defaults['action'];
102
-		}
103
-		$this->action($action);
104
-		return $this;
105
-	}
91
+    /**
92
+     * Defaults to use for this route
93
+     *
94
+     * @param array $defaults The defaults
95
+     * @return \OC\Route\Route
96
+     */
97
+    public function defaults($defaults) {
98
+        $action = $this->getDefault('action');
99
+        $this->setDefaults($defaults);
100
+        if (isset($defaults['action'])) {
101
+            $action = $defaults['action'];
102
+        }
103
+        $this->action($action);
104
+        return $this;
105
+    }
106 106
 
107
-	/**
108
-	 * Requirements for this route
109
-	 *
110
-	 * @param array $requirements The requirements
111
-	 * @return \OC\Route\Route
112
-	 */
113
-	public function requirements($requirements) {
114
-		$method = $this->getMethods();
115
-		$this->setRequirements($requirements);
116
-		if (isset($requirements['_method'])) {
117
-			$method = $requirements['_method'];
118
-		}
119
-		if ($method) {
120
-			$this->method($method);
121
-		}
122
-		return $this;
123
-	}
107
+    /**
108
+     * Requirements for this route
109
+     *
110
+     * @param array $requirements The requirements
111
+     * @return \OC\Route\Route
112
+     */
113
+    public function requirements($requirements) {
114
+        $method = $this->getMethods();
115
+        $this->setRequirements($requirements);
116
+        if (isset($requirements['_method'])) {
117
+            $method = $requirements['_method'];
118
+        }
119
+        if ($method) {
120
+            $this->method($method);
121
+        }
122
+        return $this;
123
+    }
124 124
 
125
-	/**
126
-	 * The action to execute when this route matches
127
-	 *
128
-	 * @param string|callable $class the class or a callable
129
-	 * @param string $function the function to use with the class
130
-	 * @return \OC\Route\Route
131
-	 *
132
-	 * This function is called with $class set to a callable or
133
-	 * to the class with $function
134
-	 */
135
-	public function action($class, $function = null) {
136
-		$action = [$class, $function];
137
-		if (is_null($function)) {
138
-			$action = $class;
139
-		}
140
-		$this->setDefault('action', $action);
141
-		return $this;
142
-	}
125
+    /**
126
+     * The action to execute when this route matches
127
+     *
128
+     * @param string|callable $class the class or a callable
129
+     * @param string $function the function to use with the class
130
+     * @return \OC\Route\Route
131
+     *
132
+     * This function is called with $class set to a callable or
133
+     * to the class with $function
134
+     */
135
+    public function action($class, $function = null) {
136
+        $action = [$class, $function];
137
+        if (is_null($function)) {
138
+            $action = $class;
139
+        }
140
+        $this->setDefault('action', $action);
141
+        return $this;
142
+    }
143 143
 
144
-	/**
145
-	 * The action to execute when this route matches, includes a file like
146
-	 * it is called directly
147
-	 * @param string $file
148
-	 * @return void
149
-	 */
150
-	public function actionInclude($file) {
151
-		$function = function($param) use ($file) {
152
-			unset($param["_route"]);
153
-			$_GET=array_merge($_GET, $param);
154
-			unset($param);
155
-			require_once "$file";
156
-		} ;
157
-		$this->action($function);
158
-	}
144
+    /**
145
+     * The action to execute when this route matches, includes a file like
146
+     * it is called directly
147
+     * @param string $file
148
+     * @return void
149
+     */
150
+    public function actionInclude($file) {
151
+        $function = function($param) use ($file) {
152
+            unset($param["_route"]);
153
+            $_GET=array_merge($_GET, $param);
154
+            unset($param);
155
+            require_once "$file";
156
+        } ;
157
+        $this->action($function);
158
+    }
159 159
 }
Please login to merge, or discard this patch.
lib/private/Route/CachingRouter.php 1 patch
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -27,40 +27,40 @@
 block discarded – undo
27 27
 use OCP\ILogger;
28 28
 
29 29
 class CachingRouter extends Router {
30
-	/**
31
-	 * @var \OCP\ICache
32
-	 */
33
-	protected $cache;
30
+    /**
31
+     * @var \OCP\ICache
32
+     */
33
+    protected $cache;
34 34
 
35
-	/**
36
-	 * @param \OCP\ICache $cache
37
-	 * @param ILogger $logger
38
-	 */
39
-	public function __construct($cache, ILogger $logger) {
40
-		$this->cache = $cache;
41
-		parent::__construct($logger);
42
-	}
35
+    /**
36
+     * @param \OCP\ICache $cache
37
+     * @param ILogger $logger
38
+     */
39
+    public function __construct($cache, ILogger $logger) {
40
+        $this->cache = $cache;
41
+        parent::__construct($logger);
42
+    }
43 43
 
44
-	/**
45
-	 * Generate url based on $name and $parameters
46
-	 *
47
-	 * @param string $name Name of the route to use.
48
-	 * @param array $parameters Parameters for the route
49
-	 * @param bool $absolute
50
-	 * @return string
51
-	 */
52
-	public function generate($name, $parameters = [], $absolute = false) {
53
-		asort($parameters);
54
-		$key = $this->context->getHost() . '#' . $this->context->getBaseUrl() . $name . sha1(json_encode($parameters)) . (int)$absolute;
55
-		$cachedKey = $this->cache->get($key);
56
-		if ($cachedKey) {
57
-			return $cachedKey;
58
-		} else {
59
-			$url = parent::generate($name, $parameters, $absolute);
60
-			if ($url) {
61
-				$this->cache->set($key, $url, 3600);
62
-			}
63
-			return $url;
64
-		}
65
-	}
44
+    /**
45
+     * Generate url based on $name and $parameters
46
+     *
47
+     * @param string $name Name of the route to use.
48
+     * @param array $parameters Parameters for the route
49
+     * @param bool $absolute
50
+     * @return string
51
+     */
52
+    public function generate($name, $parameters = [], $absolute = false) {
53
+        asort($parameters);
54
+        $key = $this->context->getHost() . '#' . $this->context->getBaseUrl() . $name . sha1(json_encode($parameters)) . (int)$absolute;
55
+        $cachedKey = $this->cache->get($key);
56
+        if ($cachedKey) {
57
+            return $cachedKey;
58
+        } else {
59
+            $url = parent::generate($name, $parameters, $absolute);
60
+            if ($url) {
61
+                $this->cache->set($key, $url, 3600);
62
+            }
63
+            return $url;
64
+        }
65
+    }
66 66
 }
Please login to merge, or discard this patch.
lib/private/AllConfig.php 1 patch
Indentation   +497 added lines, -497 removed lines patch added patch discarded remove patch
@@ -38,501 +38,501 @@
 block discarded – undo
38 38
  * Class to combine all the configuration options ownCloud offers
39 39
  */
40 40
 class AllConfig implements \OCP\IConfig {
41
-	/** @var SystemConfig */
42
-	private $systemConfig;
43
-
44
-	/** @var IDBConnection */
45
-	private $connection;
46
-
47
-	/**
48
-	 * 3 dimensional array with the following structure:
49
-	 * [ $userId =>
50
-	 *     [ $appId =>
51
-	 *         [ $key => $value ]
52
-	 *     ]
53
-	 * ]
54
-	 *
55
-	 * database table: preferences
56
-	 *
57
-	 * methods that use this:
58
-	 *   - setUserValue
59
-	 *   - getUserValue
60
-	 *   - getUserKeys
61
-	 *   - deleteUserValue
62
-	 *   - deleteAllUserValues
63
-	 *   - deleteAppFromAllUsers
64
-	 *
65
-	 * @var CappedMemoryCache $userCache
66
-	 */
67
-	private $userCache;
68
-
69
-	/**
70
-	 * @param SystemConfig $systemConfig
71
-	 */
72
-	public function __construct(SystemConfig $systemConfig) {
73
-		$this->userCache = new CappedMemoryCache();
74
-		$this->systemConfig = $systemConfig;
75
-	}
76
-
77
-	/**
78
-	 * TODO - FIXME This fixes an issue with base.php that cause cyclic
79
-	 * dependencies, especially with autoconfig setup
80
-	 *
81
-	 * Replace this by properly injected database connection. Currently the
82
-	 * base.php triggers the getDatabaseConnection too early which causes in
83
-	 * autoconfig setup case a too early distributed database connection and
84
-	 * the autoconfig then needs to reinit all already initialized dependencies
85
-	 * that use the database connection.
86
-	 *
87
-	 * otherwise a SQLite database is created in the wrong directory
88
-	 * because the database connection was created with an uninitialized config
89
-	 */
90
-	private function fixDIInit() {
91
-		if($this->connection === null) {
92
-			$this->connection = \OC::$server->getDatabaseConnection();
93
-		}
94
-	}
95
-
96
-	/**
97
-	 * Sets and deletes system wide values
98
-	 *
99
-	 * @param array $configs Associative array with `key => value` pairs
100
-	 *                       If value is null, the config key will be deleted
101
-	 */
102
-	public function setSystemValues(array $configs) {
103
-		$this->systemConfig->setValues($configs);
104
-	}
105
-
106
-	/**
107
-	 * Sets a new system wide value
108
-	 *
109
-	 * @param string $key the key of the value, under which will be saved
110
-	 * @param mixed $value the value that should be stored
111
-	 */
112
-	public function setSystemValue($key, $value) {
113
-		$this->systemConfig->setValue($key, $value);
114
-	}
115
-
116
-	/**
117
-	 * Looks up a system wide defined value
118
-	 *
119
-	 * @param string $key the key of the value, under which it was saved
120
-	 * @param mixed $default the default value to be returned if the value isn't set
121
-	 * @return mixed the value or $default
122
-	 */
123
-	public function getSystemValue($key, $default = '') {
124
-		return $this->systemConfig->getValue($key, $default);
125
-	}
126
-
127
-	/**
128
-	 * Looks up a boolean system wide defined value
129
-	 *
130
-	 * @param string $key the key of the value, under which it was saved
131
-	 * @param mixed $default the default value to be returned if the value isn't set
132
-	 *
133
-	 * @return bool
134
-	 *
135
-	 * @since 16.0.0
136
-	 */
137
-	public function getSystemValueBool(string $key, bool $default = false): bool {
138
-		return (bool) $this->getSystemValue($key, $default);
139
-	}
140
-
141
-	/**
142
-	 * Looks up an integer system wide defined value
143
-	 *
144
-	 * @param string $key the key of the value, under which it was saved
145
-	 * @param mixed $default the default value to be returned if the value isn't set
146
-	 *
147
-	 * @return int
148
-	 *
149
-	 * @since 16.0.0
150
-	 */
151
-	public function getSystemValueInt(string $key, int $default = 0): int {
152
-		return (int) $this->getSystemValue($key, $default);
153
-	}
154
-
155
-	/**
156
-	 * Looks up a string system wide defined value
157
-	 *
158
-	 * @param string $key the key of the value, under which it was saved
159
-	 * @param mixed $default the default value to be returned if the value isn't set
160
-	 *
161
-	 * @return string
162
-	 *
163
-	 * @since 16.0.0
164
-	 */
165
-	public function getSystemValueString(string $key, string $default = ''): string {
166
-		return (string) $this->getSystemValue($key, $default);
167
-	}
168
-
169
-	/**
170
-	 * Looks up a system wide defined value and filters out sensitive data
171
-	 *
172
-	 * @param string $key the key of the value, under which it was saved
173
-	 * @param mixed $default the default value to be returned if the value isn't set
174
-	 * @return mixed the value or $default
175
-	 */
176
-	public function getFilteredSystemValue($key, $default = '') {
177
-		return $this->systemConfig->getFilteredValue($key, $default);
178
-	}
179
-
180
-	/**
181
-	 * Delete a system wide defined value
182
-	 *
183
-	 * @param string $key the key of the value, under which it was saved
184
-	 */
185
-	public function deleteSystemValue($key) {
186
-		$this->systemConfig->deleteValue($key);
187
-	}
188
-
189
-	/**
190
-	 * Get all keys stored for an app
191
-	 *
192
-	 * @param string $appName the appName that we stored the value under
193
-	 * @return string[] the keys stored for the app
194
-	 */
195
-	public function getAppKeys($appName) {
196
-		return \OC::$server->query(\OC\AppConfig::class)->getKeys($appName);
197
-	}
198
-
199
-	/**
200
-	 * Writes a new app wide value
201
-	 *
202
-	 * @param string $appName the appName that we want to store the value under
203
-	 * @param string $key the key of the value, under which will be saved
204
-	 * @param string|float|int $value the value that should be stored
205
-	 */
206
-	public function setAppValue($appName, $key, $value) {
207
-		\OC::$server->query(\OC\AppConfig::class)->setValue($appName, $key, $value);
208
-	}
209
-
210
-	/**
211
-	 * Looks up an app wide defined value
212
-	 *
213
-	 * @param string $appName the appName that we stored the value under
214
-	 * @param string $key the key of the value, under which it was saved
215
-	 * @param string $default the default value to be returned if the value isn't set
216
-	 * @return string the saved value
217
-	 */
218
-	public function getAppValue($appName, $key, $default = '') {
219
-		return \OC::$server->query(\OC\AppConfig::class)->getValue($appName, $key, $default);
220
-	}
221
-
222
-	/**
223
-	 * Delete an app wide defined value
224
-	 *
225
-	 * @param string $appName the appName that we stored the value under
226
-	 * @param string $key the key of the value, under which it was saved
227
-	 */
228
-	public function deleteAppValue($appName, $key) {
229
-		\OC::$server->query(\OC\AppConfig::class)->deleteKey($appName, $key);
230
-	}
231
-
232
-	/**
233
-	 * Removes all keys in appconfig belonging to the app
234
-	 *
235
-	 * @param string $appName the appName the configs are stored under
236
-	 */
237
-	public function deleteAppValues($appName) {
238
-		\OC::$server->query(\OC\AppConfig::class)->deleteApp($appName);
239
-	}
240
-
241
-
242
-	/**
243
-	 * Set a user defined value
244
-	 *
245
-	 * @param string $userId the userId of the user that we want to store the value under
246
-	 * @param string $appName the appName that we want to store the value under
247
-	 * @param string $key the key under which the value is being stored
248
-	 * @param string|float|int $value the value that you want to store
249
-	 * @param string $preCondition only update if the config value was previously the value passed as $preCondition
250
-	 * @throws \OCP\PreConditionNotMetException if a precondition is specified and is not met
251
-	 * @throws \UnexpectedValueException when trying to store an unexpected value
252
-	 */
253
-	public function setUserValue($userId, $appName, $key, $value, $preCondition = null) {
254
-		if (!is_int($value) && !is_float($value) && !is_string($value)) {
255
-			throw new \UnexpectedValueException('Only integers, floats and strings are allowed as value');
256
-		}
257
-
258
-		// TODO - FIXME
259
-		$this->fixDIInit();
260
-
261
-		$prevValue = $this->getUserValue($userId, $appName, $key, null);
262
-
263
-		if ($prevValue !== null) {
264
-			if ($prevValue === (string)$value) {
265
-				return;
266
-			} else if ($preCondition !== null && $prevValue !== (string)$preCondition) {
267
-				throw new PreConditionNotMetException();
268
-			} else {
269
-				$qb = $this->connection->getQueryBuilder();
270
-				$qb->update('preferences')
271
-					->set('configvalue', $qb->createNamedParameter($value))
272
-					->where($qb->expr()->eq('userid', $qb->createNamedParameter($userId)))
273
-					->andWhere($qb->expr()->eq('appid', $qb->createNamedParameter($appName)))
274
-					->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($key)));
275
-				$qb->execute();
276
-
277
-				$this->userCache[$userId][$appName][$key] = (string)$value;
278
-				return;
279
-			}
280
-		}
281
-
282
-		$preconditionArray = [];
283
-		if (isset($preCondition)) {
284
-			$preconditionArray = [
285
-				'configvalue' => $preCondition,
286
-			];
287
-		}
288
-
289
-		$this->connection->setValues('preferences', [
290
-			'userid' => $userId,
291
-			'appid' => $appName,
292
-			'configkey' => $key,
293
-		], [
294
-			'configvalue' => $value,
295
-		], $preconditionArray);
296
-
297
-		// only add to the cache if we already loaded data for the user
298
-		if (isset($this->userCache[$userId])) {
299
-			if (!isset($this->userCache[$userId][$appName])) {
300
-				$this->userCache[$userId][$appName] = [];
301
-			}
302
-			$this->userCache[$userId][$appName][$key] = (string)$value;
303
-		}
304
-	}
305
-
306
-	/**
307
-	 * Getting a user defined value
308
-	 *
309
-	 * @param string $userId the userId of the user that we want to store the value under
310
-	 * @param string $appName the appName that we stored the value under
311
-	 * @param string $key the key under which the value is being stored
312
-	 * @param mixed $default the default value to be returned if the value isn't set
313
-	 * @return string
314
-	 */
315
-	public function getUserValue($userId, $appName, $key, $default = '') {
316
-		$data = $this->getUserValues($userId);
317
-		if (isset($data[$appName]) and isset($data[$appName][$key])) {
318
-			return $data[$appName][$key];
319
-		} else {
320
-			return $default;
321
-		}
322
-	}
323
-
324
-	/**
325
-	 * Get the keys of all stored by an app for the user
326
-	 *
327
-	 * @param string $userId the userId of the user that we want to store the value under
328
-	 * @param string $appName the appName that we stored the value under
329
-	 * @return string[]
330
-	 */
331
-	public function getUserKeys($userId, $appName) {
332
-		$data = $this->getUserValues($userId);
333
-		if (isset($data[$appName])) {
334
-			return array_keys($data[$appName]);
335
-		} else {
336
-			return [];
337
-		}
338
-	}
339
-
340
-	/**
341
-	 * Delete a user value
342
-	 *
343
-	 * @param string $userId the userId of the user that we want to store the value under
344
-	 * @param string $appName the appName that we stored the value under
345
-	 * @param string $key the key under which the value is being stored
346
-	 */
347
-	public function deleteUserValue($userId, $appName, $key) {
348
-		// TODO - FIXME
349
-		$this->fixDIInit();
350
-
351
-		$sql  = 'DELETE FROM `*PREFIX*preferences` '.
352
-				'WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?';
353
-		$this->connection->executeUpdate($sql, [$userId, $appName, $key]);
354
-
355
-		if (isset($this->userCache[$userId]) and isset($this->userCache[$userId][$appName])) {
356
-			unset($this->userCache[$userId][$appName][$key]);
357
-		}
358
-	}
359
-
360
-	/**
361
-	 * Delete all user values
362
-	 *
363
-	 * @param string $userId the userId of the user that we want to remove all values from
364
-	 */
365
-	public function deleteAllUserValues($userId) {
366
-		// TODO - FIXME
367
-		$this->fixDIInit();
368
-
369
-		$sql  = 'DELETE FROM `*PREFIX*preferences` '.
370
-			'WHERE `userid` = ?';
371
-		$this->connection->executeUpdate($sql, [$userId]);
372
-
373
-		unset($this->userCache[$userId]);
374
-	}
375
-
376
-	/**
377
-	 * Delete all user related values of one app
378
-	 *
379
-	 * @param string $appName the appName of the app that we want to remove all values from
380
-	 */
381
-	public function deleteAppFromAllUsers($appName) {
382
-		// TODO - FIXME
383
-		$this->fixDIInit();
384
-
385
-		$sql  = 'DELETE FROM `*PREFIX*preferences` '.
386
-				'WHERE `appid` = ?';
387
-		$this->connection->executeUpdate($sql, [$appName]);
388
-
389
-		foreach ($this->userCache as &$userCache) {
390
-			unset($userCache[$appName]);
391
-		}
392
-	}
393
-
394
-	/**
395
-	 * Returns all user configs sorted by app of one user
396
-	 *
397
-	 * @param string $userId the user ID to get the app configs from
398
-	 * @return array[] - 2 dimensional array with the following structure:
399
-	 *     [ $appId =>
400
-	 *         [ $key => $value ]
401
-	 *     ]
402
-	 */
403
-	private function getUserValues($userId) {
404
-		if (isset($this->userCache[$userId])) {
405
-			return $this->userCache[$userId];
406
-		}
407
-		if ($userId === null || $userId === '') {
408
-			$this->userCache[$userId]=[];
409
-			return $this->userCache[$userId];
410
-		}
411
-
412
-		// TODO - FIXME
413
-		$this->fixDIInit();
414
-
415
-		$data = [];
416
-		$query = 'SELECT `appid`, `configkey`, `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ?';
417
-		$result = $this->connection->executeQuery($query, [$userId]);
418
-		while ($row = $result->fetch()) {
419
-			$appId = $row['appid'];
420
-			if (!isset($data[$appId])) {
421
-				$data[$appId] = [];
422
-			}
423
-			$data[$appId][$row['configkey']] = $row['configvalue'];
424
-		}
425
-		$this->userCache[$userId] = $data;
426
-		return $data;
427
-	}
428
-
429
-	/**
430
-	 * Fetches a mapped list of userId -> value, for a specified app and key and a list of user IDs.
431
-	 *
432
-	 * @param string $appName app to get the value for
433
-	 * @param string $key the key to get the value for
434
-	 * @param array $userIds the user IDs to fetch the values for
435
-	 * @return array Mapped values: userId => value
436
-	 */
437
-	public function getUserValueForUsers($appName, $key, $userIds) {
438
-		// TODO - FIXME
439
-		$this->fixDIInit();
440
-
441
-		if (empty($userIds) || !is_array($userIds)) {
442
-			return [];
443
-		}
444
-
445
-		$chunkedUsers = array_chunk($userIds, 50, true);
446
-		$placeholders50 = implode(',', array_fill(0, 50, '?'));
447
-
448
-		$userValues = [];
449
-		foreach ($chunkedUsers as $chunk) {
450
-			$queryParams = $chunk;
451
-			// create [$app, $key, $chunkedUsers]
452
-			array_unshift($queryParams, $key);
453
-			array_unshift($queryParams, $appName);
454
-
455
-			$placeholders = (count($chunk) === 50) ? $placeholders50 :  implode(',', array_fill(0, count($chunk), '?'));
456
-
457
-			$query    = 'SELECT `userid`, `configvalue` ' .
458
-						'FROM `*PREFIX*preferences` ' .
459
-						'WHERE `appid` = ? AND `configkey` = ? ' .
460
-						'AND `userid` IN (' . $placeholders . ')';
461
-			$result = $this->connection->executeQuery($query, $queryParams);
462
-
463
-			while ($row = $result->fetch()) {
464
-				$userValues[$row['userid']] = $row['configvalue'];
465
-			}
466
-		}
467
-
468
-		return $userValues;
469
-	}
470
-
471
-	/**
472
-	 * Determines the users that have the given value set for a specific app-key-pair
473
-	 *
474
-	 * @param string $appName the app to get the user for
475
-	 * @param string $key the key to get the user for
476
-	 * @param string $value the value to get the user for
477
-	 * @return array of user IDs
478
-	 */
479
-	public function getUsersForUserValue($appName, $key, $value) {
480
-		// TODO - FIXME
481
-		$this->fixDIInit();
482
-
483
-		$sql  = 'SELECT `userid` FROM `*PREFIX*preferences` ' .
484
-				'WHERE `appid` = ? AND `configkey` = ? ';
485
-
486
-		if($this->getSystemValue('dbtype', 'sqlite') === 'oci') {
487
-			//oracle hack: need to explicitly cast CLOB to CHAR for comparison
488
-			$sql .= 'AND to_char(`configvalue`) = ?';
489
-		} else {
490
-			$sql .= 'AND `configvalue` = ?';
491
-		}
492
-
493
-		$result = $this->connection->executeQuery($sql, [$appName, $key, $value]);
494
-
495
-		$userIDs = [];
496
-		while ($row = $result->fetch()) {
497
-			$userIDs[] = $row['userid'];
498
-		}
499
-
500
-		return $userIDs;
501
-	}
502
-
503
-	/**
504
-	 * Determines the users that have the given value set for a specific app-key-pair
505
-	 *
506
-	 * @param string $appName the app to get the user for
507
-	 * @param string $key the key to get the user for
508
-	 * @param string $value the value to get the user for
509
-	 * @return array of user IDs
510
-	 */
511
-	public function getUsersForUserValueCaseInsensitive($appName, $key, $value) {
512
-		// TODO - FIXME
513
-		$this->fixDIInit();
514
-
515
-		$sql  = 'SELECT `userid` FROM `*PREFIX*preferences` ' .
516
-			'WHERE `appid` = ? AND `configkey` = ? ';
517
-
518
-		if($this->getSystemValue('dbtype', 'sqlite') === 'oci') {
519
-			//oracle hack: need to explicitly cast CLOB to CHAR for comparison
520
-			$sql .= 'AND LOWER(to_char(`configvalue`)) = LOWER(?)';
521
-		} else {
522
-			$sql .= 'AND LOWER(`configvalue`) = LOWER(?)';
523
-		}
524
-
525
-		$result = $this->connection->executeQuery($sql, [$appName, $key, $value]);
526
-
527
-		$userIDs = [];
528
-		while ($row = $result->fetch()) {
529
-			$userIDs[] = $row['userid'];
530
-		}
531
-
532
-		return $userIDs;
533
-	}
534
-
535
-	public function getSystemConfig() {
536
-		return $this->systemConfig;
537
-	}
41
+    /** @var SystemConfig */
42
+    private $systemConfig;
43
+
44
+    /** @var IDBConnection */
45
+    private $connection;
46
+
47
+    /**
48
+     * 3 dimensional array with the following structure:
49
+     * [ $userId =>
50
+     *     [ $appId =>
51
+     *         [ $key => $value ]
52
+     *     ]
53
+     * ]
54
+     *
55
+     * database table: preferences
56
+     *
57
+     * methods that use this:
58
+     *   - setUserValue
59
+     *   - getUserValue
60
+     *   - getUserKeys
61
+     *   - deleteUserValue
62
+     *   - deleteAllUserValues
63
+     *   - deleteAppFromAllUsers
64
+     *
65
+     * @var CappedMemoryCache $userCache
66
+     */
67
+    private $userCache;
68
+
69
+    /**
70
+     * @param SystemConfig $systemConfig
71
+     */
72
+    public function __construct(SystemConfig $systemConfig) {
73
+        $this->userCache = new CappedMemoryCache();
74
+        $this->systemConfig = $systemConfig;
75
+    }
76
+
77
+    /**
78
+     * TODO - FIXME This fixes an issue with base.php that cause cyclic
79
+     * dependencies, especially with autoconfig setup
80
+     *
81
+     * Replace this by properly injected database connection. Currently the
82
+     * base.php triggers the getDatabaseConnection too early which causes in
83
+     * autoconfig setup case a too early distributed database connection and
84
+     * the autoconfig then needs to reinit all already initialized dependencies
85
+     * that use the database connection.
86
+     *
87
+     * otherwise a SQLite database is created in the wrong directory
88
+     * because the database connection was created with an uninitialized config
89
+     */
90
+    private function fixDIInit() {
91
+        if($this->connection === null) {
92
+            $this->connection = \OC::$server->getDatabaseConnection();
93
+        }
94
+    }
95
+
96
+    /**
97
+     * Sets and deletes system wide values
98
+     *
99
+     * @param array $configs Associative array with `key => value` pairs
100
+     *                       If value is null, the config key will be deleted
101
+     */
102
+    public function setSystemValues(array $configs) {
103
+        $this->systemConfig->setValues($configs);
104
+    }
105
+
106
+    /**
107
+     * Sets a new system wide value
108
+     *
109
+     * @param string $key the key of the value, under which will be saved
110
+     * @param mixed $value the value that should be stored
111
+     */
112
+    public function setSystemValue($key, $value) {
113
+        $this->systemConfig->setValue($key, $value);
114
+    }
115
+
116
+    /**
117
+     * Looks up a system wide defined value
118
+     *
119
+     * @param string $key the key of the value, under which it was saved
120
+     * @param mixed $default the default value to be returned if the value isn't set
121
+     * @return mixed the value or $default
122
+     */
123
+    public function getSystemValue($key, $default = '') {
124
+        return $this->systemConfig->getValue($key, $default);
125
+    }
126
+
127
+    /**
128
+     * Looks up a boolean system wide defined value
129
+     *
130
+     * @param string $key the key of the value, under which it was saved
131
+     * @param mixed $default the default value to be returned if the value isn't set
132
+     *
133
+     * @return bool
134
+     *
135
+     * @since 16.0.0
136
+     */
137
+    public function getSystemValueBool(string $key, bool $default = false): bool {
138
+        return (bool) $this->getSystemValue($key, $default);
139
+    }
140
+
141
+    /**
142
+     * Looks up an integer system wide defined value
143
+     *
144
+     * @param string $key the key of the value, under which it was saved
145
+     * @param mixed $default the default value to be returned if the value isn't set
146
+     *
147
+     * @return int
148
+     *
149
+     * @since 16.0.0
150
+     */
151
+    public function getSystemValueInt(string $key, int $default = 0): int {
152
+        return (int) $this->getSystemValue($key, $default);
153
+    }
154
+
155
+    /**
156
+     * Looks up a string system wide defined value
157
+     *
158
+     * @param string $key the key of the value, under which it was saved
159
+     * @param mixed $default the default value to be returned if the value isn't set
160
+     *
161
+     * @return string
162
+     *
163
+     * @since 16.0.0
164
+     */
165
+    public function getSystemValueString(string $key, string $default = ''): string {
166
+        return (string) $this->getSystemValue($key, $default);
167
+    }
168
+
169
+    /**
170
+     * Looks up a system wide defined value and filters out sensitive data
171
+     *
172
+     * @param string $key the key of the value, under which it was saved
173
+     * @param mixed $default the default value to be returned if the value isn't set
174
+     * @return mixed the value or $default
175
+     */
176
+    public function getFilteredSystemValue($key, $default = '') {
177
+        return $this->systemConfig->getFilteredValue($key, $default);
178
+    }
179
+
180
+    /**
181
+     * Delete a system wide defined value
182
+     *
183
+     * @param string $key the key of the value, under which it was saved
184
+     */
185
+    public function deleteSystemValue($key) {
186
+        $this->systemConfig->deleteValue($key);
187
+    }
188
+
189
+    /**
190
+     * Get all keys stored for an app
191
+     *
192
+     * @param string $appName the appName that we stored the value under
193
+     * @return string[] the keys stored for the app
194
+     */
195
+    public function getAppKeys($appName) {
196
+        return \OC::$server->query(\OC\AppConfig::class)->getKeys($appName);
197
+    }
198
+
199
+    /**
200
+     * Writes a new app wide value
201
+     *
202
+     * @param string $appName the appName that we want to store the value under
203
+     * @param string $key the key of the value, under which will be saved
204
+     * @param string|float|int $value the value that should be stored
205
+     */
206
+    public function setAppValue($appName, $key, $value) {
207
+        \OC::$server->query(\OC\AppConfig::class)->setValue($appName, $key, $value);
208
+    }
209
+
210
+    /**
211
+     * Looks up an app wide defined value
212
+     *
213
+     * @param string $appName the appName that we stored the value under
214
+     * @param string $key the key of the value, under which it was saved
215
+     * @param string $default the default value to be returned if the value isn't set
216
+     * @return string the saved value
217
+     */
218
+    public function getAppValue($appName, $key, $default = '') {
219
+        return \OC::$server->query(\OC\AppConfig::class)->getValue($appName, $key, $default);
220
+    }
221
+
222
+    /**
223
+     * Delete an app wide defined value
224
+     *
225
+     * @param string $appName the appName that we stored the value under
226
+     * @param string $key the key of the value, under which it was saved
227
+     */
228
+    public function deleteAppValue($appName, $key) {
229
+        \OC::$server->query(\OC\AppConfig::class)->deleteKey($appName, $key);
230
+    }
231
+
232
+    /**
233
+     * Removes all keys in appconfig belonging to the app
234
+     *
235
+     * @param string $appName the appName the configs are stored under
236
+     */
237
+    public function deleteAppValues($appName) {
238
+        \OC::$server->query(\OC\AppConfig::class)->deleteApp($appName);
239
+    }
240
+
241
+
242
+    /**
243
+     * Set a user defined value
244
+     *
245
+     * @param string $userId the userId of the user that we want to store the value under
246
+     * @param string $appName the appName that we want to store the value under
247
+     * @param string $key the key under which the value is being stored
248
+     * @param string|float|int $value the value that you want to store
249
+     * @param string $preCondition only update if the config value was previously the value passed as $preCondition
250
+     * @throws \OCP\PreConditionNotMetException if a precondition is specified and is not met
251
+     * @throws \UnexpectedValueException when trying to store an unexpected value
252
+     */
253
+    public function setUserValue($userId, $appName, $key, $value, $preCondition = null) {
254
+        if (!is_int($value) && !is_float($value) && !is_string($value)) {
255
+            throw new \UnexpectedValueException('Only integers, floats and strings are allowed as value');
256
+        }
257
+
258
+        // TODO - FIXME
259
+        $this->fixDIInit();
260
+
261
+        $prevValue = $this->getUserValue($userId, $appName, $key, null);
262
+
263
+        if ($prevValue !== null) {
264
+            if ($prevValue === (string)$value) {
265
+                return;
266
+            } else if ($preCondition !== null && $prevValue !== (string)$preCondition) {
267
+                throw new PreConditionNotMetException();
268
+            } else {
269
+                $qb = $this->connection->getQueryBuilder();
270
+                $qb->update('preferences')
271
+                    ->set('configvalue', $qb->createNamedParameter($value))
272
+                    ->where($qb->expr()->eq('userid', $qb->createNamedParameter($userId)))
273
+                    ->andWhere($qb->expr()->eq('appid', $qb->createNamedParameter($appName)))
274
+                    ->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($key)));
275
+                $qb->execute();
276
+
277
+                $this->userCache[$userId][$appName][$key] = (string)$value;
278
+                return;
279
+            }
280
+        }
281
+
282
+        $preconditionArray = [];
283
+        if (isset($preCondition)) {
284
+            $preconditionArray = [
285
+                'configvalue' => $preCondition,
286
+            ];
287
+        }
288
+
289
+        $this->connection->setValues('preferences', [
290
+            'userid' => $userId,
291
+            'appid' => $appName,
292
+            'configkey' => $key,
293
+        ], [
294
+            'configvalue' => $value,
295
+        ], $preconditionArray);
296
+
297
+        // only add to the cache if we already loaded data for the user
298
+        if (isset($this->userCache[$userId])) {
299
+            if (!isset($this->userCache[$userId][$appName])) {
300
+                $this->userCache[$userId][$appName] = [];
301
+            }
302
+            $this->userCache[$userId][$appName][$key] = (string)$value;
303
+        }
304
+    }
305
+
306
+    /**
307
+     * Getting a user defined value
308
+     *
309
+     * @param string $userId the userId of the user that we want to store the value under
310
+     * @param string $appName the appName that we stored the value under
311
+     * @param string $key the key under which the value is being stored
312
+     * @param mixed $default the default value to be returned if the value isn't set
313
+     * @return string
314
+     */
315
+    public function getUserValue($userId, $appName, $key, $default = '') {
316
+        $data = $this->getUserValues($userId);
317
+        if (isset($data[$appName]) and isset($data[$appName][$key])) {
318
+            return $data[$appName][$key];
319
+        } else {
320
+            return $default;
321
+        }
322
+    }
323
+
324
+    /**
325
+     * Get the keys of all stored by an app for the user
326
+     *
327
+     * @param string $userId the userId of the user that we want to store the value under
328
+     * @param string $appName the appName that we stored the value under
329
+     * @return string[]
330
+     */
331
+    public function getUserKeys($userId, $appName) {
332
+        $data = $this->getUserValues($userId);
333
+        if (isset($data[$appName])) {
334
+            return array_keys($data[$appName]);
335
+        } else {
336
+            return [];
337
+        }
338
+    }
339
+
340
+    /**
341
+     * Delete a user value
342
+     *
343
+     * @param string $userId the userId of the user that we want to store the value under
344
+     * @param string $appName the appName that we stored the value under
345
+     * @param string $key the key under which the value is being stored
346
+     */
347
+    public function deleteUserValue($userId, $appName, $key) {
348
+        // TODO - FIXME
349
+        $this->fixDIInit();
350
+
351
+        $sql  = 'DELETE FROM `*PREFIX*preferences` '.
352
+                'WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?';
353
+        $this->connection->executeUpdate($sql, [$userId, $appName, $key]);
354
+
355
+        if (isset($this->userCache[$userId]) and isset($this->userCache[$userId][$appName])) {
356
+            unset($this->userCache[$userId][$appName][$key]);
357
+        }
358
+    }
359
+
360
+    /**
361
+     * Delete all user values
362
+     *
363
+     * @param string $userId the userId of the user that we want to remove all values from
364
+     */
365
+    public function deleteAllUserValues($userId) {
366
+        // TODO - FIXME
367
+        $this->fixDIInit();
368
+
369
+        $sql  = 'DELETE FROM `*PREFIX*preferences` '.
370
+            'WHERE `userid` = ?';
371
+        $this->connection->executeUpdate($sql, [$userId]);
372
+
373
+        unset($this->userCache[$userId]);
374
+    }
375
+
376
+    /**
377
+     * Delete all user related values of one app
378
+     *
379
+     * @param string $appName the appName of the app that we want to remove all values from
380
+     */
381
+    public function deleteAppFromAllUsers($appName) {
382
+        // TODO - FIXME
383
+        $this->fixDIInit();
384
+
385
+        $sql  = 'DELETE FROM `*PREFIX*preferences` '.
386
+                'WHERE `appid` = ?';
387
+        $this->connection->executeUpdate($sql, [$appName]);
388
+
389
+        foreach ($this->userCache as &$userCache) {
390
+            unset($userCache[$appName]);
391
+        }
392
+    }
393
+
394
+    /**
395
+     * Returns all user configs sorted by app of one user
396
+     *
397
+     * @param string $userId the user ID to get the app configs from
398
+     * @return array[] - 2 dimensional array with the following structure:
399
+     *     [ $appId =>
400
+     *         [ $key => $value ]
401
+     *     ]
402
+     */
403
+    private function getUserValues($userId) {
404
+        if (isset($this->userCache[$userId])) {
405
+            return $this->userCache[$userId];
406
+        }
407
+        if ($userId === null || $userId === '') {
408
+            $this->userCache[$userId]=[];
409
+            return $this->userCache[$userId];
410
+        }
411
+
412
+        // TODO - FIXME
413
+        $this->fixDIInit();
414
+
415
+        $data = [];
416
+        $query = 'SELECT `appid`, `configkey`, `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ?';
417
+        $result = $this->connection->executeQuery($query, [$userId]);
418
+        while ($row = $result->fetch()) {
419
+            $appId = $row['appid'];
420
+            if (!isset($data[$appId])) {
421
+                $data[$appId] = [];
422
+            }
423
+            $data[$appId][$row['configkey']] = $row['configvalue'];
424
+        }
425
+        $this->userCache[$userId] = $data;
426
+        return $data;
427
+    }
428
+
429
+    /**
430
+     * Fetches a mapped list of userId -> value, for a specified app and key and a list of user IDs.
431
+     *
432
+     * @param string $appName app to get the value for
433
+     * @param string $key the key to get the value for
434
+     * @param array $userIds the user IDs to fetch the values for
435
+     * @return array Mapped values: userId => value
436
+     */
437
+    public function getUserValueForUsers($appName, $key, $userIds) {
438
+        // TODO - FIXME
439
+        $this->fixDIInit();
440
+
441
+        if (empty($userIds) || !is_array($userIds)) {
442
+            return [];
443
+        }
444
+
445
+        $chunkedUsers = array_chunk($userIds, 50, true);
446
+        $placeholders50 = implode(',', array_fill(0, 50, '?'));
447
+
448
+        $userValues = [];
449
+        foreach ($chunkedUsers as $chunk) {
450
+            $queryParams = $chunk;
451
+            // create [$app, $key, $chunkedUsers]
452
+            array_unshift($queryParams, $key);
453
+            array_unshift($queryParams, $appName);
454
+
455
+            $placeholders = (count($chunk) === 50) ? $placeholders50 :  implode(',', array_fill(0, count($chunk), '?'));
456
+
457
+            $query    = 'SELECT `userid`, `configvalue` ' .
458
+                        'FROM `*PREFIX*preferences` ' .
459
+                        'WHERE `appid` = ? AND `configkey` = ? ' .
460
+                        'AND `userid` IN (' . $placeholders . ')';
461
+            $result = $this->connection->executeQuery($query, $queryParams);
462
+
463
+            while ($row = $result->fetch()) {
464
+                $userValues[$row['userid']] = $row['configvalue'];
465
+            }
466
+        }
467
+
468
+        return $userValues;
469
+    }
470
+
471
+    /**
472
+     * Determines the users that have the given value set for a specific app-key-pair
473
+     *
474
+     * @param string $appName the app to get the user for
475
+     * @param string $key the key to get the user for
476
+     * @param string $value the value to get the user for
477
+     * @return array of user IDs
478
+     */
479
+    public function getUsersForUserValue($appName, $key, $value) {
480
+        // TODO - FIXME
481
+        $this->fixDIInit();
482
+
483
+        $sql  = 'SELECT `userid` FROM `*PREFIX*preferences` ' .
484
+                'WHERE `appid` = ? AND `configkey` = ? ';
485
+
486
+        if($this->getSystemValue('dbtype', 'sqlite') === 'oci') {
487
+            //oracle hack: need to explicitly cast CLOB to CHAR for comparison
488
+            $sql .= 'AND to_char(`configvalue`) = ?';
489
+        } else {
490
+            $sql .= 'AND `configvalue` = ?';
491
+        }
492
+
493
+        $result = $this->connection->executeQuery($sql, [$appName, $key, $value]);
494
+
495
+        $userIDs = [];
496
+        while ($row = $result->fetch()) {
497
+            $userIDs[] = $row['userid'];
498
+        }
499
+
500
+        return $userIDs;
501
+    }
502
+
503
+    /**
504
+     * Determines the users that have the given value set for a specific app-key-pair
505
+     *
506
+     * @param string $appName the app to get the user for
507
+     * @param string $key the key to get the user for
508
+     * @param string $value the value to get the user for
509
+     * @return array of user IDs
510
+     */
511
+    public function getUsersForUserValueCaseInsensitive($appName, $key, $value) {
512
+        // TODO - FIXME
513
+        $this->fixDIInit();
514
+
515
+        $sql  = 'SELECT `userid` FROM `*PREFIX*preferences` ' .
516
+            'WHERE `appid` = ? AND `configkey` = ? ';
517
+
518
+        if($this->getSystemValue('dbtype', 'sqlite') === 'oci') {
519
+            //oracle hack: need to explicitly cast CLOB to CHAR for comparison
520
+            $sql .= 'AND LOWER(to_char(`configvalue`)) = LOWER(?)';
521
+        } else {
522
+            $sql .= 'AND LOWER(`configvalue`) = LOWER(?)';
523
+        }
524
+
525
+        $result = $this->connection->executeQuery($sql, [$appName, $key, $value]);
526
+
527
+        $userIDs = [];
528
+        while ($row = $result->fetch()) {
529
+            $userIDs[] = $row['userid'];
530
+        }
531
+
532
+        return $userIDs;
533
+    }
534
+
535
+    public function getSystemConfig() {
536
+        return $this->systemConfig;
537
+    }
538 538
 }
Please login to merge, or discard this patch.
lib/private/Repair/RepairMimeTypes.php 1 patch
Indentation   +174 added lines, -174 removed lines patch added patch discarded remove patch
@@ -36,196 +36,196 @@
 block discarded – undo
36 36
 use OCP\Migration\IRepairStep;
37 37
 
38 38
 class RepairMimeTypes implements IRepairStep {
39
-	/**
40
-	 * @var \OCP\IConfig
41
-	 */
42
-	protected $config;
43
-
44
-	/**
45
-	 * @var int
46
-	 */
47
-	protected $folderMimeTypeId;
48
-
49
-	/**
50
-	 * @param \OCP\IConfig $config
51
-	 */
52
-	public function __construct($config) {
53
-		$this->config = $config;
54
-	}
55
-
56
-	public function getName() {
57
-		return 'Repair mime types';
58
-	}
59
-
60
-	private static function existsStmt() {
61
-		return \OC_DB::prepare('
39
+    /**
40
+     * @var \OCP\IConfig
41
+     */
42
+    protected $config;
43
+
44
+    /**
45
+     * @var int
46
+     */
47
+    protected $folderMimeTypeId;
48
+
49
+    /**
50
+     * @param \OCP\IConfig $config
51
+     */
52
+    public function __construct($config) {
53
+        $this->config = $config;
54
+    }
55
+
56
+    public function getName() {
57
+        return 'Repair mime types';
58
+    }
59
+
60
+    private static function existsStmt() {
61
+        return \OC_DB::prepare('
62 62
 			SELECT count(`mimetype`)
63 63
 			FROM   `*PREFIX*mimetypes`
64 64
 			WHERE  `mimetype` = ?
65 65
 		');
66
-	}
66
+    }
67 67
 
68
-	private static function getIdStmt() {
69
-		return \OC_DB::prepare('
68
+    private static function getIdStmt() {
69
+        return \OC_DB::prepare('
70 70
 			SELECT `id`
71 71
 			FROM   `*PREFIX*mimetypes`
72 72
 			WHERE  `mimetype` = ?
73 73
 		');
74
-	}
74
+    }
75 75
 
76
-	private static function insertStmt() {
77
-		return \OC_DB::prepare('
76
+    private static function insertStmt() {
77
+        return \OC_DB::prepare('
78 78
 			INSERT INTO `*PREFIX*mimetypes` ( `mimetype` )
79 79
 			VALUES ( ? )
80 80
 		');
81
-	}
81
+    }
82 82
 
83
-	private static function updateByNameStmt() {
84
-		return \OC_DB::prepare('
83
+    private static function updateByNameStmt() {
84
+        return \OC_DB::prepare('
85 85
 			UPDATE `*PREFIX*filecache`
86 86
 			SET `mimetype` = ?
87 87
 			WHERE `mimetype` <> ? AND `mimetype` <> ? AND `name` ILIKE ?
88 88
 		');
89
-	}
90
-
91
-	private function updateMimetypes($updatedMimetypes) {
92
-		if (empty($this->folderMimeTypeId)) {
93
-			$result = \OC_DB::executeAudited(self::getIdStmt(), ['httpd/unix-directory']);
94
-			$this->folderMimeTypeId = (int)$result->fetchOne();
95
-		}
96
-
97
-		$count = 0;
98
-		foreach ($updatedMimetypes as $extension => $mimetype) {
99
-			$result = \OC_DB::executeAudited(self::existsStmt(), [$mimetype]);
100
-			$exists = $result->fetchOne();
101
-
102
-			if (!$exists) {
103
-				// insert mimetype
104
-				\OC_DB::executeAudited(self::insertStmt(), [$mimetype]);
105
-			}
106
-
107
-			// get target mimetype id
108
-			$result = \OC_DB::executeAudited(self::getIdStmt(), [$mimetype]);
109
-			$mimetypeId = $result->fetchOne();
110
-
111
-			// change mimetype for files with x extension
112
-			$count += \OC_DB::executeAudited(self::updateByNameStmt(), [$mimetypeId, $this->folderMimeTypeId, $mimetypeId, '%.' . $extension]);
113
-		}
114
-
115
-		return $count;
116
-	}
117
-
118
-	private function introduceImageTypes() {
119
-		$updatedMimetypes = [
120
-			'jp2' => 'image/jp2',
121
-			'webp' => 'image/webp',
122
-		];
123
-
124
-		return $this->updateMimetypes($updatedMimetypes);
125
-	}
126
-
127
-	private function introduceWindowsProgramTypes() {
128
-		$updatedMimetypes = [
129
-			'htaccess' => 'text/plain',
130
-			'bat' => 'application/x-msdos-program',
131
-			'cmd' => 'application/cmd',
132
-		];
133
-
134
-		return $this->updateMimetypes($updatedMimetypes);
135
-	}
136
-
137
-	private function introduceLocationTypes() {
138
-		$updatedMimetypes = [
139
-			'gpx' => 'application/gpx+xml',
140
-			'kml' => 'application/vnd.google-earth.kml+xml',
141
-			'kmz' => 'application/vnd.google-earth.kmz',
142
-			'tcx' => 'application/vnd.garmin.tcx+xml',
143
-		];
144
-
145
-		return $this->updateMimetypes($updatedMimetypes);
146
-	}
147
-
148
-	private function introduceInternetShortcutTypes() {
149
-		$updatedMimetypes = [
150
-			'url' => 'application/internet-shortcut',
151
-			'webloc' => 'application/internet-shortcut'
152
-		];
153
-
154
-		return $this->updateMimetypes($updatedMimetypes);
155
-	}
156
-
157
-	private function introduceStreamingTypes() {
158
-		$updatedMimetypes = [
159
-			'm3u' => 'audio/mpegurl',
160
-			'm3u8' => 'audio/mpegurl',
161
-			'pls' => 'audio/x-scpls'
162
-		];
163
-
164
-		return $this->updateMimetypes($updatedMimetypes);
165
-	}
166
-
167
-	private function introduceVisioTypes() {
168
-		$updatedMimetypes = [
169
-			'vsdm' => 'application/vnd.visio',
170
-			'vsdx' => 'application/vnd.visio',
171
-			'vssm' => 'application/vnd.visio',
172
-			'vssx' => 'application/vnd.visio',
173
-			'vstm' => 'application/vnd.visio',
174
-			'vstx' => 'application/vnd.visio',
175
-		];
176
-
177
-		return $this->updateMimetypes($updatedMimetypes);
178
-	}
179
-
180
-	private function introduceComicbookTypes() {
181
-		$updatedMimetypes = [
182
-			'cb7' => 'application/comicbook+7z',
183
-			'cba' => 'application/comicbook+ace',
184
-			'cbr' => 'application/comicbook+rar',
185
-			'cbt' => 'application/comicbook+tar',
186
-			'cbtc' => 'application/comicbook+truecrypt',
187
-			'cbz' => 'application/comicbook+zip',
188
-		];
189
-
190
-		return $this->updateMimetypes($updatedMimetypes);
191
-	}
192
-
193
-	/**
194
-	 * Fix mime types
195
-	 */
196
-	public function run(IOutput $out) {
197
-
198
-		$ocVersionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0');
199
-
200
-		// NOTE TO DEVELOPERS: when adding new mime types, please make sure to
201
-		// add a version comparison to avoid doing it every time
202
-
203
-		if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.14', '<') && $this->introduceImageTypes()) {
204
-			$out->info('Fixed image mime types');
205
-		}
206
-
207
-		if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.13', '<') && $this->introduceWindowsProgramTypes()) {
208
-			$out->info('Fixed windows program mime types');
209
-		}
210
-
211
-		if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.0', '<') && $this->introduceLocationTypes()) {
212
-			$out->info('Fixed geospatial mime types');
213
-		}
214
-
215
-		if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.3', '<') && $this->introduceInternetShortcutTypes()) {
216
-			$out->info('Fixed internet-shortcut mime types');
217
-		}
218
-
219
-		if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.6', '<') && $this->introduceStreamingTypes()) {
220
-			$out->info('Fixed streaming mime types');
221
-		}
222
-
223
-		if (version_compare($ocVersionFromBeforeUpdate, '14.0.0.8', '<') && $this->introduceVisioTypes()) {
224
-			$out->info('Fixed visio mime types');
225
-		}
226
-
227
-		if (version_compare($ocVersionFromBeforeUpdate, '14.0.0.10', '<') && $this->introduceComicbookTypes()) {
228
-			$out->info('Fixed comicbook mime types');
229
-		}
230
-	}
89
+    }
90
+
91
+    private function updateMimetypes($updatedMimetypes) {
92
+        if (empty($this->folderMimeTypeId)) {
93
+            $result = \OC_DB::executeAudited(self::getIdStmt(), ['httpd/unix-directory']);
94
+            $this->folderMimeTypeId = (int)$result->fetchOne();
95
+        }
96
+
97
+        $count = 0;
98
+        foreach ($updatedMimetypes as $extension => $mimetype) {
99
+            $result = \OC_DB::executeAudited(self::existsStmt(), [$mimetype]);
100
+            $exists = $result->fetchOne();
101
+
102
+            if (!$exists) {
103
+                // insert mimetype
104
+                \OC_DB::executeAudited(self::insertStmt(), [$mimetype]);
105
+            }
106
+
107
+            // get target mimetype id
108
+            $result = \OC_DB::executeAudited(self::getIdStmt(), [$mimetype]);
109
+            $mimetypeId = $result->fetchOne();
110
+
111
+            // change mimetype for files with x extension
112
+            $count += \OC_DB::executeAudited(self::updateByNameStmt(), [$mimetypeId, $this->folderMimeTypeId, $mimetypeId, '%.' . $extension]);
113
+        }
114
+
115
+        return $count;
116
+    }
117
+
118
+    private function introduceImageTypes() {
119
+        $updatedMimetypes = [
120
+            'jp2' => 'image/jp2',
121
+            'webp' => 'image/webp',
122
+        ];
123
+
124
+        return $this->updateMimetypes($updatedMimetypes);
125
+    }
126
+
127
+    private function introduceWindowsProgramTypes() {
128
+        $updatedMimetypes = [
129
+            'htaccess' => 'text/plain',
130
+            'bat' => 'application/x-msdos-program',
131
+            'cmd' => 'application/cmd',
132
+        ];
133
+
134
+        return $this->updateMimetypes($updatedMimetypes);
135
+    }
136
+
137
+    private function introduceLocationTypes() {
138
+        $updatedMimetypes = [
139
+            'gpx' => 'application/gpx+xml',
140
+            'kml' => 'application/vnd.google-earth.kml+xml',
141
+            'kmz' => 'application/vnd.google-earth.kmz',
142
+            'tcx' => 'application/vnd.garmin.tcx+xml',
143
+        ];
144
+
145
+        return $this->updateMimetypes($updatedMimetypes);
146
+    }
147
+
148
+    private function introduceInternetShortcutTypes() {
149
+        $updatedMimetypes = [
150
+            'url' => 'application/internet-shortcut',
151
+            'webloc' => 'application/internet-shortcut'
152
+        ];
153
+
154
+        return $this->updateMimetypes($updatedMimetypes);
155
+    }
156
+
157
+    private function introduceStreamingTypes() {
158
+        $updatedMimetypes = [
159
+            'm3u' => 'audio/mpegurl',
160
+            'm3u8' => 'audio/mpegurl',
161
+            'pls' => 'audio/x-scpls'
162
+        ];
163
+
164
+        return $this->updateMimetypes($updatedMimetypes);
165
+    }
166
+
167
+    private function introduceVisioTypes() {
168
+        $updatedMimetypes = [
169
+            'vsdm' => 'application/vnd.visio',
170
+            'vsdx' => 'application/vnd.visio',
171
+            'vssm' => 'application/vnd.visio',
172
+            'vssx' => 'application/vnd.visio',
173
+            'vstm' => 'application/vnd.visio',
174
+            'vstx' => 'application/vnd.visio',
175
+        ];
176
+
177
+        return $this->updateMimetypes($updatedMimetypes);
178
+    }
179
+
180
+    private function introduceComicbookTypes() {
181
+        $updatedMimetypes = [
182
+            'cb7' => 'application/comicbook+7z',
183
+            'cba' => 'application/comicbook+ace',
184
+            'cbr' => 'application/comicbook+rar',
185
+            'cbt' => 'application/comicbook+tar',
186
+            'cbtc' => 'application/comicbook+truecrypt',
187
+            'cbz' => 'application/comicbook+zip',
188
+        ];
189
+
190
+        return $this->updateMimetypes($updatedMimetypes);
191
+    }
192
+
193
+    /**
194
+     * Fix mime types
195
+     */
196
+    public function run(IOutput $out) {
197
+
198
+        $ocVersionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0');
199
+
200
+        // NOTE TO DEVELOPERS: when adding new mime types, please make sure to
201
+        // add a version comparison to avoid doing it every time
202
+
203
+        if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.14', '<') && $this->introduceImageTypes()) {
204
+            $out->info('Fixed image mime types');
205
+        }
206
+
207
+        if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.13', '<') && $this->introduceWindowsProgramTypes()) {
208
+            $out->info('Fixed windows program mime types');
209
+        }
210
+
211
+        if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.0', '<') && $this->introduceLocationTypes()) {
212
+            $out->info('Fixed geospatial mime types');
213
+        }
214
+
215
+        if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.3', '<') && $this->introduceInternetShortcutTypes()) {
216
+            $out->info('Fixed internet-shortcut mime types');
217
+        }
218
+
219
+        if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.6', '<') && $this->introduceStreamingTypes()) {
220
+            $out->info('Fixed streaming mime types');
221
+        }
222
+
223
+        if (version_compare($ocVersionFromBeforeUpdate, '14.0.0.8', '<') && $this->introduceVisioTypes()) {
224
+            $out->info('Fixed visio mime types');
225
+        }
226
+
227
+        if (version_compare($ocVersionFromBeforeUpdate, '14.0.0.10', '<') && $this->introduceComicbookTypes()) {
228
+            $out->info('Fixed comicbook mime types');
229
+        }
230
+    }
231 231
 }
Please login to merge, or discard this patch.
lib/private/Repair/Collation.php 1 patch
Indentation   +115 added lines, -115 removed lines patch added patch discarded remove patch
@@ -35,119 +35,119 @@
 block discarded – undo
35 35
 use OCP\Migration\IRepairStep;
36 36
 
37 37
 class Collation implements IRepairStep {
38
-	/**  @var IConfig */
39
-	protected $config;
40
-
41
-	/** @var ILogger */
42
-	protected $logger;
43
-
44
-	/** @var IDBConnection */
45
-	protected $connection;
46
-
47
-	/** @var bool */
48
-	protected $ignoreFailures;
49
-
50
-	/**
51
-	 * @param IConfig $config
52
-	 * @param ILogger $logger
53
-	 * @param IDBConnection $connection
54
-	 * @param bool $ignoreFailures
55
-	 */
56
-	public function __construct(IConfig $config, ILogger $logger, IDBConnection $connection, $ignoreFailures) {
57
-		$this->connection = $connection;
58
-		$this->config = $config;
59
-		$this->logger = $logger;
60
-		$this->ignoreFailures = $ignoreFailures;
61
-	}
62
-
63
-	public function getName() {
64
-		return 'Repair MySQL collation';
65
-	}
66
-
67
-	/**
68
-	 * Fix mime types
69
-	 */
70
-	public function run(IOutput $output) {
71
-		if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) {
72
-			$output->info('Not a mysql database -> nothing to do');
73
-			return;
74
-		}
75
-
76
-		$characterSet = $this->config->getSystemValue('mysql.utf8mb4', false) ? 'utf8mb4' : 'utf8';
77
-
78
-		$tables = $this->getAllNonUTF8BinTables($this->connection);
79
-		foreach ($tables as $table) {
80
-			$output->info("Change row format for $table ...");
81
-			$query = $this->connection->prepare('ALTER TABLE `' . $table . '` ROW_FORMAT = DYNAMIC;');
82
-			try {
83
-				$query->execute();
84
-			} catch (DriverException $e) {
85
-				// Just log this
86
-				$this->logger->logException($e);
87
-				if (!$this->ignoreFailures) {
88
-					throw $e;
89
-				}
90
-			}
91
-
92
-			$output->info("Change collation for $table ...");
93
-			if ($characterSet === 'utf8mb4') {
94
-				// need to set row compression first
95
-				$query = $this->connection->prepare('ALTER TABLE `' . $table . '` ROW_FORMAT=COMPRESSED;');
96
-				$query->execute();
97
-			}
98
-			$query = $this->connection->prepare('ALTER TABLE `' . $table . '` CONVERT TO CHARACTER SET ' . $characterSet . ' COLLATE ' . $characterSet . '_bin;');
99
-			try {
100
-				$query->execute();
101
-			} catch (DriverException $e) {
102
-				// Just log this
103
-				$this->logger->logException($e);
104
-				if (!$this->ignoreFailures) {
105
-					throw $e;
106
-				}
107
-			}
108
-		}
109
-		if (empty($tables)) {
110
-			$output->info('All tables already have the correct collation -> nothing to do');
111
-		}
112
-	}
113
-
114
-	/**
115
-	 * @param IDBConnection $connection
116
-	 * @return string[]
117
-	 */
118
-	protected function getAllNonUTF8BinTables(IDBConnection $connection) {
119
-		$dbName = $this->config->getSystemValue("dbname");
120
-		$characterSet = $this->config->getSystemValue('mysql.utf8mb4', false) ? 'utf8mb4' : 'utf8';
121
-
122
-		// fetch tables by columns
123
-		$statement = $connection->executeQuery(
124
-			"SELECT DISTINCT(TABLE_NAME) AS `table`" .
125
-			"	FROM INFORMATION_SCHEMA . COLUMNS" .
126
-			"	WHERE TABLE_SCHEMA = ?" .
127
-			"	AND (COLLATION_NAME <> '" . $characterSet . "_bin' OR CHARACTER_SET_NAME <> '" . $characterSet . "')" .
128
-			"	AND TABLE_NAME LIKE '*PREFIX*%'",
129
-			[$dbName]
130
-		);
131
-		$rows = $statement->fetchAll();
132
-		$result = [];
133
-		foreach ($rows as $row) {
134
-			$result[$row['table']] = true;
135
-		}
136
-
137
-		// fetch tables by collation
138
-		$statement = $connection->executeQuery(
139
-			"SELECT DISTINCT(TABLE_NAME) AS `table`" .
140
-			"	FROM INFORMATION_SCHEMA . TABLES" .
141
-			"	WHERE TABLE_SCHEMA = ?" .
142
-			"	AND TABLE_COLLATION <> '" . $characterSet . "_bin'" .
143
-			"	AND TABLE_NAME LIKE '*PREFIX*%'",
144
-			[$dbName]
145
-		);
146
-		$rows = $statement->fetchAll();
147
-		foreach ($rows as $row) {
148
-			$result[$row['table']] = true;
149
-		}
150
-
151
-		return array_keys($result);
152
-	}
38
+    /**  @var IConfig */
39
+    protected $config;
40
+
41
+    /** @var ILogger */
42
+    protected $logger;
43
+
44
+    /** @var IDBConnection */
45
+    protected $connection;
46
+
47
+    /** @var bool */
48
+    protected $ignoreFailures;
49
+
50
+    /**
51
+     * @param IConfig $config
52
+     * @param ILogger $logger
53
+     * @param IDBConnection $connection
54
+     * @param bool $ignoreFailures
55
+     */
56
+    public function __construct(IConfig $config, ILogger $logger, IDBConnection $connection, $ignoreFailures) {
57
+        $this->connection = $connection;
58
+        $this->config = $config;
59
+        $this->logger = $logger;
60
+        $this->ignoreFailures = $ignoreFailures;
61
+    }
62
+
63
+    public function getName() {
64
+        return 'Repair MySQL collation';
65
+    }
66
+
67
+    /**
68
+     * Fix mime types
69
+     */
70
+    public function run(IOutput $output) {
71
+        if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) {
72
+            $output->info('Not a mysql database -> nothing to do');
73
+            return;
74
+        }
75
+
76
+        $characterSet = $this->config->getSystemValue('mysql.utf8mb4', false) ? 'utf8mb4' : 'utf8';
77
+
78
+        $tables = $this->getAllNonUTF8BinTables($this->connection);
79
+        foreach ($tables as $table) {
80
+            $output->info("Change row format for $table ...");
81
+            $query = $this->connection->prepare('ALTER TABLE `' . $table . '` ROW_FORMAT = DYNAMIC;');
82
+            try {
83
+                $query->execute();
84
+            } catch (DriverException $e) {
85
+                // Just log this
86
+                $this->logger->logException($e);
87
+                if (!$this->ignoreFailures) {
88
+                    throw $e;
89
+                }
90
+            }
91
+
92
+            $output->info("Change collation for $table ...");
93
+            if ($characterSet === 'utf8mb4') {
94
+                // need to set row compression first
95
+                $query = $this->connection->prepare('ALTER TABLE `' . $table . '` ROW_FORMAT=COMPRESSED;');
96
+                $query->execute();
97
+            }
98
+            $query = $this->connection->prepare('ALTER TABLE `' . $table . '` CONVERT TO CHARACTER SET ' . $characterSet . ' COLLATE ' . $characterSet . '_bin;');
99
+            try {
100
+                $query->execute();
101
+            } catch (DriverException $e) {
102
+                // Just log this
103
+                $this->logger->logException($e);
104
+                if (!$this->ignoreFailures) {
105
+                    throw $e;
106
+                }
107
+            }
108
+        }
109
+        if (empty($tables)) {
110
+            $output->info('All tables already have the correct collation -> nothing to do');
111
+        }
112
+    }
113
+
114
+    /**
115
+     * @param IDBConnection $connection
116
+     * @return string[]
117
+     */
118
+    protected function getAllNonUTF8BinTables(IDBConnection $connection) {
119
+        $dbName = $this->config->getSystemValue("dbname");
120
+        $characterSet = $this->config->getSystemValue('mysql.utf8mb4', false) ? 'utf8mb4' : 'utf8';
121
+
122
+        // fetch tables by columns
123
+        $statement = $connection->executeQuery(
124
+            "SELECT DISTINCT(TABLE_NAME) AS `table`" .
125
+            "	FROM INFORMATION_SCHEMA . COLUMNS" .
126
+            "	WHERE TABLE_SCHEMA = ?" .
127
+            "	AND (COLLATION_NAME <> '" . $characterSet . "_bin' OR CHARACTER_SET_NAME <> '" . $characterSet . "')" .
128
+            "	AND TABLE_NAME LIKE '*PREFIX*%'",
129
+            [$dbName]
130
+        );
131
+        $rows = $statement->fetchAll();
132
+        $result = [];
133
+        foreach ($rows as $row) {
134
+            $result[$row['table']] = true;
135
+        }
136
+
137
+        // fetch tables by collation
138
+        $statement = $connection->executeQuery(
139
+            "SELECT DISTINCT(TABLE_NAME) AS `table`" .
140
+            "	FROM INFORMATION_SCHEMA . TABLES" .
141
+            "	WHERE TABLE_SCHEMA = ?" .
142
+            "	AND TABLE_COLLATION <> '" . $characterSet . "_bin'" .
143
+            "	AND TABLE_NAME LIKE '*PREFIX*%'",
144
+            [$dbName]
145
+        );
146
+        $rows = $statement->fetchAll();
147
+        foreach ($rows as $row) {
148
+            $result[$row['table']] = true;
149
+        }
150
+
151
+        return array_keys($result);
152
+    }
153 153
 }
Please login to merge, or discard this patch.
lib/private/Repair/CleanTags.php 1 patch
Indentation   +168 added lines, -168 removed lines patch added patch discarded remove patch
@@ -40,172 +40,172 @@
 block discarded – undo
40 40
  */
41 41
 class CleanTags implements IRepairStep {
42 42
 
43
-	/** @var IDBConnection */
44
-	protected $connection;
45
-
46
-	/** @var IUserManager */
47
-	protected $userManager;
48
-
49
-	protected $deletedTags = 0;
50
-
51
-	/**
52
-	 * @param IDBConnection $connection
53
-	 * @param IUserManager $userManager
54
-	 */
55
-	public function __construct(IDBConnection $connection, IUserManager $userManager) {
56
-		$this->connection = $connection;
57
-		$this->userManager = $userManager;
58
-	}
59
-
60
-	/**
61
-	 * @return string
62
-	 */
63
-	public function getName() {
64
-		return 'Clean tags and favorites';
65
-	}
66
-
67
-	/**
68
-	 * Updates the configuration after running an update
69
-	 */
70
-	public function run(IOutput $output) {
71
-		$this->deleteOrphanTags($output);
72
-		$this->deleteOrphanFileEntries($output);
73
-		$this->deleteOrphanTagEntries($output);
74
-		$this->deleteOrphanCategoryEntries($output);
75
-	}
76
-
77
-	/**
78
-	 * Delete tags for deleted users
79
-	 */
80
-	protected function deleteOrphanTags(IOutput $output) {
81
-		$offset = 0;
82
-		while ($this->checkTags($offset)) {
83
-			$offset += 50;
84
-		}
85
-
86
-		$output->info(sprintf('%d tags of deleted users have been removed.', $this->deletedTags));
87
-	}
88
-
89
-	protected function checkTags($offset) {
90
-		$query = $this->connection->getQueryBuilder();
91
-		$query->select('uid')
92
-			->from('vcategory')
93
-			->groupBy('uid')
94
-			->orderBy('uid')
95
-			->setMaxResults(50)
96
-			->setFirstResult($offset);
97
-		$result = $query->execute();
98
-
99
-		$users = [];
100
-		$hadResults = false;
101
-		while ($row = $result->fetch()) {
102
-			$hadResults = true;
103
-			if (!$this->userManager->userExists($row['uid'])) {
104
-				$users[] = $row['uid'];
105
-			}
106
-		}
107
-		$result->closeCursor();
108
-
109
-		if (!$hadResults) {
110
-			// No more tags, stop looping
111
-			return false;
112
-		}
113
-
114
-		if (!empty($users)) {
115
-			$query = $this->connection->getQueryBuilder();
116
-			$query->delete('vcategory')
117
-				->where($query->expr()->in('uid', $query->createNamedParameter($users, IQueryBuilder::PARAM_STR_ARRAY)));
118
-			$this->deletedTags += $query->execute();
119
-		}
120
-		return true;
121
-	}
122
-
123
-	/**
124
-	 * Delete tag entries for deleted files
125
-	 */
126
-	protected function deleteOrphanFileEntries(IOutput $output) {
127
-		$this->deleteOrphanEntries(
128
-			$output,
129
-			'%d tags for delete files have been removed.',
130
-			'vcategory_to_object', 'objid',
131
-			'filecache', 'fileid', 'path_hash'
132
-		);
133
-	}
134
-
135
-	/**
136
-	 * Delete tag entries for deleted tags
137
-	 */
138
-	protected function deleteOrphanTagEntries(IOutput $output) {
139
-		$this->deleteOrphanEntries(
140
-			$output,
141
-			'%d tag entries for deleted tags have been removed.',
142
-			'vcategory_to_object', 'categoryid',
143
-			'vcategory', 'id', 'uid'
144
-		);
145
-	}
146
-
147
-	/**
148
-	 * Delete tags that have no entries
149
-	 */
150
-	protected function deleteOrphanCategoryEntries(IOutput $output) {
151
-		$this->deleteOrphanEntries(
152
-			$output,
153
-			'%d tags with no entries have been removed.',
154
-			'vcategory', 'id',
155
-			'vcategory_to_object', 'categoryid', 'type'
156
-		);
157
-	}
158
-
159
-	/**
160
-	 * Deletes all entries from $deleteTable that do not have a matching entry in $sourceTable
161
-	 *
162
-	 * A query joins $deleteTable.$deleteId = $sourceTable.$sourceId and checks
163
-	 * whether $sourceNullColumn is null. If it is null, the entry in $deleteTable
164
-	 * is being deleted.
165
-	 *
166
-	 * @param string $repairInfo
167
-	 * @param string $deleteTable
168
-	 * @param string $deleteId
169
-	 * @param string $sourceTable
170
-	 * @param string $sourceId
171
-	 * @param string $sourceNullColumn	If this column is null in the source table,
172
-	 * 								the entry is deleted in the $deleteTable
173
-	 * @suppress SqlInjectionChecker
174
-	 */
175
-	protected function deleteOrphanEntries(IOutput $output, $repairInfo, $deleteTable, $deleteId, $sourceTable, $sourceId, $sourceNullColumn) {
176
-		$qb = $this->connection->getQueryBuilder();
177
-
178
-		$qb->select('d.' . $deleteId)
179
-			->from($deleteTable, 'd')
180
-			->leftJoin('d', $sourceTable, 's', $qb->expr()->eq('d.' . $deleteId, 's.' . $sourceId))
181
-			->where(
182
-				$qb->expr()->eq('d.type', $qb->expr()->literal('files'))
183
-			)
184
-			->andWhere(
185
-				$qb->expr()->isNull('s.' . $sourceNullColumn)
186
-			);
187
-		$result = $qb->execute();
188
-
189
-		$orphanItems = [];
190
-		while ($row = $result->fetch()) {
191
-			$orphanItems[] = (int) $row[$deleteId];
192
-		}
193
-
194
-		if (!empty($orphanItems)) {
195
-			$orphanItemsBatch = array_chunk($orphanItems, 200);
196
-			foreach ($orphanItemsBatch as $items) {
197
-				$qb->delete($deleteTable)
198
-					->where(
199
-						$qb->expr()->eq('type', $qb->expr()->literal('files'))
200
-					)
201
-					->andWhere($qb->expr()->in($deleteId, $qb->createParameter('ids')));
202
-				$qb->setParameter('ids', $items, IQueryBuilder::PARAM_INT_ARRAY);
203
-				$qb->execute();
204
-			}
205
-		}
206
-
207
-		if ($repairInfo) {
208
-			$output->info(sprintf($repairInfo, count($orphanItems)));
209
-		}
210
-	}
43
+    /** @var IDBConnection */
44
+    protected $connection;
45
+
46
+    /** @var IUserManager */
47
+    protected $userManager;
48
+
49
+    protected $deletedTags = 0;
50
+
51
+    /**
52
+     * @param IDBConnection $connection
53
+     * @param IUserManager $userManager
54
+     */
55
+    public function __construct(IDBConnection $connection, IUserManager $userManager) {
56
+        $this->connection = $connection;
57
+        $this->userManager = $userManager;
58
+    }
59
+
60
+    /**
61
+     * @return string
62
+     */
63
+    public function getName() {
64
+        return 'Clean tags and favorites';
65
+    }
66
+
67
+    /**
68
+     * Updates the configuration after running an update
69
+     */
70
+    public function run(IOutput $output) {
71
+        $this->deleteOrphanTags($output);
72
+        $this->deleteOrphanFileEntries($output);
73
+        $this->deleteOrphanTagEntries($output);
74
+        $this->deleteOrphanCategoryEntries($output);
75
+    }
76
+
77
+    /**
78
+     * Delete tags for deleted users
79
+     */
80
+    protected function deleteOrphanTags(IOutput $output) {
81
+        $offset = 0;
82
+        while ($this->checkTags($offset)) {
83
+            $offset += 50;
84
+        }
85
+
86
+        $output->info(sprintf('%d tags of deleted users have been removed.', $this->deletedTags));
87
+    }
88
+
89
+    protected function checkTags($offset) {
90
+        $query = $this->connection->getQueryBuilder();
91
+        $query->select('uid')
92
+            ->from('vcategory')
93
+            ->groupBy('uid')
94
+            ->orderBy('uid')
95
+            ->setMaxResults(50)
96
+            ->setFirstResult($offset);
97
+        $result = $query->execute();
98
+
99
+        $users = [];
100
+        $hadResults = false;
101
+        while ($row = $result->fetch()) {
102
+            $hadResults = true;
103
+            if (!$this->userManager->userExists($row['uid'])) {
104
+                $users[] = $row['uid'];
105
+            }
106
+        }
107
+        $result->closeCursor();
108
+
109
+        if (!$hadResults) {
110
+            // No more tags, stop looping
111
+            return false;
112
+        }
113
+
114
+        if (!empty($users)) {
115
+            $query = $this->connection->getQueryBuilder();
116
+            $query->delete('vcategory')
117
+                ->where($query->expr()->in('uid', $query->createNamedParameter($users, IQueryBuilder::PARAM_STR_ARRAY)));
118
+            $this->deletedTags += $query->execute();
119
+        }
120
+        return true;
121
+    }
122
+
123
+    /**
124
+     * Delete tag entries for deleted files
125
+     */
126
+    protected function deleteOrphanFileEntries(IOutput $output) {
127
+        $this->deleteOrphanEntries(
128
+            $output,
129
+            '%d tags for delete files have been removed.',
130
+            'vcategory_to_object', 'objid',
131
+            'filecache', 'fileid', 'path_hash'
132
+        );
133
+    }
134
+
135
+    /**
136
+     * Delete tag entries for deleted tags
137
+     */
138
+    protected function deleteOrphanTagEntries(IOutput $output) {
139
+        $this->deleteOrphanEntries(
140
+            $output,
141
+            '%d tag entries for deleted tags have been removed.',
142
+            'vcategory_to_object', 'categoryid',
143
+            'vcategory', 'id', 'uid'
144
+        );
145
+    }
146
+
147
+    /**
148
+     * Delete tags that have no entries
149
+     */
150
+    protected function deleteOrphanCategoryEntries(IOutput $output) {
151
+        $this->deleteOrphanEntries(
152
+            $output,
153
+            '%d tags with no entries have been removed.',
154
+            'vcategory', 'id',
155
+            'vcategory_to_object', 'categoryid', 'type'
156
+        );
157
+    }
158
+
159
+    /**
160
+     * Deletes all entries from $deleteTable that do not have a matching entry in $sourceTable
161
+     *
162
+     * A query joins $deleteTable.$deleteId = $sourceTable.$sourceId and checks
163
+     * whether $sourceNullColumn is null. If it is null, the entry in $deleteTable
164
+     * is being deleted.
165
+     *
166
+     * @param string $repairInfo
167
+     * @param string $deleteTable
168
+     * @param string $deleteId
169
+     * @param string $sourceTable
170
+     * @param string $sourceId
171
+     * @param string $sourceNullColumn	If this column is null in the source table,
172
+     * 								the entry is deleted in the $deleteTable
173
+     * @suppress SqlInjectionChecker
174
+     */
175
+    protected function deleteOrphanEntries(IOutput $output, $repairInfo, $deleteTable, $deleteId, $sourceTable, $sourceId, $sourceNullColumn) {
176
+        $qb = $this->connection->getQueryBuilder();
177
+
178
+        $qb->select('d.' . $deleteId)
179
+            ->from($deleteTable, 'd')
180
+            ->leftJoin('d', $sourceTable, 's', $qb->expr()->eq('d.' . $deleteId, 's.' . $sourceId))
181
+            ->where(
182
+                $qb->expr()->eq('d.type', $qb->expr()->literal('files'))
183
+            )
184
+            ->andWhere(
185
+                $qb->expr()->isNull('s.' . $sourceNullColumn)
186
+            );
187
+        $result = $qb->execute();
188
+
189
+        $orphanItems = [];
190
+        while ($row = $result->fetch()) {
191
+            $orphanItems[] = (int) $row[$deleteId];
192
+        }
193
+
194
+        if (!empty($orphanItems)) {
195
+            $orphanItemsBatch = array_chunk($orphanItems, 200);
196
+            foreach ($orphanItemsBatch as $items) {
197
+                $qb->delete($deleteTable)
198
+                    ->where(
199
+                        $qb->expr()->eq('type', $qb->expr()->literal('files'))
200
+                    )
201
+                    ->andWhere($qb->expr()->in($deleteId, $qb->createParameter('ids')));
202
+                $qb->setParameter('ids', $items, IQueryBuilder::PARAM_INT_ARRAY);
203
+                $qb->execute();
204
+            }
205
+        }
206
+
207
+        if ($repairInfo) {
208
+            $output->info(sprintf($repairInfo, count($orphanItems)));
209
+        }
210
+    }
211 211
 }
Please login to merge, or discard this patch.
lib/private/Share20/DefaultShareProvider.php 1 patch
Indentation   +1405 added lines, -1405 removed lines patch added patch discarded remove patch
@@ -63,1445 +63,1445 @@
 block discarded – undo
63 63
  */
64 64
 class DefaultShareProvider implements IShareProvider {
65 65
 
66
-	// Special share type for user modified group shares
67
-	const SHARE_TYPE_USERGROUP = 2;
68
-
69
-	/** @var IDBConnection */
70
-	private $dbConn;
71
-
72
-	/** @var IUserManager */
73
-	private $userManager;
74
-
75
-	/** @var IGroupManager */
76
-	private $groupManager;
77
-
78
-	/** @var IRootFolder */
79
-	private $rootFolder;
80
-
81
-	/** @var IMailer */
82
-	private $mailer;
83
-
84
-	/** @var Defaults */
85
-	private $defaults;
86
-
87
-	/** @var IL10N */
88
-	private $l;
89
-
90
-	/** @var IURLGenerator */
91
-	private $urlGenerator;
92
-
93
-	/**
94
-	 * DefaultShareProvider constructor.
95
-	 *
96
-	 * @param IDBConnection $connection
97
-	 * @param IUserManager $userManager
98
-	 * @param IGroupManager $groupManager
99
-	 * @param IRootFolder $rootFolder
100
-	 * @param IMailer $mailer ;
101
-	 * @param Defaults $defaults
102
-	 * @param IL10N $l
103
-	 * @param IURLGenerator $urlGenerator
104
-	 */
105
-	public function __construct(
106
-			IDBConnection $connection,
107
-			IUserManager $userManager,
108
-			IGroupManager $groupManager,
109
-			IRootFolder $rootFolder,
110
-			IMailer $mailer,
111
-			Defaults $defaults,
112
-			IL10N $l,
113
-			IURLGenerator $urlGenerator) {
114
-		$this->dbConn = $connection;
115
-		$this->userManager = $userManager;
116
-		$this->groupManager = $groupManager;
117
-		$this->rootFolder = $rootFolder;
118
-		$this->mailer = $mailer;
119
-		$this->defaults = $defaults;
120
-		$this->l = $l;
121
-		$this->urlGenerator = $urlGenerator;
122
-	}
123
-
124
-	/**
125
-	 * Return the identifier of this provider.
126
-	 *
127
-	 * @return string Containing only [a-zA-Z0-9]
128
-	 */
129
-	public function identifier() {
130
-		return 'ocinternal';
131
-	}
132
-
133
-	/**
134
-	 * Share a path
135
-	 *
136
-	 * @param \OCP\Share\IShare $share
137
-	 * @return \OCP\Share\IShare The share object
138
-	 * @throws ShareNotFound
139
-	 * @throws \Exception
140
-	 */
141
-	public function create(\OCP\Share\IShare $share) {
142
-		$qb = $this->dbConn->getQueryBuilder();
143
-
144
-		$qb->insert('share');
145
-		$qb->setValue('share_type', $qb->createNamedParameter($share->getShareType()));
146
-
147
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
148
-			//Set the UID of the user we share with
149
-			$qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
150
-			$qb->setValue('accepted', $qb->createNamedParameter(IShare::STATUS_PENDING));
151
-
152
-			//If an expiration date is set store it
153
-			if ($share->getExpirationDate() !== null) {
154
-				$qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
155
-			}
156
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
157
-			//Set the GID of the group we share with
158
-			$qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
159
-
160
-			//If an expiration date is set store it
161
-			if ($share->getExpirationDate() !== null) {
162
-				$qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
163
-			}
164
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
165
-			//set label for public link
166
-			$qb->setValue('label', $qb->createNamedParameter($share->getLabel()));
167
-			//Set the token of the share
168
-			$qb->setValue('token', $qb->createNamedParameter($share->getToken()));
169
-
170
-			//If a password is set store it
171
-			if ($share->getPassword() !== null) {
172
-				$qb->setValue('password', $qb->createNamedParameter($share->getPassword()));
173
-			}
174
-
175
-			$qb->setValue('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL));
176
-
177
-			//If an expiration date is set store it
178
-			if ($share->getExpirationDate() !== null) {
179
-				$qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
180
-			}
181
-
182
-			if (method_exists($share, 'getParent')) {
183
-				$qb->setValue('parent', $qb->createNamedParameter($share->getParent()));
184
-			}
185
-		} else {
186
-			throw new \Exception('invalid share type!');
187
-		}
188
-
189
-		// Set what is shares
190
-		$qb->setValue('item_type', $qb->createParameter('itemType'));
191
-		if ($share->getNode() instanceof \OCP\Files\File) {
192
-			$qb->setParameter('itemType', 'file');
193
-		} else {
194
-			$qb->setParameter('itemType', 'folder');
195
-		}
196
-
197
-		// Set the file id
198
-		$qb->setValue('item_source', $qb->createNamedParameter($share->getNode()->getId()));
199
-		$qb->setValue('file_source', $qb->createNamedParameter($share->getNode()->getId()));
200
-
201
-		// set the permissions
202
-		$qb->setValue('permissions', $qb->createNamedParameter($share->getPermissions()));
203
-
204
-		// Set who created this share
205
-		$qb->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()));
206
-
207
-		// Set who is the owner of this file/folder (and this the owner of the share)
208
-		$qb->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner()));
209
-
210
-		// Set the file target
211
-		$qb->setValue('file_target', $qb->createNamedParameter($share->getTarget()));
212
-
213
-		// Set the time this share was created
214
-		$qb->setValue('stime', $qb->createNamedParameter(time()));
215
-
216
-		// insert the data and fetch the id of the share
217
-		$this->dbConn->beginTransaction();
218
-		$qb->execute();
219
-		$id = $this->dbConn->lastInsertId('*PREFIX*share');
220
-
221
-		// Now fetch the inserted share and create a complete share object
222
-		$qb = $this->dbConn->getQueryBuilder();
223
-		$qb->select('*')
224
-			->from('share')
225
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
226
-
227
-		$cursor = $qb->execute();
228
-		$data = $cursor->fetch();
229
-		$this->dbConn->commit();
230
-		$cursor->closeCursor();
231
-
232
-		if ($data === false) {
233
-			throw new ShareNotFound();
234
-		}
235
-
236
-		$mailSendValue = $share->getMailSend();
237
-		$data['mail_send'] = ($mailSendValue === null) ? true : $mailSendValue;
238
-
239
-		$share = $this->createShare($data);
240
-		return $share;
241
-	}
242
-
243
-	/**
244
-	 * Update a share
245
-	 *
246
-	 * @param \OCP\Share\IShare $share
247
-	 * @return \OCP\Share\IShare The share object
248
-	 * @throws ShareNotFound
249
-	 * @throws \OCP\Files\InvalidPathException
250
-	 * @throws \OCP\Files\NotFoundException
251
-	 */
252
-	public function update(\OCP\Share\IShare $share) {
253
-
254
-		$originalShare = $this->getShareById($share->getId());
255
-
256
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
257
-			/*
66
+    // Special share type for user modified group shares
67
+    const SHARE_TYPE_USERGROUP = 2;
68
+
69
+    /** @var IDBConnection */
70
+    private $dbConn;
71
+
72
+    /** @var IUserManager */
73
+    private $userManager;
74
+
75
+    /** @var IGroupManager */
76
+    private $groupManager;
77
+
78
+    /** @var IRootFolder */
79
+    private $rootFolder;
80
+
81
+    /** @var IMailer */
82
+    private $mailer;
83
+
84
+    /** @var Defaults */
85
+    private $defaults;
86
+
87
+    /** @var IL10N */
88
+    private $l;
89
+
90
+    /** @var IURLGenerator */
91
+    private $urlGenerator;
92
+
93
+    /**
94
+     * DefaultShareProvider constructor.
95
+     *
96
+     * @param IDBConnection $connection
97
+     * @param IUserManager $userManager
98
+     * @param IGroupManager $groupManager
99
+     * @param IRootFolder $rootFolder
100
+     * @param IMailer $mailer ;
101
+     * @param Defaults $defaults
102
+     * @param IL10N $l
103
+     * @param IURLGenerator $urlGenerator
104
+     */
105
+    public function __construct(
106
+            IDBConnection $connection,
107
+            IUserManager $userManager,
108
+            IGroupManager $groupManager,
109
+            IRootFolder $rootFolder,
110
+            IMailer $mailer,
111
+            Defaults $defaults,
112
+            IL10N $l,
113
+            IURLGenerator $urlGenerator) {
114
+        $this->dbConn = $connection;
115
+        $this->userManager = $userManager;
116
+        $this->groupManager = $groupManager;
117
+        $this->rootFolder = $rootFolder;
118
+        $this->mailer = $mailer;
119
+        $this->defaults = $defaults;
120
+        $this->l = $l;
121
+        $this->urlGenerator = $urlGenerator;
122
+    }
123
+
124
+    /**
125
+     * Return the identifier of this provider.
126
+     *
127
+     * @return string Containing only [a-zA-Z0-9]
128
+     */
129
+    public function identifier() {
130
+        return 'ocinternal';
131
+    }
132
+
133
+    /**
134
+     * Share a path
135
+     *
136
+     * @param \OCP\Share\IShare $share
137
+     * @return \OCP\Share\IShare The share object
138
+     * @throws ShareNotFound
139
+     * @throws \Exception
140
+     */
141
+    public function create(\OCP\Share\IShare $share) {
142
+        $qb = $this->dbConn->getQueryBuilder();
143
+
144
+        $qb->insert('share');
145
+        $qb->setValue('share_type', $qb->createNamedParameter($share->getShareType()));
146
+
147
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
148
+            //Set the UID of the user we share with
149
+            $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
150
+            $qb->setValue('accepted', $qb->createNamedParameter(IShare::STATUS_PENDING));
151
+
152
+            //If an expiration date is set store it
153
+            if ($share->getExpirationDate() !== null) {
154
+                $qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
155
+            }
156
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
157
+            //Set the GID of the group we share with
158
+            $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
159
+
160
+            //If an expiration date is set store it
161
+            if ($share->getExpirationDate() !== null) {
162
+                $qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
163
+            }
164
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
165
+            //set label for public link
166
+            $qb->setValue('label', $qb->createNamedParameter($share->getLabel()));
167
+            //Set the token of the share
168
+            $qb->setValue('token', $qb->createNamedParameter($share->getToken()));
169
+
170
+            //If a password is set store it
171
+            if ($share->getPassword() !== null) {
172
+                $qb->setValue('password', $qb->createNamedParameter($share->getPassword()));
173
+            }
174
+
175
+            $qb->setValue('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL));
176
+
177
+            //If an expiration date is set store it
178
+            if ($share->getExpirationDate() !== null) {
179
+                $qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
180
+            }
181
+
182
+            if (method_exists($share, 'getParent')) {
183
+                $qb->setValue('parent', $qb->createNamedParameter($share->getParent()));
184
+            }
185
+        } else {
186
+            throw new \Exception('invalid share type!');
187
+        }
188
+
189
+        // Set what is shares
190
+        $qb->setValue('item_type', $qb->createParameter('itemType'));
191
+        if ($share->getNode() instanceof \OCP\Files\File) {
192
+            $qb->setParameter('itemType', 'file');
193
+        } else {
194
+            $qb->setParameter('itemType', 'folder');
195
+        }
196
+
197
+        // Set the file id
198
+        $qb->setValue('item_source', $qb->createNamedParameter($share->getNode()->getId()));
199
+        $qb->setValue('file_source', $qb->createNamedParameter($share->getNode()->getId()));
200
+
201
+        // set the permissions
202
+        $qb->setValue('permissions', $qb->createNamedParameter($share->getPermissions()));
203
+
204
+        // Set who created this share
205
+        $qb->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()));
206
+
207
+        // Set who is the owner of this file/folder (and this the owner of the share)
208
+        $qb->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner()));
209
+
210
+        // Set the file target
211
+        $qb->setValue('file_target', $qb->createNamedParameter($share->getTarget()));
212
+
213
+        // Set the time this share was created
214
+        $qb->setValue('stime', $qb->createNamedParameter(time()));
215
+
216
+        // insert the data and fetch the id of the share
217
+        $this->dbConn->beginTransaction();
218
+        $qb->execute();
219
+        $id = $this->dbConn->lastInsertId('*PREFIX*share');
220
+
221
+        // Now fetch the inserted share and create a complete share object
222
+        $qb = $this->dbConn->getQueryBuilder();
223
+        $qb->select('*')
224
+            ->from('share')
225
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
226
+
227
+        $cursor = $qb->execute();
228
+        $data = $cursor->fetch();
229
+        $this->dbConn->commit();
230
+        $cursor->closeCursor();
231
+
232
+        if ($data === false) {
233
+            throw new ShareNotFound();
234
+        }
235
+
236
+        $mailSendValue = $share->getMailSend();
237
+        $data['mail_send'] = ($mailSendValue === null) ? true : $mailSendValue;
238
+
239
+        $share = $this->createShare($data);
240
+        return $share;
241
+    }
242
+
243
+    /**
244
+     * Update a share
245
+     *
246
+     * @param \OCP\Share\IShare $share
247
+     * @return \OCP\Share\IShare The share object
248
+     * @throws ShareNotFound
249
+     * @throws \OCP\Files\InvalidPathException
250
+     * @throws \OCP\Files\NotFoundException
251
+     */
252
+    public function update(\OCP\Share\IShare $share) {
253
+
254
+        $originalShare = $this->getShareById($share->getId());
255
+
256
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
257
+            /*
258 258
 			 * We allow updating the recipient on user shares.
259 259
 			 */
260
-			$qb = $this->dbConn->getQueryBuilder();
261
-			$qb->update('share')
262
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
263
-				->set('share_with', $qb->createNamedParameter($share->getSharedWith()))
264
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
265
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
266
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
267
-				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
268
-				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
269
-				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
270
-				->set('note', $qb->createNamedParameter($share->getNote()))
271
-				->set('accepted', $qb->createNamedParameter($share->getStatus()))
272
-				->execute();
273
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
274
-			$qb = $this->dbConn->getQueryBuilder();
275
-			$qb->update('share')
276
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
277
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
278
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
279
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
280
-				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
281
-				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
282
-				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
283
-				->set('note', $qb->createNamedParameter($share->getNote()))
284
-				->execute();
285
-
286
-			/*
260
+            $qb = $this->dbConn->getQueryBuilder();
261
+            $qb->update('share')
262
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
263
+                ->set('share_with', $qb->createNamedParameter($share->getSharedWith()))
264
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
265
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
266
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
267
+                ->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
268
+                ->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
269
+                ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
270
+                ->set('note', $qb->createNamedParameter($share->getNote()))
271
+                ->set('accepted', $qb->createNamedParameter($share->getStatus()))
272
+                ->execute();
273
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
274
+            $qb = $this->dbConn->getQueryBuilder();
275
+            $qb->update('share')
276
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
277
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
278
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
279
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
280
+                ->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
281
+                ->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
282
+                ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
283
+                ->set('note', $qb->createNamedParameter($share->getNote()))
284
+                ->execute();
285
+
286
+            /*
287 287
 			 * Update all user defined group shares
288 288
 			 */
289
-			$qb = $this->dbConn->getQueryBuilder();
290
-			$qb->update('share')
291
-				->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
292
-				->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
293
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
294
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
295
-				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
296
-				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
297
-				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
298
-				->set('note', $qb->createNamedParameter($share->getNote()))
299
-				->execute();
300
-
301
-			/*
289
+            $qb = $this->dbConn->getQueryBuilder();
290
+            $qb->update('share')
291
+                ->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
292
+                ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
293
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
294
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
295
+                ->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
296
+                ->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
297
+                ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
298
+                ->set('note', $qb->createNamedParameter($share->getNote()))
299
+                ->execute();
300
+
301
+            /*
302 302
 			 * Now update the permissions for all children that have not set it to 0
303 303
 			 */
304
-			$qb = $this->dbConn->getQueryBuilder();
305
-			$qb->update('share')
306
-				->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
307
-				->andWhere($qb->expr()->neq('permissions', $qb->createNamedParameter(0)))
308
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
309
-				->execute();
310
-
311
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
312
-			$qb = $this->dbConn->getQueryBuilder();
313
-			$qb->update('share')
314
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
315
-				->set('password', $qb->createNamedParameter($share->getPassword()))
316
-				->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
317
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
318
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
319
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
320
-				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
321
-				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
322
-				->set('token', $qb->createNamedParameter($share->getToken()))
323
-				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
324
-				->set('note', $qb->createNamedParameter($share->getNote()))
325
-				->set('label', $qb->createNamedParameter($share->getLabel()))
326
-				->set('hide_download', $qb->createNamedParameter($share->getHideDownload() ? 1 : 0), IQueryBuilder::PARAM_INT)
327
-				->execute();
328
-		}
329
-
330
-		if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
331
-			$this->propagateNote($share);
332
-		}
333
-
334
-
335
-		return $share;
336
-	}
337
-
338
-	/**
339
-	 * Accept a share.
340
-	 *
341
-	 * @param IShare $share
342
-	 * @param string $recipient
343
-	 * @return IShare The share object
344
-	 * @since 9.0.0
345
-	 */
346
-	public function acceptShare(IShare $share, string $recipient): IShare {
347
-		if ($share->getShareType() === IShare::TYPE_GROUP) {
348
-			$group = $this->groupManager->get($share->getSharedWith());
349
-			$user = $this->userManager->get($recipient);
350
-
351
-			if (is_null($group)) {
352
-				throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
353
-			}
354
-
355
-			if (!$group->inGroup($user)) {
356
-				throw new ProviderException('Recipient not in receiving group');
357
-			}
358
-
359
-			// Try to fetch user specific share
360
-			$qb = $this->dbConn->getQueryBuilder();
361
-			$stmt = $qb->select('*')
362
-				->from('share')
363
-				->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
364
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
365
-				->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
366
-				->andWhere($qb->expr()->orX(
367
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
368
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
369
-				))
370
-				->execute();
371
-
372
-			$data = $stmt->fetch();
373
-			$stmt->closeCursor();
374
-
375
-			/*
304
+            $qb = $this->dbConn->getQueryBuilder();
305
+            $qb->update('share')
306
+                ->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
307
+                ->andWhere($qb->expr()->neq('permissions', $qb->createNamedParameter(0)))
308
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
309
+                ->execute();
310
+
311
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
312
+            $qb = $this->dbConn->getQueryBuilder();
313
+            $qb->update('share')
314
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
315
+                ->set('password', $qb->createNamedParameter($share->getPassword()))
316
+                ->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
317
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
318
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
319
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
320
+                ->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
321
+                ->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
322
+                ->set('token', $qb->createNamedParameter($share->getToken()))
323
+                ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
324
+                ->set('note', $qb->createNamedParameter($share->getNote()))
325
+                ->set('label', $qb->createNamedParameter($share->getLabel()))
326
+                ->set('hide_download', $qb->createNamedParameter($share->getHideDownload() ? 1 : 0), IQueryBuilder::PARAM_INT)
327
+                ->execute();
328
+        }
329
+
330
+        if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
331
+            $this->propagateNote($share);
332
+        }
333
+
334
+
335
+        return $share;
336
+    }
337
+
338
+    /**
339
+     * Accept a share.
340
+     *
341
+     * @param IShare $share
342
+     * @param string $recipient
343
+     * @return IShare The share object
344
+     * @since 9.0.0
345
+     */
346
+    public function acceptShare(IShare $share, string $recipient): IShare {
347
+        if ($share->getShareType() === IShare::TYPE_GROUP) {
348
+            $group = $this->groupManager->get($share->getSharedWith());
349
+            $user = $this->userManager->get($recipient);
350
+
351
+            if (is_null($group)) {
352
+                throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
353
+            }
354
+
355
+            if (!$group->inGroup($user)) {
356
+                throw new ProviderException('Recipient not in receiving group');
357
+            }
358
+
359
+            // Try to fetch user specific share
360
+            $qb = $this->dbConn->getQueryBuilder();
361
+            $stmt = $qb->select('*')
362
+                ->from('share')
363
+                ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
364
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
365
+                ->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
366
+                ->andWhere($qb->expr()->orX(
367
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
368
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
369
+                ))
370
+                ->execute();
371
+
372
+            $data = $stmt->fetch();
373
+            $stmt->closeCursor();
374
+
375
+            /*
376 376
 			 * Check if there already is a user specific group share.
377 377
 			 * If there is update it (if required).
378 378
 			 */
379
-			if ($data === false) {
380
-				$id = $this->createUserSpecificGroupShare($share, $recipient);
381
-			} else {
382
-				$id = $data['id'];
383
-			}
384
-
385
-		} else if ($share->getShareType() === IShare::TYPE_USER) {
386
-			if ($share->getSharedWith() !== $recipient) {
387
-				throw new ProviderException('Recipient does not match');
388
-			}
389
-
390
-			$id = $share->getId();
391
-		} else {
392
-			throw new ProviderException('Invalid shareType');
393
-		}
394
-
395
-		$qb = $this->dbConn->getQueryBuilder();
396
-		$qb->update('share')
397
-			->set('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED))
398
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
399
-			->execute();
400
-
401
-		return $share;
402
-	}
403
-
404
-	/**
405
-	 * Get all children of this share
406
-	 * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
407
-	 *
408
-	 * @param \OCP\Share\IShare $parent
409
-	 * @return \OCP\Share\IShare[]
410
-	 */
411
-	public function getChildren(\OCP\Share\IShare $parent) {
412
-		$children = [];
413
-
414
-		$qb = $this->dbConn->getQueryBuilder();
415
-		$qb->select('*')
416
-			->from('share')
417
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
418
-			->andWhere(
419
-				$qb->expr()->in(
420
-					'share_type',
421
-					$qb->createNamedParameter([
422
-						\OCP\Share::SHARE_TYPE_USER,
423
-						\OCP\Share::SHARE_TYPE_GROUP,
424
-						\OCP\Share::SHARE_TYPE_LINK,
425
-					], IQueryBuilder::PARAM_INT_ARRAY)
426
-				)
427
-			)
428
-			->andWhere($qb->expr()->orX(
429
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
430
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
431
-			))
432
-			->orderBy('id');
433
-
434
-		$cursor = $qb->execute();
435
-		while($data = $cursor->fetch()) {
436
-			$children[] = $this->createShare($data);
437
-		}
438
-		$cursor->closeCursor();
439
-
440
-		return $children;
441
-	}
442
-
443
-	/**
444
-	 * Delete a share
445
-	 *
446
-	 * @param \OCP\Share\IShare $share
447
-	 */
448
-	public function delete(\OCP\Share\IShare $share) {
449
-		$qb = $this->dbConn->getQueryBuilder();
450
-		$qb->delete('share')
451
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())));
452
-
453
-		/*
379
+            if ($data === false) {
380
+                $id = $this->createUserSpecificGroupShare($share, $recipient);
381
+            } else {
382
+                $id = $data['id'];
383
+            }
384
+
385
+        } else if ($share->getShareType() === IShare::TYPE_USER) {
386
+            if ($share->getSharedWith() !== $recipient) {
387
+                throw new ProviderException('Recipient does not match');
388
+            }
389
+
390
+            $id = $share->getId();
391
+        } else {
392
+            throw new ProviderException('Invalid shareType');
393
+        }
394
+
395
+        $qb = $this->dbConn->getQueryBuilder();
396
+        $qb->update('share')
397
+            ->set('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED))
398
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
399
+            ->execute();
400
+
401
+        return $share;
402
+    }
403
+
404
+    /**
405
+     * Get all children of this share
406
+     * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
407
+     *
408
+     * @param \OCP\Share\IShare $parent
409
+     * @return \OCP\Share\IShare[]
410
+     */
411
+    public function getChildren(\OCP\Share\IShare $parent) {
412
+        $children = [];
413
+
414
+        $qb = $this->dbConn->getQueryBuilder();
415
+        $qb->select('*')
416
+            ->from('share')
417
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
418
+            ->andWhere(
419
+                $qb->expr()->in(
420
+                    'share_type',
421
+                    $qb->createNamedParameter([
422
+                        \OCP\Share::SHARE_TYPE_USER,
423
+                        \OCP\Share::SHARE_TYPE_GROUP,
424
+                        \OCP\Share::SHARE_TYPE_LINK,
425
+                    ], IQueryBuilder::PARAM_INT_ARRAY)
426
+                )
427
+            )
428
+            ->andWhere($qb->expr()->orX(
429
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
430
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
431
+            ))
432
+            ->orderBy('id');
433
+
434
+        $cursor = $qb->execute();
435
+        while($data = $cursor->fetch()) {
436
+            $children[] = $this->createShare($data);
437
+        }
438
+        $cursor->closeCursor();
439
+
440
+        return $children;
441
+    }
442
+
443
+    /**
444
+     * Delete a share
445
+     *
446
+     * @param \OCP\Share\IShare $share
447
+     */
448
+    public function delete(\OCP\Share\IShare $share) {
449
+        $qb = $this->dbConn->getQueryBuilder();
450
+        $qb->delete('share')
451
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())));
452
+
453
+        /*
454 454
 		 * If the share is a group share delete all possible
455 455
 		 * user defined groups shares.
456 456
 		 */
457
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
458
-			$qb->orWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())));
459
-		}
460
-
461
-		$qb->execute();
462
-	}
463
-
464
-	/**
465
-	 * Unshare a share from the recipient. If this is a group share
466
-	 * this means we need a special entry in the share db.
467
-	 *
468
-	 * @param IShare $share
469
-	 * @param string $recipient UserId of recipient
470
-	 * @throws BackendError
471
-	 * @throws ProviderException
472
-	 */
473
-	public function deleteFromSelf(IShare $share, $recipient) {
474
-		if ($share->getShareType() === IShare::TYPE_GROUP) {
475
-
476
-			$group = $this->groupManager->get($share->getSharedWith());
477
-			$user = $this->userManager->get($recipient);
478
-
479
-			if (is_null($group)) {
480
-				throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
481
-			}
482
-
483
-			if (!$group->inGroup($user)) {
484
-				throw new ProviderException('Recipient not in receiving group');
485
-			}
486
-
487
-			// Try to fetch user specific share
488
-			$qb = $this->dbConn->getQueryBuilder();
489
-			$stmt = $qb->select('*')
490
-				->from('share')
491
-				->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
492
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
493
-				->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
494
-				->andWhere($qb->expr()->orX(
495
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
496
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
497
-				))
498
-				->execute();
499
-
500
-			$data = $stmt->fetch();
501
-
502
-			/*
457
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
458
+            $qb->orWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())));
459
+        }
460
+
461
+        $qb->execute();
462
+    }
463
+
464
+    /**
465
+     * Unshare a share from the recipient. If this is a group share
466
+     * this means we need a special entry in the share db.
467
+     *
468
+     * @param IShare $share
469
+     * @param string $recipient UserId of recipient
470
+     * @throws BackendError
471
+     * @throws ProviderException
472
+     */
473
+    public function deleteFromSelf(IShare $share, $recipient) {
474
+        if ($share->getShareType() === IShare::TYPE_GROUP) {
475
+
476
+            $group = $this->groupManager->get($share->getSharedWith());
477
+            $user = $this->userManager->get($recipient);
478
+
479
+            if (is_null($group)) {
480
+                throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
481
+            }
482
+
483
+            if (!$group->inGroup($user)) {
484
+                throw new ProviderException('Recipient not in receiving group');
485
+            }
486
+
487
+            // Try to fetch user specific share
488
+            $qb = $this->dbConn->getQueryBuilder();
489
+            $stmt = $qb->select('*')
490
+                ->from('share')
491
+                ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
492
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
493
+                ->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
494
+                ->andWhere($qb->expr()->orX(
495
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
496
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
497
+                ))
498
+                ->execute();
499
+
500
+            $data = $stmt->fetch();
501
+
502
+            /*
503 503
 			 * Check if there already is a user specific group share.
504 504
 			 * If there is update it (if required).
505 505
 			 */
506
-			if ($data === false) {
507
-				$id = $this->createUserSpecificGroupShare($share, $recipient);
508
-				$permissions = $share->getPermissions();
509
-			} else {
510
-				$permissions = $data['permissions'];
511
-				$id = $data['id'];
512
-			}
513
-
514
-			if ($permissions !== 0) {
515
-				// Update existing usergroup share
516
-				$qb = $this->dbConn->getQueryBuilder();
517
-				$qb->update('share')
518
-					->set('permissions', $qb->createNamedParameter(0))
519
-					->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
520
-					->execute();
521
-			}
522
-
523
-		} else if ($share->getShareType() === IShare::TYPE_USER) {
524
-
525
-			if ($share->getSharedWith() !== $recipient) {
526
-				throw new ProviderException('Recipient does not match');
527
-			}
528
-
529
-			// We can just delete user and link shares
530
-			$this->delete($share);
531
-		} else {
532
-			throw new ProviderException('Invalid shareType');
533
-		}
534
-	}
535
-
536
-	protected function createUserSpecificGroupShare(IShare $share, string $recipient): int {
537
-		$type = $share->getNodeType();
538
-
539
-		$qb = $this->dbConn->getQueryBuilder();
540
-		$qb->insert('share')
541
-			->values([
542
-				'share_type' => $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP),
543
-				'share_with' => $qb->createNamedParameter($recipient),
544
-				'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
545
-				'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
546
-				'parent' => $qb->createNamedParameter($share->getId()),
547
-				'item_type' => $qb->createNamedParameter($type),
548
-				'item_source' => $qb->createNamedParameter($share->getNodeId()),
549
-				'file_source' => $qb->createNamedParameter($share->getNodeId()),
550
-				'file_target' => $qb->createNamedParameter($share->getTarget()),
551
-				'permissions' => $qb->createNamedParameter($share->getPermissions()),
552
-				'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
553
-			])->execute();
554
-
555
-		return $qb->getLastInsertId();
556
-	}
557
-
558
-	/**
559
-	 * @inheritdoc
560
-	 *
561
-	 * For now this only works for group shares
562
-	 * If this gets implemented for normal shares we have to extend it
563
-	 */
564
-	public function restore(IShare $share, string $recipient): IShare {
565
-		$qb = $this->dbConn->getQueryBuilder();
566
-		$qb->select('permissions')
567
-			->from('share')
568
-			->where(
569
-				$qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))
570
-			);
571
-		$cursor = $qb->execute();
572
-		$data = $cursor->fetch();
573
-		$cursor->closeCursor();
574
-
575
-		$originalPermission = $data['permissions'];
576
-
577
-		$qb = $this->dbConn->getQueryBuilder();
578
-		$qb->update('share')
579
-			->set('permissions', $qb->createNamedParameter($originalPermission))
580
-			->where(
581
-				$qb->expr()->eq('parent', $qb->createNamedParameter($share->getParent()))
582
-			)->andWhere(
583
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP))
584
-			)->andWhere(
585
-				$qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))
586
-			);
587
-
588
-		$qb->execute();
589
-
590
-		return $this->getShareById($share->getId(), $recipient);
591
-	}
592
-
593
-	/**
594
-	 * @inheritdoc
595
-	 */
596
-	public function move(\OCP\Share\IShare $share, $recipient) {
597
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
598
-			// Just update the target
599
-			$qb = $this->dbConn->getQueryBuilder();
600
-			$qb->update('share')
601
-				->set('file_target', $qb->createNamedParameter($share->getTarget()))
602
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
603
-				->execute();
604
-
605
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
606
-
607
-			// Check if there is a usergroup share
608
-			$qb = $this->dbConn->getQueryBuilder();
609
-			$stmt = $qb->select('id')
610
-				->from('share')
611
-				->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
612
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
613
-				->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
614
-				->andWhere($qb->expr()->orX(
615
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
616
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
617
-				))
618
-				->setMaxResults(1)
619
-				->execute();
620
-
621
-			$data = $stmt->fetch();
622
-			$stmt->closeCursor();
623
-
624
-			if ($data === false) {
625
-				// No usergroup share yet. Create one.
626
-				$qb = $this->dbConn->getQueryBuilder();
627
-				$qb->insert('share')
628
-					->values([
629
-						'share_type' => $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP),
630
-						'share_with' => $qb->createNamedParameter($recipient),
631
-						'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
632
-						'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
633
-						'parent' => $qb->createNamedParameter($share->getId()),
634
-						'item_type' => $qb->createNamedParameter($share->getNodeType()),
635
-						'item_source' => $qb->createNamedParameter($share->getNodeId()),
636
-						'file_source' => $qb->createNamedParameter($share->getNodeId()),
637
-						'file_target' => $qb->createNamedParameter($share->getTarget()),
638
-						'permissions' => $qb->createNamedParameter($share->getPermissions()),
639
-						'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
640
-					])->execute();
641
-			} else {
642
-				// Already a usergroup share. Update it.
643
-				$qb = $this->dbConn->getQueryBuilder();
644
-				$qb->update('share')
645
-					->set('file_target', $qb->createNamedParameter($share->getTarget()))
646
-					->where($qb->expr()->eq('id', $qb->createNamedParameter($data['id'])))
647
-					->execute();
648
-			}
649
-		}
650
-
651
-		return $share;
652
-	}
653
-
654
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
655
-		$qb = $this->dbConn->getQueryBuilder();
656
-		$qb->select('*')
657
-			->from('share', 's')
658
-			->andWhere($qb->expr()->orX(
659
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
660
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
661
-			));
662
-
663
-		$qb->andWhere($qb->expr()->orX(
664
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)),
665
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)),
666
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_LINK))
667
-		));
668
-
669
-		/**
670
-		 * Reshares for this user are shares where they are the owner.
671
-		 */
672
-		if ($reshares === false) {
673
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
674
-		} else {
675
-			$qb->andWhere(
676
-				$qb->expr()->orX(
677
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
678
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
679
-				)
680
-			);
681
-		}
682
-
683
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
684
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
685
-
686
-		$qb->orderBy('id');
687
-
688
-		$cursor = $qb->execute();
689
-		$shares = [];
690
-		while ($data = $cursor->fetch()) {
691
-			$shares[$data['fileid']][] = $this->createShare($data);
692
-		}
693
-		$cursor->closeCursor();
694
-
695
-		return $shares;
696
-	}
697
-
698
-	/**
699
-	 * @inheritdoc
700
-	 */
701
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
702
-		$qb = $this->dbConn->getQueryBuilder();
703
-		$qb->select('*')
704
-			->from('share')
705
-			->andWhere($qb->expr()->orX(
706
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
707
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
708
-			));
709
-
710
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
711
-
712
-		/**
713
-		 * Reshares for this user are shares where they are the owner.
714
-		 */
715
-		if ($reshares === false) {
716
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
717
-		} else {
718
-			if ($node === null) {
719
-				$qb->andWhere(
720
-					$qb->expr()->orX(
721
-						$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
722
-						$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
723
-					)
724
-				);
725
-			}
726
-		}
727
-
728
-		if ($node !== null) {
729
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
730
-		}
731
-
732
-		if ($limit !== -1) {
733
-			$qb->setMaxResults($limit);
734
-		}
735
-
736
-		$qb->setFirstResult($offset);
737
-		$qb->orderBy('id');
738
-
739
-		$cursor = $qb->execute();
740
-		$shares = [];
741
-		while($data = $cursor->fetch()) {
742
-			$shares[] = $this->createShare($data);
743
-		}
744
-		$cursor->closeCursor();
745
-
746
-		return $shares;
747
-	}
748
-
749
-	/**
750
-	 * @inheritdoc
751
-	 */
752
-	public function getShareById($id, $recipientId = null) {
753
-		$qb = $this->dbConn->getQueryBuilder();
754
-
755
-		$qb->select('*')
756
-			->from('share')
757
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
758
-			->andWhere(
759
-				$qb->expr()->in(
760
-					'share_type',
761
-					$qb->createNamedParameter([
762
-						\OCP\Share::SHARE_TYPE_USER,
763
-						\OCP\Share::SHARE_TYPE_GROUP,
764
-						\OCP\Share::SHARE_TYPE_LINK,
765
-					], IQueryBuilder::PARAM_INT_ARRAY)
766
-				)
767
-			)
768
-			->andWhere($qb->expr()->orX(
769
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
770
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
771
-			));
772
-
773
-		$cursor = $qb->execute();
774
-		$data = $cursor->fetch();
775
-		$cursor->closeCursor();
776
-
777
-		if ($data === false) {
778
-			throw new ShareNotFound();
779
-		}
780
-
781
-		try {
782
-			$share = $this->createShare($data);
783
-		} catch (InvalidShare $e) {
784
-			throw new ShareNotFound();
785
-		}
786
-
787
-		// If the recipient is set for a group share resolve to that user
788
-		if ($recipientId !== null && $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
789
-			$share = $this->resolveGroupShares([$share], $recipientId)[0];
790
-		}
791
-
792
-		return $share;
793
-	}
794
-
795
-	/**
796
-	 * Get shares for a given path
797
-	 *
798
-	 * @param \OCP\Files\Node $path
799
-	 * @return \OCP\Share\IShare[]
800
-	 */
801
-	public function getSharesByPath(Node $path) {
802
-		$qb = $this->dbConn->getQueryBuilder();
803
-
804
-		$cursor = $qb->select('*')
805
-			->from('share')
806
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
807
-			->andWhere(
808
-				$qb->expr()->orX(
809
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)),
810
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP))
811
-				)
812
-			)
813
-			->andWhere($qb->expr()->orX(
814
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
815
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
816
-			))
817
-			->execute();
818
-
819
-		$shares = [];
820
-		while($data = $cursor->fetch()) {
821
-			$shares[] = $this->createShare($data);
822
-		}
823
-		$cursor->closeCursor();
824
-
825
-		return $shares;
826
-	}
827
-
828
-	/**
829
-	 * Returns whether the given database result can be interpreted as
830
-	 * a share with accessible file (not trashed, not deleted)
831
-	 */
832
-	private function isAccessibleResult($data) {
833
-		// exclude shares leading to deleted file entries
834
-		if ($data['fileid'] === null) {
835
-			return false;
836
-		}
837
-
838
-		// exclude shares leading to trashbin on home storages
839
-		$pathSections = explode('/', $data['path'], 2);
840
-		// FIXME: would not detect rare md5'd home storage case properly
841
-		if ($pathSections[0] !== 'files'
842
-		    	&& in_array(explode(':', $data['storage_string_id'], 2)[0], ['home', 'object'])) {
843
-			return false;
844
-		}
845
-		return true;
846
-	}
847
-
848
-	/**
849
-	 * @inheritdoc
850
-	 */
851
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
852
-		/** @var Share[] $shares */
853
-		$shares = [];
854
-
855
-		if ($shareType === \OCP\Share::SHARE_TYPE_USER) {
856
-			//Get shares directly with this user
857
-			$qb = $this->dbConn->getQueryBuilder();
858
-			$qb->select('s.*',
859
-				'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
860
-				'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
861
-				'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
862
-			)
863
-				->selectAlias('st.id', 'storage_string_id')
864
-				->from('share', 's')
865
-				->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
866
-				->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'));
867
-
868
-			// Order by id
869
-			$qb->orderBy('s.id');
870
-
871
-			// Set limit and offset
872
-			if ($limit !== -1) {
873
-				$qb->setMaxResults($limit);
874
-			}
875
-			$qb->setFirstResult($offset);
876
-
877
-			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)))
878
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
879
-				->andWhere($qb->expr()->orX(
880
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
881
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
882
-				));
883
-
884
-			// Filter by node if provided
885
-			if ($node !== null) {
886
-				$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
887
-			}
888
-
889
-			$cursor = $qb->execute();
890
-
891
-			while($data = $cursor->fetch()) {
892
-				if ($this->isAccessibleResult($data)) {
893
-					$shares[] = $this->createShare($data);
894
-				}
895
-			}
896
-			$cursor->closeCursor();
897
-
898
-		} else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
899
-			$user = $this->userManager->get($userId);
900
-			$allGroups = $this->groupManager->getUserGroups($user);
901
-
902
-			/** @var Share[] $shares2 */
903
-			$shares2 = [];
904
-
905
-			$start = 0;
906
-			while(true) {
907
-				$groups = array_slice($allGroups, $start, 100);
908
-				$start += 100;
909
-
910
-				if ($groups === []) {
911
-					break;
912
-				}
913
-
914
-				$qb = $this->dbConn->getQueryBuilder();
915
-				$qb->select('s.*',
916
-					'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
917
-					'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
918
-					'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
919
-				)
920
-					->selectAlias('st.id', 'storage_string_id')
921
-					->from('share', 's')
922
-					->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
923
-					->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'))
924
-					->orderBy('s.id')
925
-					->setFirstResult(0);
926
-
927
-				if ($limit !== -1) {
928
-					$qb->setMaxResults($limit - count($shares));
929
-				}
930
-
931
-				// Filter by node if provided
932
-				if ($node !== null) {
933
-					$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
934
-				}
935
-
936
-
937
-				$groups = array_filter($groups, function($group) { return $group instanceof IGroup; });
938
-				$groups = array_map(function(IGroup $group) { return $group->getGID(); }, $groups);
939
-
940
-				$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)))
941
-					->andWhere($qb->expr()->in('share_with', $qb->createNamedParameter(
942
-						$groups,
943
-						IQueryBuilder::PARAM_STR_ARRAY
944
-					)))
945
-					->andWhere($qb->expr()->orX(
946
-						$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
947
-						$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
948
-					));
949
-
950
-				$cursor = $qb->execute();
951
-				while($data = $cursor->fetch()) {
952
-					if ($offset > 0) {
953
-						$offset--;
954
-						continue;
955
-					}
956
-
957
-					if ($this->isAccessibleResult($data)) {
958
-						$shares2[] = $this->createShare($data);
959
-					}
960
-				}
961
-				$cursor->closeCursor();
962
-			}
963
-
964
-			/*
506
+            if ($data === false) {
507
+                $id = $this->createUserSpecificGroupShare($share, $recipient);
508
+                $permissions = $share->getPermissions();
509
+            } else {
510
+                $permissions = $data['permissions'];
511
+                $id = $data['id'];
512
+            }
513
+
514
+            if ($permissions !== 0) {
515
+                // Update existing usergroup share
516
+                $qb = $this->dbConn->getQueryBuilder();
517
+                $qb->update('share')
518
+                    ->set('permissions', $qb->createNamedParameter(0))
519
+                    ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
520
+                    ->execute();
521
+            }
522
+
523
+        } else if ($share->getShareType() === IShare::TYPE_USER) {
524
+
525
+            if ($share->getSharedWith() !== $recipient) {
526
+                throw new ProviderException('Recipient does not match');
527
+            }
528
+
529
+            // We can just delete user and link shares
530
+            $this->delete($share);
531
+        } else {
532
+            throw new ProviderException('Invalid shareType');
533
+        }
534
+    }
535
+
536
+    protected function createUserSpecificGroupShare(IShare $share, string $recipient): int {
537
+        $type = $share->getNodeType();
538
+
539
+        $qb = $this->dbConn->getQueryBuilder();
540
+        $qb->insert('share')
541
+            ->values([
542
+                'share_type' => $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP),
543
+                'share_with' => $qb->createNamedParameter($recipient),
544
+                'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
545
+                'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
546
+                'parent' => $qb->createNamedParameter($share->getId()),
547
+                'item_type' => $qb->createNamedParameter($type),
548
+                'item_source' => $qb->createNamedParameter($share->getNodeId()),
549
+                'file_source' => $qb->createNamedParameter($share->getNodeId()),
550
+                'file_target' => $qb->createNamedParameter($share->getTarget()),
551
+                'permissions' => $qb->createNamedParameter($share->getPermissions()),
552
+                'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
553
+            ])->execute();
554
+
555
+        return $qb->getLastInsertId();
556
+    }
557
+
558
+    /**
559
+     * @inheritdoc
560
+     *
561
+     * For now this only works for group shares
562
+     * If this gets implemented for normal shares we have to extend it
563
+     */
564
+    public function restore(IShare $share, string $recipient): IShare {
565
+        $qb = $this->dbConn->getQueryBuilder();
566
+        $qb->select('permissions')
567
+            ->from('share')
568
+            ->where(
569
+                $qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))
570
+            );
571
+        $cursor = $qb->execute();
572
+        $data = $cursor->fetch();
573
+        $cursor->closeCursor();
574
+
575
+        $originalPermission = $data['permissions'];
576
+
577
+        $qb = $this->dbConn->getQueryBuilder();
578
+        $qb->update('share')
579
+            ->set('permissions', $qb->createNamedParameter($originalPermission))
580
+            ->where(
581
+                $qb->expr()->eq('parent', $qb->createNamedParameter($share->getParent()))
582
+            )->andWhere(
583
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP))
584
+            )->andWhere(
585
+                $qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))
586
+            );
587
+
588
+        $qb->execute();
589
+
590
+        return $this->getShareById($share->getId(), $recipient);
591
+    }
592
+
593
+    /**
594
+     * @inheritdoc
595
+     */
596
+    public function move(\OCP\Share\IShare $share, $recipient) {
597
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
598
+            // Just update the target
599
+            $qb = $this->dbConn->getQueryBuilder();
600
+            $qb->update('share')
601
+                ->set('file_target', $qb->createNamedParameter($share->getTarget()))
602
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
603
+                ->execute();
604
+
605
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
606
+
607
+            // Check if there is a usergroup share
608
+            $qb = $this->dbConn->getQueryBuilder();
609
+            $stmt = $qb->select('id')
610
+                ->from('share')
611
+                ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
612
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
613
+                ->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
614
+                ->andWhere($qb->expr()->orX(
615
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
616
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
617
+                ))
618
+                ->setMaxResults(1)
619
+                ->execute();
620
+
621
+            $data = $stmt->fetch();
622
+            $stmt->closeCursor();
623
+
624
+            if ($data === false) {
625
+                // No usergroup share yet. Create one.
626
+                $qb = $this->dbConn->getQueryBuilder();
627
+                $qb->insert('share')
628
+                    ->values([
629
+                        'share_type' => $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP),
630
+                        'share_with' => $qb->createNamedParameter($recipient),
631
+                        'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
632
+                        'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
633
+                        'parent' => $qb->createNamedParameter($share->getId()),
634
+                        'item_type' => $qb->createNamedParameter($share->getNodeType()),
635
+                        'item_source' => $qb->createNamedParameter($share->getNodeId()),
636
+                        'file_source' => $qb->createNamedParameter($share->getNodeId()),
637
+                        'file_target' => $qb->createNamedParameter($share->getTarget()),
638
+                        'permissions' => $qb->createNamedParameter($share->getPermissions()),
639
+                        'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
640
+                    ])->execute();
641
+            } else {
642
+                // Already a usergroup share. Update it.
643
+                $qb = $this->dbConn->getQueryBuilder();
644
+                $qb->update('share')
645
+                    ->set('file_target', $qb->createNamedParameter($share->getTarget()))
646
+                    ->where($qb->expr()->eq('id', $qb->createNamedParameter($data['id'])))
647
+                    ->execute();
648
+            }
649
+        }
650
+
651
+        return $share;
652
+    }
653
+
654
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
655
+        $qb = $this->dbConn->getQueryBuilder();
656
+        $qb->select('*')
657
+            ->from('share', 's')
658
+            ->andWhere($qb->expr()->orX(
659
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
660
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
661
+            ));
662
+
663
+        $qb->andWhere($qb->expr()->orX(
664
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)),
665
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)),
666
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_LINK))
667
+        ));
668
+
669
+        /**
670
+         * Reshares for this user are shares where they are the owner.
671
+         */
672
+        if ($reshares === false) {
673
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
674
+        } else {
675
+            $qb->andWhere(
676
+                $qb->expr()->orX(
677
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
678
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
679
+                )
680
+            );
681
+        }
682
+
683
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
684
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
685
+
686
+        $qb->orderBy('id');
687
+
688
+        $cursor = $qb->execute();
689
+        $shares = [];
690
+        while ($data = $cursor->fetch()) {
691
+            $shares[$data['fileid']][] = $this->createShare($data);
692
+        }
693
+        $cursor->closeCursor();
694
+
695
+        return $shares;
696
+    }
697
+
698
+    /**
699
+     * @inheritdoc
700
+     */
701
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
702
+        $qb = $this->dbConn->getQueryBuilder();
703
+        $qb->select('*')
704
+            ->from('share')
705
+            ->andWhere($qb->expr()->orX(
706
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
707
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
708
+            ));
709
+
710
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
711
+
712
+        /**
713
+         * Reshares for this user are shares where they are the owner.
714
+         */
715
+        if ($reshares === false) {
716
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
717
+        } else {
718
+            if ($node === null) {
719
+                $qb->andWhere(
720
+                    $qb->expr()->orX(
721
+                        $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
722
+                        $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
723
+                    )
724
+                );
725
+            }
726
+        }
727
+
728
+        if ($node !== null) {
729
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
730
+        }
731
+
732
+        if ($limit !== -1) {
733
+            $qb->setMaxResults($limit);
734
+        }
735
+
736
+        $qb->setFirstResult($offset);
737
+        $qb->orderBy('id');
738
+
739
+        $cursor = $qb->execute();
740
+        $shares = [];
741
+        while($data = $cursor->fetch()) {
742
+            $shares[] = $this->createShare($data);
743
+        }
744
+        $cursor->closeCursor();
745
+
746
+        return $shares;
747
+    }
748
+
749
+    /**
750
+     * @inheritdoc
751
+     */
752
+    public function getShareById($id, $recipientId = null) {
753
+        $qb = $this->dbConn->getQueryBuilder();
754
+
755
+        $qb->select('*')
756
+            ->from('share')
757
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
758
+            ->andWhere(
759
+                $qb->expr()->in(
760
+                    'share_type',
761
+                    $qb->createNamedParameter([
762
+                        \OCP\Share::SHARE_TYPE_USER,
763
+                        \OCP\Share::SHARE_TYPE_GROUP,
764
+                        \OCP\Share::SHARE_TYPE_LINK,
765
+                    ], IQueryBuilder::PARAM_INT_ARRAY)
766
+                )
767
+            )
768
+            ->andWhere($qb->expr()->orX(
769
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
770
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
771
+            ));
772
+
773
+        $cursor = $qb->execute();
774
+        $data = $cursor->fetch();
775
+        $cursor->closeCursor();
776
+
777
+        if ($data === false) {
778
+            throw new ShareNotFound();
779
+        }
780
+
781
+        try {
782
+            $share = $this->createShare($data);
783
+        } catch (InvalidShare $e) {
784
+            throw new ShareNotFound();
785
+        }
786
+
787
+        // If the recipient is set for a group share resolve to that user
788
+        if ($recipientId !== null && $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
789
+            $share = $this->resolveGroupShares([$share], $recipientId)[0];
790
+        }
791
+
792
+        return $share;
793
+    }
794
+
795
+    /**
796
+     * Get shares for a given path
797
+     *
798
+     * @param \OCP\Files\Node $path
799
+     * @return \OCP\Share\IShare[]
800
+     */
801
+    public function getSharesByPath(Node $path) {
802
+        $qb = $this->dbConn->getQueryBuilder();
803
+
804
+        $cursor = $qb->select('*')
805
+            ->from('share')
806
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
807
+            ->andWhere(
808
+                $qb->expr()->orX(
809
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)),
810
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP))
811
+                )
812
+            )
813
+            ->andWhere($qb->expr()->orX(
814
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
815
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
816
+            ))
817
+            ->execute();
818
+
819
+        $shares = [];
820
+        while($data = $cursor->fetch()) {
821
+            $shares[] = $this->createShare($data);
822
+        }
823
+        $cursor->closeCursor();
824
+
825
+        return $shares;
826
+    }
827
+
828
+    /**
829
+     * Returns whether the given database result can be interpreted as
830
+     * a share with accessible file (not trashed, not deleted)
831
+     */
832
+    private function isAccessibleResult($data) {
833
+        // exclude shares leading to deleted file entries
834
+        if ($data['fileid'] === null) {
835
+            return false;
836
+        }
837
+
838
+        // exclude shares leading to trashbin on home storages
839
+        $pathSections = explode('/', $data['path'], 2);
840
+        // FIXME: would not detect rare md5'd home storage case properly
841
+        if ($pathSections[0] !== 'files'
842
+                && in_array(explode(':', $data['storage_string_id'], 2)[0], ['home', 'object'])) {
843
+            return false;
844
+        }
845
+        return true;
846
+    }
847
+
848
+    /**
849
+     * @inheritdoc
850
+     */
851
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
852
+        /** @var Share[] $shares */
853
+        $shares = [];
854
+
855
+        if ($shareType === \OCP\Share::SHARE_TYPE_USER) {
856
+            //Get shares directly with this user
857
+            $qb = $this->dbConn->getQueryBuilder();
858
+            $qb->select('s.*',
859
+                'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
860
+                'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
861
+                'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
862
+            )
863
+                ->selectAlias('st.id', 'storage_string_id')
864
+                ->from('share', 's')
865
+                ->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
866
+                ->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'));
867
+
868
+            // Order by id
869
+            $qb->orderBy('s.id');
870
+
871
+            // Set limit and offset
872
+            if ($limit !== -1) {
873
+                $qb->setMaxResults($limit);
874
+            }
875
+            $qb->setFirstResult($offset);
876
+
877
+            $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)))
878
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
879
+                ->andWhere($qb->expr()->orX(
880
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
881
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
882
+                ));
883
+
884
+            // Filter by node if provided
885
+            if ($node !== null) {
886
+                $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
887
+            }
888
+
889
+            $cursor = $qb->execute();
890
+
891
+            while($data = $cursor->fetch()) {
892
+                if ($this->isAccessibleResult($data)) {
893
+                    $shares[] = $this->createShare($data);
894
+                }
895
+            }
896
+            $cursor->closeCursor();
897
+
898
+        } else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
899
+            $user = $this->userManager->get($userId);
900
+            $allGroups = $this->groupManager->getUserGroups($user);
901
+
902
+            /** @var Share[] $shares2 */
903
+            $shares2 = [];
904
+
905
+            $start = 0;
906
+            while(true) {
907
+                $groups = array_slice($allGroups, $start, 100);
908
+                $start += 100;
909
+
910
+                if ($groups === []) {
911
+                    break;
912
+                }
913
+
914
+                $qb = $this->dbConn->getQueryBuilder();
915
+                $qb->select('s.*',
916
+                    'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
917
+                    'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
918
+                    'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
919
+                )
920
+                    ->selectAlias('st.id', 'storage_string_id')
921
+                    ->from('share', 's')
922
+                    ->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
923
+                    ->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'))
924
+                    ->orderBy('s.id')
925
+                    ->setFirstResult(0);
926
+
927
+                if ($limit !== -1) {
928
+                    $qb->setMaxResults($limit - count($shares));
929
+                }
930
+
931
+                // Filter by node if provided
932
+                if ($node !== null) {
933
+                    $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
934
+                }
935
+
936
+
937
+                $groups = array_filter($groups, function($group) { return $group instanceof IGroup; });
938
+                $groups = array_map(function(IGroup $group) { return $group->getGID(); }, $groups);
939
+
940
+                $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)))
941
+                    ->andWhere($qb->expr()->in('share_with', $qb->createNamedParameter(
942
+                        $groups,
943
+                        IQueryBuilder::PARAM_STR_ARRAY
944
+                    )))
945
+                    ->andWhere($qb->expr()->orX(
946
+                        $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
947
+                        $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
948
+                    ));
949
+
950
+                $cursor = $qb->execute();
951
+                while($data = $cursor->fetch()) {
952
+                    if ($offset > 0) {
953
+                        $offset--;
954
+                        continue;
955
+                    }
956
+
957
+                    if ($this->isAccessibleResult($data)) {
958
+                        $shares2[] = $this->createShare($data);
959
+                    }
960
+                }
961
+                $cursor->closeCursor();
962
+            }
963
+
964
+            /*
965 965
  			 * Resolve all group shares to user specific shares
966 966
  			 */
967
-			$shares = $this->resolveGroupShares($shares2, $userId);
968
-		} else {
969
-			throw new BackendError('Invalid backend');
970
-		}
971
-
972
-
973
-		return $shares;
974
-	}
975
-
976
-	/**
977
-	 * Get a share by token
978
-	 *
979
-	 * @param string $token
980
-	 * @return \OCP\Share\IShare
981
-	 * @throws ShareNotFound
982
-	 */
983
-	public function getShareByToken($token) {
984
-		$qb = $this->dbConn->getQueryBuilder();
985
-
986
-		$cursor = $qb->select('*')
987
-			->from('share')
988
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_LINK)))
989
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
990
-			->andWhere($qb->expr()->orX(
991
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
992
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
993
-			))
994
-			->execute();
995
-
996
-		$data = $cursor->fetch();
997
-
998
-		if ($data === false) {
999
-			throw new ShareNotFound();
1000
-		}
1001
-
1002
-		try {
1003
-			$share = $this->createShare($data);
1004
-		} catch (InvalidShare $e) {
1005
-			throw new ShareNotFound();
1006
-		}
1007
-
1008
-		return $share;
1009
-	}
1010
-
1011
-	/**
1012
-	 * Create a share object from an database row
1013
-	 *
1014
-	 * @param mixed[] $data
1015
-	 * @return \OCP\Share\IShare
1016
-	 * @throws InvalidShare
1017
-	 */
1018
-	private function createShare($data) {
1019
-		$share = new Share($this->rootFolder, $this->userManager);
1020
-		$share->setId((int)$data['id'])
1021
-			->setShareType((int)$data['share_type'])
1022
-			->setPermissions((int)$data['permissions'])
1023
-			->setTarget($data['file_target'])
1024
-			->setNote($data['note'])
1025
-			->setMailSend((bool)$data['mail_send'])
1026
-			->setStatus((int)$data['accepted'])
1027
-			->setLabel($data['label']);
1028
-
1029
-		$shareTime = new \DateTime();
1030
-		$shareTime->setTimestamp((int)$data['stime']);
1031
-		$share->setShareTime($shareTime);
1032
-
1033
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
1034
-			$share->setSharedWith($data['share_with']);
1035
-			$user = $this->userManager->get($data['share_with']);
1036
-			if ($user !== null) {
1037
-				$share->setSharedWithDisplayName($user->getDisplayName());
1038
-			}
1039
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
1040
-			$share->setSharedWith($data['share_with']);
1041
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
1042
-			$share->setPassword($data['password']);
1043
-			$share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1044
-			$share->setToken($data['token']);
1045
-		}
1046
-
1047
-		$share->setSharedBy($data['uid_initiator']);
1048
-		$share->setShareOwner($data['uid_owner']);
1049
-
1050
-		$share->setNodeId((int)$data['file_source']);
1051
-		$share->setNodeType($data['item_type']);
1052
-
1053
-		if ($data['expiration'] !== null) {
1054
-			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
1055
-			$share->setExpirationDate($expiration);
1056
-		}
1057
-
1058
-		if (isset($data['f_permissions'])) {
1059
-			$entryData = $data;
1060
-			$entryData['permissions'] = $entryData['f_permissions'];
1061
-			$entryData['parent'] = $entryData['f_parent'];
1062
-			$share->setNodeCacheEntry(Cache::cacheEntryFromData($entryData,
1063
-				\OC::$server->getMimeTypeLoader()));
1064
-		}
1065
-
1066
-		$share->setProviderId($this->identifier());
1067
-		$share->setHideDownload((int)$data['hide_download'] === 1);
1068
-
1069
-		return $share;
1070
-	}
1071
-
1072
-	/**
1073
-	 * @param Share[] $shares
1074
-	 * @param $userId
1075
-	 * @return Share[] The updates shares if no update is found for a share return the original
1076
-	 */
1077
-	private function resolveGroupShares($shares, $userId) {
1078
-		$result = [];
1079
-
1080
-		$start = 0;
1081
-		while(true) {
1082
-			/** @var Share[] $shareSlice */
1083
-			$shareSlice = array_slice($shares, $start, 100);
1084
-			$start += 100;
1085
-
1086
-			if ($shareSlice === []) {
1087
-				break;
1088
-			}
1089
-
1090
-			/** @var int[] $ids */
1091
-			$ids = [];
1092
-			/** @var Share[] $shareMap */
1093
-			$shareMap = [];
1094
-
1095
-			foreach ($shareSlice as $share) {
1096
-				$ids[] = (int)$share->getId();
1097
-				$shareMap[$share->getId()] = $share;
1098
-			}
1099
-
1100
-			$qb = $this->dbConn->getQueryBuilder();
1101
-
1102
-			$query = $qb->select('*')
1103
-				->from('share')
1104
-				->where($qb->expr()->in('parent', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1105
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
1106
-				->andWhere($qb->expr()->orX(
1107
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1108
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1109
-				));
1110
-
1111
-			$stmt = $query->execute();
1112
-
1113
-			while($data = $stmt->fetch()) {
1114
-				$shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
1115
-				$shareMap[$data['parent']]->setStatus((int)$data['accepted']);
1116
-				$shareMap[$data['parent']]->setTarget($data['file_target']);
1117
-				$shareMap[$data['parent']]->setParent($data['parent']);
1118
-			}
1119
-
1120
-			$stmt->closeCursor();
1121
-
1122
-			foreach ($shareMap as $share) {
1123
-				$result[] = $share;
1124
-			}
1125
-		}
1126
-
1127
-		return $result;
1128
-	}
1129
-
1130
-	/**
1131
-	 * A user is deleted from the system
1132
-	 * So clean up the relevant shares.
1133
-	 *
1134
-	 * @param string $uid
1135
-	 * @param int $shareType
1136
-	 */
1137
-	public function userDeleted($uid, $shareType) {
1138
-		$qb = $this->dbConn->getQueryBuilder();
1139
-
1140
-		$qb->delete('share');
1141
-
1142
-		if ($shareType === \OCP\Share::SHARE_TYPE_USER) {
1143
-			/*
967
+            $shares = $this->resolveGroupShares($shares2, $userId);
968
+        } else {
969
+            throw new BackendError('Invalid backend');
970
+        }
971
+
972
+
973
+        return $shares;
974
+    }
975
+
976
+    /**
977
+     * Get a share by token
978
+     *
979
+     * @param string $token
980
+     * @return \OCP\Share\IShare
981
+     * @throws ShareNotFound
982
+     */
983
+    public function getShareByToken($token) {
984
+        $qb = $this->dbConn->getQueryBuilder();
985
+
986
+        $cursor = $qb->select('*')
987
+            ->from('share')
988
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_LINK)))
989
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
990
+            ->andWhere($qb->expr()->orX(
991
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
992
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
993
+            ))
994
+            ->execute();
995
+
996
+        $data = $cursor->fetch();
997
+
998
+        if ($data === false) {
999
+            throw new ShareNotFound();
1000
+        }
1001
+
1002
+        try {
1003
+            $share = $this->createShare($data);
1004
+        } catch (InvalidShare $e) {
1005
+            throw new ShareNotFound();
1006
+        }
1007
+
1008
+        return $share;
1009
+    }
1010
+
1011
+    /**
1012
+     * Create a share object from an database row
1013
+     *
1014
+     * @param mixed[] $data
1015
+     * @return \OCP\Share\IShare
1016
+     * @throws InvalidShare
1017
+     */
1018
+    private function createShare($data) {
1019
+        $share = new Share($this->rootFolder, $this->userManager);
1020
+        $share->setId((int)$data['id'])
1021
+            ->setShareType((int)$data['share_type'])
1022
+            ->setPermissions((int)$data['permissions'])
1023
+            ->setTarget($data['file_target'])
1024
+            ->setNote($data['note'])
1025
+            ->setMailSend((bool)$data['mail_send'])
1026
+            ->setStatus((int)$data['accepted'])
1027
+            ->setLabel($data['label']);
1028
+
1029
+        $shareTime = new \DateTime();
1030
+        $shareTime->setTimestamp((int)$data['stime']);
1031
+        $share->setShareTime($shareTime);
1032
+
1033
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
1034
+            $share->setSharedWith($data['share_with']);
1035
+            $user = $this->userManager->get($data['share_with']);
1036
+            if ($user !== null) {
1037
+                $share->setSharedWithDisplayName($user->getDisplayName());
1038
+            }
1039
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
1040
+            $share->setSharedWith($data['share_with']);
1041
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
1042
+            $share->setPassword($data['password']);
1043
+            $share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1044
+            $share->setToken($data['token']);
1045
+        }
1046
+
1047
+        $share->setSharedBy($data['uid_initiator']);
1048
+        $share->setShareOwner($data['uid_owner']);
1049
+
1050
+        $share->setNodeId((int)$data['file_source']);
1051
+        $share->setNodeType($data['item_type']);
1052
+
1053
+        if ($data['expiration'] !== null) {
1054
+            $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
1055
+            $share->setExpirationDate($expiration);
1056
+        }
1057
+
1058
+        if (isset($data['f_permissions'])) {
1059
+            $entryData = $data;
1060
+            $entryData['permissions'] = $entryData['f_permissions'];
1061
+            $entryData['parent'] = $entryData['f_parent'];
1062
+            $share->setNodeCacheEntry(Cache::cacheEntryFromData($entryData,
1063
+                \OC::$server->getMimeTypeLoader()));
1064
+        }
1065
+
1066
+        $share->setProviderId($this->identifier());
1067
+        $share->setHideDownload((int)$data['hide_download'] === 1);
1068
+
1069
+        return $share;
1070
+    }
1071
+
1072
+    /**
1073
+     * @param Share[] $shares
1074
+     * @param $userId
1075
+     * @return Share[] The updates shares if no update is found for a share return the original
1076
+     */
1077
+    private function resolveGroupShares($shares, $userId) {
1078
+        $result = [];
1079
+
1080
+        $start = 0;
1081
+        while(true) {
1082
+            /** @var Share[] $shareSlice */
1083
+            $shareSlice = array_slice($shares, $start, 100);
1084
+            $start += 100;
1085
+
1086
+            if ($shareSlice === []) {
1087
+                break;
1088
+            }
1089
+
1090
+            /** @var int[] $ids */
1091
+            $ids = [];
1092
+            /** @var Share[] $shareMap */
1093
+            $shareMap = [];
1094
+
1095
+            foreach ($shareSlice as $share) {
1096
+                $ids[] = (int)$share->getId();
1097
+                $shareMap[$share->getId()] = $share;
1098
+            }
1099
+
1100
+            $qb = $this->dbConn->getQueryBuilder();
1101
+
1102
+            $query = $qb->select('*')
1103
+                ->from('share')
1104
+                ->where($qb->expr()->in('parent', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1105
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
1106
+                ->andWhere($qb->expr()->orX(
1107
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1108
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1109
+                ));
1110
+
1111
+            $stmt = $query->execute();
1112
+
1113
+            while($data = $stmt->fetch()) {
1114
+                $shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
1115
+                $shareMap[$data['parent']]->setStatus((int)$data['accepted']);
1116
+                $shareMap[$data['parent']]->setTarget($data['file_target']);
1117
+                $shareMap[$data['parent']]->setParent($data['parent']);
1118
+            }
1119
+
1120
+            $stmt->closeCursor();
1121
+
1122
+            foreach ($shareMap as $share) {
1123
+                $result[] = $share;
1124
+            }
1125
+        }
1126
+
1127
+        return $result;
1128
+    }
1129
+
1130
+    /**
1131
+     * A user is deleted from the system
1132
+     * So clean up the relevant shares.
1133
+     *
1134
+     * @param string $uid
1135
+     * @param int $shareType
1136
+     */
1137
+    public function userDeleted($uid, $shareType) {
1138
+        $qb = $this->dbConn->getQueryBuilder();
1139
+
1140
+        $qb->delete('share');
1141
+
1142
+        if ($shareType === \OCP\Share::SHARE_TYPE_USER) {
1143
+            /*
1144 1144
 			 * Delete all user shares that are owned by this user
1145 1145
 			 * or that are received by this user
1146 1146
 			 */
1147 1147
 
1148
-			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)));
1148
+            $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)));
1149 1149
 
1150
-			$qb->andWhere(
1151
-				$qb->expr()->orX(
1152
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1153
-					$qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1154
-				)
1155
-			);
1156
-		} else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
1157
-			/*
1150
+            $qb->andWhere(
1151
+                $qb->expr()->orX(
1152
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1153
+                    $qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1154
+                )
1155
+            );
1156
+        } else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
1157
+            /*
1158 1158
 			 * Delete all group shares that are owned by this user
1159 1159
 			 * Or special user group shares that are received by this user
1160 1160
 			 */
1161
-			$qb->where(
1162
-				$qb->expr()->andX(
1163
-					$qb->expr()->orX(
1164
-						$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)),
1165
-						$qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP))
1166
-					),
1167
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid))
1168
-				)
1169
-			);
1170
-
1171
-			$qb->orWhere(
1172
-				$qb->expr()->andX(
1173
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)),
1174
-					$qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1175
-				)
1176
-			);
1177
-		} else if ($shareType === \OCP\Share::SHARE_TYPE_LINK) {
1178
-			/*
1161
+            $qb->where(
1162
+                $qb->expr()->andX(
1163
+                    $qb->expr()->orX(
1164
+                        $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)),
1165
+                        $qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP))
1166
+                    ),
1167
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid))
1168
+                )
1169
+            );
1170
+
1171
+            $qb->orWhere(
1172
+                $qb->expr()->andX(
1173
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)),
1174
+                    $qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1175
+                )
1176
+            );
1177
+        } else if ($shareType === \OCP\Share::SHARE_TYPE_LINK) {
1178
+            /*
1179 1179
 			 * Delete all link shares owned by this user.
1180 1180
 			 * And all link shares initiated by this user (until #22327 is in)
1181 1181
 			 */
1182
-			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_LINK)));
1183
-
1184
-			$qb->andWhere(
1185
-				$qb->expr()->orX(
1186
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1187
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($uid))
1188
-				)
1189
-			);
1190
-		} else {
1191
-			\OC::$server->getLogger()->logException(new \InvalidArgumentException('Default share provider tried to delete all shares for type: ' . $shareType));
1192
-			return;
1193
-		}
1194
-
1195
-		$qb->execute();
1196
-	}
1197
-
1198
-	/**
1199
-	 * Delete all shares received by this group. As well as any custom group
1200
-	 * shares for group members.
1201
-	 *
1202
-	 * @param string $gid
1203
-	 */
1204
-	public function groupDeleted($gid) {
1205
-		/*
1182
+            $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_LINK)));
1183
+
1184
+            $qb->andWhere(
1185
+                $qb->expr()->orX(
1186
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1187
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($uid))
1188
+                )
1189
+            );
1190
+        } else {
1191
+            \OC::$server->getLogger()->logException(new \InvalidArgumentException('Default share provider tried to delete all shares for type: ' . $shareType));
1192
+            return;
1193
+        }
1194
+
1195
+        $qb->execute();
1196
+    }
1197
+
1198
+    /**
1199
+     * Delete all shares received by this group. As well as any custom group
1200
+     * shares for group members.
1201
+     *
1202
+     * @param string $gid
1203
+     */
1204
+    public function groupDeleted($gid) {
1205
+        /*
1206 1206
 		 * First delete all custom group shares for group members
1207 1207
 		 */
1208
-		$qb = $this->dbConn->getQueryBuilder();
1209
-		$qb->select('id')
1210
-			->from('share')
1211
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)))
1212
-			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1213
-
1214
-		$cursor = $qb->execute();
1215
-		$ids = [];
1216
-		while($row = $cursor->fetch()) {
1217
-			$ids[] = (int)$row['id'];
1218
-		}
1219
-		$cursor->closeCursor();
1220
-
1221
-		if (!empty($ids)) {
1222
-			$chunks = array_chunk($ids, 100);
1223
-			foreach ($chunks as $chunk) {
1224
-				$qb->delete('share')
1225
-					->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
1226
-					->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1227
-				$qb->execute();
1228
-			}
1229
-		}
1230
-
1231
-		/*
1208
+        $qb = $this->dbConn->getQueryBuilder();
1209
+        $qb->select('id')
1210
+            ->from('share')
1211
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)))
1212
+            ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1213
+
1214
+        $cursor = $qb->execute();
1215
+        $ids = [];
1216
+        while($row = $cursor->fetch()) {
1217
+            $ids[] = (int)$row['id'];
1218
+        }
1219
+        $cursor->closeCursor();
1220
+
1221
+        if (!empty($ids)) {
1222
+            $chunks = array_chunk($ids, 100);
1223
+            foreach ($chunks as $chunk) {
1224
+                $qb->delete('share')
1225
+                    ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
1226
+                    ->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1227
+                $qb->execute();
1228
+            }
1229
+        }
1230
+
1231
+        /*
1232 1232
 		 * Now delete all the group shares
1233 1233
 		 */
1234
-		$qb = $this->dbConn->getQueryBuilder();
1235
-		$qb->delete('share')
1236
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)))
1237
-			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1238
-		$qb->execute();
1239
-	}
1240
-
1241
-	/**
1242
-	 * Delete custom group shares to this group for this user
1243
-	 *
1244
-	 * @param string $uid
1245
-	 * @param string $gid
1246
-	 */
1247
-	public function userDeletedFromGroup($uid, $gid) {
1248
-		/*
1234
+        $qb = $this->dbConn->getQueryBuilder();
1235
+        $qb->delete('share')
1236
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)))
1237
+            ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1238
+        $qb->execute();
1239
+    }
1240
+
1241
+    /**
1242
+     * Delete custom group shares to this group for this user
1243
+     *
1244
+     * @param string $uid
1245
+     * @param string $gid
1246
+     */
1247
+    public function userDeletedFromGroup($uid, $gid) {
1248
+        /*
1249 1249
 		 * Get all group shares
1250 1250
 		 */
1251
-		$qb = $this->dbConn->getQueryBuilder();
1252
-		$qb->select('id')
1253
-			->from('share')
1254
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)))
1255
-			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1256
-
1257
-		$cursor = $qb->execute();
1258
-		$ids = [];
1259
-		while($row = $cursor->fetch()) {
1260
-			$ids[] = (int)$row['id'];
1261
-		}
1262
-		$cursor->closeCursor();
1263
-
1264
-		if (!empty($ids)) {
1265
-			$chunks = array_chunk($ids, 100);
1266
-			foreach ($chunks as $chunk) {
1267
-				/*
1251
+        $qb = $this->dbConn->getQueryBuilder();
1252
+        $qb->select('id')
1253
+            ->from('share')
1254
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)))
1255
+            ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1256
+
1257
+        $cursor = $qb->execute();
1258
+        $ids = [];
1259
+        while($row = $cursor->fetch()) {
1260
+            $ids[] = (int)$row['id'];
1261
+        }
1262
+        $cursor->closeCursor();
1263
+
1264
+        if (!empty($ids)) {
1265
+            $chunks = array_chunk($ids, 100);
1266
+            foreach ($chunks as $chunk) {
1267
+                /*
1268 1268
 				 * Delete all special shares wit this users for the found group shares
1269 1269
 				 */
1270
-				$qb->delete('share')
1271
-					->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
1272
-					->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($uid)))
1273
-					->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1274
-				$qb->execute();
1275
-			}
1276
-		}
1277
-	}
1278
-
1279
-	/**
1280
-	 * @inheritdoc
1281
-	 */
1282
-	public function getAccessList($nodes, $currentAccess) {
1283
-		$ids = [];
1284
-		foreach ($nodes as $node) {
1285
-			$ids[] = $node->getId();
1286
-		}
1287
-
1288
-		$qb = $this->dbConn->getQueryBuilder();
1289
-
1290
-		$or = $qb->expr()->orX(
1291
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)),
1292
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)),
1293
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_LINK))
1294
-		);
1295
-
1296
-		if ($currentAccess) {
1297
-			$or->add($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)));
1298
-		}
1299
-
1300
-		$qb->select('id', 'parent', 'share_type', 'share_with', 'file_source', 'file_target', 'permissions')
1301
-			->from('share')
1302
-			->where(
1303
-				$or
1304
-			)
1305
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1306
-			->andWhere($qb->expr()->orX(
1307
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1308
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1309
-			));
1310
-		$cursor = $qb->execute();
1311
-
1312
-		$users = [];
1313
-		$link = false;
1314
-		while($row = $cursor->fetch()) {
1315
-			$type = (int)$row['share_type'];
1316
-			if ($type === \OCP\Share::SHARE_TYPE_USER) {
1317
-				$uid = $row['share_with'];
1318
-				$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1319
-				$users[$uid][$row['id']] = $row;
1320
-			} else if ($type === \OCP\Share::SHARE_TYPE_GROUP) {
1321
-				$gid = $row['share_with'];
1322
-				$group = $this->groupManager->get($gid);
1323
-
1324
-				if ($group === null) {
1325
-					continue;
1326
-				}
1327
-
1328
-				$userList = $group->getUsers();
1329
-				foreach ($userList as $user) {
1330
-					$uid = $user->getUID();
1331
-					$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1332
-					$users[$uid][$row['id']] = $row;
1333
-				}
1334
-			} else if ($type === \OCP\Share::SHARE_TYPE_LINK) {
1335
-				$link = true;
1336
-			} else if ($type === self::SHARE_TYPE_USERGROUP && $currentAccess === true) {
1337
-				$uid = $row['share_with'];
1338
-				$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1339
-				$users[$uid][$row['id']] = $row;
1340
-			}
1341
-		}
1342
-		$cursor->closeCursor();
1343
-
1344
-		if ($currentAccess === true) {
1345
-			$users = array_map([$this, 'filterSharesOfUser'], $users);
1346
-			$users = array_filter($users);
1347
-		} else {
1348
-			$users = array_keys($users);
1349
-		}
1350
-
1351
-		return ['users' => $users, 'public' => $link];
1352
-	}
1353
-
1354
-	/**
1355
-	 * For each user the path with the fewest slashes is returned
1356
-	 * @param array $shares
1357
-	 * @return array
1358
-	 */
1359
-	protected function filterSharesOfUser(array $shares) {
1360
-		// Group shares when the user has a share exception
1361
-		foreach ($shares as $id => $share) {
1362
-			$type = (int) $share['share_type'];
1363
-			$permissions = (int) $share['permissions'];
1364
-
1365
-			if ($type === self::SHARE_TYPE_USERGROUP) {
1366
-				unset($shares[$share['parent']]);
1367
-
1368
-				if ($permissions === 0) {
1369
-					unset($shares[$id]);
1370
-				}
1371
-			}
1372
-		}
1373
-
1374
-		$best = [];
1375
-		$bestDepth = 0;
1376
-		foreach ($shares as $id => $share) {
1377
-			$depth = substr_count($share['file_target'], '/');
1378
-			if (empty($best) || $depth < $bestDepth) {
1379
-				$bestDepth = $depth;
1380
-				$best = [
1381
-					'node_id' => $share['file_source'],
1382
-					'node_path' => $share['file_target'],
1383
-				];
1384
-			}
1385
-		}
1386
-
1387
-		return $best;
1388
-	}
1389
-
1390
-	/**
1391
-	 * propagate notes to the recipients
1392
-	 *
1393
-	 * @param IShare $share
1394
-	 * @throws \OCP\Files\NotFoundException
1395
-	 */
1396
-	private function propagateNote(IShare $share) {
1397
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
1398
-			$user = $this->userManager->get($share->getSharedWith());
1399
-			$this->sendNote([$user], $share);
1400
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
1401
-			$group = $this->groupManager->get($share->getSharedWith());
1402
-			$groupMembers = $group->getUsers();
1403
-			$this->sendNote($groupMembers, $share);
1404
-		}
1405
-	}
1406
-
1407
-	/**
1408
-	 * send note by mail
1409
-	 *
1410
-	 * @param array $recipients
1411
-	 * @param IShare $share
1412
-	 * @throws \OCP\Files\NotFoundException
1413
-	 */
1414
-	private function sendNote(array $recipients, IShare $share) {
1415
-
1416
-		$toList = [];
1417
-
1418
-		foreach ($recipients as $recipient) {
1419
-			/** @var IUser $recipient */
1420
-			$email = $recipient->getEMailAddress();
1421
-			if ($email) {
1422
-				$toList[$email] = $recipient->getDisplayName();
1423
-			}
1424
-		}
1425
-
1426
-		if (!empty($toList)) {
1427
-
1428
-			$filename = $share->getNode()->getName();
1429
-			$initiator = $share->getSharedBy();
1430
-			$note = $share->getNote();
1431
-
1432
-			$initiatorUser = $this->userManager->get($initiator);
1433
-			$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
1434
-			$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
1435
-			$plainHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
1436
-			$htmlHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
1437
-			$message = $this->mailer->createMessage();
1438
-
1439
-			$emailTemplate = $this->mailer->createEMailTemplate('defaultShareProvider.sendNote');
1440
-
1441
-			$emailTemplate->setSubject($this->l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
1442
-			$emailTemplate->addHeader();
1443
-			$emailTemplate->addHeading($htmlHeading, $plainHeading);
1444
-			$emailTemplate->addBodyText(htmlspecialchars($note), $note);
1445
-
1446
-			$link = $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]);
1447
-			$emailTemplate->addBodyButton(
1448
-				$this->l->t('Open »%s«', [$filename]),
1449
-				$link
1450
-			);
1451
-
1452
-
1453
-			// The "From" contains the sharers name
1454
-			$instanceName = $this->defaults->getName();
1455
-			$senderName = $this->l->t(
1456
-				'%1$s via %2$s',
1457
-				[
1458
-					$initiatorDisplayName,
1459
-					$instanceName
1460
-				]
1461
-			);
1462
-			$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
1463
-			if ($initiatorEmailAddress !== null) {
1464
-				$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
1465
-				$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
1466
-			} else {
1467
-				$emailTemplate->addFooter();
1468
-			}
1469
-
1470
-			if (count($toList) === 1) {
1471
-				$message->setTo($toList);
1472
-			} else {
1473
-				$message->setTo([]);
1474
-				$message->setBcc($toList);
1475
-			}
1476
-			$message->useTemplate($emailTemplate);
1477
-			$this->mailer->send($message);
1478
-		}
1479
-
1480
-	}
1481
-
1482
-	public function getAllShares(): iterable {
1483
-		$qb = $this->dbConn->getQueryBuilder();
1484
-
1485
-		$qb->select('*')
1486
-			->from('share')
1487
-			->where(
1488
-				$qb->expr()->orX(
1489
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_USER)),
1490
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_GROUP)),
1491
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_LINK))
1492
-				)
1493
-			);
1494
-
1495
-		$cursor = $qb->execute();
1496
-		while($data = $cursor->fetch()) {
1497
-			try {
1498
-				$share = $this->createShare($data);
1499
-			} catch (InvalidShare $e) {
1500
-				continue;
1501
-			}
1502
-
1503
-			yield $share;
1504
-		}
1505
-		$cursor->closeCursor();
1506
-	}
1270
+                $qb->delete('share')
1271
+                    ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
1272
+                    ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($uid)))
1273
+                    ->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1274
+                $qb->execute();
1275
+            }
1276
+        }
1277
+    }
1278
+
1279
+    /**
1280
+     * @inheritdoc
1281
+     */
1282
+    public function getAccessList($nodes, $currentAccess) {
1283
+        $ids = [];
1284
+        foreach ($nodes as $node) {
1285
+            $ids[] = $node->getId();
1286
+        }
1287
+
1288
+        $qb = $this->dbConn->getQueryBuilder();
1289
+
1290
+        $or = $qb->expr()->orX(
1291
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)),
1292
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)),
1293
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_LINK))
1294
+        );
1295
+
1296
+        if ($currentAccess) {
1297
+            $or->add($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)));
1298
+        }
1299
+
1300
+        $qb->select('id', 'parent', 'share_type', 'share_with', 'file_source', 'file_target', 'permissions')
1301
+            ->from('share')
1302
+            ->where(
1303
+                $or
1304
+            )
1305
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1306
+            ->andWhere($qb->expr()->orX(
1307
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1308
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1309
+            ));
1310
+        $cursor = $qb->execute();
1311
+
1312
+        $users = [];
1313
+        $link = false;
1314
+        while($row = $cursor->fetch()) {
1315
+            $type = (int)$row['share_type'];
1316
+            if ($type === \OCP\Share::SHARE_TYPE_USER) {
1317
+                $uid = $row['share_with'];
1318
+                $users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1319
+                $users[$uid][$row['id']] = $row;
1320
+            } else if ($type === \OCP\Share::SHARE_TYPE_GROUP) {
1321
+                $gid = $row['share_with'];
1322
+                $group = $this->groupManager->get($gid);
1323
+
1324
+                if ($group === null) {
1325
+                    continue;
1326
+                }
1327
+
1328
+                $userList = $group->getUsers();
1329
+                foreach ($userList as $user) {
1330
+                    $uid = $user->getUID();
1331
+                    $users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1332
+                    $users[$uid][$row['id']] = $row;
1333
+                }
1334
+            } else if ($type === \OCP\Share::SHARE_TYPE_LINK) {
1335
+                $link = true;
1336
+            } else if ($type === self::SHARE_TYPE_USERGROUP && $currentAccess === true) {
1337
+                $uid = $row['share_with'];
1338
+                $users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1339
+                $users[$uid][$row['id']] = $row;
1340
+            }
1341
+        }
1342
+        $cursor->closeCursor();
1343
+
1344
+        if ($currentAccess === true) {
1345
+            $users = array_map([$this, 'filterSharesOfUser'], $users);
1346
+            $users = array_filter($users);
1347
+        } else {
1348
+            $users = array_keys($users);
1349
+        }
1350
+
1351
+        return ['users' => $users, 'public' => $link];
1352
+    }
1353
+
1354
+    /**
1355
+     * For each user the path with the fewest slashes is returned
1356
+     * @param array $shares
1357
+     * @return array
1358
+     */
1359
+    protected function filterSharesOfUser(array $shares) {
1360
+        // Group shares when the user has a share exception
1361
+        foreach ($shares as $id => $share) {
1362
+            $type = (int) $share['share_type'];
1363
+            $permissions = (int) $share['permissions'];
1364
+
1365
+            if ($type === self::SHARE_TYPE_USERGROUP) {
1366
+                unset($shares[$share['parent']]);
1367
+
1368
+                if ($permissions === 0) {
1369
+                    unset($shares[$id]);
1370
+                }
1371
+            }
1372
+        }
1373
+
1374
+        $best = [];
1375
+        $bestDepth = 0;
1376
+        foreach ($shares as $id => $share) {
1377
+            $depth = substr_count($share['file_target'], '/');
1378
+            if (empty($best) || $depth < $bestDepth) {
1379
+                $bestDepth = $depth;
1380
+                $best = [
1381
+                    'node_id' => $share['file_source'],
1382
+                    'node_path' => $share['file_target'],
1383
+                ];
1384
+            }
1385
+        }
1386
+
1387
+        return $best;
1388
+    }
1389
+
1390
+    /**
1391
+     * propagate notes to the recipients
1392
+     *
1393
+     * @param IShare $share
1394
+     * @throws \OCP\Files\NotFoundException
1395
+     */
1396
+    private function propagateNote(IShare $share) {
1397
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
1398
+            $user = $this->userManager->get($share->getSharedWith());
1399
+            $this->sendNote([$user], $share);
1400
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
1401
+            $group = $this->groupManager->get($share->getSharedWith());
1402
+            $groupMembers = $group->getUsers();
1403
+            $this->sendNote($groupMembers, $share);
1404
+        }
1405
+    }
1406
+
1407
+    /**
1408
+     * send note by mail
1409
+     *
1410
+     * @param array $recipients
1411
+     * @param IShare $share
1412
+     * @throws \OCP\Files\NotFoundException
1413
+     */
1414
+    private function sendNote(array $recipients, IShare $share) {
1415
+
1416
+        $toList = [];
1417
+
1418
+        foreach ($recipients as $recipient) {
1419
+            /** @var IUser $recipient */
1420
+            $email = $recipient->getEMailAddress();
1421
+            if ($email) {
1422
+                $toList[$email] = $recipient->getDisplayName();
1423
+            }
1424
+        }
1425
+
1426
+        if (!empty($toList)) {
1427
+
1428
+            $filename = $share->getNode()->getName();
1429
+            $initiator = $share->getSharedBy();
1430
+            $note = $share->getNote();
1431
+
1432
+            $initiatorUser = $this->userManager->get($initiator);
1433
+            $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
1434
+            $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
1435
+            $plainHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
1436
+            $htmlHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
1437
+            $message = $this->mailer->createMessage();
1438
+
1439
+            $emailTemplate = $this->mailer->createEMailTemplate('defaultShareProvider.sendNote');
1440
+
1441
+            $emailTemplate->setSubject($this->l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
1442
+            $emailTemplate->addHeader();
1443
+            $emailTemplate->addHeading($htmlHeading, $plainHeading);
1444
+            $emailTemplate->addBodyText(htmlspecialchars($note), $note);
1445
+
1446
+            $link = $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]);
1447
+            $emailTemplate->addBodyButton(
1448
+                $this->l->t('Open »%s«', [$filename]),
1449
+                $link
1450
+            );
1451
+
1452
+
1453
+            // The "From" contains the sharers name
1454
+            $instanceName = $this->defaults->getName();
1455
+            $senderName = $this->l->t(
1456
+                '%1$s via %2$s',
1457
+                [
1458
+                    $initiatorDisplayName,
1459
+                    $instanceName
1460
+                ]
1461
+            );
1462
+            $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
1463
+            if ($initiatorEmailAddress !== null) {
1464
+                $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
1465
+                $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
1466
+            } else {
1467
+                $emailTemplate->addFooter();
1468
+            }
1469
+
1470
+            if (count($toList) === 1) {
1471
+                $message->setTo($toList);
1472
+            } else {
1473
+                $message->setTo([]);
1474
+                $message->setBcc($toList);
1475
+            }
1476
+            $message->useTemplate($emailTemplate);
1477
+            $this->mailer->send($message);
1478
+        }
1479
+
1480
+    }
1481
+
1482
+    public function getAllShares(): iterable {
1483
+        $qb = $this->dbConn->getQueryBuilder();
1484
+
1485
+        $qb->select('*')
1486
+            ->from('share')
1487
+            ->where(
1488
+                $qb->expr()->orX(
1489
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_USER)),
1490
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_GROUP)),
1491
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_LINK))
1492
+                )
1493
+            );
1494
+
1495
+        $cursor = $qb->execute();
1496
+        while($data = $cursor->fetch()) {
1497
+            try {
1498
+                $share = $this->createShare($data);
1499
+            } catch (InvalidShare $e) {
1500
+                continue;
1501
+            }
1502
+
1503
+            yield $share;
1504
+        }
1505
+        $cursor->closeCursor();
1506
+    }
1507 1507
 }
Please login to merge, or discard this patch.