Completed
Branch Gutenberg/event-attendees-bloc... (e27df5)
by
unknown
42:51 queued 28:10
created

CoffeeMaker::resolveInstantiationMethod()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 6
nop 1
dl 0
loc 19
rs 9.0111
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\services\container;
4
5
use EventEspresso\core\exceptions\InvalidClassException;
6
use EventEspresso\core\exceptions\InvalidIdentifierException;
7
use EventEspresso\core\services\container\exceptions\InstantiationException;
8
9
/**
10
 * Class CoffeeMaker
11
 * Abstract Parent class for CoffeeMakers which are responsible
12
 * for building objects that are requested from the CoffeeShop
13
 *
14
 * @package       Event Espresso
15
 * @author        Brent Christensen
16
 * @since         4.9.1
17
 */
18
abstract class CoffeeMaker implements CoffeeMakerInterface
19
{
20
21
    /**
22
     * Indicates that CoffeeMaker should construct a NEW entity instance from the provided arguments (if given)
23
     */
24
    const BREW_NEW = 'new';
25
26
    /**
27
     * Indicates that CoffeeMaker should always return a SHARED instance
28
     */
29
    const BREW_SHARED = 'shared';
30
31
    /**
32
     * Indicates that CoffeeMaker should only load the file/class/interface but NOT instantiate
33
     */
34
    const BREW_LOAD_ONLY = 'load_only';
35
36
37
    /**
38
     * @var CoffeePotInterface $coffee_pot
39
     */
40
    private $coffee_pot;
41
42
    /**
43
     * @var DependencyInjector $injector
44
     */
45
    private $injector;
46
47
48
    /**
49
     * @return array
50
     */
51
    public static function getTypes()
52
    {
53
        return (array) apply_filters(
54
            'FHEE__EventEspresso\core\services\container\CoffeeMaker__getTypes',
55
            array(
56
                CoffeeMaker::BREW_NEW,
57
                CoffeeMaker::BREW_SHARED,
58
                CoffeeMaker::BREW_LOAD_ONLY,
59
            )
60
        );
61
    }
62
63
64
    /**
65
     * @param $type
66
     * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
67
     */
68
    public static function validateType($type)
69
    {
70
        $types = CoffeeMaker::getTypes();
71
        if (! in_array($type, $types, true)) {
72
            throw new InvalidIdentifierException(
73
                is_object($type) ? get_class($type) : gettype($type),
74
                __(
75
                    'recipe type (one of the class constants on \EventEspresso\core\services\container\CoffeeMaker)',
76
                    'event_espresso'
77
                )
78
            );
79
        }
80
        return $type;
81
    }
82
83
84
    /**
85
     * CoffeeMaker constructor.
86
     *
87
     * @param CoffeePotInterface $coffee_pot
88
     * @param InjectorInterface  $injector
89
     */
90
    public function __construct(CoffeePotInterface $coffee_pot, InjectorInterface $injector)
91
    {
92
        $this->coffee_pot = $coffee_pot;
93
        $this->injector = $injector;
0 ignored issues
show
Documentation Bug introduced by
$injector is of type object<EventEspresso\cor...iner\InjectorInterface>, but the property $injector was declared to be of type object<EventEspresso\cor...ner\DependencyInjector>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
94
    }
95
96
97
    /**
98
     * @return \EventEspresso\core\services\container\CoffeePotInterface
99
     */
100
    protected function coffeePot()
101
    {
102
        return $this->coffee_pot;
103
    }
104
105
106
    /**
107
     * @return \EventEspresso\core\services\container\DependencyInjector
108
     */
109
    protected function injector()
110
    {
111
        return $this->injector;
112
    }
113
114
115
    /**
116
     * Examines the constructor to determine which method should be used for instantiation
117
     *
118
     * @param \ReflectionClass $reflector
119
     * @return mixed
120
     * @throws InstantiationException
121
     */
122
    protected function resolveInstantiationMethod(\ReflectionClass $reflector)
123
    {
124
        if ($reflector->getConstructor() === null) {
125
            return 'NewInstance';
126
        }
127
        if ($reflector->isInstantiable()) {
128
            return 'NewInstanceArgs';
129
        }
130
        if (method_exists($reflector->getName(), 'instance')) {
0 ignored issues
show
Bug introduced by
Consider using $reflector->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
131
            return 'instance';
132
        }
133
        if (method_exists($reflector->getName(), 'new_instance')) {
0 ignored issues
show
Bug introduced by
Consider using $reflector->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
134
            return 'new_instance';
135
        }
136
        if (method_exists($reflector->getName(), 'new_instance_from_db')) {
0 ignored issues
show
Bug introduced by
Consider using $reflector->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
137
            return 'new_instance_from_db';
138
        }
139
        throw new InstantiationException($reflector->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflector->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
140
    }
141
142
143
    /**
144
     * Ensures files for classes that are not PSR-4 compatible are loaded
145
     * and then verifies that classes exist where applicable
146
     *
147
     * @param RecipeInterface $recipe
148
     * @return bool
149
     * @throws InvalidClassException
150
     */
151
    protected function resolveClassAndFilepath(RecipeInterface $recipe)
152
    {
153
        $paths = $recipe->paths();
154
        if (! empty($paths)) {
155
            foreach ($paths as $path) {
156
                if (strpos($path, '*') === false && is_readable($path)) {
157
                    require_once($path);
158
                }
159
            }
160
        }
161
        // re: using "false" for class_exists() second param:
162
        // if a class name is not already known to PHP, then class_exists() will run through
163
        // all of the registered spl_autoload functions until it either finds the class,
164
        // or gets to the end of the registered spl_autoload functions.
165
        // When the second parameter is true, it will also attempt to load the class file,
166
        // but it will also trigger an error if the class can not be loaded.
167
        // We don't want that extra error in the mix, so we have set the second param to "false"
168
        if ($recipe->type() !== CoffeeMaker::BREW_LOAD_ONLY && ! class_exists($recipe->fqcn(), false)) {
169
            throw new InvalidClassException($recipe->identifier());
170
        }
171
        return true;
172
    }
173
}
174