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

AdapterFactory::setDefaultAdapterClasses()   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\Parser\Sqlite\Adapter;
5
6
use Crossjoin\Browscap\Exception\BrowscapException;
7
use Crossjoin\Browscap\Exception\InvalidArgumentException;
8
use Crossjoin\Browscap\Exception\ParserConditionNotSatisfiedException;
9
use Crossjoin\Browscap\Exception\UnexpectedValueException;
10
11
/**
12
 * Class AdapterFactory
13
 *
14
 * @package Crossjoin\Browscap\Parser\Sqlite\Adapter
15
 * @author Christoph Ziegenberg <[email protected]>
16
 * @link https://github.com/crossjoin/browscap
17
 */
18 View Code Duplication
class AdapterFactory
19
{
20
    /**
21
     * @var array
22
     */
23
    protected static $defaultAdapterClasses = [
24
        '\Crossjoin\Browscap\Parser\Sqlite\Adapter\Pdo',
25
        '\Crossjoin\Browscap\Parser\Sqlite\Adapter\Sqlite3',
26
    ];
27
28
    /**
29
     * @var array|null
30
     */
31
    protected static $adapterClasses;
32
33
    /**
34
     * @param string $fileName
35
     *
36
     * @return AdapterInterface
37
     * @throws ParserConditionNotSatisfiedException
38
     * @throws UnexpectedValueException
39
     */
40
    public static function getInstance(string $fileName) : AdapterInterface
41
    {
42
        // Initialize adapter classes
43
        if (static::$adapterClasses === null) {
44
            self::setDefaultAdapterClasses();
45
        }
46
        
47
        foreach (static::$adapterClasses as $className) {
0 ignored issues
show
Bug introduced by
The expression static::$adapterClasses 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...
48
            $instance = static::getInstanceByClassName($className, $fileName);
49
            if ($instance !== null) {
50
                return $instance;
51
            }
52
        }
53
54
        throw new ParserConditionNotSatisfiedException(
55
            "No Sqlite extension found. Either 'pdo_sqlite' or 'sqlite3' extension required."
56
        );
57
    }
58
    
59
    public static function setDefaultAdapterClasses()
60
    {
61
        self::setAdapterClasses(self::$defaultAdapterClasses);
62
    }
63
64
    /**
65
     * @param array $fullyQualifiedClassNames
66
     *
67
     * @throws InvalidArgumentException
68
     */
69
    public static function setAdapterClasses(array $fullyQualifiedClassNames)
70
    {
71
        $rememberClasses = self::$adapterClasses;
72
73
        self::$adapterClasses = [];
74
        foreach ($fullyQualifiedClassNames as $className) {
75
            if (is_string($className)) {
76
                self::$adapterClasses[] = $className;
77
            } else {
78
                // Reset to previous value on error
79
                self::$adapterClasses = $rememberClasses;
80
81
                throw new InvalidArgumentException(
82
                    "A value in the class name array is of type '" . gettype($className) . "'. String expected."
83
                );
84
            }
85
        }
86
    }
87
88
    /**
89
     * @param string $className
90
     * @param string $fileName
91
     *
92
     * @return AdapterInterface|null
93
     * @throws UnexpectedValueException
94
     */
95
    protected static function getInstanceByClassName(string $className, string $fileName)
96
    {
97
        if (class_exists($className)) {
98
            $interface = '\Crossjoin\Browscap\Parser\Sqlite\Adapter\AdapterFactoryInterface';
99
            $interfaces = class_implements($className);
100
            if (array_key_exists(ltrim($interface, '\\'), $interfaces)) {
101
                try {
102
                    return new $className($fileName);
103
                } catch (BrowscapException $e) {
104
                    // Ignore exception, because we just return NULL on failure
105
                }
106
            } else {
107
                throw new UnexpectedValueException(
108
                    "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...
109
                    1459000689
110
                );
111
            }
112
        } else {
113
            throw new UnexpectedValueException("Class '$className' doesn't exist.", 1459000690);
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...
114
        }
115
116
        return null;
117
    }
118
}
119