Completed
Push — 4.0 ( 87d096...bcc1be )
by Kiyotaka
05:44 queued 11s
created

Controller/Admin/Store/OwnerStoreController.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * This file is part of EC-CUBE
5
 *
6
 * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.ec-cube.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.store.plugin.search.not_auth', '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)
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
        // .maintenanceファイルを設置
268
        $this->systemService->switchMaintenance(true);
269
270
        // TERMINATE時のイベントを設定
271
        $this->systemService->disableMaintenance(SystemService::AUTO_MAINTENANCE);
272
273
        $this->cacheUtil->clearCache();
274
275
        $pluginCode = $request->get('pluginCode');
276
277
        $log = null;
278
        try {
279
            $log = $this->composerService->execRequire('ec-cube/'.$pluginCode);
280
281
            return $this->json(['success' => true, 'log' => $log]);
282
        } catch (\Exception $e) {
283
            $log = $e->getMessage();
284
            log_error($e);
285
        }
286
287
        return $this->json(['success' => false, 'log' => $log], 500);
288
    }
289
290
    /**
291
     * New ways to remove plugin: using composer command
292
     *
293
     * @Route("/delete/{id}/uninstall", requirements={"id" = "\d+"}, name="admin_store_plugin_api_uninstall", methods={"DELETE"})
294
     *
295
     * @param Plugin $Plugin
296
     *
297
     * @return \Symfony\Component\HttpFoundation\JsonResponse
298
     */
299
    public function apiUninstall(Plugin $Plugin)
300
    {
301
        $this->isTokenValid();
302
303
        // .maintenanceファイルを設置
304
        $this->systemService->switchMaintenance(true);
305
306
        // TERMINATE時のイベントを設定
307
        $this->systemService->disableMaintenance(SystemService::AUTO_MAINTENANCE);
308
309
        $this->cacheUtil->clearCache();
310
311
        if ($Plugin->isEnabled()) {
312
            return $this->json(['success' => false, 'message' => trans('admin.plugin.uninstall.error.not_disable')], 400);
313
        }
314
315
        $pluginCode = $Plugin->getCode();
316
        $otherDepend = $this->pluginService->findDependentPlugin($pluginCode);
317
318
        if (!empty($otherDepend)) {
319
            $DependPlugin = $this->pluginRepository->findOneBy(['code' => $otherDepend[0]]);
320
            $dependName = $otherDepend[0];
321
            if ($DependPlugin) {
322
                $dependName = $DependPlugin->getName();
323
            }
324
            $message = trans('admin.plugin.uninstall.depend', ['%name%' => $Plugin->getName(), '%depend_name%' => $dependName]);
325
326
            return $this->json(['success' => false, 'message' => $message], 400);
327
        }
328
329
        $pluginCode = $Plugin->getCode();
330
        $packageName = self::$vendorName.'/'.$pluginCode;
331
332
        try {
333
            $log = $this->composerService->execRemove($packageName);
334
335
            return $this->json(['success' => false, 'log' => $log]);
336
        } catch (\Exception $e) {
337
            log_error($e);
338
339
            return $this->json(['success' => false, 'log' => $e->getMessage()], 500);
340
        }
341
    }
342
343
    /**
344
     * オーナーズブラグインインストール、アップデート
345
     *
346
     * @Route("/upgrade", name="admin_store_plugin_api_upgrade", methods={"POST"})
347
     *
348
     * @param Request $request
349
     *
350
     * @return \Symfony\Component\HttpFoundation\JsonResponse
351
     */
352
    public function apiUpgrade(Request $request)
353
    {
354
        $this->isTokenValid();
355
356
        $this->cacheUtil->clearCache();
357
358
        $pluginCode = $request->get('pluginCode');
359
        $version = $request->get('version');
360
361
        $log = null;
362
        try {
363
            $log = $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version);
364
365
            return $this->json(['success' => true, 'log' => $log]);
366
        } catch (\Exception $e) {
367
            $log = $e->getMessage();
368
            log_error($e);
369
        }
370
371
        return $this->json(['success' => false, 'log' => $log], 500);
372
    }
