Completed
Pull Request — master (#1163)
by
unknown
01:46
created

LaravelDatabaseRepository::has()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Nwidart\Modules\Laravel;
4
5
use Illuminate\Contracts\Filesystem\FileNotFoundException;
6
use Illuminate\Support\Facades\Schema;
7
use Illuminate\Support\Str;
8
use Nwidart\Modules\Collection;
9
use Nwidart\Modules\Contracts\ActivatorInterface;
10
use Nwidart\Modules\Contracts\DatabaseRepositoryInterface;
11
use Nwidart\Modules\Entities\ModuleEntity;
12
use Nwidart\Modules\Exceptions\ModuleNotFoundException;
13
use Nwidart\Modules\Generators\DatabaseModuleGenerator;
14
use Nwidart\Modules\Json;
15
16
class LaravelDatabaseRepository extends LaravelFileRepository implements DatabaseRepositoryInterface
17
{
18
    /**
19
     * Creates a new Module instance.
20
     *
21
     * @param mixed ...$args
22
     *
23
     * @return DatabaseModule
24
     */
25
    protected function createModule(...$args)
26
    {
27
        return new DatabaseModule(...$args);
0 ignored issues
show
Bug introduced by
The call to DatabaseModule::__construct() misses some required arguments starting with $name.
Loading history...
Documentation introduced by
$args is of type array<integer,*>, but the function expects a object<Illuminate\Container\Container>.

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...
28
    }
29
30
    /**
31
     * @return ModuleEntity
32
     */
33
    public function getModel()
34
    {
35
        return new ModuleEntity();
36
    }
37
38
    /**
39
     * Scan & get all available modules.
40
     */
41
    public function scan()
42
    {
43
        /**
44
         * @var ModuleEntity[] $rows
45
         */
46
        $rows = $this->getModel()->get();
47
        $modules = [];
48
        if (!empty($rows)) {
49
            foreach ($rows as $row) {
50
                if (file_exists($row->path)) {
51
                    $modules[$row->name] = $this->createModule($this->app, $row->name, $row->path);
52
                }
53
            }
54
        }
55
56
        return $modules;
57
    }
58
59
    /**
60
     * Determine whether the given module exist.
61
     *
62
     * @param $name
63
     *
64
     * @return bool
65
     */
66
    public function has($name): bool
67
    {
68
        return $this->getModel()->where('name', $name)->exists();
69
    }
70
71
    /**
72
     * @inheritDoc
73
     */
74
    public function find(string $name)
75
    {
76
        /** @var ModuleEntity $module */
77
        $module = $this->getModel()->where('name', $name)->first();
78
        if (!$module) {
79
            return null;
80
        }
81
        if (!file_exists($module->path)) {
82
            return null;
83
        }
84
85
        return $this->createModule($this->app, $module->name, $module->path);
86
    }
87
88
    /**
89
     * Get all modules as laravel collection instance.
90
     *
91
     * @param $status
92
     *
93
     * @return Collection
94
     */
95
    public function collections($status = 1): Collection
96
    {
97
        return new Collection($this->getByStatus($status));
98
    }
99
100
    /**
101
     * Get module path for a specific module.
102
     *
103
     * @param $name
104
     *
105
     * @return string
106
     */
107
    public function getModulePath($name)
108
    {
109
        $module = $this->find($name);
110
        if ($module) {
111
            return $module->getPath() . '/';
112
        }
113
114
        return $this->getPath() . '/' . Str::studly($name) . '/';
115
    }
116
117
    /**
118
     * Get modules by status.
119
     *
120
     * @param $status
121
     *
122
     * @return array
123
     */
124 View Code Duplication
    public function getByStatus($status): array
125
    {
126
        $modules = [];
127
128
        foreach ($this->all() as $name => $module) {
129
            if ($module->isStatus($status) == $status) {
130
                $modules[$name] = $module;
131
            }
132
        }
133
134
        return $modules;
135
    }
136
137
    /**
138
     * Format the cached data as array of modules.
139
     *
140
     * @param array $cached
141
     *
142
     * @return array
143
     */
144
    protected function formatCached($cached)
145
    {
146
        $modules = [];
147
148
        foreach ($cached as $moduleEntity) {
149
            $module = $this->createModule($this->app, $moduleEntity['name'], $moduleEntity['path']);
150
            $module->setAttributes($moduleEntity->toArray());
151
            $modules[$moduleEntity['name']] = $module;
152
        }
153
154
        return $modules;
155
    }
156
157
    /**
158
     * Get cached modules from database.
159
     *
160
     * @return ModuleEntity[]
161
     */
162
    public function getCached()
163
    {
164
        return $this->app['cache']->remember($this->config('cache.key'), $this->config('cache.lifetime'), function () {
165
            return $this->getModel()->all();
166
        });
167
    }
168
169
    public function all(): array
170
    {
171
        // Do not load or register if there are no modules table yet.
172
        if (!Schema::hasTable('modules')) {
173
            return [];
174
        }
175
176
        return parent::all();
177
    }
178
179
    public function create($params, $force = true, $isApi = true, $isPlain = true)
180
    {
181
        $moduleType = $this->getModuleType($isApi, $isPlain); // Custom later.
182
        /** @var DatabaseModuleGenerator $generator */
183
        $generator = with(new DatabaseModuleGenerator($params['name']));
184
        $code = $generator
185
            ->setFilesystem(app('files'))
186
            ->setModule($this)
187
            ->setConfig(app('config'))
188
            ->setActivator(app(ActivatorInterface::class))
189
            ->setForce($force)
190
            ->setType($moduleType)
191
            ->setActive($params['is_active'])
192
            ->setSilentOutput(true) // Don't use console output
193
            ->generate();
194
195
        return $code ? $this->find($params['name']) : false;
196
    }
197
198
    /**
199
     * Get module type .
200
     *
201
     * @param bool $isApi
202
     * @param bool $isPlain
203
     *
204
     * @return string
205
     */
206
    public function getModuleType($isApi = true, $isPlain = true)
207
    {
208
        if ($isPlain && $isApi) {
209
            return 'web';
210
        }
211
        if ($isPlain) {
212
            return 'plain';
213
        } elseif ($isApi) {
214
            return 'api';
215
        } else {
216
            return 'web';
217
        }
218
    }
219
220
    /**
221
     * Get module used for cli session.
222
     * @return string
223
     * @throws ModuleNotFoundException|FileNotFoundException
224
     */
225
    public function getUsedNow(): string
226
    {
227
        $module = $this->getFiles()->get($this->getUsedStoragePath());
228
        if (!$module) {
229
            return '';
230
        }
231
232
        return $this->findOrFail($module);
233
    }
234
235
    public function migrateFileToDatabase()
236
    {
237
        $paths = $this->getScanPaths();
238
        $modules = [];
239
240
        foreach ($paths as $key => $path) {
241
            $manifests = $this->getFiles()->glob("{$path}/module.json");
242
243
            is_array($manifests) || $manifests = [];
244
245
            foreach ($manifests as $manifest) {
246
                $json = Json::make($manifest);
247
                $data = $json->getAttributes();
248
                $data['path'] = str_replace('module.json', '', $json->getPath());
249
                if (!isset($data['version'])) {
250
                    $data['version'] = '1.0.0';
251
                }
252
                $module = $this->find($data['name']);
253
                $data = $this->validateAttributes($data);
254
                if (!$module) {
255
                    $modules[] = $this->getModel()->create($data);
256 View Code Duplication
                } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
257
                    // Check version, if version is higher then update module.json into database.
258
                    if (version_compare($module->getVersion(), $data['version'], '<')) {
259
                        $modules[] = $this->getModel()->where(['name' => $data['name']])->update($data);
260
                    }
261
                }
262
            }
263
        }
264
265
        return $modules;
266
    }
267
268
    public function update($name)
269
    {
270
        if ($this->config('database_management.update_file_to_database_when_updating')) {
271
272
            /** @var DatabaseModule $module */
273
            $module = $this->findOrFail($name);
274
275
            $json = Json::make($module->getPath() . '/' . 'module.json');
276
            $data = $json->getAttributes();
277
278
            if (!isset($data['version'])) {
279
                $data['version'] = '1.0.0';
280
            }
281
282
            // Check version, if version is higher then update module.json into database.
283 View Code Duplication
            if (version_compare($module->getVersion(), $data['version'], '<=')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
284
                $data = $this->validateAttributes($data);
285
                $this->getModel()->where(['name' => $data['name']])->update($data);
286
            }
287
        }
288
289
        parent::update($name);
290
    }
291
292
    /**
293
     * Validate array attributes before insert/update into database.
294
     *
295
     * @param array $attributes
296
     * @param array $allows
297
     *
298
     * @return array
299
     */
300
    protected function validateAttributes(array $attributes, array $allows = [])
301
    {
302
        if (empty($allows)) {
303
            $allows = $this->getModel()->getFillable();
304
        }
305
306
        return array_filter($attributes, function ($k) use ($allows) {
307
            return in_array($k, $allows);
308
        }, ARRAY_FILTER_USE_KEY);
309
    }
310
}
311