Passed
Push — master ( 2a4926...ff2c39 )
by Joas
13:44 queued 13s
created
apps/encryption/lib/HookManager.php 1 patch
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -26,34 +26,34 @@
 block discarded – undo
26 26
 use OCA\Encryption\Hooks\Contracts\IHook;
27 27
 
28 28
 class HookManager {
29
-	/** @var IHook[] */
30
-	private $hookInstances = [];
29
+    /** @var IHook[] */
30
+    private $hookInstances = [];
31 31
 
32
-	/**
33
-	 * @param array|IHook $instances
34
-	 *        - This accepts either a single instance of IHook or an array of instances of IHook
35
-	 * @return bool
36
-	 */
37
-	public function registerHook($instances) {
38
-		if (is_array($instances)) {
39
-			foreach ($instances as $instance) {
40
-				if (!$instance instanceof IHook) {
41
-					return false;
42
-				}
43
-				$this->hookInstances[] = $instance;
44
-			}
45
-		} elseif ($instances instanceof IHook) {
46
-			$this->hookInstances[] = $instances;
47
-		}
48
-		return true;
49
-	}
32
+    /**
33
+     * @param array|IHook $instances
34
+     *        - This accepts either a single instance of IHook or an array of instances of IHook
35
+     * @return bool
36
+     */
37
+    public function registerHook($instances) {
38
+        if (is_array($instances)) {
39
+            foreach ($instances as $instance) {
40
+                if (!$instance instanceof IHook) {
41
+                    return false;
42
+                }
43
+                $this->hookInstances[] = $instance;
44
+            }
45
+        } elseif ($instances instanceof IHook) {
46
+            $this->hookInstances[] = $instances;
47
+        }
48
+        return true;
49
+    }
50 50
 
51
-	public function fireHooks() {
52
-		foreach ($this->hookInstances as $instance) {
53
-			/**
54
-			 * Fire off the add hooks method of each instance stored in cache
55
-			 */
56
-			$instance->addHooks();
57
-		}
58
-	}
51
+    public function fireHooks() {
52
+        foreach ($this->hookInstances as $instance) {
53
+            /**
54
+             * Fire off the add hooks method of each instance stored in cache
55
+             */
56
+            $instance->addHooks();
57
+        }
58
+    }
59 59
 }
Please login to merge, or discard this patch.
lib/private/Search.php 1 patch
Indentation   +76 added lines, -76 removed lines patch added patch discarded remove patch
@@ -36,85 +36,85 @@
 block discarded – undo
36 36
  * Provide an interface to all search providers
37 37
  */
38 38
 class Search implements ISearch {
39
-	/** @var Provider[] */
40
-	private $providers = [];
41
-	private $registeredProviders = [];
39
+    /** @var Provider[] */
40
+    private $providers = [];
41
+    private $registeredProviders = [];
42 42
 
43
-	/**
44
-	 * Search all providers for $query
45
-	 * @param string $query
46
-	 * @param string[] $inApps optionally limit results to the given apps
47
-	 * @param int $page pages start at page 1
48
-	 * @param int $size, 0 = all
49
-	 * @return array An array of OC\Search\Result's
50
-	 */
51
-	public function searchPaged($query, array $inApps = [], $page = 1, $size = 30) {
52
-		$this->initProviders();
53
-		$results = [];
54
-		foreach ($this->providers as $provider) {
55
-			if (! $provider->providesResultsFor($inApps)) {
56
-				continue;
57
-			}
58
-			if ($provider instanceof PagedProvider) {
59
-				$results = array_merge($results, $provider->searchPaged($query, $page, $size));
60
-			} elseif ($provider instanceof Provider) {
61
-				$providerResults = $provider->search($query);
62
-				if ($size > 0) {
63
-					$slicedResults = array_slice($providerResults, ($page - 1) * $size, $size);
64
-					$results = array_merge($results, $slicedResults);
65
-				} else {
66
-					$results = array_merge($results, $providerResults);
67
-				}
68
-			} else {
69
-				\OC::$server->getLogger()->warning('Ignoring Unknown search provider', ['provider' => $provider]);
70
-			}
71
-		}
72
-		return $results;
73
-	}
43
+    /**
44
+     * Search all providers for $query
45
+     * @param string $query
46
+     * @param string[] $inApps optionally limit results to the given apps
47
+     * @param int $page pages start at page 1
48
+     * @param int $size, 0 = all
49
+     * @return array An array of OC\Search\Result's
50
+     */
51
+    public function searchPaged($query, array $inApps = [], $page = 1, $size = 30) {
52
+        $this->initProviders();
53
+        $results = [];
54
+        foreach ($this->providers as $provider) {
55
+            if (! $provider->providesResultsFor($inApps)) {
56
+                continue;
57
+            }
58
+            if ($provider instanceof PagedProvider) {
59
+                $results = array_merge($results, $provider->searchPaged($query, $page, $size));
60
+            } elseif ($provider instanceof Provider) {
61
+                $providerResults = $provider->search($query);
62
+                if ($size > 0) {
63
+                    $slicedResults = array_slice($providerResults, ($page - 1) * $size, $size);
64
+                    $results = array_merge($results, $slicedResults);
65
+                } else {
66
+                    $results = array_merge($results, $providerResults);
67
+                }
68
+            } else {
69
+                \OC::$server->getLogger()->warning('Ignoring Unknown search provider', ['provider' => $provider]);
70
+            }
71
+        }
72
+        return $results;
73
+    }
74 74
 
75
-	/**
76
-	 * Remove all registered search providers
77
-	 */
78
-	public function clearProviders() {
79
-		$this->providers = [];
80
-		$this->registeredProviders = [];
81
-	}
75
+    /**
76
+     * Remove all registered search providers
77
+     */
78
+    public function clearProviders() {
79
+        $this->providers = [];
80
+        $this->registeredProviders = [];
81
+    }
82 82
 
83
-	/**
84
-	 * Remove one existing search provider
85
-	 * @param string $provider class name of a OC\Search\Provider
86
-	 */
87
-	public function removeProvider($provider) {
88
-		$this->registeredProviders = array_filter(
89
-			$this->registeredProviders,
90
-			function ($element) use ($provider) {
91
-				return ($element['class'] != $provider);
92
-			}
93
-		);
94
-		// force regeneration of providers on next search
95
-		$this->providers = [];
96
-	}
83
+    /**
84
+     * Remove one existing search provider
85
+     * @param string $provider class name of a OC\Search\Provider
86
+     */
87
+    public function removeProvider($provider) {
88
+        $this->registeredProviders = array_filter(
89
+            $this->registeredProviders,
90
+            function ($element) use ($provider) {
91
+                return ($element['class'] != $provider);
92
+            }
93
+        );
94
+        // force regeneration of providers on next search
95
+        $this->providers = [];
96
+    }
97 97
 
98
-	/**
99
-	 * Register a new search provider to search with
100
-	 * @param string $class class name of a OC\Search\Provider
101
-	 * @param array $options optional
102
-	 */
103
-	public function registerProvider($class, array $options = []) {
104
-		$this->registeredProviders[] = ['class' => $class, 'options' => $options];
105
-	}
98
+    /**
99
+     * Register a new search provider to search with
100
+     * @param string $class class name of a OC\Search\Provider
101
+     * @param array $options optional
102
+     */
103
+    public function registerProvider($class, array $options = []) {
104
+        $this->registeredProviders[] = ['class' => $class, 'options' => $options];
105
+    }
106 106
 
107
-	/**
108
-	 * Create instances of all the registered search providers
109
-	 */
110
-	private function initProviders() {
111
-		if (! empty($this->providers)) {
112
-			return;
113
-		}
114
-		foreach ($this->registeredProviders as $provider) {
115
-			$class = $provider['class'];
116
-			$options = $provider['options'];
117
-			$this->providers[] = new $class($options);
118
-		}
119
-	}
107
+    /**
108
+     * Create instances of all the registered search providers
109
+     */
110
+    private function initProviders() {
111
+        if (! empty($this->providers)) {
112
+            return;
113
+        }
114
+        foreach ($this->registeredProviders as $provider) {
115
+            $class = $provider['class'];
116
+            $options = $provider['options'];
117
+            $this->providers[] = new $class($options);
118
+        }
119
+    }
120 120
 }