373
374
    /**
375
     * オーナーズブラグインインストール、スキーマ更新
376
     *
377
     * @Route("/schema_update", name="admin_store_plugin_api_schema_update", methods={"POST"})
378
     *
379
     * @param Request $request
380
     *
381
     * @return \Symfony\Component\HttpFoundation\JsonResponse
382
     */
383
    public function apiSchemaUpdate(Request $request)
384
    {
385
        $this->isTokenValid();
386
387
        $this->cacheUtil->clearCache();
388
389
        $pluginCode = $request->get('pluginCode');
390
391
        try {
392
            $Plugin = $this->pluginRepository->findByCode($pluginCode);
393
394
            if (!$Plugin) {
395
                throw new NotFoundHttpException();
396
            }
397
398
            $config = $this->pluginService->readConfig($this->pluginService->calcPluginDir($Plugin->getCode()));
399
400
            ob_start();
401
            $this->pluginService->generateProxyAndUpdateSchema($Plugin, $config);
402
403
            // 初期化されていなければインストール処理を実行する
404
            if (!$Plugin->isInitialized()) {
405
                $this->pluginService->callPluginManagerMethod($config, 'install');
406
                $Plugin->setInitialized(true);
407
                $this->entityManager->persist($Plugin);
408
                $this->entityManager->flush();
409
            }
410
411
            $log = ob_get_clean();
412
            while (ob_get_level() > 0) {
413
                ob_end_flush();
414
            }
415
416
            return $this->json(['success' => true, 'log' => $log]);
417
        } catch (\Exception $e) {
418
            $log = $e->getMessage();
419
            log_error($e);
420
421
            return $this->json(['success' => false, 'log' => $log], 500);
422
        }
423
    }
424
425
    /**
426
     * オーナーズブラグインインストール、更新処理
427
     *
428
     * @Route("/update", name="admin_store_plugin_api_update", methods={"POST"})
429
     *
430
     * @param Request $request
431
     *
432
     * @return \Symfony\Component\HttpFoundation\JsonResponse
433
     */
434
    public function apiUpdate(Request $request)
435
    {
436
        $this->isTokenValid();
437
438
        // TERMINATE時のイベントを設定
439
        $this->systemService->disableMaintenance(SystemService::AUTO_MAINTENANCE_UPDATE);
440
441
        $this->cacheUtil->clearCache();
442
443
        $pluginCode = $request->get('pluginCode');
444
445
        $log = null;
446
        try {
447
            $Plugin = $this->pluginRepository->findByCode($pluginCode);
448
            if (!$Plugin) {
449
                throw new NotFoundHttpException();
450
            }
451
452
            $config = $this->pluginService->readConfig($this->pluginService->calcPluginDir($Plugin->getCode()));
453
            ob_start();
454
            $this->pluginService->updatePlugin($Plugin, $config);
455
            $log = ob_get_clean();
456
            while (ob_get_level() > 0) {
457
                ob_end_flush();
458
            }
459
460
            return $this->json(['success' => true, 'log' => $log]);
461
        } catch (\Exception $e) {
462
            $log = $e->getMessage();
463
            log_error($e);
464
        }
465
466
        return $this->json(['success' => false, 'log' => $log], 500);
467
    }
468
469
    /**
470
     * Do confirm update page
471
     *
472
     * @Route("/upgrade/{id}/confirm", requirements={"id" = "\d+"}, name="admin_store_plugin_update_confirm")
473
     * @Template("@admin/Store/plugin_confirm.twig")
474
     *
475
     * @param Plugin $Plugin
476
     *
477
     * @return array
478
     */
479
    public function doUpdateConfirm(Plugin $Plugin)
480
    {
481
        try {
482
            $item = $this->pluginApiService->getPlugin($Plugin->getSource());
483
484
            return [
485
                'item' => $item,
486
                'requires' => [],
487
                'is_update' => true,
488
                'Plugin' => $Plugin,
489
            ];
490
        } catch (PluginApiException $e) {
491
            $this->addError($e->getMessage(), 'admin');
492
493
            return $this->redirectToRoute('admin_store_authentication_setting');
494
        }
495
    }
496
}
497