Failed Conditions
Push — fix/install-log ( f0e34f )
by Kiyotaka
07:03
created

OwnerStoreController::apiSchemaUpdate()   B

Complexity

Conditions 5
Paths 28

Size

Total Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 28
nop 1
dl 0
loc 41
rs 8.9528
c 0
b 0
f 0
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\Controller\AbstractController;
17
use Eccube\Entity\BaseInfo;
18
use Eccube\Entity\Master\PageMax;
19
use Eccube\Entity\Plugin;
20
use Eccube\Exception\PluginApiException;
21
use Eccube\Form\Type\Admin\SearchPluginApiType;
22
use Eccube\Repository\BaseInfoRepository;
23
use Eccube\Repository\PluginRepository;
24
use Eccube\Service\Composer\ComposerProcessService;
25
use Eccube\Service\Composer\ComposerServiceInterface;
26
use Eccube\Service\PluginApiService;
27
use Eccube\Service\PluginService;
28
use Eccube\Service\SystemService;
29
use Eccube\Util\CacheUtil;
30
use Eccube\Util\FormUtil;
31
use Knp\Component\Pager\Paginator;
32
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
33
use Symfony\Component\HttpFoundation\Request;
34
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
35
use Symfony\Component\Routing\Annotation\Route;
36
37
/**
38
 * @Route("/%eccube_admin_route%/store/plugin/api")
39
 */
