GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 9c0c8a...f2b063 )
by Brad
05:17 queued 02:45
created

FooGallery_Pro_Video_YouTube::search()   C

Complexity

Conditions 15
Paths 16

Size

Total Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
nc 16
nop 3
dl 0
loc 59
rs 5.9166
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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 14 and the first side effect is on line 12.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
/**
4
 * Created by PhpStorm.
5
 * User: steve
6
 * Date: 4/17/2018
7
 * Time: 10:09 PM
8
 */
9
10
if ( !class_exists("FooGallery_Pro_Video_YouTube") ){
11
12
	require_once dirname(__FILE__) . '/class-foogallery-pro-video-base.php';
13
14
	class FooGallery_Pro_Video_YouTube extends FooGallery_Pro_Video_Base {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
15
16
		// region Properties
17
18
		/**
19
		 * The regular expression used to match a YouTube video URL.
20
		 * @var string
21
		 */
22
		public $regex_pattern;
23
24
		// endregion
25
26
		function __construct() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
27
			$this->regex_pattern = '/(www\.)?youtube|youtu\.be/i';
28
		}
29
30
		/**
31
		 * Takes a URL and checks if this class handles it.
32
		 *
33
		 * @param string $url The URL to check.
34
		 * @param array &$matches Optional. If matches is provided, it is passed to the `preg_match` call used to check the URL.
35
		 * @return int Returns 1 if the URL is handled, 0 if it is not, or FALSE if an error occurred.
36
		 */
37
		function handles($url, &$matches = array()){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
38
			return preg_match($this->regex_pattern, $url, $matches);
39
		}
40
41
		/**
42
		 * Takes a string value and determines whether or not it is a YouTube video id.
43
		 *
44
		 * @param string $value The value to test.
45
		 * @return bool
46
		 *
47
		 * @see https://stackoverflow.com/questions/6180138/whats-the-maximum-length-of-a-youtube-video-id
48
		 *
49
		 * @description At present YouTube's video ids always have 11 characters, while this is not
50
		 * guaranteed it should stay that way until all 73,786,976,294,838,206,464 possible combinations
51
		 * are exhausted.
52
		 */
53
		function is_video_id($value) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
54
			return !empty($value) && is_string($value) && strlen($value) === 11 && strpos($value, " ") === false && $this->url_exists("https://www.youtube.com/watch?v=" . $value);
55
		}
56
57
		/**
58
		 * Takes a string value and determines whether or not it is a YouTube playlist id.
59
		 *
60
		 * @param string $value The value to test.
61
		 * @return bool
62
		 *
63
		 * @description At present YouTube's playlist ids always have 34 characters and begin with "PL", while
64
		 * this is not guaranteed it should stay that way until all possible combinations are exhausted.
65
		 */
66
		function is_playlist_id($value) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
67
			return !empty($value) && is_string($value) && strlen($value) === 34 && strpos($value, " ") === false && $this->url_exists("https://www.youtube.com/playlist?list=" . $value);
68
		}
69
70
		/**
71
		 * Takes the supplied query and optional page number, determines the correct method to call and then returns its' data.
72
		 *
73
		 * @param string $query The query value to parse.
74
		 * @param int [$page=1] If this is a search query the page number could also be supplied.
75
		 * @param int [$offset=0] The number of items already retrieved for the query.
76
		 * @return array
77
		 */
78
		function query($query, $page = 1, $offset = 0) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
79
			if ($this->is_playlist_id($query)) {
80
				return $this->fetch_playlist($query);
81
			}
82
83
			if ($this->is_video_id($query)) {
84
				return $this->fetch_video($query);
85
			}
86
87
			// if we get here we assume the query is a search
88
			return $this->search($query, $page, $offset);
89
		}
90
91
		/**
92
		 * Takes the supplied YouTube url and attempts to fetch its' data.
93
		 *
94
		 * @description At present this method supports the following url patterns:
95
		 *
96
		 * - http(s)://www.youtube.com/watch?v=[ID]
97
		 * - http(s)://youtu.be/[ID]
98
		 * - http(s)://www.youtube.com/embed/[ID]
99
		 * - http(s)://www.youtube.com/playlist?list=[ID]
100
		 *
101
		 * @param string $url The url to fetch the data for.
102
		 * @return array
103
		 */
104
		function fetch($url) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
105
			// make sure we're dealing with a YouTube url in case this method is called externally
