Test Setup Failed
Pull Request — master (#47)
by Alex
12:44
created

MetadataProvider   B

Complexity

Total Complexity 39

Size/Duplication

Total Lines 247
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 7.14%

Importance

Changes 8
Bugs 0 Features 0
Metric Value
wmc 39
c 8
b 0
f 0
lcom 1
cbo 6
dl 0
loc 247
ccs 5
cts 70
cp 0.0714
rs 8.2857

6 Methods

Rating   Name   Duplication   Size   Complexity  
B boot() 0 38 6
A setupRoute() 0 8 1
A register() 0 6 1
B getCandidateModels() 0 14 5
B getEntityTypesAndResourceSets() 0 28 3
F calculateRoundTripRelations() 0 124 23
1
<?php
2
3
namespace AlgoWeb\PODataLaravel\Providers;
4
5
use Illuminate\Support\Facades\App;
6
use Illuminate\Support\ServiceProvider;
7
use Illuminate\Support\Facades\Cache;
8
use POData\Providers\Metadata\IMetadataProvider;
9
use POData\Providers\Metadata\SimpleMetadataProvider;
10
use Illuminate\Support\Facades\Route;
11
use Illuminate\Support\Facades\Schema as Schema;
12
13
class MetadataProvider extends MetadataBaseProvider
14
{
15
    protected $multConstraints = [ '0..1' => ['1'], '1' => ['0..1', '*'], '*' => ['1', '*']];
16
    protected static $METANAMESPACE = "Data";
17
18
    /**
19
     * Bootstrap the application services.  Post-boot.
20 1
     *
21
     * @return void
22 1
     */
23
    public function boot()
24
    {
25 1
        self::$METANAMESPACE = env('ODataMetaNamespace', 'Data');
26
        // If we aren't migrated, there's no DB tables to pull metadata _from_, so bail out early
27
        try {
28 1
            if (!Schema::hasTable('migrations')) {
29 1
                return;
30
            }
31
        } catch (\Exception $e) {
32
            return;
33
        }
34
35
        self::setupRoute();
36
        $isCaching = true === $this->getIsCaching();
37
        $hasCache = Cache::has('metadata');
38
39
        if ($isCaching && $hasCache) {
40
            $meta = Cache::get('metadata');
41
            App::instance('metadata', $meta);
1 ignored issue
show
Bug introduced by
The method instance() does not exist on Illuminate\Support\Facades\App. Did you maybe mean clearResolvedInstance()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
42
            return;
43
        }
44
        $meta = App::make('metadata');
45
46
        $modelNames = $this->getCandidateModels();
47
48
        list($EntityTypes, $ResourceSets, $ends) = $this->getEntityTypesAndResourceSets($meta, $modelNames);
49
50
        // now that endpoints are hooked up, tackle the relationships
51
        // if we'd tried earlier, we'd be guaranteed to try to hook a relation up to null, which would be bad
52
        foreach ($ends as $bitter) {
53
            $fqModelName = $bitter;
54
            $instance = new $fqModelName();
55
            $instance->hookUpRelationships($EntityTypes, $ResourceSets);
56
        }
57
58
        $key = 'metadata';
59
        $this->handlePostBoot($isCaching, $hasCache, $key, $meta);
60
    }
61
62
    private static function setupRoute()
63
    {
64
        $valueArray = [];
0 ignored issues
show
Unused Code introduced by
$valueArray is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
65
66
        Route::any('odata.svc/{section}', 'AlgoWeb\PODataLaravel\Controllers\ODataController@index')
67
            ->where(['section' => '.*']);
68
        Route::any('odata.svc', 'AlgoWeb\PODataLaravel\Controllers\ODataController@index');
69
    }
70
71
    /**
72
     * Register the application services.  Boot-time only.
73
     *
74
     * @return void
75
     */
76
    public function register()
77
    {
78
        $this->app->singleton('metadata', function ($app) {
0 ignored issues
show
Unused Code introduced by
The parameter $app is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
79
            return new SimpleMetadataProvider('Data', self::$METANAMESPACE);
80
        });
81
    }
82
83
    /**
84
     * @return array
85
     */
86
    protected function getCandidateModels()
87
    {
88
        $Classes = $this->getClassMap();
89
        $ends = [];
90
        $startName = defined('PODATA_LARAVEL_APP_ROOT_NAMESPACE') ? PODATA_LARAVEL_APP_ROOT_NAMESPACE : "App";
91
        foreach ($Classes as $name) {
92
            if (\Illuminate\Support\Str::startsWith($name, $startName)) {
93
                if (in_array("AlgoWeb\\PODataLaravel\\Models\\MetadataTrait", class_uses($name))) {
94
                    $ends[] = $name;
95
                }
96
            }
97
        }
98
        return $ends;
99
    }
100
101
    /**
102
     * @param $meta
103
     * @param $ends
104
     * @return array
105
     */
106
    protected function getEntityTypesAndResourceSets($meta, $ends)
107
    {
108
        assert($meta instanceof IMetadataProvider, get_class($meta));
109
        $EntityTypes = [];
110
        $ResourceSets = [];
111
        $begins = [];
112
        $numEnds = count($ends);
113
114
        for ($i = 0; $i < $numEnds; $i++) {
115
            $bitter = $ends[$i];
116
            $fqModelName = $bitter;
117
118
            $instance = App::make($fqModelName);
119
            $name = strtolower($instance->getEndpointName());
120
            $metaSchema = $instance->getXmlSchema();
121
122
            // if for whatever reason we don't get an XML schema, move on to next entry and drop current one from
123
            // further processing
124
            if (null == $metaSchema) {
125
                continue;
126
            }
127
            $EntityTypes[$fqModelName] = $metaSchema;
128
            $ResourceSets[$fqModelName] = $meta->addResourceSet($name, $metaSchema);
129
            $begins[] = $bitter;
130
        }
131
132
        return array($EntityTypes, $ResourceSets, $begins);
133
    }
134
135
    public function calculateRoundTripRelations()
136
    {
137
        $modelNames = $this->getCandidateModels();
138
139
        $hooks = [];
140
        foreach ($modelNames as $name) {
141
            $model = new $name();
142
            $rels = $model->getRelationships();
143
            if (0 < count($rels)) {
144
                $hooks[$name] = $rels;
145
            }
146
        }
147
148
        // models with non-empty relation gubbins are assembled, now the hard bit starts
149
        // storing assembled bidirectional relationship schema
150
        $lines = [];
151
        // storing unprocessed relation gubbins for second-pass processing
152
        $remix = [];
153
        foreach ($hooks as $principalType => $value) {
154
            foreach ($value as $fk => $localRels) {
155
                foreach ($localRels as $dependentType => $deets) {
156
                    $principalMult = $deets['multiplicity'];
157
                    $principalProperty = $deets['property'];
158
                    $principalKey = $deets['local'];
159
                    $dependentMult = null;
0 ignored issues
show
Unused Code introduced by
$dependentMult is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
160
                    $dependentProperty = null;
0 ignored issues
show
Unused Code introduced by
$dependentProperty is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
161
162
                    $foreign = $hooks[$dependentType];
163
                    $foreign = null != $foreign && isset($foreign[$principalKey]) ? $foreign[$principalKey] : null;
164
165
                    if (null != $foreign && isset($foreign[$principalType])) {
166
                        $foreign = $foreign[$principalType];
167
                        $dependentMult = $foreign['multiplicity'];
168
                        $dependentProperty = $foreign['property'];
169
                        assert(
170
                            in_array($dependentMult, $this->multConstraints[$principalMult]),
171
                            "Cannot pair multiplicities ".$dependentMult. " and ".$principalMult
172
                        );
173
                        assert(
174
                            in_array($principalMult, $this->multConstraints[$dependentMult]),
175
                            "Cannot pair multiplicities ".$principalMult. " and ".$dependentMult
176
                        );
177
                        // add forward relation
178
                        $forward = ['principalType' => $principalType, 'principalMult' => $principalMult,
179
                            'principalProp' => $principalProperty, 'dependentType' => $dependentType,
180
                            'dependentMult' => $dependentMult, 'dependentProp' => $dependentProperty];
181
                        if (!in_array($forward, $lines)) {
182
                            $lines[] = $forward;
183
                        }
184
                        // add reverse relation
185
                        $reverse = ['principalType' => $dependentType, 'principalMult' => $dependentMult,
186
                            'principalProp' => $dependentProperty, 'dependentType' => $principalType,
187
                            'dependentMult' => $principalMult, 'dependentProp' => $principalProperty];
188
                        if (!in_array($reverse, $lines)) {
189
                            $lines[] = $reverse;
190
                        }
191
                    } else {
192
                        if (!isset($remix[$principalType])) {
193
                            $remix[$principalType] = [];
194
                        }
195
                        if (!isset($remix[$principalType][$fk])) {
196
                            $remix[$principalType][$fk] = [];
197
                        }
198
                        if (!isset($remix[$principalType][$fk][$dependentType])) {
199
                            $remix[$principalType][$fk][$dependentType] = $deets;
200
                        }
201
                        assert(isset($remix[$principalType][$fk][$dependentType]));
202
                    }
203
                }
204
            }
205
        }
206
207
        // now for second processing pass, to pick up stuff that first didn't handle
208
        foreach ($remix as $principalType => $value) {
209
            foreach ($value as $fk => $localRels) {
210
                foreach ($localRels as $dependentType => $deets) {
211
                    $principalMult = $deets['multiplicity'];
212
                    $principalProperty = $deets['property'];
213
                    $principalKey = $deets['local'];
214
                    $dependentMult = null;
0 ignored issues
show
Unused Code introduced by
$dependentMult is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
215
                    $dependentProperty = null;
0 ignored issues
show
Unused Code introduced by
$dependentProperty is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
216
217
                    if (!isset($remix[$dependentType])) {
218
                        continue;
219
                    }
220
                    $foreign = $remix[$dependentType];
221
                    if (!isset($foreign[$principalKey])) {
222
                        continue;
223
                    }
224
                    $foreign = $foreign[$principalKey];
225
                    $dependentKey = $foreign[$dependentType]['local'];
226
                    if ($fk != $dependentKey) {
227
                        continue;
228
                    }
229
                    $dependentMult = $foreign[$dependentType]['multiplicity'];
230
                    $dependentProperty = $foreign[$dependentType]['property'];
231
                    assert(
232
                        in_array($dependentMult, $this->multConstraints[$principalMult]),
233
                        "Cannot pair multiplicities ".$dependentMult. " and ".$principalMult
234
                    );
235
                    assert(
236
                        in_array($principalMult, $this->multConstraints[$dependentMult]),
237
                        "Cannot pair multiplicities ".$principalMult. " and ".$dependentMult
238
                    );
239
                    // add forward relation
240
                    $forward = ['principalType' => $principalType, 'principalMult' => $principalMult,
241
                        'principalProp' => $principalProperty, 'dependentType' => $dependentType,
242
                        'dependentMult' => $dependentMult, 'dependentProp' => $dependentProperty];
243
                    if (!in_array($forward, $lines)) {
244
                        $lines[] = $forward;
245
                    }
246
                    // add reverse relation
247
                    $reverse = ['principalType' => $dependentType, 'principalMult' => $dependentMult,
248
                        'principalProp' => $dependentProperty, 'dependentType' => $principalType,
249
                        'dependentMult' => $principalMult, 'dependentProp' => $principalProperty];
250
                    if (!in_array($reverse, $lines)) {
251
                        $lines[] = $reverse;
252
                    }
253
                }
254
            }
255
        }
256
257
        return $lines;
258
    }
259
}
260