Completed
Push — wip-public-release ( 7c11a5...54ec9d )
by Bogdan
05:19
created

JsSandboxServiceProvider   C

Complexity

Total Complexity 12

Size/Duplication

Total Lines 200
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 27

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 27
dl 0
loc 200
c 0
b 0
f 0
rs 5

7 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 8 1
A registerIsolateAndContext() 0 10 1
B registerCallbackGuard() 0 38 6
A registerFunctionCallHandler() 0 8 1
A registerWrapper() 0 52 1
B registerExtractor() 0 41 1
B provides() 0 32 1
1
<?php declare(strict_types=1);
2
3
/*
4
 * This file is part of the pinepain/php-v8-js-sandbox PHP library.
5
 *
6
 * Copyright (c) 2016-2017 Bogdan Padalko <[email protected]>
7
 *
8
 * Licensed under the MIT license: http://opensource.org/licenses/MIT
9
 *
10
 * For the full copyright and license information, please view the
11
 * LICENSE file that was distributed with this source or visit
12
 * http://opensource.org/licenses/MIT
13
 */
14
15
16
namespace Pinepain\JsSandbox\Laravel;
17
18
19
use Illuminate\Contracts\Container\Container;
20
use Illuminate\Support\ServiceProvider;
21
use InvalidArgumentException;
22
use Pinepain\JsSandbox\Extractors\Extractor;
23
use Pinepain\JsSandbox\Extractors\ExtractorDefinitionBuilder;
24
use Pinepain\JsSandbox\Extractors\ExtractorDefinitionBuilderInterface;
25
use Pinepain\JsSandbox\Extractors\ExtractorInterface;
26
use Pinepain\JsSandbox\Extractors\ExtractorsCollection;
27
use Pinepain\JsSandbox\Extractors\ExtractorsCollectionInterface;
28
use Pinepain\JsSandbox\Extractors\ObjectComponents\ExtractorsObjectStore;
29
use Pinepain\JsSandbox\Extractors\ObjectComponents\ExtractorsObjectStoreInterface;
30
use Pinepain\JsSandbox\Extractors\PlainExtractors\ArrayExtractor;
31
use Pinepain\JsSandbox\Extractors\PlainExtractors\AssocExtractor;
32
use Pinepain\JsSandbox\Extractors\PlainExtractors\BoolExtractor;
33
use Pinepain\JsSandbox\Extractors\PlainExtractors\DateExtractor;
34
use Pinepain\JsSandbox\Extractors\PlainExtractors\DateTimeExtractor;
35
use Pinepain\JsSandbox\Extractors\PlainExtractors\FunctionExtractor;
36
use Pinepain\JsSandbox\Extractors\PlainExtractors\InstanceExtractor;
37
use Pinepain\JsSandbox\Extractors\PlainExtractors\NullExtractor;
38
use Pinepain\JsSandbox\Extractors\PlainExtractors\NumberExtractor;
39
use Pinepain\JsSandbox\Extractors\PlainExtractors\ObjectExtractor;
40
use Pinepain\JsSandbox\Extractors\PlainExtractors\PrimitiveExtractor;
41
use Pinepain\JsSandbox\Extractors\PlainExtractors\RawExtractor;
42
use Pinepain\JsSandbox\Extractors\PlainExtractors\RegExpExtractor;
43
use Pinepain\JsSandbox\Extractors\PlainExtractors\ScalarExtractor;
44
use Pinepain\JsSandbox\Extractors\PlainExtractors\StringExtractor;
45
use Pinepain\JsSandbox\Extractors\PlainExtractors\UndefinedExtractor;
46
use Pinepain\JsSandbox\Specs\Builder\BindingSpecBuilder;
47
use Pinepain\JsSandbox\Specs\Builder\BindingSpecBuilderInterface;
48
use Pinepain\JsSandbox\Specs\Builder\FunctionSpecBuilder;
49
use Pinepain\JsSandbox\Specs\Builder\FunctionSpecBuilderInterface;
50
use Pinepain\JsSandbox\Specs\Builder\ObjectSpecBuilder;
51
use Pinepain\JsSandbox\Specs\Builder\ObjectSpecBuilderInterface;
52
use Pinepain\JsSandbox\Specs\Builder\ParameterSpecBuilder;
53
use Pinepain\JsSandbox\Specs\Builder\ParameterSpecBuilderInterface;
54
use Pinepain\JsSandbox\Specs\Builder\PropertySpecBuilder;
55
use Pinepain\JsSandbox\Specs\Builder\PropertySpecBuilderInterface;
56
use Pinepain\JsSandbox\Specs\ObjectSpecsCollection;
57
use Pinepain\JsSandbox\Specs\ObjectSpecsCollectionInterface;
58
use Pinepain\JsSandbox\Wrappers\ArrayWrapper;
59
use Pinepain\JsSandbox\Wrappers\CallbackGuards\CallbackGuard;
60
use Pinepain\JsSandbox\Wrappers\CallbackGuards\CallbackGuardInterface;
61
use Pinepain\JsSandbox\Wrappers\CallbackGuards\DebugCallbackGuard;
62
use Pinepain\JsSandbox\Wrappers\CallbackGuards\DevCallbackGuard;
63
use Pinepain\JsSandbox\Wrappers\FunctionComponents\ArgumentsExtractor;
64
use Pinepain\JsSandbox\Wrappers\FunctionComponents\ArgumentsExtractorInterface;
65
use Pinepain\JsSandbox\Wrappers\FunctionComponents\FunctionCallHandler;
66
use Pinepain\JsSandbox\Wrappers\FunctionComponents\FunctionCallHandlerInterface;
67
use Pinepain\JsSandbox\Wrappers\FunctionComponents\FunctionExceptionHandler;
68
use Pinepain\JsSandbox\Wrappers\FunctionComponents\FunctionExceptionHandlerInterface;
69
use Pinepain\JsSandbox\Wrappers\FunctionComponents\FunctionWrappersCache;
70
use Pinepain\JsSandbox\Wrappers\FunctionComponents\FunctionWrappersCacheInterface;
71
use Pinepain\JsSandbox\Wrappers\FunctionComponents\ReturnValueSetter;
72
use Pinepain\JsSandbox\Wrappers\FunctionComponents\ReturnValueSetterInterface;
73
use Pinepain\JsSandbox\Wrappers\FunctionWrapper;
74
use Pinepain\JsSandbox\Wrappers\ObjectComponents\PropertiesHandler;
75
use Pinepain\JsSandbox\Wrappers\ObjectComponents\PropertiesHandlerInterface;
76
use Pinepain\JsSandbox\Wrappers\ObjectComponents\WrappersObjectStore;
77
use Pinepain\JsSandbox\Wrappers\ObjectComponents\WrappersObjectStoreInterface;
78
use Pinepain\JsSandbox\Wrappers\ObjectWrapper;
79
use Pinepain\JsSandbox\Wrappers\PrimitiveWrapper;
80
use Pinepain\JsSandbox\Wrappers\Wrapper;
81
use Pinepain\JsSandbox\Wrappers\WrapperInterface;
82
use Pinepain\ObjectMaps\ObjectBiMap;
83
use Pinepain\ObjectMaps\ObjectMap;
84
use V8\Context;
85
use V8\Isolate;
86
87
88
class JsSandboxServiceProvider extends ServiceProvider
89
{
90
    protected $defer = true;
91
92
    public function register()
93
    {
94
        $this->registerIsolateAndContext();
95
        $this->registerCallbackGuard();
96
        $this->registerFunctionCallHandler();
97
        $this->registerWrapper();
98
        $this->registerExtractor();
99
    }
100
101
    protected function registerIsolateAndContext()
102
    {
103
        $this->app->singleton(Isolate::class, function (/*Container $app*/) {
104
            return new Isolate();
105
        });
106
107
        $this->app->singleton(Context::class, function (Container $app) {
108
            return new Context($app->make(Isolate::class));
109
        });
110
    }
111
112
    protected function registerCallbackGuard()
113
    {
114
115
        $config = $this->app->make('config');
116
117
        $guards = [
118
            'prod'  => CallbackGuard::class,
119
            'dev'   => DevCallbackGuard::class,
120
            'debug' => DebugCallbackGuard::class,
121
        ];
122
123
        $guard = $config->get('js_sandbox.guard', 'auto');
124
125
        if ('auto' == $guard) {
126
            if ($config->get('app.debug')) {
127
                if ($this->app->environment('production')) {
0 ignored issues
show
Unused Code introduced by
The call to Application::environment() has too many arguments starting with 'production'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
128
                    $guard = 'debug';
129
                } else {
130
                    $guard = 'dev';
131
                }
132
            } else {
133
                if ($this->app->environment('production')) {
0 ignored issues
show
Unused Code introduced by
The call to Application::environment() has too many arguments starting with 'production'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
134
                    $guard = 'prod';
135
                } else {
136
                    $guard = 'debug';
137
                }
138
            }
139
        }
140
141
        if (!isset($guards[$guard])) {
142
            $expected = '[\'auto\', \'' . implode('\', \'', array_keys($guards)) . '\']';
143
            throw new InvalidArgumentException("Invalid guard mode specified: expected one of {$expected}, '$guard' given instead");
144
        }
145
146
147
        $this->app->singleton(CallbackGuardInterface::class, $guards[$guard]);
148
149
    }
150
151
    protected function registerFunctionCallHandler()
152
    {
153
        $this->app->singleton(ArgumentsExtractorInterface::class, ArgumentsExtractor::class);
154
        $this->app->singleton(FunctionExceptionHandlerInterface::class, FunctionExceptionHandler::class);
155
        $this->app->singleton(ReturnValueSetterInterface::class, ReturnValueSetter::class);
156
157
        $this->app->singleton(FunctionCallHandlerInterface::class, FunctionCallHandler::class);
158
    }
159
160
    protected function registerWrapper()
161
    {
162
        $function_wrappers_map = new ObjectMap(ObjectMap::WEAK_VALUE);
163
164
        $this->app->singleton(ObjectSpecsCollectionInterface::class, ObjectSpecsCollection::class);
165
        $this->app->singleton(FunctionWrappersCacheInterface::class, new FunctionWrappersCache($function_wrappers_map));
0 ignored issues
show
Documentation introduced by
new \Pinepain\JsSandbox\...$function_wrappers_map) is of type object<Pinepain\JsSandbo...\FunctionWrappersCache>, but the function expects a object<Closure>|string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
166
167
        $object_store_map = new ObjectBiMap();
168
169
        // $this->app->when(WrappersObjectStore::class)
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
170
        //           ->needs(ObjectMapInterface::class)
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
171
        //           ->give(function () use ($object_store_map) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
172
        //               return $object_store_map;
173
        //           });
174
        //
175
        // $this->app->when(ExtractorsObjectStoreInterface::class)
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
176
        //           ->needs(ObjectMapInterface::class)
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
177
        //           ->give(function () use ($object_store_map) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
178
        //               return $object_store_map->values();
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
179
        //           });
180
        //
181
        // $this->app->singleton(WrappersObjectStoreInterface::class, WrappersObjectStore::class);
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
182
        // $this->app->singleton(ExtractorsObjectStoreInterface::class, ExtractorsObjectStore::class);
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
183
184
        $this->app->instance(WrappersObjectStoreInterface::class, new WrappersObjectStore($object_store_map));
185
        $this->app->instance(ExtractorsObjectStoreInterface::class, new ExtractorsObjectStore($object_store_map->values()));
186
187
        $this->app->singleton(PropertiesHandlerInterface::class, PropertiesHandler::class);
188
189
        $this->app->singleton(WrapperInterface::class, function (Container $app) {
190
191
            $wrapper = new Wrapper();
192
193
            $primitive_wrapper = $app->make(PrimitiveWrapper::class);
194
195
            $array_wrapper = $app->make(ArrayWrapper::class);
196
            $array_wrapper->setWrapper($wrapper);
197
198
            $function_wrapper = $app->make(FunctionWrapper::class);
199
            $function_wrapper->setWrapper($wrapper);
200
201
            $object_wrapper = $app->make(ObjectWrapper::class);
202
            $object_wrapper->setWrapper($wrapper);
203
204
            $wrapper->setPrimitiveWrapper($primitive_wrapper);
205
            $wrapper->setArrayWrapper($array_wrapper);
206
            $wrapper->setFunctionWrapper($function_wrapper);
207
            $wrapper->setObjectWrapper($object_wrapper);
208
209
            return $wrapper;
210
        });
211
    }
