Completed
Push — stable9 ( cf9757...ecc50c )
by Blizzz
10s
created

BookmarkController::newBookmark()   C

Complexity

Conditions 13
Paths 39

Size

Total Lines 41
Code Lines 25

Duplication

Lines 3
Ratio 7.32 %

Code Coverage

Tests 0
CRAP Score 182

Importance

Changes 5
Bugs 1 Features 0
Metric Value
c 5
b 1
f 0
dl 3
loc 41
ccs 0
cts 30
cp 0
rs 5.1234
cc 13
eloc 25
nc 39
nop 6
crap 182

How to fix   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
/**
4
 * ownCloud - bookmarks
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Stefan Klemm <[email protected]>
10
 * @copyright Stefan Klemm 2014
11
 */
12
13
namespace OCA\Bookmarks\Controller\Rest;
14
15
use \OCP\IRequest;
16
use \OCP\AppFramework\ApiController;
17
use \OCP\AppFramework\Http\JSONResponse;
18
use \OCP\AppFramework\Http;
19
use \OCP\IDb;
20
use \OCA\Bookmarks\Controller\Lib\Bookmarks;
21
use \OCA\Bookmarks\Controller\Lib\ExportResponse;
22
23
class BookmarkController extends ApiController {
24
25
	private $userId;
26
	private $db;
27
28 View Code Duplication
	public function __construct($appName, IRequest $request, $userId, IDb $db) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
29
		parent::__construct($appName, $request);
30
		$this->userId = $userId;
31
		$this->db = $db;
32
		$this->request = $request;
33
	}
34
35
	/**
36
	 * @NoAdminRequired
37
	 */
38
	public function legacyGetBookmarks($type = "bookmark", $tag = '', $page = 0, $sort = "bookmarks_sorting_recent") {
39
		return $this->getBookmarks($type, $tag, $page, $sort);
40
	}
41
42
	/**
43
	 * @NoAdminRequired
44
	 */
45
	public function getBookmarks($type = "bookmark", $tag = '', $page = 0, $sort = "bookmarks_sorting_recent") {
46
47
		if ($type == 'rel_tags') {
48
			$tags = Bookmarks::analyzeTagRequest($tag);
49
			$qtags = Bookmarks::findTags($this->userId, $this->db, $tags);
50
			return new JSONResponse(array('data' => $qtags, 'status' => 'success'));
51
		} else { // type == bookmark
52
			$filterTag = Bookmarks::analyzeTagRequest($tag);
53
54
			$offset = $page * 10;
55
56
			if ($sort == 'bookmarks_sorting_clicks') {
57
				$sqlSortColumn = 'clickcount';
58
			} else {
59
				$sqlSortColumn = 'lastmodified';
60
			}
61
			$bookmarks = Bookmarks::findBookmarks($this->userId, $this->db, $offset, $sqlSortColumn, $filterTag, true);
62
			return new JSONResponse(array('data' => $bookmarks, 'status' => 'success'));
63
		}
64
	}
65
66
	/**
67
	 * @NoAdminRequired
68
	 */