40
class OwnerStoreController extends AbstractController
41
{
42
    /**
43
     * @var PluginRepository
44
     */
45
    protected $pluginRepository;
46
47
    /**
48
     * @var PluginService
49
     */
50
    protected $pluginService;
51
52
    /**
53
     * @var ComposerServiceInterface
54
     */
55
    protected $composerService;
56
57
    /**
58
     * @var SystemService
59
     */
60
    protected $systemService;
61
62
    /**
63
     * @var PluginApiService
64
     */
65
    protected $pluginApiService;
66
67
    private static $vendorName = 'ec-cube';
68
69
    /** @var BaseInfo */
70
    private $BaseInfo;
71
72
    /** @var CacheUtil */
73
    private $cacheUtil;
74
75
    /**
76
     * OwnerStoreController constructor.
77
     *
78
     * @param PluginRepository $pluginRepository
79
     * @param PluginService $pluginService
80
     * @param ComposerProcessService $composerProcessService
81
     * @param ComposerServiceInterface $composerService
82
     * @param SystemService $systemService
83
     * @param PluginApiService $pluginApiService
84
     * @param BaseInfoRepository $baseInfoRepository
85
     * @param CacheUtil $cacheUtil
86
     *
87
     * @throws \Doctrine\ORM\NoResultException
88
     * @throws \Doctrine\ORM\NonUniqueResultException
89
     */
90
    public function __construct(
91
        PluginRepository $pluginRepository,
92
        PluginService $pluginService,
93
        ComposerProcessService $composerProcessService,
94
        ComposerServiceInterface $composerService,
95
        SystemService $systemService,
96
        PluginApiService $pluginApiService,
97
        BaseInfoRepository $baseInfoRepository,
98
        CacheUtil $cacheUtil
99
    ) {
100
        $this->pluginRepository = $pluginRepository;
101
        $this->pluginService = $pluginService;
102
        $this->systemService = $systemService;
103
        $this->pluginApiService = $pluginApiService;
104
        $this->BaseInfo = $baseInfoRepository->get();
105
        $this->cacheUtil = $cacheUtil;
106
107
        // TODO: Check the flow of the composer service below
108
        $memoryLimit = $this->systemService->getMemoryLimit();
109
        if ($memoryLimit == -1 or $memoryLimit >= $this->eccubeConfig['eccube_composer_memory_limit']) {
110
            $this->composerService = $composerService;
111
        } else {
112
            $this->composerService = $composerProcessService;
113
        }
114
    }
115
116
    /**
117
     * Owner's Store Plugin Installation Screen - Search function
118
     *
119
     * @Route("/search", name="admin_store_plugin_owners_search")
120
     * @Route("/search/page/{page_no}", name="admin_store_plugin_owners_search_page", requirements={"page_no" = "\d+"})
121
     * @Template("@admin/Store/plugin_search.twig")
122
     *
123
     * @param Request     $request
124
     * @param int $page_no
125
     * @param Paginator $paginator
126
     *
127
     * @return array
128
     */
129
    public function search(Request $request, $page_no = null, Paginator $paginator)
130
    {
131
        if (empty($this->BaseInfo->getAuthenticationKey())) {
132
            $this->addWarning('認証キーを設定してください。', 'admin');
133
134
            return $this->redirectToRoute('admin_store_authentication_setting');
135
        }
136
137
        // Acquire downloadable plug-in information from owners store
138
        $category = [];
139
140
        $json = $this->pluginApiService->getCategory();
141
        if (!empty($json)) {
142
            $data = json_decode($json, true);
143
            $category = array_column($data, 'name', 'id');
144
        }
145
146
        // build form with master data
147
        $builder = $this->formFactory
148
            ->createBuilder(SearchPluginApiType::class, null, ['category' => $category]);
149
        $searchForm = $builder->getForm();
150
151
        $searchForm->handleRequest($request);
152
        $searchData = $searchForm->getData();
153
        if ($searchForm->isSubmitted()) {
154
            if ($searchForm->isValid()) {
155
                $page_no = 1;
156
                $searchData = $searchForm->getData();
157
                $this->session->set('eccube.admin.plugin_api.search', FormUtil::getViewData($searchForm));
158
                $this->session->set('eccube.admin.plugin_api.search.page_no', $page_no);
159
            }
160
        } else {
161
            // quick search
162
            if (is_numeric($categoryId = $request->get('category_id')) && array_key_exists($categoryId, $category)) {
163
                $searchForm['category_id']->setData($categoryId);
164
            }
165
            // reset page count
166
            $this->session->set('eccube.admin.plugin_api.search.page_count', $this->eccubeConfig->get('eccube_default_page_count'));
167 View Code Duplication
            if (null !== $page_no || $request->get('resume')) {
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...
168
                if ($page_no) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $page_no of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
169
                    $this->session->set('eccube.admin.plugin_api.search.page_no', (int) $page_no);
170
                } else {
171
                    $page_no = $this->session->get('eccube.admin.plugin_api.search.page_no', 1);
172
                }
173
                $viewData = $this->session->get('eccube.admin.plugin_api.search', []);
174
                $searchData = FormUtil::submitAndGetData($searchForm, $viewData);
175
            } else {
176
                $page_no = 1;
177
                // submit default value
178
                $viewData = FormUtil::getViewData($searchForm);
179
                $searchData = FormUtil::submitAndGetData($searchForm, $viewData);
180
                $this->session->set('eccube.admin.plugin_api.search', $searchData);
181
                $this->session->set('eccube.admin.plugin_api.search.page_no', $page_no);
182
            }
183
        }
184
185
        // set page count
186
        $pageCount = $this->session->get('eccube.admin.plugin_api.search.page_count', $this->eccubeConfig->get('eccube_default_page_count'));
187
        if (($PageMax = $searchForm['page_count']->getData()) instanceof PageMax) {
188
            $pageCount = $PageMax->getId();
189
            $this->session->set('eccube.admin.plugin_api.search.page_count', $pageCount);
190
        }
191
192
        // Owner's store communication
193
        $searchData['page_no'] = $page_no;
194
        $searchData['page_count'] = $pageCount;
195
196
        $total = 0;
197
        $items = [];
198
199
        try {
200
            $data = $this->pluginApiService->getPlugins($searchData);
201
            $total = $data['total'];
202
            $items = $data['plugins'];
203
        } catch (PluginApiException $e) {
204
            $this->addError($e->getMessage(), 'admin');
205
        }
206
207
        // The usage is set because `$items` are already paged.
208
        // virtual paging
209
        $pagination = $paginator->paginate($items, 1, $pageCount);
210
        $pagination->setTotalItemCount($total);
211
        $pagination->setCurrentPageNumber($page_no);
212
        $pagination->setItemNumberPerPage($pageCount);
213
214
        return [
215
            'pagination' => $pagination,
216
            'total' => $total,
217
            'searchForm' => $searchForm->createView(),
218
            'page_no' => $page_no,
219
            'Categories' => $category,
220
        ];
221
    }
