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) 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.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) { |
||
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
|
|||
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 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.