Failed Conditions
Pull Request — 4.0 (#3763)
by Kiyotaka
06:00
created

PluginController::enable()   B

Complexity

Conditions 8
Paths 13

Size

Total Lines 60

Duplication

Lines 21
Ratio 35 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
cc 8
nc 13
nop 3
dl 21
loc 60
ccs 0
cts 28
cp 0
crap 72
rs 7.6282
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of EC-CUBE
5
 *
6
 * Copyright(c) LOCKON CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.lockon.co.jp/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Eccube\Controller\Admin\Store;
15
16
use Eccube\Common\Constant;
17
use Eccube\Controller\AbstractController;
18
use Eccube\Entity\BaseInfo;
19
use Eccube\Entity\Plugin;
20
use Eccube\Exception\PluginApiException;
21
use Eccube\Exception\PluginException;
22
use Eccube\Form\Type\Admin\AuthenticationType;
23
use Eccube\Form\Type\Admin\PluginLocalInstallType;
24
use Eccube\Form\Type\Admin\PluginManagementType;
25
use Eccube\Repository\BaseInfoRepository;
26
use Eccube\Repository\PluginRepository;
27
use Eccube\Service\PluginApiService;
28
use Eccube\Service\PluginService;
29
use Eccube\Util\CacheUtil;
30
use Eccube\Util\StringUtil;
31
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
32
use Symfony\Component\DependencyInjection\Container;
33
use Symfony\Component\Filesystem\Filesystem;
34
use Symfony\Component\Finder\Finder;
35
use Symfony\Component\HttpFoundation\File\UploadedFile;
36
use Symfony\Component\HttpFoundation\JsonResponse;
37
use Symfony\Component\HttpFoundation\RedirectResponse;
38
use Symfony\Component\HttpFoundation\Request;
39
use Symfony\Component\Routing\Annotation\Route;
40
use Symfony\Component\Routing\Exception\RouteNotFoundException;
41
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
42
43
class PluginController extends AbstractController
44
{
45
    /**
46
     * @var PluginService
47
     */
48
    protected $pluginService;
49
50
    /**
51
     * @var BaseInfo
52
     */
53
    protected $BaseInfo;
54
55
    /**
56
     * @var PluginRepository
57
     */
58
    protected $pluginRepository;
59
60
    /**
61
     * @var PluginApiService
62
     */
63
    protected $pluginApiService;
64
65
    /**
66
     * PluginController constructor.
67
     *
68
     * @param PluginRepository $pluginRepository
69
     * @param PluginService $pluginService
70
     * @param BaseInfoRepository $baseInfoRepository
71
     * @param PluginApiService $pluginApiService
72
     *
73
     * @throws \Doctrine\ORM\NoResultException
74
     * @throws \Doctrine\ORM\NonUniqueResultException
75
     */
76 View Code Duplication
    public function __construct(PluginRepository $pluginRepository, PluginService $pluginService, BaseInfoRepository $baseInfoRepository, PluginApiService $pluginApiService)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
77
    {
78
        $this->pluginRepository = $pluginRepository;
79
        $this->pluginService = $pluginService;
80
        $this->BaseInfo = $baseInfoRepository->get();
81
        $this->pluginApiService = $pluginApiService;
82
    }
83
84
    /**
85
     * インストール済プラグイン画面
86
     *
87
     * @Route("/%eccube_admin_route%/store/plugin", name="admin_store_plugin")
88
     * @Template("@admin/Store/plugin.twig")
89
     *
90
     * @return array
91
     *
92
     * @throws PluginException
93
     */
94
    public function index()
95
    {
96
        $pluginForms = [];
97
        $configPages = [];
98
        $Plugins = $this->pluginRepository->findBy([], ['code' => 'ASC']);
99
100
        // ファイル設置プラグインの取得.
101
        $unregisteredPlugins = $this->getUnregisteredPlugins($Plugins);
102
        $unregisteredPluginsConfigPages = [];
103
        foreach ($unregisteredPlugins as $unregisteredPlugin) {
104
            try {
105
                $code = $unregisteredPlugin['code'];
106
                // プラグイン用設定画面があれば表示(プラグイン用のサービスプロバイダーに定義されているか)
107
                $unregisteredPluginsConfigPages[$code] = $this->generateUrl('plugin_'.$code.'_config');
108
            } catch (RouteNotFoundException $e) {
109
                // プラグインで設定画面のルートが定義されていない場合は無視
110
            }
111
        }
112
113
        $officialPlugins = [];
114
        $unofficialPlugins = [];
115
116
        foreach ($Plugins as $Plugin) {
117
            $form = $this->formFactory
118
                ->createNamedBuilder(
119
                    'form'.$Plugin->getId(),
120
                    PluginManagementType::class,
121
                    null,
122
                    [
123
                        'plugin_id' => $Plugin->getId(),
124
                    ]
125
                )
126
                ->getForm();
127
            $pluginForms[$Plugin->getId()] = $form->createView();
128
129
            try {
130
                // プラグイン用設定画面があれば表示(プラグイン用のサービスプロバイダーに定義されているか)
131
                $configPages[$Plugin->getCode()] = $this->generateUrl(Container::underscore($Plugin->getCode()).'_admin_config');
132
            } catch (\Exception $e) {
133
                // プラグインで設定画面のルートが定義されていない場合は無視
134
            }
135
            if ($Plugin->getSource() == 0) {
136
                // 商品IDが設定されていない場合、非公式プラグイン
137
                $unofficialPlugins[] = $Plugin;
138
            } else {
139
                $officialPlugins[$Plugin->getSource()] = $Plugin;
140
            }
141
        }
142
143
        // オーナーズストア通信
144
        $officialPluginsDetail = [];
145
        try {
146
            $data = $this->pluginApiService->getPurchased();
147
            foreach ($data as $item) {
148
                $Plugin = null;
149
150
                if (isset($officialPlugins[$item['id']])) {
151
                    $Plugin = $officialPlugins[$item['id']];
152
                } else {
153
                    $Plugin = new Plugin();
154
                    $Plugin->setName($item['name']);
155
                    $Plugin->setCode($item['code']);
156
                    $Plugin->setVersion($item['version']);
157
                    $Plugin->setSource($item['id']);
158
                    $Plugin->setEnabled(false);
159
                    $officialPlugins[$item['id']] = $Plugin;
160
                }
161
162
                $officialPluginsDetail[$item['id']] = $item;
163
                $officialPluginsDetail[$item['id']]['update_status'] = 0;
164
                if ($this->pluginService->isUpdate($Plugin->getVersion(), $item['version'])) {
165
                    $officialPluginsDetail[$item['id']]['update_status'] = 1;
166
                }
167
            }
168
        } catch (PluginApiException $e) {
169
            $this->addWarning($e->getMessage(), 'admin');
170
        }
171
172
        return [
173
            'plugin_forms' => $pluginForms,
174
            'officialPlugins' => $officialPlugins,
175
            'unofficialPlugins' => $unofficialPlugins,
176
            'configPages' => $configPages,
177
            'unregisteredPlugins' => $unregisteredPlugins,
178
            'unregisteredPluginsConfigPages' => $unregisteredPluginsConfigPages,
179
            'officialPluginsDetail' => $officialPluginsDetail,
180
        ];
181
    }
182
183
    /**
184
     * インストール済プラグインからのアップデート
185
     *
186
     * @Route("/%eccube_admin_route%/store/plugin/{id}/update", requirements={"id" = "\d+"}, name="admin_store_plugin_update", methods={"POST"})
187
     *
188
     * @param Request $request
189
     * @param Plugin $Plugin
190
     *
191
     * @return RedirectResponse
192
     */
193
    public function update(Request $request, Plugin $Plugin)
194
    {
195
        $form = $this->formFactory
196
            ->createNamedBuilder(
197
                'form'.$Plugin->getId(),
198
                PluginManagementType::class,
199
                null,
200
                [
201
                    'plugin_id' => null, // placeHolder
202
                ]
203
            )
204
            ->getForm();
205
206
        $message = '';
207
        $form->handleRequest($request);
208
        if ($form->isSubmitted() && $form->isValid()) {
209
            $tmpDir = null;
210
            try {
211
                $formFile = $form['plugin_archive']->getData();
212
                $tmpDir = $this->pluginService->createTempDir();
213
                $tmpFile = sha1(StringUtil::random(32)).'.'.$formFile->getClientOriginalExtension();
214
                $formFile->move($tmpDir, $tmpFile);
215
                $this->pluginService->update($Plugin, $tmpDir.'/'.$tmpFile);
216
                $fs = new Filesystem();
217
                $fs->remove($tmpDir);
218
                $this->addSuccess('admin.plugin.update.complete', 'admin');
219
220
                return $this->redirectToRoute('admin_store_plugin');
221
            } catch (PluginException $e) {
222
                if (!empty($tmpDir) && file_exists($tmpDir)) {
223
                    $fs = new Filesystem();
224
                    $fs->remove($tmpDir);
225
                }
226
                $message = $e->getMessage();
227
            } catch (\Exception $er) {
228
                // Catch composer install error | Other error
229
                if (!empty($tmpDir) && file_exists($tmpDir)) {
230
                    $fs = new Filesystem();
231
                    $fs->remove($tmpDir);
232
                }
233
                log_error('plugin install failed.', ['original-message' => $er->getMessage()]);
234
                $message = 'admin.plugin.install.fail';
235
            }
236
        } else {
237
            $errors = $form->getErrors(true);
238
            foreach ($errors as $error) {
239
                $message = $error->getMessage();
0 ignored issues
show
Bug introduced by
The method getMessage does only exist in Symfony\Component\Form\FormError, but not in Symfony\Component\Form\FormErrorIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
240
            }
241
        }
242
243
        $this->addError($message, 'admin');
244
245
        return $this->redirectToRoute('admin_store_plugin');
246
    }
247
248
    /**
249
     * 対象のプラグインを有効にします。
250
     *
251
     * @Route("/%eccube_admin_route%/store/plugin/{id}/enable", requirements={"id" = "\d+"}, name="admin_store_plugin_enable", methods={"POST"})
252
     *
253
     * @param Plugin $Plugin
254
     *
255
     * @return RedirectResponse|JsonResponse
256
     *
257
     * @throws PluginException
258
     */
259
    public function enable(Plugin $Plugin, CacheUtil $cacheUtil, Request $request)
260
    {
261
        $this->isTokenValid();
262
263
        $log = null;
264
265
        if ($Plugin->isEnabled()) {
266
            if ($request->isXmlHttpRequest()) {
267
                return $this->json(['success' => true]);
268
            } else {
269
                $this->addError('admin.plugin.already.enable', 'admin');
270
            }
271
        } else {
272
            // ストアからインストールしたプラグインは依存プラグインが有効化されているかを確認
273
            if ($Plugin->getSource()) {
274
                $requires = $this->pluginService->getPluginRequired($Plugin);
275 View Code Duplication
                $requires = array_filter($requires, function ($req) {
276
                    $code = preg_replace('/^ec-cube\//', '', $req['name']);
277
                    /** @var Plugin $DependPlugin */
278
                    $DependPlugin = $this->pluginRepository->findOneBy(['code' => $code]);
279
280
                    return $DependPlugin->isEnabled() == false;
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
281
                });
282
                if (!empty($requires)) {
283
                    $names = array_map(function ($req) {
284
                        return "「${req['description']}」";
285
                    }, $requires);
286
                    $message = trans('%depend_name%を先に有効化してください。', ['%name%' => $Plugin->getName(), '%depend_name%' => implode(', ', $names)]);
287
288 View Code Duplication
                    if ($request->isXmlHttpRequest()) {
289
                        return $this->json(['success' => false, 'message' => $message], 400);
290
                    } else {
291
                        $this->addError($message, 'admin');
292
293
                        return $this->redirectToRoute('admin_store_plugin');
294
                    }
295
                }
296
            }
297
298
            ob_start();
299
300
            if (!$Plugin->isInitialized()) {
301
                $this->pluginService->installWithCode($Plugin->getCode());
302
            }
303
304
            $this->pluginService->enable($Plugin);
305
            $log = ob_get_clean();
306
            ob_end_flush();
307
        }
308
309
        $cacheUtil->clearCache();
310
311 View Code Duplication
        if ($request->isXmlHttpRequest()) {
312
            return $this->json(['success' => true, 'log' => $log]);
313
        } else {
314
            $this->addSuccess(trans('「%plugin_name%」を有効にしました。', ['%plugin_name%' => $Plugin->getName()]), 'admin');
315
316
            return $this->redirectToRoute('admin_store_plugin');
317
        }
318
    }
319
320
    /**
321
     * 対象のプラグインを無効にします。
322
     *
323
     * @Route("/%eccube_admin_route%/store/plugin/{id}/disable", requirements={"id" = "\d+"}, name="admin_store_plugin_disable", methods={"POST"})
324
     *
325
     * @param Request $request
326
     * @param Plugin $Plugin
327
     * @param CacheUtil $cacheUtil
328
     *
329
     * @return \Symfony\Component\HttpFoundation\JsonResponse|RedirectResponse
330
     */
331
    public function disable(Request $request, Plugin $Plugin, CacheUtil $cacheUtil)
332
    {
333
        $this->isTokenValid();
334
335
        $log = null;
336
        if ($Plugin->isEnabled()) {
337
            $dependents = $this->pluginService->findDependentPluginNeedDisable($Plugin->getCode());
338
            if (!empty($dependents)) {
339
                $dependName = $dependents[0];
340
                $DependPlugin = $this->pluginRepository->findOneBy(['code' => $dependents[0]]);
341
                if ($DependPlugin) {
342
                    $dependName = $DependPlugin->getName();
343
                }
344
                $message = trans('admin.plugin.disable.depend', ['%name%' => $Plugin->getName(), '%depend_name%' => $dependName]);
345
346 View Code Duplication
                if ($request->isXmlHttpRequest()) {
347
                    return $this->json(['message' => $message], 400);
348
                } else {
349
                    $this->addError($message, 'admin');
350
351
                    return $this->redirectToRoute('admin_store_plugin');
352
                }
353
            }
354
355
            ob_start();
356
            $this->pluginService->disable($Plugin);
357
            $log = ob_get_clean();
358
            ob_end_flush();
359 View Code Duplication
        } else {
360
            if ($request->isXmlHttpRequest()) {
361
                return $this->json(['success' => true, 'log' => $log]);
362
            } else {
363
                $this->addError('admin.plugin.already.disable', 'admin');
364
365
                return $this->redirectToRoute('admin_store_plugin');
366
            }
367
        }
368
369
        $cacheUtil->clearCache();
370
371 View Code Duplication
        if ($request->isXmlHttpRequest()) {
372
            return $this->json(['success' => true, 'log' => $log]);
373
        } else {
374
            $this->addSuccess('admin.plugin.disable.complete', 'admin');
375
376
            return $this->redirectToRoute('admin_store_plugin');
377
        }
378
    }
379
380
    /**
381
     * 対象のプラグインを削除します。
382
     *
383
     * @Route("/%eccube_admin_route%/store/plugin/{id}/uninstall", requirements={"id" = "\d+"}, name="admin_store_plugin_uninstall", methods={"DELETE"})
384
     *
385
     * @param Plugin $Plugin
386
     *
387
     * @return RedirectResponse
388
     *
389
     * @throws \Exception
390
     */
391
    public function uninstall(Plugin $Plugin)
392
    {
393
        $this->isTokenValid();
394
395
        if ($Plugin->isEnabled()) {
396
            $this->addError('admin.plugin.uninstall.error.not_disable', 'admin');
397
398
            return $this->redirectToRoute('admin_store_plugin');
399
        }
400
401
        // Check other plugin depend on it
402
        $pluginCode = $Plugin->getCode();
403
        $otherDepend = $this->pluginService->findDependentPlugin($pluginCode);
404
        if (!empty($otherDepend)) {
405
            $DependPlugin = $this->pluginRepository->findOneBy(['code' => $otherDepend[0]]);
406
            $dependName = $otherDepend[0];
407
            if ($DependPlugin) {
408
                $dependName = $DependPlugin->getName();
409
            }
410
            $message = trans('admin.plugin.uninstall.depend', ['%name%' => $Plugin->getName(), '%depend_name%' => $dependName]);
411
            $this->addError($message, 'admin');
412
413
            return $this->redirectToRoute('admin_store_plugin');
414
        }
415
416
        $this->pluginService->uninstall($Plugin);
417
        $this->addSuccess('admin.plugin.uninstall.complete', 'admin');
418
419
        return $this->redirectToRoute('admin_store_plugin');
420
    }
421
422
    /**
423
     * プラグインファイルアップロード画面
424
     *
425
     * @Route("/%eccube_admin_route%/store/plugin/install", name="admin_store_plugin_install")
426
     * @Template("@admin/Store/plugin_install.twig")
427
     *
428
     * @param Request $request
429
     *
430
     * @return array|RedirectResponse
431
     */
432
    public function install(Request $request)
433
    {
434
        $form = $this->formFactory
435
            ->createBuilder(PluginLocalInstallType::class)
436
            ->getForm();
437
        $errors = [];
438
        $form->handleRequest($request);
439
        if ($form->isSubmitted() && $form->isValid()) {
440
            $tmpDir = null;
441
            try {
442
                $service = $this->pluginService;
443
                /** @var UploadedFile $formFile */
444
                $formFile = $form['plugin_archive']->getData();
445
                $tmpDir = $service->createTempDir();
446
                // 拡張子を付けないとpharが動かないので付ける
447
                $tmpFile = sha1(StringUtil::random(32)).'.'.$formFile->getClientOriginalExtension();
448
                $formFile->move($tmpDir, $tmpFile);
449
                $tmpPath = $tmpDir.'/'.$tmpFile;
450
                $service->install($tmpPath);
451
                // Remove tmp file
452
                $fs = new Filesystem();
453
                $fs->remove($tmpDir);
454
                $this->addSuccess('admin.plugin.install.complete', 'admin');
455
456
                return $this->redirectToRoute('admin_store_plugin');
457
            } catch (PluginException $e) {
458
                if (!empty($tmpDir) && file_exists($tmpDir)) {
459
                    $fs = new Filesystem();
460
                    $fs->remove($tmpDir);
461
                }
462
                log_error('plugin install failed.', ['original-message' => $e->getMessage()]);
463
                $errors[] = $e;
464
            } catch (\Exception $er) {
465
                // Catch composer install error | Other error
466
                if (!empty($tmpDir) && file_exists($tmpDir)) {
467
                    $fs = new Filesystem();
468
                    $fs->remove($tmpDir);
469
                }
470
                log_error('plugin install failed.', ['original-message' => $er->getMessage()]);
471
                $this->addError('admin.plugin.install.fail', 'admin');
472
            }
473
        } else {
474
            foreach ($form->getErrors(true) as $error) {
475
                $errors[] = $error;
476
            }
477
        }
478
479
        return [
480
            'form' => $form->createView(),
481
            'errors' => $errors,
482
        ];
483
    }
484
485
    /**
486
     * 認証キー設定画面
487
     *
488
     * @Route("/%eccube_admin_route%/store/plugin/authentication_setting", name="admin_store_authentication_setting")
489
     * @Template("@admin/Store/authentication_setting.twig")
490
     */
491
    public function authenticationSetting(Request $request)
492
    {
493
        $builder = $this->formFactory
494
            ->createBuilder(AuthenticationType::class, $this->BaseInfo);
495
496
        $form = $builder->getForm();
497
        $form->handleRequest($request);
498
499
        if ($form->isSubmitted() && $form->isValid()) {
500
            // 認証キーの登録 and PHP path
501
            $this->BaseInfo = $form->getData();
502
            $this->entityManager->persist($this->BaseInfo);
503
            $this->entityManager->flush();
504
505
            $this->addSuccess('admin.common.save_complete', 'admin');
506
        }
507
508
        return [
509
            'form' => $form->createView(),
510
            'eccubeUrl' => $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL),
511
            'eccubeShopName' => $this->BaseInfo->getShopName(),
512
        ];
513
    }
514
515
    /**
516
     * フォルダ設置のみのプラグインを取得する.
517
     *
518
     * @param array $plugins
519
     *
520
     * @return array
521
     *
522
     * @throws PluginException
523
     */
524
    protected function getUnregisteredPlugins(array $plugins)
525
    {
526
        $finder = new Finder();
527
        $pluginCodes = [];
528
529
        // DB登録済みプラグインコードのみ取得
530
        foreach ($plugins as $key => $plugin) {
531
            $pluginCodes[] = $plugin->getCode();
532
        }
533
        // DB登録済みプラグインコードPluginディレクトリから排他
534
        $dirs = $finder->in($this->eccubeConfig['plugin_realdir'])->depth(0)->directories();
535
536
        // プラグイン基本チェック
537
        $unregisteredPlugins = [];
538
        foreach ($dirs as $dir) {
539
            $pluginCode = $dir->getBasename();
540
            if (in_array($pluginCode, $pluginCodes, true)) {
541
                continue;
542
            }
543
            try {
544
                $this->pluginService->checkPluginArchiveContent($dir->getRealPath());
545
            } catch (PluginException $e) {
546
                //config.yamlに不備があった際は全てスキップ
547
                log_warning($e->getMessage());
548
                continue;
549
            }
550
            $config = $this->pluginService->readConfig($dir->getRealPath());
551
            $unregisteredPlugins[$pluginCode]['name'] = isset($config['name']) ? $config['name'] : null;
552
            $unregisteredPlugins[$pluginCode]['event'] = isset($config['event']) ? $config['event'] : null;
553
            $unregisteredPlugins[$pluginCode]['version'] = isset($config['version']) ? $config['version'] : null;
554
            $unregisteredPlugins[$pluginCode]['enabled'] = Constant::DISABLED;
555
            $unregisteredPlugins[$pluginCode]['code'] = isset($config['code']) ? $config['code'] : null;
556
        }
557
558
        return $unregisteredPlugins;
559
    }
560
}
561