212
213
    protected function registerExtractor()
214
    {
215
        $this->app->singleton(ExtractorDefinitionBuilderInterface::class, ExtractorDefinitionBuilder::class);
216
        $this->app->singleton(PropertySpecBuilderInterface::class, PropertySpecBuilder::class);
217
        $this->app->singleton(ParameterSpecBuilderInterface::class, ParameterSpecBuilder::class);
218
        $this->app->singleton(FunctionSpecBuilderInterface::class, FunctionSpecBuilder::class);
219
        $this->app->singleton(BindingSpecBuilderInterface::class, BindingSpecBuilder::class);
220
        $this->app->singleton(ObjectSpecBuilderInterface::class, ObjectSpecBuilder::class);
221
222
        $this->app->singleton(ExtractorInterface::class, Extractor::class);
223
224
        $this->app->singleton(ExtractorsCollectionInterface::class, function (Container $app) {
225
226
            $collection = new ExtractorsCollection();
227
228
            // TODO: register basic extractor
229
230
            $collection->put('raw', $raw = new RawExtractor());
231
            $collection->put('array', $array = new ArrayExtractor());
232
            $collection->put('primitive', $primitive = new PrimitiveExtractor());
233
234
            $collection->put('string', $string = new StringExtractor());
235
            $collection->put('number', $number = new NumberExtractor());
236
            $collection->put('bool', $bool = new BoolExtractor());
237
            $collection->put('null', $null = new NullExtractor());
238
            $collection->put('undefined', $undefined = new UndefinedExtractor());
239
240
            $collection->put('regexp', $regexp = new RegExpExtractor());
241
            $collection->put('date', $date = new DateExtractor());
242
            $collection->put('datetime', $datetime = new DateTimeExtractor());
243
            $collection->put('object', $object = new ObjectExtractor());
244
            $collection->put('function', $function = new FunctionExtractor());
245
            $collection->put('instance', $instance = $app->make(InstanceExtractor::class));
246
247
            $collection->put('assoc', $assoc = new AssocExtractor());
248
            $collection->put('scalar', $scalar = new ScalarExtractor($string, $number, $bool, $null, $undefined));
249
250
            return $collection;
251
        });
252
253
    }
254
255
    public function provides()
256
    {
257
        return [
258
            Isolate::class,
259
            Context::class,
260
261
            CallbackGuardInterface::class,
262
263
            ArgumentsExtractorInterface::class,
264
            FunctionExceptionHandlerInterface::class,
265
            ReturnValueSetterInterface::class,
266
            FunctionCallHandlerInterface::class,
267
268
            ObjectSpecsCollectionInterface::class,
269
            FunctionWrappersCacheInterface::class,
270
            WrappersObjectStoreInterface::class,
271
            PropertiesHandlerInterface::class,
272
            WrapperInterface::class,
273
274
            ExtractorDefinitionBuilderInterface::class,
275
            PropertySpecBuilderInterface::class,
276
            ParameterSpecBuilderInterface::class .
277
            FunctionSpecBuilderInterface::class,
278
            BindingSpecBuilderInterface::class,
279
            ObjectSpecBuilderInterface::class,
280
281
            ExtractorsCollectionInterface::class,
282
            ExtractorsObjectStoreInterface::class,
283
            ExtractorInterface::class,
284
285
        ];
286
    }
287
}
288