222
223
    /**
224
     * Do confirm page
225
     *
226
     * @Route("/install/{id}/confirm", requirements={"id" = "\d+"}, name="admin_store_plugin_install_confirm")
227
     * @Template("@admin/Store/plugin_confirm.twig")
228
     *
229
     * @param Request $request
230
     *
231
     * @return array
232
     *
233
     * @throws \Eccube\Exception\PluginException
234
     */
235
    public function doConfirm(Request $request, $id)
0 ignored issues
show
Unused Code introduced by
The parameter $request 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...
236
    {
237
        try {
238
            $item = $this->pluginApiService->getPlugin($id);
239
            // Todo: need define item's dependency mechanism
240
            $requires = $this->pluginService->getPluginRequired($item);
241
242
            return [
243
                'item' => $item,
244
                'requires' => $requires,
245
                'is_update' => false,
246
            ];
247
        } catch (PluginApiException $e) {
248
            $this->addError($e->getMessage(), 'admin');
249
250
            return $this->redirectToRoute('admin_store_authentication_setting');
251
        }
252
    }
253
254
    /**
255
     * Api Install plugin by composer connect with package repo
256
     *
257
     * @Route("/install", name="admin_store_plugin_api_install", methods={"POST"})
258
     *
259
     * @param Request $request
260
     *
261
     * @return \Symfony\Component\HttpFoundation\JsonResponse
262
     */
263
    public function apiInstall(Request $request)
264
    {
265
        $this->isTokenValid();
266
267
        $this->cacheUtil->clearCache();
268
269
        $pluginCode = $request->get('pluginCode');
270
271
        $log = null;
272
        try {
273
            $log = $this->composerService->execRequire('ec-cube/'.$pluginCode);
274
275
            return $this->json(['success' => true, 'log' => $log]);
276
        } catch (\Exception $e) {
277
            $log = $e->getMessage();
278
            log_error($e);
279
        }
280
281
        return $this->json(['success' => false, 'log' => $log], 500);
282
    }
283
284
    /**
285
     * New ways to remove plugin: using composer command
286
     *
287
     * @Route("/delete/{id}/uninstall", requirements={"id" = "\d+"}, name="admin_store_plugin_api_uninstall", methods={"DELETE"})
288
     *
289
     * @param Plugin $Plugin
290
     *
291
     * @return \Symfony\Component\HttpFoundation\JsonResponse
292
     */
293
    public function apiUninstall(Plugin $Plugin)
294
    {
295
        $this->isTokenValid();
296
297
        $this->cacheUtil->clearCache();
298
299
        if ($Plugin->isEnabled()) {
300
            return $this->json(['success' => false, 'message' => trans('admin.plugin.uninstall.error.not_disable')], 400);
301
        }
302
303
        $pluginCode = $Plugin->getCode();
304
        $otherDepend = $this->pluginService->findDependentPlugin($pluginCode);
305
306
        if (!empty($otherDepend)) {
307
            $DependPlugin = $this->pluginRepository->findOneBy(['code' => $otherDepend[0]]);
308
            $dependName = $otherDepend[0];
309
            if ($DependPlugin) {
310
                $dependName = $DependPlugin->getName();
311
            }
312
            $message = trans('admin.plugin.uninstall.depend', ['%name%' => $Plugin->getName(), '%depend_name%' => $dependName]);
313
314
            return $this->json(['success' => false, 'message' => $message], 400);
315
        }
316
317
        $pluginCode = $Plugin->getCode();
318
        $packageName = self::$vendorName.'/'.$pluginCode;
319
320
        try {
321
            $log = $this->composerService->execRemove($packageName);
322
323
            return $this->json(['success' => false, 'log' => $log]);
324
        } catch (\Exception $e) {
325
            log_error($e);
326
327
            return $this->json(['success' => false, 'log' => $e->getMessage()], 500);
328
        }
329
    }
330
331
    /**
332
     * オーナーズブラグインインストール、アップデート
333
     *
334
     * @Route("/upgrade", name="admin_store_plugin_api_upgrade", methods={"POST"})
335
     *
336
     * @param Request $request
337
     *
338
     * @return \Symfony\Component\HttpFoundation\JsonResponse
339
     */
340
    public function apiUpgrade(Request $request)
