Completed
Branch master (9dcfc4)
by Daniel
24:32
created

ExternalURLCheck::check()   C

Complexity

Conditions 13
Paths 144

Size

Total Lines 65
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

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