RepositoryRegistryImpl   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 74.36%

Importance

Changes 0
Metric Value
dl 0
loc 149
c 0
b 0
f 0
wmc 15
lcom 1
cbo 2
ccs 29
cts 39
cp 0.7436
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A registerProvider() 0 16 2
A getRepositories() 0 7 1
A hasRepositoryByClassName() 0 4 1
A getRepositoryByClassName() 0 6 2
A getRepositoryByEntity() 0 8 2
A hasRepositoryByName() 0 4 1
A getRepositoryByName() 0 6 2
A resolveProvider() 0 16 3
1
<?php
2
/**
3
 * Created by gerk on 04.12.17 05:54
4
 */
5
6
namespace PeekAndPoke\Component\Slumber\Data;
7
8
use PeekAndPoke\Component\Psi\Psi;
9
10
/**
11
 *
12
 *
13
 * @author Karsten J. Gerber <[email protected]>
14
 */
15
class RepositoryRegistryImpl implements RepositoryRegistry
16
{
17
    /**
18
     * @var \SplObjectStorage
19
     */
20
    private $repositoriesByProviders;
21
22
    /**
23
     * Maps tables name to repository providers
24
     *
25
     * @var \Closure
26
     */
27
    private $providersByNames = [];
28
29
    /**
30
     * Maps class names to repository providers
31
     *
32
     * @var \Closure
33
     */
34
    private $providersByClassNames = [];
35
36
    /**
37
     */
38 4
    public function __construct()
39
    {
40 4
        $this->repositoriesByProviders = new \SplObjectStorage();
41 4
    }
42
43
    /**
44
     * Registers a repositories with its table name and all class names stored in the repository
45
     *
46
     * This is an optimization. It allows to register repositories without the need to autoload the repository class upfront.
47
     * The repository class will only be loaded once the provider is called.
48
     * This helps to speed up requests when the number of repositories grow considerably big.
49
     *
50
     * @param string   $name
51
     * @param array    $classes
52
     * @param \Closure $provider
53
     *
54
     * @return $this
55
     */
56
    public function registerProvider($name, array $classes, \Closure $provider)
57
    {
58 4
        $realProvider = function () use ($name, $classes, $provider) {
59 2
            $context = new RepositoryRegistry\ProviderContext($name, $classes);
60
61 2
            return $provider($context);
62 4
        };
63
64 4
        $this->providersByNames[$name] = $realProvider;
65
66 4
        foreach ($classes as $class) {
67 4
            $this->providersByClassNames[$class] = $realProvider;
68
        }
69
70 4
        return $this;
71
    }
72
73
    /**
74
     * @return Repository[]
75
     */
76
    public function getRepositories()
77
    {
78
        return Psi::it($this->providersByNames)
79
            ->filter(new Psi\IsInstanceOf(\Closure::class))
80
            ->map(function (\Closure $c) { return $this->resolveProvider($c); })
81
            ->toArray();
82
    }
83
84
    /**
85
     * @param string $class
86
     *
87
     * @return bool
88
     */
89
    public function hasRepositoryByClassName($class)
90
    {
91
        return isset($this->providersByClassNames[$class]);
92
    }
93
94
    /**
95
     * @param string $class
96
     *
97
     * @return null|Repository
98
     */
99 22
    public function getRepositoryByClassName($class)
100
    {
101 22
        return isset($this->providersByClassNames[$class])
102 22
            ? $this->resolveProvider($this->providersByClassNames[$class])
103 22
            : null;
104
    }
105
106
    /**
107
     * @param mixed $entity
108
     *
109
     * @return null|Repository
110
     */
111 6
    public function getRepositoryByEntity($entity)
112
    {
113 6
        if (! \is_object($entity)) {
114
            return null;
115
        }
116
117 6
        return $this->getRepositoryByClassName(\get_class($entity));
118
    }
119
120
    /**
121
     * @param string $name
122
     *
123
     * @return bool
124
     */
125
    public function hasRepositoryByName($name)
126
    {
127
        return isset($this->providersByNames[$name]);
128
    }
129
130
    /**
131
     * @param string $name
132
     *
133
     * @return null|Repository
134
     */
135 3
    public function getRepositoryByName($name)
136
    {
137 3
        return isset($this->providersByNames[$name])
138 2
            ? $this->resolveProvider($this->providersByNames[$name])
139 3
            : null;
140
    }
141
142
    /**
143
     * @param \Closure|null $provider
144
     *
145
     * @return null|Repository
146
     */
147 23
    private function resolveProvider(\Closure $provider = null)
148
    {
149 23
        if ($provider === null) {
150
            return null;
151
        }
152
153 23
        if ($this->repositoriesByProviders->contains($provider)) {
154 23
            return $this->repositoriesByProviders->offsetGet($provider);
155
        }
156
157 2
        $createdRepo = $provider();
158
159 2
        $this->repositoriesByProviders->offsetSet($provider, $createdRepo);
160
161 2
        return $createdRepo;
162
    }
163
}
164