src/Eccube/Controller/Admin/Store/OwnerStoreController.php line 161

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of EC-CUBE
  4.  *
  5.  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6.  *
  7.  * http://www.ec-cube.co.jp/
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  */
  12. namespace Eccube\Controller\Admin\Store;
  13. use Eccube\Controller\AbstractController;
  14. use Eccube\Entity\BaseInfo;
  15. use Eccube\Entity\Master\PageMax;
  16. use Eccube\Entity\Plugin;
  17. use Eccube\Exception\PluginApiException;
  18. use Eccube\Form\Type\Admin\SearchPluginApiType;
  19. use Eccube\Repository\BaseInfoRepository;
  20. use Eccube\Repository\PluginRepository;
  21. use Eccube\Service\Composer\ComposerServiceInterface;
  22. use Eccube\Service\PluginApiService;
  23. use Eccube\Service\PluginService;
  24. use Eccube\Service\SystemService;
  25. use Eccube\Util\CacheUtil;
  26. use Eccube\Util\FormUtil;
  27. use Knp\Component\Pager\PaginatorInterface;
  28. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  29. use Symfony\Component\HttpFoundation\Request;
  30. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  31. use Symfony\Component\Routing\Annotation\Route;
  32. /**
  33.  * @Route("/%eccube_admin_route%/store/plugin/api")
  34.  */
  35. class OwnerStoreController extends AbstractController
  36. {
  37.     /**
  38.      * @var PluginRepository
  39.      */
  40.     protected $pluginRepository;
  41.     /**
  42.      * @var PluginService
  43.      */
  44.     protected $pluginService;
  45.     /**
  46.      * @var ComposerServiceInterface
  47.      */
  48.     protected $composerService;
  49.     /**
  50.      * @var SystemService
  51.      */
  52.     protected $systemService;
  53.     /**
  54.      * @var PluginApiService
  55.      */
  56.     protected $pluginApiService;
  57.     private static $vendorName 'ec-cube';
  58.     /** @var BaseInfo */
  59.     private $BaseInfo;
  60.     /** @var CacheUtil */
  61.     private $cacheUtil;
  62.     /**
  63.      * OwnerStoreController constructor.
  64.      *
  65.      * @param PluginRepository $pluginRepository
  66.      * @param PluginService $pluginService
  67.      * @param ComposerServiceInterface $composerService
  68.      * @param SystemService $systemService
  69.      * @param PluginApiService $pluginApiService
  70.      * @param BaseInfoRepository $baseInfoRepository
  71.      * @param CacheUtil $cacheUtil
  72.      *
  73.      * @throws \Doctrine\ORM\NoResultException
  74.      * @throws \Doctrine\ORM\NonUniqueResultException
  75.      */
  76.     public function __construct(
  77.         PluginRepository $pluginRepository,
  78.         PluginService $pluginService,
  79.         ComposerServiceInterface $composerService,
  80.         SystemService $systemService,
  81.         PluginApiService $pluginApiService,
  82.         BaseInfoRepository $baseInfoRepository,
  83.         CacheUtil $cacheUtil
  84.     ) {
  85.         $this->pluginRepository $pluginRepository;
  86.         $this->pluginService $pluginService;
  87.         $this->systemService $systemService;
  88.         $this->pluginApiService $pluginApiService;
  89.         $this->BaseInfo $baseInfoRepository->get();
  90.         $this->cacheUtil $cacheUtil;
  91.         // TODO: Check the flow of the composer service below
  92.         $this->composerService $composerService;
  93.     }
  94.     /**
  95.      * Owner's Store Plugin Installation Screen - Search function
  96.      *
  97.      * @Route("/search", name="admin_store_plugin_owners_search", methods={"GET", "POST"})
  98.      * @Route("/search/page/{page_no}", name="admin_store_plugin_owners_search_page", requirements={"page_no" = "\d+"}, methods={"GET", "POST"})
  99.      * @Template("@admin/Store/plugin_search.twig")
  100.      *
  101.      * @param Request     $request
  102.      * @param int $page_no
  103.      * @param PaginatorInterface $paginator
  104.      *
  105.      * @return array
  106.      */
  107.     public function search(Request $requestPaginatorInterface $paginator$page_no null)
  108.     {
  109.         if (empty($this->BaseInfo->getAuthenticationKey())) {
  110.             $this->addWarning('admin.store.plugin.search.not_auth''admin');
  111.             return $this->redirectToRoute('admin_store_authentication_setting');
  112.         }
  113.         // Acquire downloadable plug-in information from owners store
  114.         $category = [];
  115.         $json $this->pluginApiService->getCategory();
  116.         if (!empty($json)) {
  117.             $data json_decode($jsontrue);
  118.             $category array_column($data'name''id');
  119.         }
  120.         // build form with master data
  121.         $builder $this->formFactory
  122.             ->createBuilder(SearchPluginApiType::class, null, ['category' => $category]);
  123.         $searchForm $builder->getForm();
  124.         $searchForm->handleRequest($request);
  125.         $searchData $searchForm->getData();
  126.         if ($searchForm->isSubmitted()) {
  127.             if ($searchForm->isValid()) {
  128.                 $page_no 1;
  129.                 $searchData $searchForm->getData();
  130.                 $this->session->set('eccube.admin.plugin_api.search'FormUtil::getViewData($searchForm));
  131.                 $this->session->set('eccube.admin.plugin_api.search.page_no'$page_no);
  132.             }
  133.         } else {
  134.             // quick search
  135.             if (is_numeric($categoryId $request->get('category_id')) && array_key_exists($categoryId$category)) {
  136.                 $searchForm['category_id']->setData($categoryId);
  137.             }
  138.             // reset page count
  139.             $this->session->set('eccube.admin.plugin_api.search.page_count'$this->eccubeConfig->get('eccube_default_page_count'));
  140.             if (null !== $page_no || $request->get('resume')) {
  141.                 if ($page_no) {
  142.                     $this->session->set('eccube.admin.plugin_api.search.page_no', (int) $page_no);
  143.                 } else {
  144.                     $page_no $this->session->get('eccube.admin.plugin_api.search.page_no'1);
  145.                 }
  146.                 $viewData $this->session->get('eccube.admin.plugin_api.search', []);
  147.                 $searchData FormUtil::submitAndGetData($searchForm$viewData);
  148.             } else {
  149.                 $page_no 1;
  150.                 // submit default value
  151.                 $viewData FormUtil::getViewData($searchForm);
  152.                 $searchData FormUtil::submitAndGetData($searchForm$viewData);
  153.                 $this->session->set('eccube.admin.plugin_api.search'$searchData);
  154.                 $this->session->set('eccube.admin.plugin_api.search.page_no'$page_no);
  155.             }
  156.         }
  157.         // set page count
  158.         $pageCount $this->session->get('eccube.admin.plugin_api.search.page_count'$this->eccubeConfig->get('eccube_default_page_count'));
  159.         if (($PageMax $searchForm['page_count']->getData()) instanceof PageMax) {
  160.             $pageCount $PageMax->getId();
  161.             $this->session->set('eccube.admin.plugin_api.search.page_count'$pageCount);
  162.         }
  163.         // Owner's store communication
  164.         $searchData['page_no'] = $page_no;
  165.         $searchData['page_count'] = $pageCount;
  166.         $total 0;
  167.         $items = [];
  168.         try {
  169.             $data $this->pluginApiService->getPlugins($searchData);
  170.             $total $data['total'];
  171.             $items $data['plugins'];
  172.         } catch (PluginApiException $e) {
  173.             $this->addError($e->getMessage(), 'admin');
  174.         }
  175.         // The usage is set because `$items` are already paged.
  176.         // virtual paging
  177.         $pagination $paginator->paginate($items1$pageCount);
  178.         $pagination->setTotalItemCount($total);
  179.         $pagination->setCurrentPageNumber($page_no);
  180.         $pagination->setItemNumberPerPage($pageCount);
  181.         return [
  182.             'pagination' => $pagination,
  183.             'total' => $total,
  184.             'searchForm' => $searchForm->createView(),
  185.             'page_no' => $page_no,
  186.             'Categories' => $category,
  187.         ];
  188.     }
  189.     /**
  190.      * Do confirm page
  191.      *
  192.      * @Route("/install/{id}/confirm", requirements={"id" = "\d+"}, name="admin_store_plugin_install_confirm", methods={"GET"})
  193.      * @Template("@admin/Store/plugin_confirm.twig")
  194.      *
  195.      * @param Request $request
  196.      *
  197.      * @return array
  198.      *
  199.      * @throws \Eccube\Exception\PluginException
  200.      */
  201.     public function doConfirm(Request $request$id)
  202.     {
  203.         try {
  204.             $item $this->pluginApiService->getPlugin($id);
  205.             // Todo: need define item's dependency mechanism
  206.             $requires $this->pluginService->getPluginRequired($item);
  207.             return [
  208.                 'item' => $item,
  209.                 'requires' => $requires,
  210.                 'is_update' => false,
  211.             ];
  212.         } catch (PluginApiException $e) {
  213.             $this->addError($e->getMessage(), 'admin');
  214.             return $this->redirectToRoute('admin_store_authentication_setting');
  215.         }
  216.     }
  217.     /**
  218.      * Api Install plugin by composer connect with package repo
  219.      *
  220.      * @Route("/install", name="admin_store_plugin_api_install", methods={"POST"})
  221.      *
  222.      * @param Request $request
  223.      *
  224.      * @return \Symfony\Component\HttpFoundation\JsonResponse
  225.      */
  226.     public function apiInstall(Request $request)
  227.     {
  228.         $this->isTokenValid();
  229.         // .maintenanceファイルを設置
  230.         $this->systemService->switchMaintenance(true);
  231.         $this->cacheUtil->clearCache();
  232.         $pluginCode $request->get('pluginCode');
  233.         try {
  234.             $log $this->composerService->execRequire('ec-cube/'.$pluginCode);
  235.             return $this->json(['success' => true'log' => $log]);
  236.         } catch (\Exception $e) {
  237.             $log $e->getMessage();
  238.             log_error($e);
  239.         }
  240.         return $this->json(['success' => false'log' => $log], 500);
  241.     }
  242.     /**
  243.      * New ways to remove plugin: using composer command
  244.      *
  245.      * @Route("/delete/{id}/uninstall", requirements={"id" = "\d+"}, name="admin_store_plugin_api_uninstall", methods={"DELETE"})
  246.      *
  247.      * @param Plugin $Plugin
  248.      *
  249.      * @return \Symfony\Component\HttpFoundation\JsonResponse
  250.      */
  251.     public function apiUninstall(Plugin $Plugin)
  252.     {
  253.         $this->isTokenValid();
  254.         // .maintenanceファイルを設置
  255.         $this->systemService->switchMaintenance(true);
  256.         $this->cacheUtil->clearCache();
  257.         if ($Plugin->isEnabled()) {
  258.             return $this->json(['success' => false'message' => trans('admin.plugin.uninstall.error.not_disable')], 400);
  259.         }
  260.         $pluginCode $Plugin->getCode();
  261.         $otherDepend $this->pluginService->findDependentPlugin($pluginCode);
  262.         if (!empty($otherDepend)) {
  263.             $DependPlugin $this->pluginRepository->findOneBy(['code' => $otherDepend[0]]);
  264.             $dependName $otherDepend[0];
  265.             if ($DependPlugin) {
  266.                 $dependName $DependPlugin->getName();
  267.             }
  268.             $message trans('admin.plugin.uninstall.depend', ['%name%' => $Plugin->getName(), '%depend_name%' => $dependName]);
  269.             return $this->json(['success' => false'message' => $message], 400);
  270.         }
  271.         $pluginCode $Plugin->getCode();
  272.         $packageName self::$vendorName.'/'.$pluginCode;
  273.         try {
  274.             $log $this->composerService->execRemove($packageName);
  275.             return $this->json(['success' => false'log' => $log]);
  276.         } catch (\Exception $e) {
  277.             log_error($e);
  278.             return $this->json(['success' => false'log' => $e->getMessage()], 500);
  279.         }
  280.     }
  281.     /**
  282.      * オーナーズブラグインインストール、アップデート
  283.      *
  284.      * @Route("/upgrade", name="admin_store_plugin_api_upgrade", methods={"POST"})
  285.      *
  286.      * @param Request $request
  287.      *
  288.      * @return \Symfony\Component\HttpFoundation\JsonResponse
  289.      */
  290.     public function apiUpgrade(Request $request)
  291.     {
  292.         $this->isTokenValid();
  293.         $this->cacheUtil->clearCache();
  294.         $pluginCode $request->get('pluginCode');
  295.         $version $request->get('version');
  296.         try {
  297.             $log $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version);
  298.             return $this->json(['success' => true'log' => $log]);
  299.         } catch (\Exception $e) {
  300.             $log $e->getMessage();
  301.             log_error($e);
  302.         }
  303.         return $this->json(['success' => false'log' => $log], 500);
  304.     }
  305.     /**
  306.      * オーナーズブラグインインストール、スキーマ更新
  307.      *
  308.      * @Route("/schema_update", name="admin_store_plugin_api_schema_update", methods={"POST"})
  309.      *
  310.      * @param Request $request
  311.      *
  312.      * @return \Symfony\Component\HttpFoundation\JsonResponse
  313.      */
  314.     public function apiSchemaUpdate(Request $request)
  315.     {
  316.         $this->isTokenValid();
  317.         $this->cacheUtil->clearCache();
  318.         $pluginCode $request->get('pluginCode');
  319.         try {
  320.             $Plugin $this->pluginRepository->findByCode($pluginCode);
  321.             if (!$Plugin) {
  322.                 throw new NotFoundHttpException();
  323.             }
  324.             $config $this->pluginService->readConfig($this->pluginService->calcPluginDir($Plugin->getCode()));
  325.             ob_start();
  326.             $this->pluginService->generateProxyAndUpdateSchema($Plugin$config);
  327.             // 初期化されていなければインストール処理を実行する
  328.             if (!$Plugin->isInitialized()) {
  329.                 $this->pluginService->callPluginManagerMethod($config'install');
  330.                 $Plugin->setInitialized(true);
  331.                 $this->entityManager->persist($Plugin);
  332.                 $this->entityManager->flush();
  333.             }
  334.             $log ob_get_clean();
  335.             while (ob_get_level() > 0) {
  336.                 ob_end_flush();
  337.             }
  338.             return $this->json(['success' => true'log' => $log]);
  339.         } catch (\Exception $e) {
  340.             $log $e->getMessage();
  341.             log_error($e);
  342.             return $this->json(['success' => false'log' => $log], 500);
  343.         }
  344.     }
  345.     /**
  346.      * オーナーズブラグインインストール、更新処理
  347.      *
  348.      * @Route("/update", name="admin_store_plugin_api_update", methods={"POST"})
  349.      *
  350.      * @param Request $request
  351.      *
  352.      * @return \Symfony\Component\HttpFoundation\JsonResponse
  353.      */
  354.     public function apiUpdate(Request $request)
  355.     {
  356.         $this->isTokenValid();
  357.         $this->cacheUtil->clearCache();
  358.         $pluginCode $request->get('pluginCode');
  359.         try {
  360.             $Plugin $this->pluginRepository->findByCode($pluginCode);
  361.             if (!$Plugin) {
  362.                 throw new NotFoundHttpException();
  363.             }
  364.             $config $this->pluginService->readConfig($this->pluginService->calcPluginDir($Plugin->getCode()));
  365.             ob_start();
  366.             $this->pluginService->updatePlugin($Plugin$config);
  367.             $log ob_get_clean();
  368.             while (ob_get_level() > 0) {
  369.                 ob_end_flush();
  370.             }
  371.             return $this->json(['success' => true'log' => $log]);
  372.         } catch (\Exception $e) {
  373.             $log $e->getMessage();
  374.             log_error($e);
  375.         }
  376.         return $this->json(['success' => false'log' => $log], 500);
  377.     }
  378.     /**
  379.      * Do confirm update page
  380.      *
  381.      * @Route("/upgrade/{id}/confirm", requirements={"id" = "\d+"}, name="admin_store_plugin_update_confirm", methods={"GET"})
  382.      * @Template("@admin/Store/plugin_confirm.twig")
  383.      *
  384.      * @param Plugin $Plugin
  385.      *
  386.      * @return array
  387.      */
  388.     public function doUpdateConfirm(Plugin $Plugin)
  389.     {
  390.         try {
  391.             $item $this->pluginApiService->getPlugin($Plugin->getSource());
  392.             return [
  393.                 'item' => $item,
  394.                 'requires' => [],
  395.                 'is_update' => true,
  396.                 'Plugin' => $Plugin,
  397.             ];
  398.         } catch (PluginApiException $e) {
  399.             $this->addError($e->getMessage(), 'admin');
  400.             return $this->redirectToRoute('admin_store_authentication_setting');
  401.         }
  402.     }
  403. }