Please login to merge, or discard this patch.
core/templates/404.php 1 patch
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -4,11 +4,11 @@
 block discarded – undo
4 4
 /** @var \OCP\Defaults $theme */
5 5
 // @codeCoverageIgnoreStart
6 6
 if (!isset($_)) {//standalone  page is not supported anymore - redirect to /
7
-	require_once '../../lib/base.php';
7
+    require_once '../../lib/base.php';
8 8
 
9
-	$urlGenerator = \OC::$server->getURLGenerator();
10
-	header('Location: ' . $urlGenerator->getAbsoluteURL('/'));
11
-	exit;
9
+    $urlGenerator = \OC::$server->getURLGenerator();
10
+    header('Location: ' . $urlGenerator->getAbsoluteURL('/'));
11
+    exit;
12 12
 }
13 13
 // @codeCoverageIgnoreEnd
14 14
 ?>
Please login to merge, or discard this patch.
apps/settings/lib/Search/AppSearch.php 1 patch
Indentation   +72 added lines, -72 removed lines patch added patch discarded remove patch
@@ -33,76 +33,76 @@
 block discarded – undo
33 33
 
34 34
 class AppSearch implements IProvider {
35 35
 
36
-	/** @var INavigationManager */
37
-	protected $navigationManager;
38
-
39
-	/** @var IL10N */
40
-	protected $l;
41
-
42
-	public function __construct(INavigationManager $navigationManager,
43
-								IL10N $l) {
44
-		$this->navigationManager = $navigationManager;
45
-		$this->l = $l;
46
-	}
47
-
48
-	/**
49
-	 * @inheritDoc
50
-	 */
51
-	public function getId(): string {
52
-		return 'settings_apps';
53
-	}
54
-
55
-	/**
56
-	 * @inheritDoc
57
-	 */
58
-	public function getName(): string {
59
-		return $this->l->t('Apps');
60
-	}
61
-
62
-	/**
63
-	 * @inheritDoc
64
-	 */
65
-	public function getOrder(string $route, array $routeParameters): int {
66
-		return -50;
67
-	}
68
-
69
-	/**
70
-	 * @inheritDoc
71
-	 */
72
-	public function search(IUser $user, ISearchQuery $query): SearchResult {
73
-		$entries = $this->navigationManager->getAll('all');
74
-
75
-		$result = [];
76
-		foreach ($entries as $entry) {
77
-			if (
78
-				stripos($entry['name'], $query->getTerm()) === false &&
79
-				stripos($entry['id'], $query->getTerm()) === false
80
-			) {
81
-				continue;
82
-			}
83
-
84
-			if (strpos($query->getRoute(), $entry['id'] . '.') === 0) {
85
-				// Skip the current app, unlikely this is intended
86
-				continue;
87
-			}
88
-
89
-			if ($entry['href'] === '') {
90
-				// Nothing we can open, so ignore
91
-				continue;
92
-			}
93
-
94
-			$result[] = new SearchResultEntry(
95
-				'',
96
-				$entry['name'],
97
-				'',
98
-				$entry['href'],
99
-				'icon-confirm'
100
-			);
101
-		}
102
-
103
-		return SearchResult::complete(
104
-			$this->l->t('Apps'),
105
-			$result
106
-		);
107
-	}
36
+    /** @var INavigationManager */
37
+    protected $navigationManager;
38
+
39
+    /** @var IL10N */
40
+    protected $l;
41
+
42
+    public function __construct(INavigationManager $navigationManager,
43
+                                IL10N $l) {
44
+        $this->navigationManager = $navigationManager;
45
+        $this->l = $l;
46
+    }
47
+
48
+    /**
49
+     * @inheritDoc
50
+     */
51
+    public function getId(): string {
52
+        return 'settings_apps';
53
+    }
54
+
55
+    /**
56
+     * @inheritDoc
57
+     */
58
+    public function getName(): string {
59
+        return $this->l->t('Apps');
60
+    }
61
+
62
+    /**
63
+     * @inheritDoc
64
+     */
65
+    public function getOrder(string $route, array $routeParameters): int {
66
+        return -50;
67
+    }
68
+
69
+    /**
70
+     * @inheritDoc
71
+     */
72
+    public function search(IUser $user, ISearchQuery $query): SearchResult {
73
+        $entries = $this->navigationManager->getAll('all');
74
+
75
+        $result = [];
76
+        foreach ($entries as $entry) {
77
+            if (
78
+                stripos($entry['name'], $query->getTerm()) === false &&
79
+                stripos($entry['id'], $query->getTerm()) === false
80
+            ) {
81
+                continue;
82
+            }
83
+
84
+            if (strpos($query->getRoute(), $entry['id'] . '.') === 0) {
85
+                // Skip the current app, unlikely this is intended
86
+                continue;
87
+            }
88
+
89
+            if ($entry['href'] === '') {
90
+                // Nothing we can open, so ignore
91
+                continue;
92
+            }
93
+
94
+            $result[] = new SearchResultEntry(
95
+                '',
96
+                $entry['name'],
97
+                '',
98
+                $entry['href'],
99
+                'icon-confirm'
100
+            );
101
+        }
102
+
103
+        return SearchResult::complete(
104
+            $this->l->t('Apps'),
105
+            $result
106
+        );
107
+    }
108 108
 }
Please login to merge, or discard this patch.
lib/public/Files/Config/IRootMountProvider.php 1 patch
Indentation   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -31,11 +31,11 @@
 block discarded – undo
31 31
  * @since 20.0.0
32 32
  */
33 33
 interface IRootMountProvider {
34
-	/**
35
-	 * Get all root mountpoints of this provider
36
-	 *
37
-	 * @return \OCP\Files\Mount\IMountPoint[]
38
-	 * @since 20.0.0
39
-	 */
40
-	public function getRootMounts(IStorageFactory $loader): array;
34
+    /**
35
+     * Get all root mountpoints of this provider
36
+     *
37
+     * @return \OCP\Files\Mount\IMountPoint[]
38
+     * @since 20.0.0
39
+     */
40
+    public function getRootMounts(IStorageFactory $loader): array;
41 41
 }
Please login to merge, or discard this patch.
apps/dav/lib/DAV/Sharing/Plugin.php 1 patch
Indentation   +171 added lines, -171 removed lines patch added patch discarded remove patch
@@ -38,175 +38,175 @@
 block discarded – undo
38 38
 use Sabre\HTTP\ResponseInterface;
39 39
 