106
			if (preg_match($this->regex_pattern, $url)) {
107
				$query_string = array();
108
				$url_parts = parse_url($url);
109
				// check if we were supplied a query string i.e. anything after ?
110
				if (!empty($url_parts["query"])) {
111
					// if we have a query string then parse it into an array of key value pairs
112
					parse_str($url_parts["query"], $query_string);
113
				}
114
115
				// check if we are dealing with a playlist url
116
				if (preg_match('/(www\.)?youtube\.com\/playlist/i', $url)) {
117
					return $this->fetch_playlist($query_string["list"]);
118
				}
119
120
				// otherwise we are dealing with one of the single video supported formats
121
				$id = $query_string["v"];
122
				// if the id does not exist in the query string then we are dealing with a YouTube
123
				// short or embed url so grab the id from the last part of the url
124
				if (empty($id) && preg_match('/(www\.)?youtube\.com\/embed|youtu\.be/i', $url)) {
125
					// here we split the url on all forward-slashes
126
					$parts = explode("/", $url);
127
					// then grab the last part to use as the id
128
					$id = end($parts);
129
				}
130
131
				return $this->fetch_video($id);
132
			}
133
			return $this->error_response("Unrecognized YouTube url.");
134
		}
135
136
		/**
137
		 * Takes the supplied YouTube playlist id and fetches its' data.
138
		 *
139
		 * @param string $id The playlist id to fetch.
140
		 * @return array(
0 ignored issues
show
Documentation introduced by
The doc-type array( could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
141
		 *  "mode" => "playlist",
142
		 *  "thumbnail" => string,
143
		 *  "title" => string,
144
		 *  "description" => string,
145
		 *  "videos" => array,
146
		 *  "total" => number
147
		 * )
148
		 * @return array(
0 ignored issues
show
Documentation introduced by
The doc-type array( could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
149
		 *  "mode" => "error",
150
		 *  "message" => string
151
		 * )
152
		 */
153
		function fetch_playlist($id) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
154
155
			if (!$this->is_playlist_id($id)) {
156
				return $this->error_response("Invalid playlist id supplied.");
157
			}
158
159
			// we have as valid an id as we can hope for until we make the actual request so request it
160
			$url = "https://www.youtube.com/list_ajax?style=json&action_get_list=true&list=" . $id;
161
			// get the json object from the supplied url
162
			$json = $this->json_get($url);
163
164
			// if an error occurred return it
165
			if ($this->is_error($json)) {
166
				return $json;
167
			}
168
169
			// do basic validation on the json object
170
			if (empty($json) || empty($json->video) || !is_array($json->video)) {
171
				return $this->error_response("No videos in response.");
172
			}
173
174
			// if we get here we need to build a response to return to the frontend
175
			$response = array(
176
				"mode" => "playlist",
177
				"id" => $id,
178
				"total" => 0,
179
				"page" => 1,
180
				"nextPage" => 0,
181
				"offset" => 0,
182
				"videos" => array()
183
			);
184
185
			// iterate each of the returned videos and add them to the response in our desired format
186
			foreach ($json->video as $video) {
187
				if (!empty($video->thumbnail) && !empty($video->encrypted_id) && !empty($video->title)) {
188
					$response["videos"][] = array(
189
						"provider" => "youtube",
190
						"id" => $video->encrypted_id,
191
						"url" => "https://www.youtube.com/embed/" . $video->encrypted_id,
192
						"thumbnail" => $video->thumbnail,
193
						"title" => $video->title,
194
						"description" => !empty($video->description) ? $video->description : ""
195
					);
196
				}
197
			}
198
199
			// update the offset and total with the current video count
200
			$response["offset"] = $response["total"] = count($response["videos"]);
201
202
			// if we have no videos then none were valid
203
			if ($response["total"] === 0) {
204
				return $this->error_response("No valid videos in response.");
205
			}
206
207
			return $response;
208
		}
209
210
		/**
211
		 * Takes the supplied YouTube video id and fetches its' data.
212
		 *
213
		 * @param string $id The video id to fetch.
214
		 * @return array(
0 ignored issues
show
Documentation introduced by
The doc-type array( could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
215
		 *  "mode" => "video",
216
		 *  "url" => string,
217
		 *  "thumbnail" => string,
218
		 *  "title" => string,
219
		 *  "description" => string
220
		 * )
221
		 * @return array(
0 ignored issues
show
Documentation introduced by
The doc-type array( could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
222
		 *  "mode" => "error",
223
		 *  "message" => string
224
		 * )
225
		 */
226
		function fetch_video($id) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
