Completed
Push — master ( e090e4...18d79e )
by Damian
02:26
created

code/checks/ExternalURLCheck.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * Checks that one or more URLs are reachable via HTTP.
5
 * Note that the HTTP connectivity can just be verified from the server to the remote URL,
6
 * it can still fail if the URL in question is requested by the client, e.g. through an iframe.
7
 * 
8
 * Requires curl to present, so ensure to check it before with the following:
9
 * <code>EnvironmentCheckSuite::register('check', 'HasFunctionCheck("curl_init")', "Does PHP have CURL support?");</code>
10
 */
11
class ExternalURLCheck implements EnvironmentCheck {
0 ignored issues
show
As per PSR2, the opening brace for this class should be on a new line.
Loading history...
12
	/**
13
	 * @var array
14
	 */
15
	protected $urls = array();
16
17
	/**
18
	 * @var Int Timeout in seconds.
19
	 */
20
	protected $timeout;
21
22
	/**
23
	 * @param string $urls Space-separated list of absolute URLs.
24
	 * @param int $timeout
25
	 */
26
	function __construct($urls, $timeout = 15) {
27
		if($urls) $this->urls = explode(' ', $urls);
28
		$this->timeout = $timeout;
29
	}
30
31
	/**
32
	 * @inheritdoc
33
	 *
34
	 * @return array
35
	 */
36
	function check() {
37
		$urls = $this->getURLs();
38
39
		$chs = array();
40
		foreach($urls as $url)	{
41
			$ch = curl_init();
42
			$chs[] = $ch;
43
			curl_setopt_array($ch, $this->getCurlOpts($url));
44
		}	
45
		// Parallel execution for faster performance
46
		$mh = curl_multi_init();
47
		foreach($chs as $ch) curl_multi_add_handle($mh,$ch);
48
		
49
		$active = null;
50
		// Execute the handles
51
		do {
52
			$mrc = curl_multi_exec($mh, $active);
53
			curl_multi_select($mh);
54
		} while ($active > 0);
55
56
		while ($active && $mrc == CURLM_OK) {
57
			if (curl_multi_select($mh) != -1) {
58
				do {
59
						$mrc = curl_multi_exec($mh, $active);
60
				} while ($mrc == CURLM_CALL_MULTI_PERFORM);
61
			}
62
		}
63
64
		$hasError = false;
65
		$msgs = array();
66
		foreach($chs as $ch) {
67
			$url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
68
			$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
69
			if(curl_errno($ch) || $code >= 400) {
70
				$hasError = true;
71
				$msgs[] = sprintf(
72
					'Error retrieving "%s": %s (Code: %s)',
73
					$url,
74
					curl_error($ch),
75
					$code
76
				);
77
			} else {
78
				$msgs[] = sprintf(
79
					'Success retrieving "%s" (Code: %s)',
80
					$url,
81
					$code
82
				);
83
			}
84
		}
85
86
		// Close the handles
87
		foreach($chs as $ch) curl_multi_remove_handle($mh, $ch);
88
		curl_multi_close($mh);
89
		
90
		if($hasError) {
91
			return array(EnvironmentCheck::ERROR, implode(', ', $msgs));
92
		} else {
93
			return array(EnvironmentCheck::OK, implode(', ', $msgs));
94
		}
95
	}
96
97
	/**
98
	 * @return array
99
	 */
100
	protected function getCurlOpts($url) {
101
		return array(
102
			CURLOPT_URL => $url,
103
			CURLOPT_HEADER => 0,
104
			CURLOPT_RETURNTRANSFER => 1,
105
			CURLOPT_FAILONERROR => 1,
106
			CURLOPT_TIMEOUT => $this->timeout,
107
		);
108
	}
109
110
	/**
111
	 * @return array
112
	 */
113
	protected function getURLs() {
114
		return $this->urls;
115
	}
116
}
117