40 40
 class Plugin extends ServerPlugin {
41
-	public const NS_OWNCLOUD = 'http://owncloud.org/ns';
42
-	public const NS_NEXTCLOUD = 'http://nextcloud.com/ns';
43
-
44
-	/** @var Auth */
45
-	private $auth;
46
-
47
-	/** @var IRequest */
48
-	private $request;
49
-
50
-	/** @var IConfig */
51
-	private $config;
52
-
53
-	/**
54
-	 * Plugin constructor.
55
-	 *
56
-	 * @param Auth $authBackEnd
57
-	 * @param IRequest $request
58
-	 * @param IConfig $config
59
-	 */
60
-	public function __construct(Auth $authBackEnd, IRequest $request, IConfig $config) {
61
-		$this->auth = $authBackEnd;
62
-		$this->request = $request;
63
-		$this->config = $config;
64
-	}
65
-
66
-	/**
67
-	 * Reference to SabreDAV server object.
68
-	 *
69
-	 * @var \Sabre\DAV\Server
70
-	 */
71
-	protected $server;
72
-
73
-	/**
74
-	 * This method should return a list of server-features.
75
-	 *
76
-	 * This is for example 'versioning' and is added to the DAV: header
77
-	 * in an OPTIONS response.
78
-	 *
79
-	 * @return string[]
80
-	 */
81
-	public function getFeatures() {
82
-		return ['oc-resource-sharing'];
83
-	}
84
-
85
-	/**
86
-	 * Returns a plugin name.
87
-	 *
88
-	 * Using this name other plugins will be able to access other plugins
89
-	 * using Sabre\DAV\Server::getPlugin
90
-	 *
91
-	 * @return string
92
-	 */
93
-	public function getPluginName() {
94
-		return 'oc-resource-sharing';
95
-	}
96
-
97
-	/**
98
-	 * This initializes the plugin.
99
-	 *
100
-	 * This function is called by Sabre\DAV\Server, after
101
-	 * addPlugin is called.
102
-	 *
103
-	 * This method should set up the required event subscriptions.
104
-	 *
105
-	 * @param Server $server
106
-	 * @return void
107
-	 */
108
-	public function initialize(Server $server) {
109
-		$this->server = $server;
110
-		$this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}share'] = ShareRequest::class;
111
-		$this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}invite'] = Invite::class;
112
-
113
-		$this->server->on('method:POST', [$this, 'httpPost']);
114
-		$this->server->on('propFind',    [$this, 'propFind']);
115
-	}
116
-
117
-	/**
118
-	 * We intercept this to handle POST requests on a dav resource.
119
-	 *
120
-	 * @param RequestInterface $request
121
-	 * @param ResponseInterface $response
122
-	 * @return null|false
123
-	 */
124
-	public function httpPost(RequestInterface $request, ResponseInterface $response) {
125
-		$path = $request->getPath();
126
-
127
-		// Only handling xml
128
-		$contentType = $request->getHeader('Content-Type');
129
-		if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false) {
130
-			return;
131
-		}
132
-
133
-		// Making sure the node exists
134
-		try {
135
-			$node = $this->server->tree->getNodeForPath($path);
136
-		} catch (NotFound $e) {
137
-			return;
138
-		}
139
-
140
-		$requestBody = $request->getBodyAsString();
141
-
142
-		// If this request handler could not deal with this POST request, it
143
-		// will return 'null' and other plugins get a chance to handle the
144
-		// request.
145
-		//
146
-		// However, we already requested the full body. This is a problem,
147
-		// because a body can only be read once. This is why we preemptively
148
-		// re-populated the request body with the existing data.
149
-		$request->setBody($requestBody);
150
-
151
-		$message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
152
-
153
-		switch ($documentType) {
154
-
155
-			// Dealing with the 'share' document, which modified invitees on a
156
-			// calendar.
157
-			case '{' . self::NS_OWNCLOUD . '}share':
158
-
159
-				// We can only deal with IShareableCalendar objects
160
-				if (!$node instanceof IShareable) {
161
-					return;
162
-				}
163
-
164
-				$this->server->transactionType = 'post-oc-resource-share';
165
-
166
-				// Getting ACL info
167
-				$acl = $this->server->getPlugin('acl');
168
-
169
-				// If there's no ACL support, we allow everything
170
-				if ($acl) {
171
-					/** @var \Sabre\DAVACL\Plugin $acl */
172
-					$acl->checkPrivileges($path, '{DAV:}write');
173
-
174
-					$limitSharingToOwner = $this->config->getAppValue('dav', 'limitAddressBookAndCalendarSharingToOwner', 'no') === 'yes';
175
-					$isOwner = $acl->getCurrentUserPrincipal() === $node->getOwner();
176
-					if ($limitSharingToOwner && !$isOwner) {
177
-						return;
178
-					}
179
-				}
180
-
181
-				$node->updateShares($message->set, $message->remove);
182
-
183
-				$response->setStatus(200);
184
-				// Adding this because sending a response body may cause issues,
185
-				// and I wanted some type of indicator the response was handled.
186
-				$response->setHeader('X-Sabre-Status', 'everything-went-well');
187
-
188
-				// Breaking the event chain
189
-				return false;
190
-		}
191
-	}
192
-
193
-	/**
194
-	 * This event is triggered when properties are requested for a certain
195
-	 * node.
196
-	 *
197
-	 * This allows us to inject any properties early.
198
-	 *
199
-	 * @param PropFind $propFind
200
-	 * @param INode $node
201
-	 * @return void
202
-	 */
203
-	public function propFind(PropFind $propFind, INode $node) {
204
-		if ($node instanceof IShareable) {
205
-			$propFind->handle('{' . Plugin::NS_OWNCLOUD . '}invite', function () use ($node) {
206
-				return new Invite(
207
-					$node->getShares()
208
-				);
209
-			});
210
-		}
211
-	}
41
+    public const NS_OWNCLOUD = 'http://owncloud.org/ns';
42
+    public const NS_NEXTCLOUD = 'http://nextcloud.com/ns';
43
+
44
+    /** @var Auth */
45
+    private $auth;
46
+
47
+    /** @var IRequest */
48
+    private $request;
49
+
50
+    /** @var IConfig */
51
+    private $config;
52
+
53
+    /**
54
+     * Plugin constructor.
55
+     *
56
+     * @param Auth $authBackEnd
57
+     * @param IRequest $request
58
+     * @param IConfig $config
59
+     */
60
+    public function __construct(Auth $authBackEnd, IRequest $request, IConfig $config) {
61
+        $this->auth = $authBackEnd;
62
+        $this->request = $request;
63
+        $this->config = $config;
64
+    }
65
+
66
+    /**
67
+     * Reference to SabreDAV server object.
68
+     *
69
+     * @var \Sabre\DAV\Server
70
+     */
71
+    protected $server;
72
+
73
+    /**
74
+     * This method should return a list of server-features.
75
+     *
76
+     * This is for example 'versioning' and is added to the DAV: header
77
+     * in an OPTIONS response.
78
+     *
79
+     * @return string[]
80
+     */
81
+    public function getFeatures() {
82
+        return ['oc-resource-sharing'];
83
+    }
84
+
85
+    /**
86
+     * Returns a plugin name.
87
+     *
88
+     * Using this name other plugins will be able to access other plugins
89
+     * using Sabre\DAV\Server::getPlugin
90
+     *
91
+     * @return string
92
+     */
93
+    public function getPluginName() {
94
+        return 'oc-resource-sharing';
95
+    }
96
+
97
+    /**
98
+     * This initializes the plugin.
99
+     *
100
+     * This function is called by Sabre\DAV\Server, after
101
+     * addPlugin is called.
102
+     *
103
+     * This method should set up the required event subscriptions.
104
+     *
105
+     * @param Server $server
106
+     * @return void
107
+     */
108
+    public function initialize(Server $server) {
109
+        $this->server = $server;
110
+        $this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}share'] = ShareRequest::class;
111
+        $this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}invite'] = Invite::class;
112
+
113
+        $this->server->on('method:POST', [$this, 'httpPost']);
114
+        $this->server->on('propFind',    [$this, 'propFind']);
115
+    }
116
+
117
+    /**
118
+     * We intercept this to handle POST requests on a dav resource.
119
+     *
120
+     * @param RequestInterface $request
121
+     * @param ResponseInterface $response
122
+     * @return null|false
123
+     */
124
+    public function httpPost(RequestInterface $request, ResponseInterface $response) {
125
+        $path = $request->getPath();
126
+
127
+        // Only handling xml
128
+        $contentType = $request->getHeader('Content-Type');
129
+        if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false) {
130
+            return;
131
+        }
132
+
133
+        // Making sure the node exists
134
+        try {
135
+            $node = $this->server->tree->getNodeForPath($path);
136
+        } catch (NotFound $e) {
137
+            return;
138
+        }
139
+
140
+        $requestBody = $request->getBodyAsString();
141
+
142
+        // If this request handler could not deal with this POST request, it
143
+        // will return 'null' and other plugins get a chance to handle the
144
+        // request.
145
+        //
146
+        // However, we already requested the full body. This is a problem,
147
+        // because a body can only be read once. This is why we preemptively
148
+        // re-populated the request body with the existing data.
149
+        $request->setBody($requestBody);
150
+
151
+        $message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
152
+
153
+        switch ($documentType) {
154
+
155
+            // Dealing with the 'share' document, which modified invitees on a
156
+            // calendar.
157
+            case '{' . self::NS_OWNCLOUD . '}share':
158
+
159
+                // We can only deal with IShareableCalendar objects
160
+                if (!$node instanceof IShareable) {
161
+                    return;
162
+                }
163
+
164
+                $this->server->transactionType = 'post-oc-resource-share';
165
+
166
+                // Getting ACL info
167
+                $acl = $this->server->getPlugin('acl');
168
+
169
+                // If there's no ACL support, we allow everything
170
+                if ($acl) {
171
+                    /** @var \Sabre\DAVACL\Plugin $acl */
172
+                    $acl->checkPrivileges($path, '{DAV:}write');
173
+
174
+                    $limitSharingToOwner = $this->config->getAppValue('dav', 'limitAddressBookAndCalendarSharingToOwner', 'no') === 'yes';
175
+                    $isOwner = $acl->getCurrentUserPrincipal() === $node->getOwner();
176
+                    if ($limitSharingToOwner && !$isOwner) {
177
+                        return;
178
+                    }
179
+                }
180
+
181
+                $node->updateShares($message->set, $message->remove);
182
+
183
+                $response->setStatus(200);
184
+                // Adding this because sending a response body may cause issues,
185
+                // and I wanted some type of indicator the response was handled.
186
+                $response->setHeader('X-Sabre-Status', 'everything-went-well');
187
+
188
+                // Breaking the event chain
189
+                return false;
190
+        }
191
+    }
192
+
193
+    /**
194
+     * This event is triggered when properties are requested for a certain
195
+     * node.
196
+     *
197
+     * This allows us to inject any properties early.
198
+     *
199
+     * @param PropFind $propFind
200
+     * @param INode $node
201
+     * @return void
202
+     */
203
+    public function propFind(PropFind $propFind, INode $node) {
204
+        if ($node instanceof IShareable) {
205
+            $propFind->handle('{' . Plugin::NS_OWNCLOUD . '}invite', function () use ($node) {
206
+                return new Invite(
207
+                    $node->getShares()
208
+                );
209
+            });
210
+        }
211
+    }
212 212
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Migration/DummyUserSession.php 1 patch
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -29,45 +29,45 @@
 block discarded – undo