227
228
			if (!$this->is_video_id($id)) {
229
				return $this->error_response("Invalid video id supplied.");
230
			}
231
232
			// we have as valid an id as we can hope for until we make the actual request so request it
233
			$url = "http://www.youtube.com/oembed?url=" . urlencode("https://www.youtube.com/watch?v=" . $id);
234
			// get the json object from the supplied url
235
			$json = $this->json_get($url);
236
237
			// if an error occurred return it
238
			if ($this->is_error($json)) {
239
				return $json;
240
			}
241
242
			// do basic validation on the parsed object
243
			if (empty($json) || empty($json->thumbnail_url) || empty($json->title)) {
244
				return $this->error_response("No video in response.");
245
			}
246
247
			$response = array(
248
				"mode" => "single",
249
				"videos" => array()
250
			);
251
252
			$response["videos"][] = array(
253
				"provider" => "youtube",
254
				"id" => $id,
255
				"url" => "https://www.youtube.com/embed/" . $id,
256
				"thumbnail" => $json->thumbnail_url,
257
				"title" => $json->title,
258
				"description" => !empty($json->description) ? $json->description : ""
259
			);
260
261
			return $response;
262
		}
263
264
		/**
265
		 * Takes the supplied query and optional page number and performs a YouTube search.
266
		 *
267
		 * @param string $query The query to use as a search term.
268
		 * @param int [$page=1] The page number to retrieve.
269
		 * @param int [$offset=0] The number of items already retrieved for the query.
270
		 * @return array(
0 ignored issues
show
Documentation introduced by
The doc-type array( could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
271
		 *  "mode" => "search",
272
		 *  "total" => number,
273
		 *  "page" => number,
274
		 *  "offset" => number,
275
		 *  "nextPage" => number,
276
		 *  "videos" => array(
277
		 * 		array(
278
		 * 			"provider" => "youtube",
279
		 * 			"id" => string,
280
		 * 			"url" => string,
281
		 * 			"thumbnail" => string,
282
		 * 			"title" => string,
283
		 * 			"description" => string
284
		 * 		)
285
		 * 	)
286
		 * )
287
		 * @return array(
0 ignored issues
show
Documentation introduced by
The doc-type array( could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
288
		 *  "mode" => "error",
289
		 *  "title" => string,
290
		 *  "message" => string
291
		 * )
292
		 */
293
		function search($query, $page = 1, $offset = 0) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
294
			if (empty($query)) {
295
				return $this->error_response("Empty search query.");
296
			}
297
298
			if ($query === "!ERROR"){
299
				return $this->error_response("Dummy error.");
300
			}
301
302
			$url = "https://www.youtube.com/search_ajax?style=json&search_query=" . urlencode($query) . "&page=" . $page;
303
			// get the json object from the supplied url
304
			$json = $this->json_get($url);
305
306
			// if an error occurred return it
307
			if ($this->is_error($json)) {
308
				return $json;
309
			}
310
311
			// do basic validation on the parsed object
312
			if (empty($json) || empty($json->hits) || empty($json->video) || !is_array($json->video)) {
313
				return $this->error_response("No videos in response.");
314
			}
315
316
			// if we get here we need to build a response to return to the frontend
317
			$response = array(
318
				"mode" => "search",
319
				"total" => $json->hits,
320
				"page" => $page,
321
				"offset" => $offset,
322
				"nextPage" => 0,
323
				"videos" => array()
324
			);
325
326
			// iterate each of the returned videos and add them to the response in our desired format
327
			foreach ($json->video as $video) {
328
				if (!empty($video->thumbnail) && !empty($video->encrypted_id) && !empty($video->title)) {
329
					$response["videos"][] = array(
330
						"provider" => "youtube",
331
						"id" => $video->encrypted_id,
332
						"url" => "https://www.youtube.com/embed/" . $video->encrypted_id,
333
						"thumbnail" => $video->thumbnail,
334
						"title" => $video->title,
335
						"description" => !empty($video->description) ? $video->description : ""
336
					);
337
				}
338
			}
339
340
			// if we have no videos then none of the videos were valid
341
			if ($response["total"] === 0) {
342
				return $this->error_response("No valid videos in response.");
343
			}
344
345
			$response["offset"] = $response["offset"] + count($response["videos"]);
346
			if ($response["total"] > $response["offset"]){
347
				$response["nextPage"] = $response["page"] + 1;
348
			}
349
350
			return $response;
351
		}
352
353
	}
354
355
}