RepositoryFactory   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 189
Duplicated Lines 0 %

Test Coverage

Coverage 90.57%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 48
dl 0
loc 189
ccs 48
cts 53
cp 0.9057
rs 10
c 2
b 0
f 0
wmc 17

9 Methods

Rating   Name   Duplication   Size   Complexity  
A resolveCallable() 0 16 3
A loadFixtures() 0 12 1
A mock() 0 17 1
A getFixtureResolver() 0 9 2
A getSolid() 0 9 2
A resetAll() 0 4 2
A __construct() 0 9 3
A getRepository() 0 9 2
A reset() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Prozorov\Repositories;
6
7
use Prozorov\Repositories\Contracts\{FixtureResolverInterface, RepositoryInterface, ResolverInterface};
8
use Prozorov\Repositories\Exceptions\CouldNotResolve;
9
use Mockery;
10
11
class RepositoryFactory
12
{
13
    /**
14
     * @var array $bindings
15
     */
16
    protected $bindings = [];
17
18
    /**
19
     * @var array $resolved
20
     */
21
    protected $resolved = [];
22
23
    /**
24
     * @var ResolverInterface $resolver
25
     */
26
    protected $resolver;
27
28
    /**
29
     * @var string $fixtureResolverClass
30
     */
31
    protected $fixtureResolverClass;
32
33
    /**
34
     * @var string $fixtureResolver
35
     */
36
    protected $fixtureResolver;
37
38 8
    public function __construct(ResolverInterface $resolver, array $bindings, string $fixtureResolverClass = null)
39
    {
40 8
        $this->resolver = $resolver;
41 8
        $this->bindings = $bindings;
42
43 8
        if (! empty($fixtureResolverClass) && class_exists($fixtureResolverClass)) {
44
            $this->fixtureResolverClass = $fixtureResolverClass;
45
        } else {
46 8
            $this->fixtureResolverClass = ArrayFixtureResolver::class;
47
        }
48 8
    }
49
50
    /**
51
     * getRepository.
52
     *
53
     * @access	public
54
     * @param	string	$code
55
     * @return	RepositoryInterface
56
     */
57 8
    public function getRepository(string $code): RepositoryInterface
58
    {
59 8
        $solid = $this->getSolid($code);
60
61 7
        if (empty($this->resolved[$solid])) {
62 5
            $this->resolved[$solid] = $this->resolver->resolve($solid);
63
        }
64
65 5
        return $this->resolved[$solid];
66
    }
67
68
    /**
69
     * getResolvedInstance.
70
     *
71
     * @access	protected
72
     * @param	string	$code	
73
     * @return	string
74
     */
75 8
    protected function getSolid(string $code): string
76
    {
77 8
        $solid = $this->bindings[$code] ?? $code;
78
79 8
        if (is_callable($solid)) {
80 3
            return $this->resolveCallable($code, $solid);
81
        }
82
83 5
        return $solid;
84
    }
85
86
    /**
87
     * Resolves callable
88
     *
89
     * @access	protected
90
     * @param	string  	$code 	
91
     * @param	callable	$solid	
92
     * @return	string
93
     */
94 3
    protected function resolveCallable(string $code, callable $solid): string
95
    {
96 3
        if (empty($this->resolved[$code])) {
97 3
            $resolved = $solid();
98
99 3
            if (! ($resolved instanceof RepositoryInterface)) {
100 1
                $exception = new CouldNotResolve();
101 1
                $exception->setRepositoryCode($code);
102
103 1
                throw $exception;
104
            }
105
106 2
            $this->resolved[$code] = $solid();
107
        }
108
109 2
        return $code;
110
    }
111
112
    /**
113
     * Clears resolved instance
114
     *
115
     * @access	public
116
     * @param	string	$code
117
     * @return	void
118
     */
119 2
    public function reset(string $code): void
120
    {
121 2
        unset($this->resolved[$code]);
122 2
    }
123
124
    /**
125
     * Clears resolved instance
126
     *
127
     * @access	public
128
     * @return	void
129
     */
130
    public function resetAll(): void
131
    {
132
        foreach ($this->resolved as $repository) {
133
            unset($repository);
134
        }
135
    }
136
137
    /**
138
     * getFixtureResolver.
139
     *
140
     * @access	protected
141
     * @return	FixtureResolverInterface
142
     */
143 1
    protected function getFixtureResolver(): FixtureResolverInterface
144
    {
145 1
        if (empty($this->fixtureResolver)) {
146 1
            $this->fixtureResolver = new $this->fixtureResolverClass;
0 ignored issues
show
Documentation Bug introduced by
It seems like new $this->fixtureResolverClass() of type object is incompatible with the declared type string of property $fixtureResolver.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
147
        }
148
149
        // Assert $this->fixtureResolver implements FixtureResolverInterface
150
151 1
        return $this->fixtureResolver;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->fixtureResolver could return the type string which is incompatible with the type-hinted return Prozorov\Repositories\Co...ixtureResolverInterface. Consider adding an additional type-check to rule them out.
Loading history...
152
    }
153
154
    /**
155
     * mock.
156
     *
157
     * @access	public
158
     * @param	string	$code	
159
     * @return	mixed
160
     */
161 2
    public function mock(string $code)
162
    {
163 2
        $solid = $this->getRepository($code);
164
165 2
        $className = get_class($solid);
166
167 2
        $this->reset($code);
168
169 2
        $solid = $this->getSolid($code);
170
171 2
        $mock = Mockery::mock($className)
172 2
            ->makePartial()
173 2
            ->shouldAllowMockingProtectedMethods();
174
175 2
        $this->resolved[$solid] = $mock;
176
177 2
        return $this->resolved[$solid];
178
    }
179
180
    /**
181
     * loadFixtures.
182
     *
183
     * @access	public
184
     * @param	string	$code
185
     * @param	mixed 	$fixtures
186
     * @return	void
187
     */
188 1
    public function loadFixtures(string $code, $fixtures): void
189
    {
190 1
        $solid = $this->getSolid($code);
191
192 1
        $this->mock($code);
193
194
        // Assert $code is a FixturableRepository
195
196 1
        $fixtures = $this->getFixtureResolver()->getFixtures($fixtures);
197
198 1
        $this->resolved[$solid]->shouldReceive('isFake')->andReturn(true);
199 1
        $this->resolved[$solid]->shouldReceive('fixtures')->andReturn($fixtures);
200 1
    }
201
}
202