KoalamonReporter::init()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 9.568
c 0
b 0
f 0
cc 2
nc 2
nop 11

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace whm\Smoke\Extensions\SmokeReporter\Reporter;
4
5
use Koalamon\Client\Reporter\Event;
6
use Koalamon\Client\Reporter\WebhookReporter as KoalaReporter;
7
use Symfony\Component\Console\Output\OutputInterface;
8
use whm\Html\Uri;
9
use whm\Smoke\Config\Configuration;
10
use whm\Smoke\Extensions\SmokeResponseRetriever\Retriever\Retriever;
11
use whm\Smoke\Scanner\Result;
12
13
/**
14
 * Class XUnitReporter.
15
 */
16
class KoalamonReporter implements Reporter
0 ignored issues
show
Bug introduced by
There is one abstract method processResults in this class; you could implement it, or declare this class as abstract.
Loading history...
17
{
18
    /**
19
     * @var Result[]
20
     */
21
    private $results = [];
22
23
    private $config;
24
    private $system;
25
    private $collect;
26
    private $identifier;
27
    private $systemUseRetriever;
28
    private $tool = 'smoke';
29
    private $groupBy;
30
    private $server;
31
    private $addComingFrom;
32
33
    /**
34
     * @var KoalaReporter
35
     */
36
    private $reporter;
37
38
    /*
39
     * @var Retriever
40
     */
41
    private $retriever;
42
43
    private $output;
44
45
    const STATUS_SUCCESS = 'success';
46
    const STATUS_FAILURE = 'failure';
47
48
    public function init($apiKey, Configuration $_configuration, OutputInterface $_output, $server = 'https://webhook.koalamon.com', $system = '', $identifier = '', $tool = '', $collect = true, $systemUseRetriever = false, $groupBy = false, $addComingFrom = true)
49
    {
50
        $httpClient = new \GuzzleHttp\Client();
51
        $this->reporter = new KoalaReporter('', $apiKey, $httpClient, $server);
52
53
        $this->config = $_configuration;
54
        $this->systemUseRetriever = $systemUseRetriever;
55
56
        $this->system = $system;
57
        $this->collect = $collect;
58
        $this->identifier = $identifier;
59
        $this->groupBy = $groupBy;
60
61
        $this->addComingFrom = $addComingFrom;
62
63
        if ($tool) {
64
            $this->tool = $tool;
65
        }
66
67
        $this->server = $server;
68
        $this->output = $_output;
69
    }
70
71
    public function setResponseRetriever(Retriever $retriever)
72
    {
73
        $this->retriever = $retriever;
74
    }
75
76
    /**
77
     * @param Rule [];
78
     *
79
     * @return array
80
     */
81
    private function getRuleKeys()
82
    {
83
        $keys = array();
84
        foreach ($this->config->getRules() as $key => $rule) {
85
            $keys[] = $key;
86
        }
87
88
        return $keys;
89
    }
90
91
    public function processResult(Result $result)
92
    {
93
        $this->results[] = $result;
94
    }
95
96
    public function finish()
97
    {
98
        $this->output->writeln('Sending results to ' . $this->server . " ... \n");
99
100
        if ($this->groupBy === 'prefix') {
101
            $this->sendGroupedByPrefix();
102
        } else {
103
            if ($this->collect) {
104
                $this->sendCollected();
105
            } else {
106
                $this->sendSingle();
107
            }
108
        }
109
    }
110
111
    private function getPrefix($string)
112
    {
113
        return substr($string, 0, strpos($string, '_'));
114
    }
115
116
    private function sendGroupedByPrefix()
117
    {
118
        $failureMessages = array();
119
        $counter = array();
120
121
        if ($this->systemUseRetriever) {
122
            $systems = $this->retriever->getSystems();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface whm\Smoke\Extensions\Smo...ver\Retriever\Retriever as the method getSystems() does only exist in the following implementations of said interface: whm\Smoke\Extensions\Smo...ever\Koalamon\Retriever, whm\Smoke\Extensions\Smo...ListRetriever\Retriever.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
123
        } else {
124
            $systems = array($this->system);
125
        }
126
127
        foreach ($this->getRuleKeys() as $rule) {
128
            foreach ($systems as $system) {
129
                $identifier = $this->tool . '_' . $this->getPrefix($rule) . '_' . $system;
130
                $failureMessages[$identifier]['message'] = '';
131
                $failureMessages[$identifier]['system'] = $system;
132
                $failureMessages[$identifier]['tool'] = $this->getPrefix($rule);
133
134
                $counter[$identifier] = 0;
135
            }
136
        }
137
138
        foreach ($this->results as $result) {
139
            if ($result->isFailure()) {
140
                foreach ($result->getMessages() as $ruleLKey => $message) {
141
                    $system = $this->system;
142
                    if ($this->systemUseRetriever) {
143
                        $system = $this->retriever->getSystem(($result->getUrl()));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface whm\Smoke\Extensions\Smo...ver\Retriever\Retriever as the method getSystem() does only exist in the following implementations of said interface: whm\Smoke\Extensions\Smo...ListRetriever\Retriever.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
144
                    }
145
146
                    $identifer = $this->tool . '_' . $this->getPrefix($ruleLKey) . '_' . $system;
147
148
                    if ($failureMessages[$identifer]['message'] === '') {
149
                        $failureMessages[$identifer]['message'] = 'The ' . $this->getPrefix($ruleLKey) . ' test for #system_name# failed.<ul>';
150
                    }
151
                    ++$counter[$identifer];
152
                    $message = '<li>' . $message . '<br>url: ' . $result->getUrl();
153
                    if ($this->addComingFrom) {
154
                        $message .= ', coming from: ' . $this->retriever->getComingFrom($result->getUrl());
155
                    }
156
                    $message .= '</li>';
157
                    $failureMessages[$identifer]['message'] .= $message;
158
                }
159
            }
160
        }
161
162
        foreach ($failureMessages as $key => $failureMessage) {
163
            if ($failureMessage['message'] !== '') {
164
                $this->send($this->identifier . '_' . $key, $failureMessage['system'], $failureMessage['message'] . '</ul>', self::STATUS_FAILURE, '', $counter[$key], $failureMessage['tool']);
165
            } else {
166
                $this->send($this->identifier . '_' . $key, $failureMessage['system'], '', self::STATUS_SUCCESS, '', 0, $failureMessage['tool']);
167
            }
168
        }
169
    }
170
171
    private function sendSingle()
172
    {
173
        $rules = $this->getRuleKeys();
174
        foreach ($this->results as $result) {
175
            $failedTests = array();
176
            if ($result->isFailure()) {
177
                foreach ($result->getMessages() as $ruleLKey => $message) {
178
                    $identifier = 'smoke_' . $ruleLKey . '_' . $result->getUrl();
179
180
                    if ($this->system === '') {
181
                        $system = str_replace('http://', '', $result->getUrl());
182
                    } else {
183
                        $system = $this->system;
184
                    }
185
                    $this->send($identifier, $system, 'smoke', $message, self::STATUS_FAILURE, (string) $result->getUrl());
186
                    $failedTests[] = $ruleLKey;
187
                }
188
            }
189
            foreach ($rules as $rule) {
190
                if (!in_array($rule, $failedTests, true)) {
191
                    $identifier = 'smoke_' . $rule . '_' . $result->getUrl();
192
193
                    if ($this->systemUseRetriever) {
194
                        $system = $this->retriever->getSystem($result->getUrl());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface whm\Smoke\Extensions\Smo...ver\Retriever\Retriever as the method getSystem() does only exist in the following implementations of said interface: whm\Smoke\Extensions\Smo...ListRetriever\Retriever.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
195
                    } elseif ($this->system === '') {
196
                        $system = str_replace('http://', '', $result->getUrl());
197
                    } else {
198
                        $system = $this->system;
199
                    }
200
                    $this->send($identifier, $system, 'smoke_' . $rule . '_' . $result->getUrl(), self::STATUS_SUCCESS, (string) $result->getUrl());
201
                }
202
            }
203
        }
204
    }
205
206
    private function sendCollected()
207
    {
208
        $failureMessages = array();
209
        $counter = array();
210
211
        foreach ($this->getRuleKeys() as $rule) {
212
            $failureMessages[$rule] = '';
213
            $counter[$rule] = 0;
214
        }
215
216
        foreach ($this->results as $result) {
217
            if ($result->isFailure()) {
218
                foreach ($result->getMessages() as $ruleLKey => $message) {
219
                    $system = $this->system;
220
                    if ($this->systemUseRetriever) {
221
                        $system = $this->retriever->getSystem(new Uri($result->getUrl()));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface whm\Smoke\Extensions\Smo...ver\Retriever\Retriever as the method getSystem() does only exist in the following implementations of said interface: whm\Smoke\Extensions\Smo...ListRetriever\Retriever.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
222
                    }
223
                    if ($failureMessages[$ruleLKey] === '') {
224
                        $failureMessages[$ruleLKey]['message'] = '    The smoke test for #system_name# failed (Rule: ' . $ruleLKey . ').<ul>';
225
                    }
226
                    ++$counter[$ruleLKey];
227
228
                    $comingFrom = '';
229
230
                    if ($this->addComingFrom && $this->retriever->getComingFrom($result->getUrl())) {
231
                        $comingFrom = ', coming from: ' . $this->retriever->getComingFrom($result->getUrl());
232
                    }
233
234
                    $failureMessages[$ruleLKey]['message'] .= '<li>' . $message . ' (url: ' . $result->getUrl() . $comingFrom . ')</li > ';
235
                    $failureMessages[$ruleLKey]['system'] = $system;
236
                }
237
            }
238
        }
239
240
        foreach ($failureMessages as $key => $failureMessage) {
241
            if ($failureMessage !== '') {
242
                $this->send($this->identifier . '_' . $key, $this->system, $failureMessage['message'] . ' </ul > ', self::STATUS_FAILURE, '', $counter[$key]);
243
            } else {
244
                $this->send($this->identifier . '_' . $key, $this->system, '', self::STATUS_SUCCESS, '', 0);
245
            }
246
        }
247
    }
248
249
    private function send($identifier, $system, $message, $status, $url = '', $value = 0, $tool = null)
0 ignored issues
show
Unused Code introduced by
The parameter $url is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
250
    {
251
        if (is_null($tool)) {
252
            $tool = $this->tool;
253
        }
254
        $event = new Event($identifier, $system, $status, $tool, $message, $value);
255
256
        $this->reporter->sendEvent($event);
257
    }
258
}
259