Completed
Push — master ( 59d725...9f24e3 )
by Alex
17s queued 14s
created

getCandidateControllers()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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