Passed
Push — master ( dff13b...dab0e7 )
by Jesse
03:04
created

Instantiator   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 54
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 9
dl 0
loc 54
c 0
b 0
f 0
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A forThe() 0 3 1
A class() 0 3 1
A instance() 0 6 2
A newInstanceFromDeserialization() 0 8 1
A __construct() 0 12 4
1
<?php
2
declare(strict_types=1);
3
4
namespace Stratadox\Instantiator;
5
6
use ReflectionClass;
7
use ReflectionException;
8
use function sprintf;
9
use function strlen;
10
use Throwable;
11
12
/**
13
 * Simple Instantiator.
14
 *
15
 * @author Stratadox
16
 */
17
final class Instantiator extends ReflectionClass implements ProvidesInstances
18
{
19
    /** @throws CannotInstantiateThis */
20
    public function __construct(string $class)
21
    {
22
        try {
23
            parent::__construct($class);
24
        } catch (ReflectionException $exception) {
25
            throw CannotFindTheClass::encountered($exception);
26
        }
27
        if ($this->isAbstract()) {
28
            throw ClassIsAbstract::cannotInstantiate($class);
29
        }
30
        if ($this->isInterface()) {
31
            throw ThatIsAnInterface::cannotInstantiate($class);
32
        }
33
    }
34
35
    /**
36
     * Produces a new instantiator.
37
     *
38
     * @param string $class      The class to create the instantiator for.
39
     * @return ProvidesInstances The instantiator for the class.
40
     * @throws CannotInstantiateThis
41
     */
42
    public static function forThe(string $class): ProvidesInstances
43
    {
44
        return new Instantiator($class);
45
    }
46
47
    /** @inheritdoc */
48
    public function instance(): object
49
    {
50
        try {
51
            return $this->newInstanceWithoutConstructor();
52
        } catch (Throwable $exception) {
53
            return $this->newInstanceFromDeserialization();
54
        }
55
    }
56
57
    /** @inheritdoc */
58
    public function class(): string
59
    {
60
        return $this->getName();
61
    }
62
63
    private function newInstanceFromDeserialization(): object
64
    {
65
        $class = $this->getName();
66
        return unserialize(sprintf(
67
            'O:%d:"%s":0:{}',
68
            strlen($class),
69
            $class
70
        ), ['allowed_classes' => [$class]]);
71
    }
72
}
73