Completed
Push — master ( b2e2fb...3dd80e )
by Delete
02:52
created

SourceFactory::setDefaultSourceClasses()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 4
Ratio 100 %
Metric Value
dl 4
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Crossjoin\Browscap\Source;
5
6
use Crossjoin\Browscap\Exception\BrowscapException;
7
use Crossjoin\Browscap\Exception\InvalidArgumentException;
8
use Crossjoin\Browscap\Exception\UnexpectedValueException;
9
10
/**
11
 * Class SourceFactory
12
 *
13
 * @package Crossjoin\Browscap\Source
14
 * @author Christoph Ziegenberg <[email protected]>
15
 * @link https://github.com/crossjoin/browscap
16
 */
17 View Code Duplication
class SourceFactory
18
{
19
    /**
20
     * @var array
21
     */
22
    protected static $defaultSourceClasses  = [
23
        '\Crossjoin\Browscap\Source\Ini\BrowscapOrg',
24
        '\Crossjoin\Browscap\Source\Ini\PhpSetting',
25
    ];
26
27
    /**
28
     * @var array|null
29
     */
30
    protected static $sourceClasses;
31
32
    /**
33
     * @return SourceInterface
34
     * @throws UnexpectedValueException
35
     */
36
    public static function getInstance() : SourceInterface
37
    {
38
        // Initialize adapter classes
39
        if (static::$sourceClasses === null) {
40
            self::setDefaultSourceClasses();
41
        }
42
        
43
        foreach (static::$sourceClasses as $className) {
0 ignored issues
show
Bug introduced by
The expression static::$sourceClasses of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
44
            $instance = static::getInstanceByClassName($className);
45
            if ($instance !== null) {
46
                return $instance;
47
            }
48
        }
49
50
        return new None();
51
    }
52
53
    public static function setDefaultSourceClasses()
54
    {
55
        self::setSourceClasses(self::$defaultSourceClasses);
56
    }
57
58
    /**
59
     * @param array $fullyQualifiedClassNames
60
     *
61
     * @throws InvalidArgumentException
62
     */
63
    public static function setSourceClasses(array $fullyQualifiedClassNames)
64
    {
65
        $rememberClasses = self::$sourceClasses;
66
67
        self::$sourceClasses = [];
68
        foreach ($fullyQualifiedClassNames as $className) {
69
            if (is_string($className)) {
70
                self::$sourceClasses[] = $className;
71
            } else {
72
                // Reset to previous value on error
73
                self::$sourceClasses = $rememberClasses;
74
75
                throw new InvalidArgumentException(
76
                    "A value in the class name array is of type '" . gettype($className) . "'. String expected."
77
                );
78
            }
79
        }
80
    }
81
82
    /**
83
     * @param string $className
84
     *
85
     * @return SourceInterface|null
86
     * @throws UnexpectedValueException
87
     */
88
    protected static function getInstanceByClassName(string $className)
89
    {
90
        if (class_exists($className)) {
91
            $interface = '\Crossjoin\Browscap\Source\SourceFactoryInterface';
92
            $interfaces = class_implements($className);
93
            if (array_key_exists(ltrim($interface, '\\'), $interfaces)) {
94
                try {
95
                    return new $className();
96
                } catch (BrowscapException $e) {
97
                    // Ignore exception, because we just return NULL on failure
98
                }
99
            } else {
100
                throw new UnexpectedValueException(
101
                    "Class '$className' has to implement the interface '$interface'.",
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $className instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $interface instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
102
                    1459069587
103
                );
104
            }
105
        } else {
106
            throw new UnexpectedValueException("Class '$className' doesn't exist.", 1459069588);
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $className instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
107
        }
108
109
        return null;
110
    }
111
}
112