Completed
Pull Request — 4.0 (#3885)
by Kiyotaka
13:51 queued 06:44
created

OwnerStoreController::doConfirm()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
nc 3
nop 2
dl 0
loc 18
rs 9.6666
c 0
b 0
f 0
ccs 0
cts 13
cp 0
crap 6
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')) {
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