Completed
Push — dev ( 66849d...6005d6 )
by Marc
03:41
created

ArtificerServiceProvider::requireFiles()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 9
Bugs 3 Features 1
Metric Value
c 9
b 3
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php namespace Mascame\Artificer;
2
3
use App;
4
use Illuminate\Support\ServiceProvider;
5
use Illuminate\Support\Str;
6
use Mascame\Artificer\Extension\Booter;
7
use Mascame\Artificer\Model\ModelManager;
8
use Mascame\Artificer\Model\ModelObtainer;
9
use Mascame\Artificer\Model\ModelSchema;
10
use Mascame\Artificer\Widget\Manager as WidgetManager;
11
use Mascame\Artificer\Plugin\Manager as PluginManager;
12
use Mascame\Extender\Event\Event;
13
use Mascame\Extender\Installer\FileInstaller;
14
use Mascame\Extender\Installer\FileWriter;
15
16
17
class ArtificerServiceProvider extends ServiceProvider {
18
19
	use AutoPublishable, ServiceProviderLoader;
20
	
21
	protected $name = 'admin';
22
23
    protected $corePlugins = [
24
        \Mascame\Artificer\LoginPlugin::class
25
    ];
26
27
	/**
28
	 * Indicates if loading of the provider is deferred.
29
	 *
30
	 * @var bool
31
	 */
32
	protected $defer = false;
33
34
	/**
35
	 * @var bool
36
	 */
37
	protected $isBootable = false;
38
39
	/**
40
	 * Bootstrap the application events.
41
	 *
42
	 * @return void
43
	 */
44
	public function boot()
45
	{
46
		if (! $this->isBootable) return;
47
48
		$this->addPublishableFiles();
49
50
		// Wait until app is ready for config to be published
51
		if (! $this->isPublished()) return;
52
53
		$this->providers(config('admin.providers'));
54
		$this->aliases(config('admin.aliases'));
55
		$this->commands(config('admin.commands'));
56
57
        Artificer::pluginManager()->boot();
58
        Artificer::widgetManager()->boot();
59
60
        $this->manageCorePlugins();
61
62
        Artificer::assetManager()->add(config('admin.assets', []));
63
64
        if (! $this->app->routesAreCached()) {
0 ignored issues
show
Bug introduced by
The method routesAreCached() does not seem to exist on object<Illuminate\Contra...Foundation\Application>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
65
            require_once __DIR__ . '/../routes/admin.php';
66
        }
67
	}
68
69
    /**
70
     * Ensure core plugins are installed
71
     *
72
     * @throws \Exception
73
     */
74
	protected function manageCorePlugins() {
75
	    // Avoid installing plugins when using CLI
76
        if (App::runningInConsole() || App::runningUnitTests()) return true;
77
78
        $pluginManager = Artificer::pluginManager();
79
        $needsRefresh = false;
80
81
        foreach ($this->corePlugins as $corePlugin) {
82
            if (! $pluginManager->isInstalled($corePlugin)) {
83
                $installed = $pluginManager->installer()->install($corePlugin);
84
85
                if (! $installed) {
86
                    throw new \Exception("Unable to install Artificer core plugin {$corePlugin}");
87
                }
88
89
                $needsRefresh = true;
90
            }
91
        }
92
93
        // Refresh to allow changes made by core plugins to take effect
94
        if ($needsRefresh) {
95
            /**
96
             * File driver is slow... wait some seconds (else we would have too many redirects)
97
             *
98
             * Fortunately we only do this in the first run. Ye, I don't like it either.
99
             */
100
            sleep(2);
101
102
            header('Location: '. \URL::current());
103
            die();
104
        }
105
    }
106
107
    /**
108
     * Determines if is on admin
109
     *
110
     * @return bool
111
     */
112
    public function isBootable($path, $routePrefix = null) {
113
        if (App::runningInConsole() || App::runningUnitTests()) return true;
114
115
        return (
116
            $path == $routePrefix || Str::startsWith($path, $routePrefix . '/')
117
        );
118
    }
119
120
	protected function getConfigPath() {
121
		return config_path($this->name) . DIRECTORY_SEPARATOR;
122
	}
123
124
	private function addPublishableFiles()
125
    {
126
        $this->autoPublishes(function() {
127
            $this->publishes([
128
                __DIR__.'/../resources/assets' => public_path('packages/mascame/' . $this->name),
129
            ], 'public');
130
131
            $this->publishes([
132
                __DIR__.'/../config/' => $this->getConfigPath(),
133
            ], 'config');
134
135
            $this->loadTranslationsFrom(__DIR__.'/../resources/lang', $this->name);
136
        });
137
    }
138
139
	private function addLocalization()
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
140
	{
141
		App::singleton('ArtificerLocalization', function () {
142
			return new Localization();
143
		});
144
	}
145
146
	private function getExtensionInstaller($type) {
147
        if (config('admin.extension_driver') == 'file') {
148
            $extensionConfig = $this->getConfigPath() . 'extensions/'. $type .'.php';
149
150
            return new FileInstaller(new FileWriter(), $extensionConfig);
151
        }
152
    }
153
154
	private function addManagers()
155
	{
156
        App::singleton('ArtificerModelManager', function () {
157
            return new ModelManager(new ModelSchema(new ModelObtainer()));
158
        });
159
160
		App::singleton('ArtificerWidgetManager', function() {
161
            return new WidgetManager(
162
                $this->getExtensionInstaller('widgets'),
0 ignored issues
show
Bug introduced by
It seems like $this->getExtensionInstaller('widgets') can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
163
                new Booter(),
164
                new Event(app('events'))
165
            );
166
        });
167
168
		App::singleton('ArtificerPluginManager', function() {
169
            return new PluginManager(
170
                $this->getExtensionInstaller('plugins'),
0 ignored issues
show
Bug introduced by
It seems like $this->getExtensionInstaller('plugins') can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
171
                new \Mascame\Artificer\Plugin\Booter(),
172
                new Event(app('events'))
173
            );
174
		});
175
176
        App::singleton('ArtificerAssetManager', function() {
177
            return \Assets::config(array_merge([
178
                // Reset those dirs to avoid wrong paths
179
                'css_dir' => '',
180
                'js_dir' => '',
181
            ], config('admin.assets')));
182
        });
183
	}
184
185
	/**
186
	 * Register the service provider.
187
	 *
188
	 * @return void
189
	 */
190
	public function register()
191
	{
192
		// We still haven't modified config, that's why 'admin.admin'
193
		$routePrefix = config('admin.admin.route_prefix');
194
195
		// Avoid bloating the App with files that will not be needed
196
		$this->isBootable = $this->isBootable(request()->path(), $routePrefix);
197
198
		if (! $this->isBootable) return;
199
200
		// We need the config published before we can use this package!
201
		if ($this->isPublished()) {
202
			$this->loadConfig();
203
204
            // Todo
205
//			$this->addLocalization();
206
			$this->addManagers();
207
		}
208
	}
209
210
	/**
211
	 * Moves admin/admin.php keys to the root level for commodity
212
	 */
213
	protected function loadConfig() {
214
		$config = config('admin');
215
		$config = ['admin' => array_merge($config, $config['admin'])];
216
		unset($config['admin']['admin']);
217
218
		config()->set($config);
219
	}
220
221
	/**
222
	 * Get the services provided by the provider.
223
	 *
224
	 * @return array
225
	 */
226
	public function provides()
227
	{
228
		return [];
229
	}
230
231
}
232