Completed
Push — master ( de59c0...367b4e )
by Vladimir
03:16
created

ActivatorParser::parse()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 46
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 7.2269

Importance

Changes 0
Metric Value
cc 7
eloc 24
nc 6
nop 1
dl 0
loc 46
ccs 15
cts 18
cp 0.8333
crap 7.2269
rs 6.7272
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace FondBot\Conversation;
6
7
use InvalidArgumentException;
8
use FondBot\Conversation\Activators\Exact;
9
use FondBot\Conversation\Activators\Regex;
10
use FondBot\Conversation\Activators\InArray;
11
use FondBot\Conversation\Activators\Payload;
12
use FondBot\Contracts\Conversation\Activator;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, FondBot\Conversation\Activator.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
13
use FondBot\Conversation\Activators\Contains;
14
use FondBot\Conversation\Activators\Attachment;
15
16
class ActivatorParser
17
{
18
    private static $activators = [
19
        'contains' => Contains::class,
20
        'exact' => Exact::class,
21
        'in_array' => InArray::class,
22
        'regex' => Regex::class,
23
        'attachment' => Attachment::class,
24
        'payload' => Payload::class,
25
    ];
26
27
    private static $arrayActivators = [
28
        'in_array',
29
    ];
30
31
    /**
32
     * @param array $data
33
     *
34
     * @return Activator[]
35
     */
36 2
    public static function parse(array $data): array
37
    {
38 2
        $result = [];
39
40 2
        foreach ($data as $key => $activator) {
41 2
            if ($activator instanceof Activator) {
42 1
                $result[] = $activator;
43
44 1
                continue;
45
            }
46
47 2
            [$name, $parameters] = explode(':', $activator, 2);
0 ignored issues
show
Bug introduced by
The variable $name does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $parameters does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
48
49 2
            $parameters = collect(str_getcsv($parameters));
50
51 2
            if (in_array($name, static::$arrayActivators, true)) {
0 ignored issues
show
Bug introduced by
Since $arrayActivators is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $arrayActivators to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
52 1
                $value = $parameters;
53
            } else {
54 2
                $value = $parameters->first();
55 2
                $parameters = $parameters->slice(1)->values()->transform(function ($item) {
56 1
                    if ($item === 'true') {
57 1
                        return true;
58
                    }
59
60
                    if ($item === 'false') {
61
                        return false;
62
                    }
63
64
                    return $item;
65 2
                });
66
            }
67
68
            if (isset(static::$activators[$name])) {
0 ignored issues
show
Bug introduced by
Since $activators is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $activators to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
69
                /** @var Activator $activator */
70
                $activator = new static::$activators[$name]($value, ...$parameters);
0 ignored issues
show
Bug introduced by
Since $activators is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $activators to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
71
72
                $result[] = $activator;
73
74
                continue;
75
            }
76
77
            throw new InvalidArgumentException('Activator `'.$name.'` does not exist.');
78
        }
79
80
        return $result;
81
    }
82
}
83