Passed
Push — master ( f097b8...6cffe8 )
by Bjørn
02:33
created

CustomTester::bypassStandardErrorHandling()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 10
ccs 7
cts 7
cp 1
rs 10
cc 4
nc 3
nop 2
crap 4
1
<?php
2
3
namespace HtaccessCapabilityTester\Testers;
4
5
use \HtaccessCapabilityTester\HtaccessCapabilityTester;
6
use \HtaccessCapabilityTester\HttpRequesterInterface;
7
use \HtaccessCapabilityTester\HttpResponse;
8
use \HtaccessCapabilityTester\SimpleHttpRequester;
9
use \HtaccessCapabilityTester\TestResult;
10
use \HtaccessCapabilityTester\Testers\Helpers\ResponseInterpreter;
11
12
class CustomTester extends AbstractTester
13
{
14
    /** @var array  A definition defining the test */
15
    protected $test;
16
17
    /** @var array  For convenience, all tests */
18
    private $tests;
19
20
    /**
21
     * Constructor.
22
     *
23
     * @param  array   $test     The test (may contain subtests)
24
     *
25
     * @return void
26
     */
27 80
    public function __construct($test)
28
    {
29 80
        $this->test = $test;
30
31 80
        if (isset($test['subtests'])) {
32 38
            $this->tests = $test['subtests'];
33
34
            // Add main subdir to subdir for all subtests
35 38
            foreach ($this->tests as &$subtest) {
36 38
                if (isset($subtest['subdir'])) {
37 38
                    $subtest['subdir'] = $test['subdir'] . '/' . $subtest['subdir'];
38
                }
39
            }
40
        } else {
41 65
            $this->tests = [$test];
42
        }
43
44
        //echo '<pre>' . print_r($this->tests, true) . '</pre>';
45
        //echo json_encode($this->tests) . '<br>';
46 80
        parent::__construct();
47 80
    }
48
49
    /**
50
     * Register the test files using the "registerTestFile" method
51
     *
52
     * @return  void
53
     */
54 80
    protected function registerTestFiles()
55
    {
56
57 80
        foreach ($this->tests as $test) {
58 80
            if (isset($test['files'])) {
59 80
                foreach ($test['files'] as $file) {
60
                    // Two syntaxes are allowed:
61
                    // - Simple array (ie: ['0.txt', '0']
62
                    // - Named, ie:  ['filename' => '0.txt', 'content' => '0']
63
                    // The second makes more readable YAML definitions
64 80
                    if (isset($file['filename'])) {
65
                        $filename = $file['filename'];
66
                        $content = $file['content'];
67
                    } else {
68 80
                        list ($filename, $content) = $file;
69
                    }
70 80
                    $this->registerTestFile($test['subdir'] . '/' . $filename, $content);
71
                }
72
            }
73
        }
74 80
    }
75
76 75
    public function getSubDir()
77
    {
78 75
        return $this->test['subdir'];
79
    }
80
81
    /**
82
     *  Standard Error handling
83
     *
84
     * @param  HttpResponse  $response
85
     *
86
     * @return TestResult|null  If no errors, null is returned, otherwise a TestResult
87
     */
88 71
    private function standardErrorHandling($response)
89
    {
90 71
        switch ($response->statusCode) {
91 71
            case '403':
92 9
                return new TestResult(null, '403 Forbidden');
93 62
            case '404':
94
                return new TestResult(null, '404 Not Found');
95 62
            case '500':
96 10
                $hct = $this->getHtaccessCapabilityTester();
97
98
                // Run innocent request / get it from cache. This sets
99
                // $statusCodeOfLastRequest, which we need now
100 10
                $hct->innocentRequestWorks();
101 10
                if ($hct->statusCodeOfLastRequest == '500') {
102 2
                    return new TestResult(null, 'Errored with 500. Everything errors with 500.');
103
                } else {
104 8
                    return new TestResult(
105 8
                        false,
106
                        'Errored with 500. ' .
107 8
                        'Not all goes 500, so it must be a forbidden directive in the .htaccess'
108
                    );
109
                }
110
        }
111 52
        return null;
112
    }
113
114
    /**
115
     * Checks if standard error handling should be bypassed on the test.
116
     *
117
     * This stuff is controlled in the test definition. More precisely, by the "bypass-standard-error-handling"
118
     * property bellow the "request" property. If this property is set to ie ['404', '500'], the standard error
119
     * handler will be bypassed for those codes (but still be in effect for ie '403'). If set to ['all'], all
120
     * standard error handling will be bypassed.
121
     *
122
     * @param  array         $test      the subtest
123
     * @param  HttpResponse  $response  the response
124
     *
125
     * @return bool          true if error handling should be bypassed
126
     */
127 80
    private function bypassStandardErrorHandling($test, $response)
128
    {
129 80
        if (!(isset($test['request']['bypass-standard-error-handling']))) {
130 68
            return false;
131
        }
132 35
        $bypassErrors = $test['request']['bypass-standard-error-handling'];
133 35
        if (in_array($response->statusCode, $bypassErrors) || in_array('all', $bypassErrors)) {
134 30
            return true;
135
        }
136 7
        return false;
137
    }
138
139
    /**
140
     *  Run single test
141
     *
142
     * @param  array  $test  the subtest to run
143
     *
144
     * @return TestResult  Returns a test result
145
     */
146 80
    private function realRunSubTest($test)
147
    {
148 80
        $requestUrl = $this->baseUrl . '/' . $test['subdir'] . '/';
149 80
        if (isset($test['request']['url'])) {
150 46
            $requestUrl .= $test['request']['url'];
151
        } else {
152 65
            $requestUrl .= $test['request'];
153
        }
154
        //echo $requestUrl . '<br>';
155 80
        $response = $this->makeHttpRequest($requestUrl);
156
157
        // Standard error handling
158 80
        if (!($this->bypassStandardErrorHandling($test, $response))) {
159 71
            $errorResult = $this->standardErrorHandling($response);
160 71
            if (!is_null($errorResult)) {
161 19
                return $errorResult;
162
            }
163
        }
164 71
        return ResponseInterpreter::interpret($response, $test['interpretation']);
165
    }
166
167
    /**
168
     *  Run
169
     *
170
     * @param  string  $baseDir  Directory on the server where the test files can be put
171
     * @param  string  $baseUrl  The base URL of the test files
172
     *
173
     * @return TestResult  Returns a test result
174
     * @throws \Exception  In case the test cannot be run due to serious issues
175
     */
176 80
    private function realRun($baseDir, $baseUrl)
177
    {
178 80
        $this->prepareForRun($baseDir, $baseUrl);
179
180 80
        $result = null;
181 80
        foreach ($this->tests as $i => $test) {
182
            /*
183
            Disabled, as I'm no longer sure if it is that useful
184
185
            if (isset($test['requirements'])) {
186
            $hct = $this->getHtaccessCapabilityTester();
187
188
            foreach ($test['requirements'] as $requirement) {
189
                $requirementResult = $hct->callMethod($requirement);
190
                if (!$requirementResult) {
191
                    // Skip test
192
                    continue 2;
193
                }
194
            }
195
            }*/
196 80
            if (isset($test['request'])) {
197 80
                $result = $this->realRunSubTest($test);
198 80
                if ($result->info != 'no-match') {
199 79
                    return $result;
200
                }
201
            }
202
        }
203 13
        if (is_null($result)) {
204
            $result = new TestResult(null, 'Nothing to test!');
205
        }
206 13
        return $result;
207
    }
208
209
    /**
210
     *  Run
211
     *
212
     * @param  string  $baseDir  Directory on the server where the test files can be put
213
     * @param  string  $baseUrl  The base URL of the test files
214
     *
215
     * @return TestResult  Returns a test result
216
     * @throws \Exception  In case the test cannot be run due to serious issues
217
     */
218 80
    public function run($baseDir, $baseUrl)
219
    {
220 80
        $testResult = $this->realRun($baseDir, $baseUrl);
221
222
        // A test might not create a request if it has an unfulfilled requirement
223 80
        if (isset($this->lastHttpResponse)) {
224 80
            $testResult->statusCodeOfLastRequest = $this->lastHttpResponse->statusCode;
225
        }
226 80
        return $testResult;
227
    }
228
}
229