69
	public function newBookmark($url = "", $item = array(), $from_own = 0, $title = "", $is_public = false, $description = "") {
70
71
		if ($from_own == 0) {
72
			// allow only http(s) and (s)ftp
73
			$protocols = '/^(https?|s?ftp)\:\/\//i';
74
			if (preg_match($protocols, $url)) {
75
				$data = Bookmarks::getURLMetadata($url);
76
			// if not (allowed) protocol is given, assume http and https (and fetch both)
77
			} else { 
78
				// append https to url and fetch it
79
				$url_https = 'https://' . $url;
80
				$data_https = Bookmarks::getURLMetadata($url_https);
81
				// append http to url and fetch it
82
				$url_http = 'http://' . $url;
83
				$data_http = Bookmarks::getURLMetadata($url_http);
84
			}
85
86
			if ($title === '' && isset($data['title'])) { // prefer original url if working
87
				$title = $data['title'];
88
				//url remains unchanged
89
			} elseif (isset($data_https['title'])) { // test if https works
90
				$title = $title === '' ? $data_https['title'] : $title;
91
				$url = $url_https;
0 ignored issues
show
Bug introduced by
The variable $url_https does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
92
			} elseif (isset($data_http['title'])) { // otherwise test http for results
93
				$title = $title === '' ? $data_http['title'] : $title;
94
				$url = $url_http;
0 ignored issues
show
Bug introduced by
The variable $url_http does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
95
			}
96
		}
97
98
		// Check if it is a valid URL (after adding http(s) prefix)
99
		$urlData = parse_url($url);
100 View Code Duplication
		if ($urlData === false || !isset($urlData['scheme']) || !isset($urlData['host'])) {
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...
101
			return new JSONResponse(array('status' => 'error'), Http::STATUS_BAD_REQUEST);
102
		}
103
104
		$tags = isset($item['tags']) ? $item['tags'] : array();
105
106
		$id = Bookmarks::addBookmark($this->userId, $this->db, $url, $title, $tags, $description, $is_public);
107
		$bm = Bookmarks::findUniqueBookmark($id, $this->userId, $this->db);
108
		return new JSONResponse(array('item' => $bm, 'status' => 'success'));
109
	}
110
111
	/**
112
	  @NoAdminRequired
113
	 * 
114
	 * @param int $id
115
	 * @param bool $is_public Description
116
	 * @return \OCP\AppFramework\Http\TemplateResponse
117
	 */
118
	//TODO id vs record_id?
119
	public function legacyEditBookmark($id = null, $url = "", $item = array(), $title = "", $is_public = false, $record_id = null, $description = "") {
120
		if ($id == null) {
121
			return $this->newBookmark($url, $item, false, $title, $is_public, $description);
122
		} else {
123
			return $this->editBookmark($id, $url, $item, $title, $is_public, $record_id, $description);
124
		}
125
	}
126
127
	/**
128
	  @NoAdminRequired
129
	 * 
130
	 * @param int $id
131
	 * @param bool $is_public Description
132
	 * @return \OCP\AppFramework\Http\TemplateResponse
133
	 */
134
	public function editBookmark($id = null, $url = "", $item = array(), $title = "", $is_public = false, $record_id = null, $description = "") {
135
136
		// Check if it is a valid URL
137
		$urlData = parse_url($url);
138 View Code Duplication
		if ($urlData === false || !isset($urlData['scheme']) || !isset($urlData['host'])) {
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...
139
			return new JSONResponse(array(), Http::STATUS_BAD_REQUEST);
140
		}
141
142
		if ($record_id == null) {
143
			return new JSONResponse(array(), Http::STATUS_BAD_REQUEST);
144
		}
145
146
		$tags = isset($item['tags']) ? $item['tags'] : array();
147
148
		if (is_numeric($record_id)) {
149
			$id = Bookmarks::editBookmark($this->userId, $this->db, $record_id, $url, $title, $tags, $description, $is_public = false);
150
		}
151
152
		$bm = Bookmarks::findUniqueBookmark($id, $this->userId, $this->db);
153
		return new JSONResponse(array('item' => $bm, 'status' => 'success'));
154
	}
155
156
	/**
157
	  @NoAdminRequired
158
	 * 
159
	 * @param int $id
160
	 * @param bool $is_public Description
0 ignored issues
show
Bug introduced by
There is no parameter named $is_public. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
161
	 * @return \OCP\AppFramework\Http\JSONResponse
162
	 */
163
	public function legacyDeleteBookmark($id = -1) {
164
		return $this->deleteBookmark($id);
165
	}
166
167
	/**
168
	  @NoAdminRequired
169
	 * 
170
	 * @param int $id
171
	 * @param bool $is_public Description
0 ignored issues
show
Bug introduced by
There is no parameter named $is_public. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
172
	 * @return \OCP\AppFramework\Http\JSONResponse
173
	 */