29 29
 
30 30
 class DummyUserSession implements IUserSession {
31 31
 
32
-	/**
33
-	 * @var IUser
34
-	 */
35
-	private $user;
32
+    /**
33
+     * @var IUser
34
+     */
35
+    private $user;
36 36
 
37
-	public function login($uid, $password) {
38
-	}
37
+    public function login($uid, $password) {
38
+    }
39 39
 
40
-	public function logout() {
41
-	}
40
+    public function logout() {
41
+    }
42 42
 
43
-	public function setUser($user) {
44
-		$this->user = $user;
45
-	}
43
+    public function setUser($user) {
44
+        $this->user = $user;
45
+    }
46 46
 
47
-	public function getUser() {
48
-		return $this->user;
49
-	}
47
+    public function getUser() {
48
+        return $this->user;
49
+    }
50 50
 
51
-	public function isLoggedIn() {
52
-		return !is_null($this->user);
53
-	}
51
+    public function isLoggedIn() {
52
+        return !is_null($this->user);
53
+    }
54 54
 
55
-	/**
56
-	 * get getImpersonatingUserID
57
-	 *
58
-	 * @return string|null
59
-	 * @since 17.0.0
60
-	 */
61
-	public function getImpersonatingUserID() : ?string {
62
-		return null;
63
-	}
55
+    /**
56
+     * get getImpersonatingUserID
57
+     *
58
+     * @return string|null
59
+     * @since 17.0.0
60
+     */
61
+    public function getImpersonatingUserID() : ?string {
62
+        return null;
63
+    }
64 64
 
65
-	/**
66
-	 * set setImpersonatingUserID
67
-	 *
68
-	 * @since 17.0.0
69
-	 */
70
-	public function setImpersonatingUserID(bool $useCurrentUser = true): void {
71
-		//no OP
72
-	}
65
+    /**
66
+     * set setImpersonatingUserID
67
+     *
68
+     * @since 17.0.0
69
+     */
70
+    public function setImpersonatingUserID(bool $useCurrentUser = true): void {
71
+        //no OP
72
+    }
73 73
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Lib/Auth/Password/UserProvided.php 1 patch
Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -38,51 +38,51 @@
 block discarded – undo
38 38
  * User provided Username and Password
39 39
  */
40 40
 class UserProvided extends AuthMechanism implements IUserProvided {
41
-	public const CREDENTIALS_IDENTIFIER_PREFIX = 'password::userprovided/';
41
+    public const CREDENTIALS_IDENTIFIER_PREFIX = 'password::userprovided/';
42 42
 
43
-	/** @var ICredentialsManager */
44
-	protected $credentialsManager;
43
+    /** @var ICredentialsManager */
44
+    protected $credentialsManager;
45 45
 
46
-	public function __construct(IL10N $l, ICredentialsManager $credentialsManager) {
47
-		$this->credentialsManager = $credentialsManager;
46
+    public function __construct(IL10N $l, ICredentialsManager $credentialsManager) {
47
+        $this->credentialsManager = $credentialsManager;
48 48
 
49
-		$this
50
-			->setIdentifier('password::userprovided')
51
-			->setVisibility(BackendService::VISIBILITY_ADMIN)
52
-			->setScheme(self::SCHEME_PASSWORD)
53
-			->setText($l->t('User entered, store in database'))
54
-			->addParameters([
55
-				(new DefinitionParameter('user', $l->t('Username')))
56
-					->setFlag(DefinitionParameter::FLAG_USER_PROVIDED),
57
-				(new DefinitionParameter('password', $l->t('Password')))
58
-					->setType(DefinitionParameter::VALUE_PASSWORD)
59
-					->setFlag(DefinitionParameter::FLAG_USER_PROVIDED),
60
-			]);
61
-	}
49
+        $this
50
+            ->setIdentifier('password::userprovided')
51
+            ->setVisibility(BackendService::VISIBILITY_ADMIN)
52
+            ->setScheme(self::SCHEME_PASSWORD)
53
+            ->setText($l->t('User entered, store in database'))
54
+            ->addParameters([
55
+                (new DefinitionParameter('user', $l->t('Username')))
56
+                    ->setFlag(DefinitionParameter::FLAG_USER_PROVIDED),
57
+                (new DefinitionParameter('password', $l->t('Password')))
58
+                    ->setType(DefinitionParameter::VALUE_PASSWORD)
59
+                    ->setFlag(DefinitionParameter::FLAG_USER_PROVIDED),
60
+            ]);
61
+    }
62 62
 
63
-	private function getCredentialsIdentifier($storageId) {
64
-		return self::CREDENTIALS_IDENTIFIER_PREFIX . $storageId;
65
-	}
63
+    private function getCredentialsIdentifier($storageId) {
64
+        return self::CREDENTIALS_IDENTIFIER_PREFIX . $storageId;
65
+    }
66 66
 
67
-	public function saveBackendOptions(IUser $user, $mountId, array $options) {
68
-		$this->credentialsManager->store($user->getUID(), $this->getCredentialsIdentifier($mountId), [
69
-			'user' => $options['user'], // explicitly copy the fields we want instead of just passing the entire $options array
70
-			'password' => $options['password'] // this way we prevent users from being able to modify any other field
71
-		]);
72
-	}
67
+    public function saveBackendOptions(IUser $user, $mountId, array $options) {
68
+        $this->credentialsManager->store($user->getUID(), $this->getCredentialsIdentifier($mountId), [
69
+            'user' => $options['user'], // explicitly copy the fields we want instead of just passing the entire $options array
70
+            'password' => $options['password'] // this way we prevent users from being able to modify any other field
71
+        ]);
72
+    }
73 73
 
74
-	public function manipulateStorageConfig(StorageConfig &$storage, IUser $user = null) {
75
-		if (!isset($user)) {
76
-			throw new InsufficientDataForMeaningfulAnswerException('No credentials saved');
77
-		}
78
-		$uid = $user->getUID();
79
-		$credentials = $this->credentialsManager->retrieve($uid, $this->getCredentialsIdentifier($storage->getId()));
74
+    public function manipulateStorageConfig(StorageConfig &$storage, IUser $user = null) {
75
+        if (!isset($user)) {
76
+            throw new InsufficientDataForMeaningfulAnswerException('No credentials saved');
77
+        }
78
+        $uid = $user->getUID();
79
+        $credentials = $this->credentialsManager->retrieve($uid, $this->getCredentialsIdentifier($storage->getId()));
80 80
 
81
-		if (!isset($credentials)) {
82
-			throw new InsufficientDataForMeaningfulAnswerException('No credentials saved');
83
-		}
81
+        if (!isset($credentials)) {
82
+            throw new InsufficientDataForMeaningfulAnswerException('No credentials saved');
83
+        }
84 84
 
85
-		$storage->setBackendOption('user', $credentials['user']);
86
-		$storage->setBackendOption('password', $credentials['password']);
87
-	}
85
+        $storage->setBackendOption('user', $credentials['user']);
86
+        $storage->setBackendOption('password', $credentials['password']);
87
+    }
88 88
 }
Please login to merge, or discard this patch.
lib/private/SystemTag/SystemTagManager.php 1 patch
Indentation   +385 added lines, -385 removed lines patch added patch discarded remove patch
@@ -45,389 +45,389 @@
 block discarded – undo
45 45
  * Manager class for system tags
46 46
  */
47 47
 class SystemTagManager implements ISystemTagManager {
48
-	public const TAG_TABLE = 'systemtag';
49
-	public const TAG_GROUP_TABLE = 'systemtag_group';
50
-
51
-	/** @var IDBConnection */
52
-	protected $connection;
53
-
54
-	/** @var EventDispatcherInterface */
55
-	protected $dispatcher;
56
-
57
-	/** @var IGroupManager */
58
-	protected $groupManager;
59
-
60
-	/**
61
-	 * Prepared query for selecting tags directly
62
-	 *
63
-	 * @var \OCP\DB\QueryBuilder\IQueryBuilder
64
-	 */
65
-	private $selectTagQuery;
66
-
67
-	/**
68
-	 * Constructor.
69
-	 *
70
-	 * @param IDBConnection $connection database connection
71
-	 * @param IGroupManager $groupManager
72
-	 * @param EventDispatcherInterface $dispatcher
73
-	 */
74
-	public function __construct(
75
-		IDBConnection $connection,
76
-		IGroupManager $groupManager,
77
-		EventDispatcherInterface $dispatcher
78
-	) {
79
-		$this->connection = $connection;
80
-		$this->groupManager = $groupManager;
81
-		$this->dispatcher = $dispatcher;
82
-
83
-		$query = $this->connection->getQueryBuilder();
84
-		$this->selectTagQuery = $query->select('*')
85
-			->from(self::TAG_TABLE)
86
-			->where($query->expr()->eq('name', $query->createParameter('name')))
87
-			->andWhere($query->expr()->eq('visibility', $query->createParameter('visibility')))
88
-			->andWhere($query->expr()->eq('editable', $query->createParameter('editable')));
89
-	}
90
-
91
-	/**
92
-	 * {@inheritdoc}
93
-	 */
94
-	public function getTagsByIds($tagIds): array {
95
-		if (!\is_array($tagIds)) {
96
-			$tagIds = [$tagIds];
97
-		}
98
-
99
-		$tags = [];
100
-
101
-		// note: not all databases will fail if it's a string or starts with a number
102
-		foreach ($tagIds as $tagId) {
103
-			if (!is_numeric($tagId)) {
104
-				throw new \InvalidArgumentException('Tag id must be integer');
105
-			}
106
-		}
107
-
108
-		$query = $this->connection->getQueryBuilder();
109
-		$query->select('*')
110
-			->from(self::TAG_TABLE)
111
-			->where($query->expr()->in('id', $query->createParameter('tagids')))
112
-			->addOrderBy('name', 'ASC')
113
-			->addOrderBy('visibility', 'ASC')
114
-			->addOrderBy('editable', 'ASC')
115
-			->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY);
116
-
117
-		$result = $query->execute();
118
-		while ($row = $result->fetch()) {
119
-			$tags[$row['id']] = $this->createSystemTagFromRow($row);
120
-		}
121
-
122
-		$result->closeCursor();
123
-
124
-		if (\count($tags) !== \count($tagIds)) {
125
-			throw new TagNotFoundException(
126
-				'Tag id(s) not found', 0, null, array_diff($tagIds, array_keys($tags))
127
-			);
128
-		}
129
-
130
-		return $tags;
131
-	}
132
-
133
-	/**
134
-	 * {@inheritdoc}
135
-	 */
136
-	public function getAllTags($visibilityFilter = null, $nameSearchPattern = null): array {
137
-		$tags = [];
138
-
139
-		$query = $this->connection->getQueryBuilder();
140
-		$query->select('*')
141
-			->from(self::TAG_TABLE);
142
-
143
-		if (!\is_null($visibilityFilter)) {
144
-			$query->andWhere($query->expr()->eq('visibility', $query->createNamedParameter((int)$visibilityFilter)));
145
-		}
146
-
147
-		if (!empty($nameSearchPattern)) {
148
-			$query->andWhere(
149
-				$query->expr()->like(
150
-					'name',
151
-					$query->createNamedParameter('%' . $this->connection->escapeLikeParameter($nameSearchPattern). '%')
152
-				)
153
-			);
154
-		}
155
-
156
-		$query
157
-			->addOrderBy('name', 'ASC')
158
-			->addOrderBy('visibility', 'ASC')
159
-			->addOrderBy('editable', 'ASC');
160
-
161
-		$result = $query->execute();
162
-		while ($row = $result->fetch()) {
163
-			$tags[$row['id']] = $this->createSystemTagFromRow($row);
164
-		}
165
-
166
-		$result->closeCursor();
167
-
168
-		return $tags;
169
-	}
170
-
171
-	/**
172
-	 * {@inheritdoc}
173
-	 */
174
-	public function getTag(string $tagName, bool $userVisible, bool $userAssignable): ISystemTag {
175
-		$result = $this->selectTagQuery
176
-			->setParameter('name', $tagName)
177
-			->setParameter('visibility', $userVisible ? 1 : 0)
178
-			->setParameter('editable', $userAssignable ? 1 : 0)
179
-			->execute();
180
-
181
-		$row = $result->fetch();
182
-		$result->closeCursor();
183
-		if (!$row) {
184
-			throw new TagNotFoundException(
185
-				'Tag ("' . $tagName . '", '. $userVisible . ', ' . $userAssignable . ') does not exist'
186
-			);
187
-		}
188
-
189
-		return $this->createSystemTagFromRow($row);
190
-	}
191
-
192
-	/**
193
-	 * {@inheritdoc}
194
-	 */
195
-	public function createTag(string $tagName, bool $userVisible, bool $userAssignable): ISystemTag {
196
-		$query = $this->connection->getQueryBuilder();
197
-		$query->insert(self::TAG_TABLE)
198
-			->values([
199
-				'name' => $query->createNamedParameter($tagName),
200
-				'visibility' => $query->createNamedParameter($userVisible ? 1 : 0),
201
-				'editable' => $query->createNamedParameter($userAssignable ? 1 : 0),
202
-			]);
203
-
204
-		try {
205
-			$query->execute();
206
-		} catch (UniqueConstraintViolationException $e) {
207
-			throw new TagAlreadyExistsException(
208
-				'Tag ("' . $tagName . '", '. $userVisible . ', ' . $userAssignable . ') already exists',
209
-				0,
210
-				$e
211
-			);
212
-		}
213
-
214
-		$tagId = $query->getLastInsertId();
215
-
216
-		$tag = new SystemTag(
217
-			(string)$tagId,
218
-			$tagName,
219
-			$userVisible,
220
-			$userAssignable
221
-		);
222
-
223
-		$this->dispatcher->dispatch(ManagerEvent::EVENT_CREATE, new ManagerEvent(
224
-			ManagerEvent::EVENT_CREATE, $tag
225
-		));
226
-
227
-		return $tag;
228
-	}
229
-
230
-	/**
231
-	 * {@inheritdoc}
232
-	 */
233
-	public function updateTag(string $tagId, string $newName, bool $userVisible, bool $userAssignable) {
234
-		try {
235
-			$tags = $this->getTagsByIds($tagId);
236
-		} catch (TagNotFoundException $e) {
237
-			throw new TagNotFoundException(
238
-				'Tag does not exist', 0, null, [$tagId]
239
-			);
240
-		}
241
-
242
-		$beforeUpdate = array_shift($tags);
243
-		$afterUpdate = new SystemTag(
244
-			$tagId,
245
-			$newName,
246
-			$userVisible,
247
-			$userAssignable
248
-		);
249
-
250
-		$query = $this->connection->getQueryBuilder();
251
-		$query->update(self::TAG_TABLE)
252
-			->set('name', $query->createParameter('name'))
253
-			->set('visibility', $query->createParameter('visibility'))
254
-			->set('editable', $query->createParameter('editable'))
255
-			->where($query->expr()->eq('id', $query->createParameter('tagid')))
256
-			->setParameter('name', $newName)
257
-			->setParameter('visibility', $userVisible ? 1 : 0)
258
-			->setParameter('editable', $userAssignable ? 1 : 0)
259
-			->setParameter('tagid', $tagId);
260
-
261
-		try {
262
-			if ($query->execute() === 0) {
263
-				throw new TagNotFoundException(
264
-					'Tag does not exist', 0, null, [$tagId]
265
-				);
266
-			}
267
-		} catch (UniqueConstraintViolationException $e) {
268
-			throw new TagAlreadyExistsException(
269
-				'Tag ("' . $newName . '", '. $userVisible . ', ' . $userAssignable . ') already exists',
270
-				0,
271
-				$e
272
-			);
273
-		}
274
-
275
-		$this->dispatcher->dispatch(ManagerEvent::EVENT_UPDATE, new ManagerEvent(
276
-			ManagerEvent::EVENT_UPDATE, $afterUpdate, $beforeUpdate
277
-		));
278
-	}
279
-
280
-	/**
281
-	 * {@inheritdoc}
282
-	 */
283
-	public function deleteTags($tagIds) {
284
-		if (!\is_array($tagIds)) {
285
-			$tagIds = [$tagIds];
286
-		}
287
-
288
-		$tagNotFoundException = null;
289
-		$tags = [];
290
-		try {
291
-			$tags = $this->getTagsByIds($tagIds);
292
-		} catch (TagNotFoundException $e) {
293
-			$tagNotFoundException = $e;
294
-
295
-			// Get existing tag objects for the hooks later
296
-			$existingTags = array_diff($tagIds, $tagNotFoundException->getMissingTags());
297
-			if (!empty($existingTags)) {
298
-				try {
299
-					$tags = $this->getTagsByIds($existingTags);
300
-				} catch (TagNotFoundException $e) {
301
-					// Ignore further errors...
302
-				}
303
-			}
304
-		}
305
-
306
-		// delete relationships first
307
-		$query = $this->connection->getQueryBuilder();
308
-		$query->delete(SystemTagObjectMapper::RELATION_TABLE)
309
-			->where($query->expr()->in('systemtagid', $query->createParameter('tagids')))
310
-			->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY)
311
-			->execute();
312
-
313
-		$query = $this->connection->getQueryBuilder();
314
-		$query->delete(self::TAG_TABLE)
315
-			->where($query->expr()->in('id', $query->createParameter('tagids')))
316
-			->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY)
317
-			->execute();
318
-
319
-		foreach ($tags as $tag) {
320
-			$this->dispatcher->dispatch(ManagerEvent::EVENT_DELETE, new ManagerEvent(
321
-				ManagerEvent::EVENT_DELETE, $tag
322
-			));
323
-		}
324
-
325
-		if ($tagNotFoundException !== null) {
326
-			throw new TagNotFoundException(
327
-				'Tag id(s) not found', 0, $tagNotFoundException, $tagNotFoundException->getMissingTags()
328
-			);
329
-		}
330
-	}
331
-
332
-	/**
333
-	 * {@inheritdoc}
334
-	 */
335
-	public function canUserAssignTag(ISystemTag $tag, IUser $user): bool {
336
-		// early check to avoid unneeded group lookups
337
-		if ($tag->isUserAssignable() && $tag->isUserVisible()) {
338
-			return true;
339
-		}
340
-
341
-		if ($this->groupManager->isAdmin($user->getUID())) {
342
-			return true;
343
-		}
344
-
345
-		if (!$tag->isUserVisible()) {
346
-			return false;
347
-		}
348
-
349
-		$groupIds = $this->groupManager->getUserGroupIds($user);
350
-		if (!empty($groupIds)) {
351
-			$matchingGroups = array_intersect($groupIds, $this->getTagGroups($tag));
352
-			if (!empty($matchingGroups)) {
353
-				return true;
354
-			}
355
-		}
356
-
357
-		return false;
358
-	}
359
-
360
-	/**
361
-	 * {@inheritdoc}
362
-	 */
363
-	public function canUserSeeTag(ISystemTag $tag, IUser $user): bool {
364
-		if ($tag->isUserVisible()) {
365
-			return true;
366
-		}
367
-
368
-		if ($this->groupManager->isAdmin($user->getUID())) {
369
-			return true;
370
-		}
371
-
372
-		return false;
373
-	}
374
-
375
-	private function createSystemTagFromRow($row) {
376
-		return new SystemTag((string)$row['id'], $row['name'], (bool)$row['visibility'], (bool)$row['editable']);
377
-	}
378
-
379
-	/**
380
-	 * {@inheritdoc}
381
-	 */
382
-	public function setTagGroups(ISystemTag $tag, array $groupIds) {
383
-		// delete relationships first
384
-		$this->connection->beginTransaction();
385
-		try {
386
-			$query = $this->connection->getQueryBuilder();
387
-			$query->delete(self::TAG_GROUP_TABLE)
388
-				->where($query->expr()->eq('systemtagid', $query->createNamedParameter($tag->getId())))
389
-				->execute();
390
-
391
-			// add each group id
392
-			$query = $this->connection->getQueryBuilder();
393
-			$query->insert(self::TAG_GROUP_TABLE)
394
-				->values([
395
-					'systemtagid' => $query->createNamedParameter($tag->getId()),
396
-					'gid' => $query->createParameter('gid'),
397
-				]);
398
-			foreach ($groupIds as $groupId) {
399
-				if ($groupId === '') {
400
-					continue;
401
-				}
402
-				$query->setParameter('gid', $groupId);
403
-				$query->execute();
404
-			}
405
-
406
-			$this->connection->commit();
407
-		} catch (\Exception $e) {
408
-			$this->connection->rollBack();
409
-			throw $e;
410
-		}
411
-	}
412
-
413
-	/**
414
-	 * {@inheritdoc}
415
-	 */
416
-	public function getTagGroups(ISystemTag $tag): array {
417
-		$groupIds = [];
418
-		$query = $this->connection->getQueryBuilder();
419
-		$query->select('gid')
420
-			->from(self::TAG_GROUP_TABLE)
421
-			->where($query->expr()->eq('systemtagid', $query->createNamedParameter($tag->getId())))
422
-			->orderBy('gid');
423
-
424
-		$result = $query->execute();
425
-		while ($row = $result->fetch()) {
426
-			$groupIds[] = $row['gid'];
427
-		}
428
-
429
-		$result->closeCursor();
430
-
431
-		return $groupIds;
432
-	}
48
+    public const TAG_TABLE = 'systemtag';
49
+    public const TAG_GROUP_TABLE = 'systemtag_group';
50
+
51
+    /** @var IDBConnection */
52
+    protected $connection;
53
+
54
+    /** @var EventDispatcherInterface */
55
+    protected $dispatcher;
56
+
57
+    /** @var IGroupManager */
58
+    protected $groupManager;
59
+
60
+    /**
61
+     * Prepared query for selecting tags directly
62
+     *
63
+     * @var \OCP\DB\QueryBuilder\IQueryBuilder
64
+     */
65
+    private $selectTagQuery;
66
+
67
+    /**
68
+     * Constructor.
69
+     *
70
+     * @param IDBConnection $connection database connection
71
+     * @param IGroupManager $groupManager
72
+     * @param EventDispatcherInterface $dispatcher
73
+     */
74
+    public function __construct(
75
+        IDBConnection $connection,
76
+        IGroupManager $groupManager,
77
+        EventDispatcherInterface $dispatcher
78
+    ) {
79
+        $this->connection = $connection;
80
+        $this->groupManager = $groupManager;
81
+        $this->dispatcher = $dispatcher;
82
+
83
+        $query = $this->connection->getQueryBuilder();
84
+        $this->selectTagQuery = $query->select('*')
85
+            ->from(self::TAG_TABLE)
86
+            ->where($query->expr()->eq('name', $query->createParameter('name')))
87
+            ->andWhere($query->expr()->eq('visibility', $query->createParameter('visibility')))
88
+            ->andWhere($query->expr()->eq('editable', $query->createParameter('editable')));
89
+    }
90
+
91
+    /**
92
+     * {@inheritdoc}
93
+     */
94
+    public function getTagsByIds($tagIds): array {
95
+        if (!\is_array($tagIds)) {
96
+            $tagIds = [$tagIds];
97
+        }
98
+
99
+        $tags = [];
100
+
101
+        // note: not all databases will fail if it's a string or starts with a number
102
+        foreach ($tagIds as $tagId) {
103
+            if (!is_numeric($tagId)) {
104
+                throw new \InvalidArgumentException('Tag id must be integer');
105
+            }
106
+        }
107
+
108
+        $query = $this->connection->getQueryBuilder();
109
+        $query->select('*')
110
+            ->from(self::TAG_TABLE)
111
+            ->where($query->expr()->in('id', $query->createParameter('tagids')))
112
+            ->addOrderBy('name', 'ASC')
113
+            ->addOrderBy('visibility', 'ASC')
114
+            ->addOrderBy('editable', 'ASC')
115
+            ->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY);
116
+
117
+        $result = $query->execute();
118
+        while ($row = $result->fetch()) {
119
+            $tags[$row['id']] = $this->createSystemTagFromRow($row);
120
+        }
121
+
122
+        $result->closeCursor();
123
+
124
+        if (\count($tags) !== \count($tagIds)) {
125
+            throw new TagNotFoundException(
126
+                'Tag id(s) not found', 0, null, array_diff($tagIds, array_keys($tags))
127
+            );
128
+        }
129
+
130
+        return $tags;
131
+    }
132
+
133
+    /**
134
+     * {@inheritdoc}
135
+     */
136
+    public function getAllTags($visibilityFilter = null, $nameSearchPattern = null): array {
137
+        $tags = [];
138
+
139
+        $query = $this->connection->getQueryBuilder();
140
+        $query->select('*')
141
+            ->from(self::TAG_TABLE);
142
+
143
+        if (!\is_null($visibilityFilter)) {
144
+            $query->andWhere($query->expr()->eq('visibility', $query->createNamedParameter((int)$visibilityFilter)));
145
+        }
146
+
147
+        if (!empty($nameSearchPattern)) {
148
+            $query->andWhere(
149
+                $query->expr()->like(
150
+                    'name',
151
+                    $query->createNamedParameter('%' . $this->connection->escapeLikeParameter($nameSearchPattern). '%')
152
+                )
153
+            );
154
+        }
155
+
156
+        $query
157
+            ->addOrderBy('name', 'ASC')
158
+            ->addOrderBy('visibility', 'ASC')
159
+            ->addOrderBy('editable', 'ASC');
160
+
161
+        $result = $query->execute();
162
+        while ($row = $result->fetch()) {
163
+            $tags[$row['id']] = $this->createSystemTagFromRow($row);
164
+        }
165
+
166
+        $result->closeCursor();
167
+
168
+        return $tags;
169
+    }
170
+
171
+    /**
172
+     * {@inheritdoc}
173
+     */
174
+    public function getTag(string $tagName, bool $userVisible, bool $userAssignable): ISystemTag {
175
+        $result = $this->selectTagQuery
176
+            ->setParameter('name', $tagName)
177
+            ->setParameter('visibility', $userVisible ? 1 : 0)
178
+            ->setParameter('editable', $userAssignable ? 1 : 0)
179
+            ->execute();
180
+
181
+        $row = $result->fetch();
182
+        $result->closeCursor();
183
+        if (!$row) {
184
+            throw new TagNotFoundException(
185
+                'Tag ("' . $tagName . '", '. $userVisible . ', ' . $userAssignable . ') does not exist'
186
+            );
187
+        }
188
+
189
+        return $this->createSystemTagFromRow($row);
190
+    }
191
+
192
+    /**
193
+     * {@inheritdoc}
194
+     */
195
+    public function createTag(string $tagName, bool $userVisible, bool $userAssignable): ISystemTag {
196
+        $query = $this->connection->getQueryBuilder();
197
+        $query->insert(self::TAG_TABLE)
198
+            ->values([
199
+                'name' => $query->createNamedParameter($tagName),
200
+                'visibility' => $query->createNamedParameter($userVisible ? 1 : 0),
201
+                'editable' => $query->createNamedParameter($userAssignable ? 1 : 0),
202
+            ]);
203
+
204
+        try {
205
+            $query->execute();
206
+        } catch (UniqueConstraintViolationException $e) {
207
+            throw new TagAlreadyExistsException(
208
+                'Tag ("' . $tagName . '", '. $userVisible . ', ' . $userAssignable . ') already exists',
209
+                0,
210
+                $e
211
+            );
212
+        }
213
+
214
+        $tagId = $query->getLastInsertId();
215
+
216
+        $tag = new SystemTag(
217
+            (string)$tagId,
218
+            $tagName,
219
+            $userVisible,
220
+            $userAssignable
221
+        );
222
+
223
+        $this->dispatcher->dispatch(ManagerEvent::EVENT_CREATE, new ManagerEvent(
224
+            ManagerEvent::EVENT_CREATE, $tag
225
+        ));
226
+
227
+        return $tag;
228
+    }
229
+
230
+    /**
231
+     * {@inheritdoc}
232
+     */
233
+    public function updateTag(string $tagId, string $newName, bool $userVisible, bool $userAssignable) {
234
+        try {
235
+            $tags = $this->getTagsByIds($tagId);
236
+        } catch (TagNotFoundException $e) {
237
+            throw new TagNotFoundException(
238
+                'Tag does not exist', 0, null, [$tagId]
239
+            );
240
+        }
241
+
242
+        $beforeUpdate = array_shift($tags);
243
+        $afterUpdate = new SystemTag(
244
+            $tagId,
245
+            $newName,
246
+            $userVisible,
247
+            $userAssignable
248
+        );
249
+
250
+        $query = $this->connection->getQueryBuilder();
251
+        $query->update(self::TAG_TABLE)
252
+            ->set('name', $query->createParameter('name'))
253
+            ->set('visibility', $query->createParameter('visibility'))
254
+            ->set('editable', $query->createParameter('editable'))
255
+            ->where($query->expr()->eq('id', $query->createParameter('tagid')))
256
+            ->setParameter('name', $newName)
257
+            ->setParameter('visibility', $userVisible ? 1 : 0)
258
+            ->setParameter('editable', $userAssignable ? 1 : 0)
259
+            ->setParameter('tagid', $tagId);
260
+
261
+        try {
262
+            if ($query->execute() === 0) {
263
+                throw new TagNotFoundException(
264
+                    'Tag does not exist', 0, null, [$tagId]
265
+                );
266
+            }
267
+        } catch (UniqueConstraintViolationException $e) {
268
+            throw new TagAlreadyExistsException(
269
+                'Tag ("' . $newName . '", '. $userVisible . ', ' . $userAssignable . ') already exists',
270
+                0,
271
+                $e
272
+            );
273
+        }
274
+
275
+        $this->dispatcher->dispatch(ManagerEvent::EVENT_UPDATE, new ManagerEvent(
276
+            ManagerEvent::EVENT_UPDATE, $afterUpdate, $beforeUpdate
277
+        ));
278
+    }
279
+
280
+    /**
281
+     * {@inheritdoc}
282
+     */
283
+    public function deleteTags($tagIds) {
284
+        if (!\is_array($tagIds)) {
285
+            $tagIds = [$tagIds];
286
+        }
287
+
288
+        $tagNotFoundException = null;
289
+        $tags = [];
290
+        try {
291
+            $tags = $this->getTagsByIds($tagIds);
292
+        } catch (TagNotFoundException $e) {
293
+            $tagNotFoundException = $e;
294
+
295
+            // Get existing tag objects for the hooks later
296
+            $existingTags = array_diff($tagIds, $tagNotFoundException->getMissingTags());
297
+            if (!empty($existingTags)) {
298
+                try {
299
+                    $tags = $this->getTagsByIds($existingTags);
300
+                } catch (TagNotFoundException $e) {
301
+                    // Ignore further errors...
302
+                }
303
+            }
304
+        }
305
+
306
+        // delete relationships first
307
+        $query = $this->connection->getQueryBuilder();
308
+        $query->delete(SystemTagObjectMapper::RELATION_TABLE)
309
+            ->where($query->expr()->in('systemtagid', $query->createParameter('tagids')))
310
+            ->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY)
311
+            ->execute();
312
+
313
+        $query = $this->connection->getQueryBuilder();
314
+        $query->delete(self::TAG_TABLE)
315
+            ->where($query->expr()->in('id', $query->createParameter('tagids')))
316
+            ->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY)
317
+            ->execute();
318
+
319
+        foreach ($tags as $tag) {
320
+            $this->dispatcher->dispatch(ManagerEvent::EVENT_DELETE, new ManagerEvent(
321
+                ManagerEvent::EVENT_DELETE, $tag
322
+            ));
323
+        }
324
+
325
+        if ($tagNotFoundException !== null) {
326
+            throw new TagNotFoundException(
327
+                'Tag id(s) not found', 0, $tagNotFoundException, $tagNotFoundException->getMissingTags()
328
+            );
329
+        }
330
+    }
331
+
332
+    /**
333
+     * {@inheritdoc}
334
+     */
335
+    public function canUserAssignTag(ISystemTag $tag, IUser $user): bool {
336
+        // early check to avoid unneeded group lookups
337
+        if ($tag->isUserAssignable() && $tag->isUserVisible()) {
338
+            return true;
339
+        }
340
+
341
+        if ($this->groupManager->isAdmin($user->getUID())) {
342
+            return true;
343
+        }
344
+
345
+        if (!$tag->isUserVisible()) {
346
+            return false;
347
+        }
348
+
349
+        $groupIds = $this->groupManager->getUserGroupIds($user);
350
+        if (!empty($groupIds)) {
351
+            $matchingGroups = array_intersect($groupIds, $this->getTagGroups($tag));
352
+            if (!empty($matchingGroups)) {
353
+                return true;
354
+            }
355
+        }
356
+
357
+        return false;
358
+    }
359
+
360
+    /**
361
+     * {@inheritdoc}
362
+     */
363
+    public function canUserSeeTag(ISystemTag $tag, IUser $user): bool {
364
+        if ($tag->isUserVisible()) {
365
+            return true;
366
+        }
367
+
368
+        if ($this->groupManager->isAdmin($user->getUID())) {
369
+            return true;
370
+        }
371
+
372
+        return false;
373
+    }
374
+
375
+    private function createSystemTagFromRow($row) {
376
+        return new SystemTag((string)$row['id'], $row['name'], (bool)$row['visibility'], (bool)$row['editable']);
377
+    }
378
+
379
+    /**
380
+     * {@inheritdoc}
381
+     */
382
+    public function setTagGroups(ISystemTag $tag, array $groupIds) {
383
+        // delete relationships first
384
+        $this->connection->beginTransaction();
385
+        try {
386
+            $query = $this->connection->getQueryBuilder();
387
+            $query->delete(self::TAG_GROUP_TABLE)
388
+                ->where($query->expr()->eq('systemtagid', $query->createNamedParameter($tag->getId())))
389
+                ->execute();
390
+
391
+            // add each group id
392
+            $query = $this->connection->getQueryBuilder();
393
+            $query->insert(self::TAG_GROUP_TABLE)
394
+                ->values([
395
+                    'systemtagid' => $query->createNamedParameter($tag->getId()),
396
+                    'gid' => $query->createParameter('gid'),
397
+                ]);
398
+            foreach ($groupIds as $groupId) {
399
+                if ($groupId === '') {
400
+                    continue;
401
+                }
402
+                $query->setParameter('gid', $groupId);
403
+                $query->execute();
404
+            }
405
+
406
+            $this->connection->commit();
407
+        } catch (\Exception $e) {
408
+            $this->connection->rollBack();
409
+            throw $e;
410
+        }
411
+    }
412
+
413
+    /**
414
+     * {@inheritdoc}
415
+     */
416
+    public function getTagGroups(ISystemTag $tag): array {
417
+        $groupIds = [];
418
+        $query = $this->connection->getQueryBuilder();
419
+        $query->select('gid')
420
+            ->from(self::TAG_GROUP_TABLE)
421
+            ->where($query->expr()->eq('systemtagid', $query->createNamedParameter($tag->getId())))
422
+            ->orderBy('gid');
423
+
424
+        $result = $query->execute();
425
+        while ($row = $result->fetch()) {
426
+            $groupIds[] = $row['gid'];
427
+        }
428
+
429
+        $result->closeCursor();
430
+
431
+        return $groupIds;
432
+    }
433 433
 }
Please login to merge, or discard this patch.