MetadataControllerProvider   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 90
Duplicated Lines 0 %

Test Coverage

Coverage 79.17%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 12
eloc 36
c 4
b 0
f 0
dl 0
loc 90
rs 10
ccs 38
cts 48
cp 0.7917

3 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 6 1
B boot() 0 51 10
A getCandidateControllers() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AlgoWeb\PODataLaravel\Providers;
6
7
use AlgoWeb\PODataLaravel\Controllers\MetadataControllerContainer;
8
use AlgoWeb\PODataLaravel\Controllers\MetadataControllerTrait;
9
use AlgoWeb\PODataLaravel\Models\ClassReflectionHelper;
10
use Cruxinator\ClassFinder\ClassFinder;
11
use Illuminate\Routing\Controller;
12
use Illuminate\Support\Facades\App;
13
use Illuminate\Support\Facades\Cache;
14
use POData\Common\InvalidOperationException;
15
16 68
class MetadataControllerProvider extends MetadataBaseProvider
17
{
18 68
    /*
19
     * Optional crud verbs - these need to be deduplicated for empty mappings
20 68
     */
21
    /** @var string[] */
22
    protected $optionalVerbs = ['bulkCreate', 'bulkUpdate'];
23
24
    /**
25
     * Bootstrap the application services.  Post-boot.
26 68
     *
27
     * @throws InvalidOperationException
28 68
     * @throws \Exception
29 68
     * @return void
30 68
     */
31 68
    public function boot()
32 68
    {
33 68
        $isCaching = true === $this->getIsCaching();
34 68
        $hasCache  = null;
35
36 68
        if ($isCaching) {
37 68
            $hasCache = Cache::has('metadataControllers');
38 68
            if ($hasCache) {
39 68
                $meta = Cache::get('metadataControllers');
40
                App::instance('metadataControllers', $meta);
41 68
                return;
42 68
            }
43 68
        }
44 68
45 67
        /** @var MetadataControllerContainer $meta */
46 67
        $meta = App::make('metadataControllers');
47 68
48
        $ends = $this->getCandidateControllers();
49
        // now process each class that uses the metadata controller trait and stick results in $metamix
50 68
        $metamix = [];
51
        foreach ($ends as $end) {
52
            $map = $end->getMappings();
53 68
            // verify uniqueness - must be exactly one mapping for model-verb combo - different verb mappings for
54 68
            // a model can glom onto different controllers
55 67
            foreach ($map as $key => $lock) {
56
                if (!array_key_exists($key, $metamix)) {
57
                    // if we haven't yet got a mapping for this model, grab it holus-bolus
58 67
                    $metamix[$key] = $lock;
59 67
                    continue;
60
                }
61 67
                // if we do, make sure we aren't re-adding mappings for any of the CRUD verbs
62 67
                foreach ($lock as $barrel => $roll) {
63
                    $isOptional = in_array($barrel, $this->optionalVerbs);
64
                    $alreadyKey = array_key_exists($barrel, $metamix[$key]);
65
                    if ($isOptional) {
66
                        // if we've picked up a default mapping for an optional verb, then we can overwrite it
67
                        $alreadyKey = null === $metamix[$key][$barrel] ? false : $alreadyKey;
68
                    }
69
                    if ($alreadyKey) {
70
                        $msg = 'Mapping already defined for model ' . $key . ' and CRUD verb ' . $barrel;
71
                        throw new InvalidOperationException($msg);
72
                    }
73 67
                    $metamix[$key][$barrel] = $roll;
74 68
                }
75
            }
76 68
        }
77
78 68
        $meta->setMetadata($metamix);
79
80
        $key = 'metadataControllers';
81
        $this->handlePostBoot($isCaching, $hasCache, $key, $meta);
82
    }
83
84
    /**
85
     * Register the application services.  Boot-time only.
86
     *
87 68
     * @return void
88 68
     */
89 68
    public function register()
90 68
    {
91
        $this->app->/* @scrutinizer ignore-call */singleton(
92
            'metadataControllers',
93
            function () {
94
                return new MetadataControllerContainer();
95
            }
96
        );
97
    }
98
99
    /**
100
     * @return mixed
101
     * @throws \Exception
102
     */
103
    protected function getCandidateControllers()
104
    {
105
        return ClassReflectionHelper::getCandidateControllers();
106
    }
107
}
108