Completed
Push — master ( 6ca8ce...06e969 )
by Lukas
47:33 queued 38:57
created

PublishPlugin::httpPost()   C

Complexity

Conditions 10
Paths 9

Size

Total Lines 88
Code Lines 35

Duplication

Lines 56
Ratio 63.64 %

Importance

Changes 0
Metric Value
cc 10
eloc 35
nc 9
nop 2
dl 56
loc 88
rs 5.2313
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @author Thomas Citharel <[email protected]>
4
 *
5
 * @copyright Copyright (c) 2016 Thomas Citharel <[email protected]>
6
 * @license GNU AGPL version 3 or any later version
7
 *
8
 * This code is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License, version 3,
10
 * as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License, version 3,
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
19
 *
20
 */
21
namespace OCA\DAV\CalDAV\Publishing;
22
23
use Sabre\DAV\PropFind;
24
use Sabre\DAV\INode;
25
use Sabre\DAV\Server;
26
use Sabre\DAV\ServerPlugin;
27
use Sabre\DAV\Exception\NotFound;
28
use Sabre\HTTP\RequestInterface;
29
use Sabre\HTTP\ResponseInterface;
30
use Sabre\CalDAV\Xml\Property\AllowedSharingModes;
31
use OCA\DAV\CalDAV\Publishing\Xml\Publisher;
32
use OCA\DAV\CalDAV\Calendar;
33
use OCP\IURLGenerator;
34
use OCP\IConfig;
35
36
class PublishPlugin extends ServerPlugin {
37
	const NS_CALENDARSERVER = 'http://calendarserver.org/ns/';
38
39
	/**
40
	 * Reference to SabreDAV server object.
41
	 *
42
	 * @var \Sabre\DAV\Server
43
	 */
44
	protected $server;
45
46
	/**
47
	 * Config instance to get instance secret.
48
	 *
49
	 * @var IConfig
50
	 */
51
	protected $config;
52
53
	/**
54
	 * URL Generator for absolute URLs.
55
	 *
56
	 * @var IURLGenerator
57
	 */
58
	protected $urlGenerator;
59
60
	/**
61
	 * PublishPlugin constructor.
62
	 *
63
	 * @param IConfig $config
64
	 * @param IURLGenerator $urlGenerator
65
	 */
66
	public function __construct(IConfig $config, IURLGenerator $urlGenerator) {
67
		$this->config = $config;
68
		$this->urlGenerator = $urlGenerator;
69
	}
70
71
	/**
72
	 * This method should return a list of server-features.
73
	 *
74
	 * This is for example 'versioning' and is added to the DAV: header
75
	 * in an OPTIONS response.
76
	 *
77
	 * @return string[]
78
	 */
79
	public function getFeatures() {
80
		// May have to be changed to be detected
81
		return ['oc-calendar-publishing', 'calendarserver-sharing'];
82
	}
83
84
	/**
85
	 * Returns a plugin name.
86
	 *
87
	 * Using this name other plugins will be able to access other plugins
88
	 * using Sabre\DAV\Server::getPlugin
89
	 *
90
	 * @return string
91
	 */
92
	public function getPluginName()	{
93
		return 'oc-calendar-publishing';
94
	}
95
96
	/**
97
	 * This initializes the plugin.
98
	 *
99
	 * This function is called by Sabre\DAV\Server, after
100
	 * addPlugin is called.
101
	 *
102
	 * This method should set up the required event subscriptions.
103
	 *
104
	 * @param Server $server
105
	 */
106
	public function initialize(Server $server) {
107
		$this->server = $server;
108
109
		$this->server->on('method:POST', [$this, 'httpPost']);
110
		$this->server->on('propFind',    [$this, 'propFind']);
111
	}
112
113
	public function propFind(PropFind $propFind, INode $node) {
114
		if ($node instanceof Calendar) {
115
			$propFind->handle('{'.self::NS_CALENDARSERVER.'}publish-url', function () use ($node) {
116
				if ($node->getPublishStatus()) {
117
					// We return the publish-url only if the calendar is published.
118
					$token = $node->getPublishStatus();
119
					$publishUrl = $this->urlGenerator->getAbsoluteURL($this->server->getBaseUri().'public-calendars/').$token;
120
121
					return new Publisher($publishUrl, true);
122
				}
123
			});
124
125
			$propFind->handle('{'.self::NS_CALENDARSERVER.'}allowed-sharing-modes', function() use ($node) {
126
				return new AllowedSharingModes(!$node->isSubscription(), !$node->isSubscription());
127
			});
128
		}
129
	}
130
131
	/**
132
	 * We intercept this to handle POST requests on calendars.
133
	 *
134
	 * @param RequestInterface $request
135
	 * @param ResponseInterface $response
136
	 *
137
	 * @return void|bool
138
	 */
139
	public function httpPost(RequestInterface $request, ResponseInterface $response) {
140
		$path = $request->getPath();
141
142
		// Only handling xml
143
		$contentType = $request->getHeader('Content-Type');
144 View Code Duplication
		if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
145
			return;
146
		}
147
148
		// Making sure the node exists
149
		try {
150
			$node = $this->server->tree->getNodeForPath($path);
151
		} catch (NotFound $e) {
0 ignored issues
show
Bug introduced by
The class Sabre\DAV\Exception\NotFound does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
152
			return;
153
		}
154
155
		$requestBody = $request->getBodyAsString();
156
157
		// If this request handler could not deal with this POST request, it
158
		// will return 'null' and other plugins get a chance to handle the
159
		// request.
160
		//
161
		// However, we already requested the full body. This is a problem,
162
		// because a body can only be read once. This is why we preemptively
163
		// re-populated the request body with the existing data.
164
		$request->setBody($requestBody);
165
166
		$this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
0 ignored issues
show
Bug introduced by
The variable $documentType does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
167
168
		switch ($documentType) {
169
170 View Code Duplication
			case '{'.self::NS_CALENDARSERVER.'}publish-calendar' :
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
171
172
			// We can only deal with IShareableCalendar objects
173
			if (!$node instanceof Calendar) {
174
				return;
175
			}
176
			$this->server->transactionType = 'post-publish-calendar';
177
178
			// Getting ACL info
179
			$acl = $this->server->getPlugin('acl');
180
181
			// If there's no ACL support, we allow everything
182
			if ($acl) {
183
				$acl->checkPrivileges($path, '{DAV:}write');
184
			}
185
186
			$node->setPublishStatus(true);
187
188
			// iCloud sends back the 202, so we will too.
189
			$response->setStatus(202);
190
191
			// Adding this because sending a response body may cause issues,
192
			// and I wanted some type of indicator the response was handled.
193
			$response->setHeader('X-Sabre-Status', 'everything-went-well');
194
195
			// Breaking the event chain
196
			return false;
197
198 View Code Duplication
			case '{'.self::NS_CALENDARSERVER.'}unpublish-calendar' :
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
199
200
			// We can only deal with IShareableCalendar objects
201
			if (!$node instanceof Calendar) {
202
				return;
203
			}
204
			$this->server->transactionType = 'post-unpublish-calendar';
205
206
			// Getting ACL info
207
			$acl = $this->server->getPlugin('acl');
208
209
			// If there's no ACL support, we allow everything
210
			if ($acl) {
211
				$acl->checkPrivileges($path, '{DAV:}write');
212
			}
213
214
			$node->setPublishStatus(false);
215
216
			$response->setStatus(200);
217
218
			// Adding this because sending a response body may cause issues,
219
			// and I wanted some type of indicator the response was handled.
220
			$response->setHeader('X-Sabre-Status', 'everything-went-well');
221
222
			// Breaking the event chain
223
			return false;
224
225
		}
226
	}
227
}
228