Completed
Push — master ( 9b8114...2ed294 )
by Nils
02:31
created

Scanner::scan()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.2
c 0
b 0
f 0
cc 4
eloc 8
nc 3
nop 0
1
<?php
2
3
namespace whm\Smoke\Scanner;
4
5
use Ivory\HttpAdapter\HttpAdapterInterface;
6
use phmLabs\Components\Annovent\Dispatcher;
7
use phmLabs\Components\Annovent\Event\Event;
8
use whm\Smoke\Extensions\SmokeResponseRetriever\Retriever\Retriever;
9
use whm\Smoke\Http\ClientAware;
10
use whm\Smoke\Http\Response;
11
use whm\Smoke\Rules\CheckResult;
12
use whm\Smoke\Rules\Rule;
13
use whm\Smoke\Rules\ValidationFailedException;
14
15
class Scanner
16
{
17
    const ERROR = 'error';
18
    const PASSED = 'passed';
19
20
    /**
21
     * @var Rule[]
22
     */
23
    private $rules;
24
    private $eventDispatcher;
25
26
    private $responseRetriever;
27
28
    private $status = 0;
29
30
    public function __construct(array $rules, HttpAdapterInterface $client, Dispatcher $eventDispatcher, Retriever $responseRetriever)
31
    {
32
        $eventDispatcher->simpleNotify('Scanner.Init', array('rules' => $rules, 'httpClient' => $client, 'dispatcher' => $eventDispatcher));
33
34
        $this->initRules($rules, $client);
35
36
        $this->eventDispatcher = $eventDispatcher;
37
38
        $this->responseRetriever = $responseRetriever;
39
40
        $this->eventDispatcher->simpleNotify('Scanner.Init.ResponseRetriever', array('responseRetriever' => $this->responseRetriever));
41
    }
42
43
    private function initRules($rules, HttpAdapterInterface $client)
44
    {
45
        $this->rules = $rules;
46
        foreach ($this->rules as $rule) {
47
            if ($rule instanceof ClientAware) {
48
                $rule->setClient($client);
49
            }
50
        }
51
    }
52
53
    public function scan()
54
    {
55
        $this->eventDispatcher->simpleNotify('Scanner.Scan.Begin');
56
57
        while (($response = $this->responseRetriever->next()) && !$this->eventDispatcher->notifyUntil(new Event('Scanner.Scan.isStopped'))) {
58
59
            // this is the url filter
60
            if ($this->eventDispatcher->notifyUntil(new Event('Scanner.ProcessHtml.isFiltered', array('uri' => $response->getUri())))) {
61
                continue;
62
            }
63
64
            $results = $this->checkResponse($response);
65
66
            $this->eventDispatcher->simpleNotify('Scanner.Scan.Validate', array('results' => $results, 'response' => $response));
67
        }
68
69
        $this->eventDispatcher->simpleNotify('Scanner.Scan.Finish');
70
    }
71
72
    public function getStatus()
73
    {
74
        return $this->status;
75
    }
76
77
    private function checkResponse(Response $response)
78
    {
79
        $results = [];
80
81
        foreach ($this->rules as $name => $rule) {
82
            if ($this->eventDispatcher->notifyUntil(new Event('Scanner.CheckResponse.isFiltered', array('ruleName' => $name, 'rule' => $rule, 'response' => $response)))) {
83
                continue;
84
            }
85
            try {
86
                $result = $rule->validate($response);
87
                if (!$result) {
88
                    $result = new CheckResult(CheckResult::STATUS_SUCCESS, 'Check successful.');
89
                }
90
            } catch (ValidationFailedException $e) {
91
                $result = new CheckResult(CheckResult::STATUS_FAILURE, $e->getMessage());
92
            }
93
            $result->setResponse($response);
94
            $result->setRuleName($name);
95
            $results[$name] = $result;
96
        }
97
98
        return $results;
99
    }
100
}
101