341
    {
342
        $this->isTokenValid();
343
344
        $this->cacheUtil->clearCache();
345
346
        $pluginCode = $request->get('pluginCode');
347
        $version = $request->get('version');
348
349
        $log = null;
350
        try {
351
            $log = $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version);
352
            return $this->json(['success' => true, 'log' => $log]);
353
        } catch (\Exception $e) {
354
            $log = $e->getMessage();
355
            log_error($e);
356
        }
357
358
        return $this->json(['success' => false, 'log' => $log], 500);
359
    }
360
361
    /**
362
     * オーナーズブラグインインストール、スキーマ更新
363
     *
364
     * @Route("/schema_update", name="admin_store_plugin_api_schema_update", methods={"POST"})
365
     *
366
     * @param Request $request
367
     *
368
     * @return \Symfony\Component\HttpFoundation\JsonResponse
369
     */
370
    public function apiSchemaUpdate(Request $request)
371
    {
372
        $this->isTokenValid();
373
374
        $this->cacheUtil->clearCache();
375
376
        $pluginCode = $request->get('pluginCode');
377
378
        try {
379
            $Plugin = $this->pluginRepository->findByCode($pluginCode);
380
381
            if (!$Plugin) {
382
                throw new NotFoundHttpException();
383
            }
384
385
            $config = $this->pluginService->readConfig($this->pluginService->calcPluginDir($Plugin->getCode()));
386
387
            ob_start();
388
            $this->pluginService->generateProxyAndUpdateSchema($Plugin, $config);
389
390
            // 初期化されていなければインストール処理を実行する
391
            if (!$Plugin->isInitialized()) {
392
                $this->pluginService->callPluginManagerMethod($config, 'install');
393
                $Plugin->setInitialized(true);
394
                $this->entityManager->persist($Plugin);
395
                $this->entityManager->flush();
396
            }
397
398
            $log = ob_get_clean();
399
            while (ob_get_level() > 0) {
400
                ob_end_flush();
401
            }
402
403
            return $this->json(['success' => true, 'log' => $log]);
404
        } catch (\Exception $e) {
405
            $log = $e->getMessage();
406
            log_error($e);
407
408
            return $this->json(['success' => false, 'log' => $log], 500);
409
        }
410
    }
411
412
    /**
413
     * オーナーズブラグインインストール、更新処理
414
     *
415
     * @Route("/update", name="admin_store_plugin_api_update", methods={"POST"})
416
     *
417
     * @param Request $request
418
     *
419
     * @return \Symfony\Component\HttpFoundation\JsonResponse
420
     */
421
    public function apiUpdate(Request $request)
422
    {
423
        $this->isTokenValid();
424
425
        $this->cacheUtil->clearCache();
426
427
        $pluginCode = $request->get('pluginCode');
428
429
        $log = null;
430
        try {
431
            $Plugin = $this->pluginRepository->findByCode($pluginCode);
432
            if (!$Plugin) {
433
                throw new NotFoundHttpException();
434
            }
435
436
            $config = $this->pluginService->readConfig($this->pluginService->calcPluginDir($Plugin->getCode()));
437
            ob_start();
438
            $this->pluginService->updatePlugin($Plugin, $config);
439
            $log = ob_get_clean();
440
            while (ob_get_level() > 0) {
441
                ob_end_flush();
442
            }
443
444
            return $this->json(['success' => true, 'log' => $log]);
445
        } catch (\Exception $e) {
446
            $log = $e->getMessage();
447
            log_error($e);
448
        }
449
450
        return $this->json(['success' => false, 'log' => $log], 500);
451
    }
452
453
    /**
454
     * Do confirm update page
455
     *
456
     * @Route("/upgrade/{id}/confirm", requirements={"id" = "\d+"}, name="admin_store_plugin_update_confirm")
457
     * @Template("@admin/Store/plugin_confirm.twig")
458
     *
459
     * @param Plugin $Plugin
460
     *
461
     * @return array
462
     */
463
    public function doUpdateConfirm(Plugin $Plugin)
464
    {
465
        try {
466
            $item = $this->pluginApiService->getPlugin($Plugin->getSource());
467
468
            return [
469
                'item' => $item,
470
                'requires' => [],
471
                'is_update' => true,
472
                'Plugin' => $Plugin,
473
            ];
474
        } catch (PluginApiException $e) {
475
            $this->addError($e->getMessage(), 'admin');
476
477
            return $this->redirectToRoute('admin_store_authentication_setting');
478
        }
479
    }
480
}
481