174
	public function deleteBookmark($id = -1) {
175
		if ($id == -1) {
176
			return new JSONResponse(array(), Http::STATUS_BAD_REQUEST);
177
		}
178
179
		if (!Bookmarks::deleteUrl($this->userId, $this->db, $id)) {
180
			return new JSONResponse(array(), Http::STATUS_BAD_REQUEST);
181
		} else {
182
			return new JSONResponse(array('status' => 'success'), Http::STATUS_OK);
183
		}
184
	}
185
186
	/**
187
	  @NoAdminRequired
188
	 * 
189
	 * @param string $url
190
	 * @return \OCP\AppFramework\Http\JSONResponse
191
	 */
192
	public function clickBookmark($url = "") {
193
194
		// Check if it is a valid URL
195
		$urlData = parse_url($url);
196 View Code Duplication
		if ($urlData === false || !isset($urlData['scheme']) || !isset($urlData['host'])) {
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...
197
			return new JSONResponse(array(), Http::STATUS_BAD_REQUEST);
198
		}
199
200
		$query = $this->db->prepareQuery('
201
	UPDATE `*PREFIX*bookmarks`
202
	SET `clickcount` = `clickcount` + 1
203
	WHERE `user_id` = ?
204
		AND `url` LIKE ?
205
	');
206
207
		$params = array($this->userId, htmlspecialchars_decode($url));
208
		$query->execute($params);
209
210
		return new JSONResponse(array('status' => 'success'), Http::STATUS_OK);
211
	}
212
213
	/**
214
	  @NoAdminRequired
215
	 * 
216
	 * @return \OCP\AppFramework\Http\JSONResponse
217
	 */
218
	public function importBookmark() {
219
220
		$l = new \OC_l10n('bookmarks');
221
222
		$full_input = $this->request->getUploadedFile("bm_import");
223
224
		if (empty($full_input)) {
225
			\OCP\Util::writeLog('bookmarks', "No file provided for import", \OCP\Util::WARN);
226
			$error = array();
227
			$error[] = $l->t('No file provided for import');
228
		} else {
229
			$error = array();
230
			$file = $full_input['tmp_name'];
231
			if ($full_input['type'] == 'text/html') {
232
				$error = Bookmarks::importFile($this->userId, $this->db, $file);
233
				if (empty($error)) {
234
					return new JSONResponse(array('status' => 'success'));
235
				}
236
			} else {
237
				$error[] = $l->t('Unsupported file type for import');
238
			}
239
		}
240
241
		return new JSONResponse(array('status' => 'error', 'data' => $error));
242
	}
243
244
	/**
245
	  @NoAdminRequired
246
	 * 
247
	 * @return \OCP\AppFramework\Http\JSONResponse
248
	 */
249
	public function exportBookmark() {
250
251
		$file = <<<EOT
252
<!DOCTYPE NETSCAPE-Bookmark-file-1>
253
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
254
<!-- This is an automatically generated file.
255
It will be read and overwritten.
256
Do Not Edit! -->
257
<TITLE>Bookmarks</TITLE>
258
<H1>Bookmarks</H1>
259
<DL><p>
260
EOT;
261
		$bookmarks = Bookmarks::findBookmarks($this->userId, $this->db, 0, 'id', array(), true, -1);
262
		foreach ($bookmarks as $bm) {
263
			$title = $bm['title'];
264
			if (trim($title) === '') {
265
				$url_parts = parse_url($bm['url']);
266
				$title = isset($url_parts['host']) ? OCA\Bookmarks\Controller\Lib\Helper::getDomainWithoutExt($url_parts['host']) : $bm['url'];
267
			}
268
			$file .= '<DT><A HREF="' . \OC_Util::sanitizeHTML($bm['url']) . '" TAGS="' . implode(',', \OC_Util::sanitizeHTML($bm['tags'])) . '">';
269
			$file .= htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '</A>';
270
			if ($bm['description'])
271
				$file .= '<DD>' . htmlspecialchars($bm['description'], ENT_QUOTES, 'UTF-8');
272
			$file .= "\n";
273
		}
274
275
		return new ExportResponse($file);
276
	}
277
278
}
279