|
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\Content; |
|
15
|
|
|
|
|
16
|
|
|
use Doctrine\ORM\EntityRepository; |
|
17
|
|
|
use Doctrine\ORM\NoResultException; |
|
18
|
|
|
use Eccube\Controller\AbstractController; |
|
19
|
|
|
use Eccube\Entity\BlockPosition; |
|
20
|
|
|
use Eccube\Entity\Layout; |
|
21
|
|
|
use Eccube\Entity\PageLayout; |
|
22
|
|
|
use Eccube\Entity\Master\DeviceType; |
|
23
|
|
|
use Eccube\Form\Type\Master\DeviceTypeType; |
|
24
|
|
|
use Eccube\Entity\Master\ProductStatus; |
|
25
|
|
|
use Symfony\Bridge\Doctrine\Form\Type\EntityType; |
|
26
|
|
|
use Eccube\Repository\BlockRepository; |
|
27
|
|
|
use Eccube\Repository\LayoutRepository; |
|
28
|
|
|
use Eccube\Repository\PageLayoutRepository; |
|
29
|
|
|
use Eccube\Repository\PageRepository; |
|
30
|
|
|
use Eccube\Repository\ProductRepository; |
|
31
|
|
|
use Eccube\Repository\Master\DeviceTypeRepository; |
|
32
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; |
|
33
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; |
|
34
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; |
|
35
|
|
|
use Symfony\Component\Form\Extension\Core\Type\FormType; |
|
36
|
|
|
use Symfony\Component\Form\Extension\Core\Type\TextType; |
|
37
|
|
|
use Symfony\Component\HttpFoundation\JsonResponse; |
|
38
|
|
|
use Symfony\Component\HttpFoundation\Request; |
|
39
|
|
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; |
|
40
|
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
|
41
|
|
|
use Symfony\Component\Validator\Constraints\NotBlank; |
|
42
|
|
|
use Twig\Environment as Twig; |
|
43
|
|
|
use Symfony\Component\HttpFoundation\RedirectResponse; |
|
44
|
|
|
|
|
45
|
|
|
// todo プレビュー実装 |
|
46
|
|
|
class LayoutController extends AbstractController |
|
47
|
|
|
{ |
|
48
|
|
|
const DUMMY_BLOCK_ID = 9999999999; |
|
49
|
|
|
|
|
50
|
|
|
/** |
|
51
|
|
|
* @var BlockRepository |
|
52
|
|
|
*/ |
|
53
|
|
|
protected $blockRepository; |
|
54
|
|
|
|
|
55
|
|
|
/** |
|
56
|
|
|
* @var LayoutRepository |
|
57
|
|
|
*/ |
|
58
|
|
|
protected $layoutRepository; |
|
59
|
|
|
|
|
60
|
|
|
/** |
|
61
|
|
|
* @var PageLayoutRepository |
|
62
|
|
|
*/ |
|
63
|
|
|
protected $pageLayoutRepository; |
|
64
|
6 |
|
|
|
65
|
|
|
/** |
|
66
|
6 |
|
* @var PageRepository |
|
67
|
6 |
|
*/ |
|
68
|
6 |
|
protected $pageRepository; |
|
69
|
|
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* @var ProductRepository |
|
72
|
|
|
*/ |
|
73
|
|
|
protected $productRepository; |
|
74
|
|
|
|
|
75
|
3 |
|
/** |
|
76
|
|
|
* @var DeviceTypeRepository |
|
77
|
3 |
|
*/ |
|
78
|
|
|
protected $deviceTypeRepository; |
|
79
|
|
|
|
|
80
|
3 |
|
/** |
|
81
|
|
|
* @var boolean |
|
82
|
|
|
*/ |
|
83
|
|
|
protected $isPreview = false; |
|
84
|
|
|
|
|
85
|
|
|
/** |
|
86
|
|
|
* LayoutController constructor. |
|
87
|
|
|
* |
|
88
|
|
|
* @param BlockRepository $blockRepository |
|
89
|
|
|
* @param LayoutRepository $layoutRepository |
|
90
|
|
|
* @param PageLayoutRepository $pageLayoutRepository |
|
91
|
|
|
* @param pageRepository $pageRepository |
|
92
|
2 |
|
* @param ProductRepository $productRepository |
|
93
|
|
|
* @param DeviceTypeRepository $deviceTypeRepository |
|
94
|
2 |
|
*/ |
|
95
|
|
|
public function __construct(BlockRepository $blockRepository, LayoutRepository $layoutRepository, PageLayoutRepository $pageLayoutRepository, PageRepository $pageRepository, ProductRepository $productRepository, DeviceTypeRepository $deviceTypeRepository) |
|
96
|
|
|
{ |
|
97
|
2 |
|
$this->blockRepository = $blockRepository; |
|
98
|
1 |
|
$this->layoutRepository = $layoutRepository; |
|
99
|
|
|
$this->pageLayoutRepository = $pageLayoutRepository; |
|
100
|
1 |
|
$this->pageRepository = $pageRepository; |
|
101
|
|
|
$this->productRepository = $productRepository; |
|
102
|
|
|
$this->deviceTypeRepository = $deviceTypeRepository; |
|
103
|
1 |
|
} |
|
104
|
1 |
|
|
|
105
|
|
|
/** |
|
106
|
1 |
|
* @Route("/%eccube_admin_route%/content/layout", name="admin_content_layout") |
|
107
|
|
|
* @Template("@admin/Content/layout_list.twig") |
|
108
|
1 |
|
*/ |
|
109
|
|
|
public function index() |
|
110
|
|
|
{ |
|
111
|
|
|
$qb = $this->layoutRepository->createQueryBuilder('l'); |
|
112
|
|
|
$Layouts = $qb->where('l.id != 0') |
|
113
|
|
|
->orderBy('l.DeviceType', 'DESC') |
|
114
|
|
|
->addOrderBy('l.id', 'ASC') |
|
115
|
|
|
->getQuery() |
|
116
|
2 |
|
->getResult(); |
|
117
|
|
|
|
|
118
|
2 |
|
return [ |
|
119
|
1 |
|
'Layouts' => $Layouts, |
|
120
|
|
|
]; |
|
121
|
|
|
} |
|
122
|
|
|
|
|
123
|
1 |
|
/** |
|
124
|
1 |
|
* @Method("DELETE") |
|
125
|
1 |
|
* @Route("/%eccube_admin_route%/content/layout/{id}/delete", requirements={"id" = "\d+"}, name="admin_content_layout_delete") |
|
126
|
1 |
|
* |
|
127
|
1 |
|
* @param Layout $Layout |
|
128
|
1 |
|
* |
|
129
|
1 |
|
* @return RedirectResponse |
|
130
|
1 |
|
*/ |
|
131
|
1 |
|
public function delete(Layout $Layout) |
|
132
|
|
|
{ |
|
133
|
|
|
$this->isTokenValid(); |
|
134
|
|
|
|
|
135
|
|
|
/** @var Layout $Layout */ |
|
136
|
|
|
if (!$Layout->isDeletable()) { |
|
137
|
|
|
$this->deleteMessage(); |
|
138
|
|
|
|
|
139
|
2 |
|
return $this->redirectToRoute('admin_content_layout'); |
|
140
|
2 |
|
} |
|
141
|
1 |
|
|
|
142
|
|
|
$this->entityManager->remove($Layout); |
|
143
|
1 |
|
$this->entityManager->flush($Layout); |
|
|
|
|
|
|
144
|
1 |
|
|
|
145
|
1 |
|
$this->addSuccess('admin.delete.complete', 'admin'); |
|
146
|
1 |
|
|
|
147
|
1 |
|
return $this->redirectToRoute('admin_content_layout'); |
|
148
|
1 |
|
} |
|
149
|
1 |
|
|
|
150
|
|
|
/** |
|
151
|
|
|
* @Route("/%eccube_admin_route%/content/layout/new", name="admin_content_layout_new") |
|
152
|
2 |
|
* @Route("/%eccube_admin_route%/content/layout/{id}/edit", requirements={"id" = "\d+"}, name="admin_content_layout_edit") |
|
153
|
|
|
* @Template("@admin/Content/layout.twig") |
|
154
|
2 |
|
*/ |
|
155
|
2 |
|
public function edit(Request $request, $id = null, $origId = null) |
|
156
|
2 |
|
{ |
|
157
|
|
|
if (is_null($id)) { |
|
158
|
2 |
|
$Layout = new Layout(); |
|
159
|
2 |
|
} else { |
|
160
|
|
|
// todo レポジトリへ移動 |
|
161
|
|
|
try { |
|
162
|
2 |
|
$Layout = $this->layoutRepository->createQueryBuilder('l') |
|
163
|
|
|
->select('l, bp, b') |
|
164
|
2 |
|
->leftJoin('l.BlockPositions', 'bp') |
|
165
|
2 |
|
->leftJoin('bp.Block', 'b') |
|
166
|
2 |
|
->where('l.id = :layout_id') |
|
167
|
|
|
->orderBy('bp.block_row', 'ASC') |
|
168
|
2 |
|
->setParameter('layout_id', $this->isPreview ? 0 : $id) |
|
169
|
2 |
|
->getQuery() |
|
170
|
|
|
->getSingleResult(); |
|
171
|
|
|
} catch (NoResultException $e) { |
|
172
|
|
|
throw new NotFoundHttpException(); |
|
173
|
|
|
} |
|
174
|
|
|
} |
|
175
|
2 |
|
|
|
176
|
2 |
|
$Page = $this->pageRepository->createQueryBuilder('p') |
|
177
|
|
|
->select('p') |
|
178
|
2 |
|
->andWhere('p.id = :page_id') |
|
179
|
|
|
->setParameter('page_id', $origId) |
|
180
|
1 |
|
->getQuery() |
|
181
|
1 |
|
->getOneOrNullResult(); |
|
182
|
1 |
|
|
|
183
|
|
|
// todo レポジトリへ移動 |
|
184
|
|
|
// 未使用ブロックの取得 |
|
185
|
|
|
$Blocks = $Layout->getBlocks(); |
|
186
|
1 |
|
if (empty($Blocks)) { |
|
187
|
1 |
|
$UnusedBlocks = $this->blockRepository->findAll(); |
|
188
|
1 |
|
} else { |
|
189
|
1 |
|
$UnusedBlocks = $this->blockRepository |
|
190
|
1 |
|
->createQueryBuilder('b') |
|
191
|
|
|
->select('b') |
|
192
|
|
|
->where('b not in (:blocks)') |
|
193
|
|
|
->setParameter('blocks', $Blocks) |
|
194
|
1 |
|
->getQuery() |
|
195
|
1 |
|
->getResult(); |
|
196
|
1 |
|
} |
|
197
|
|
|
|
|
198
|
1 |
|
$builder = $this->formFactory->createBuilder(FormType::class, $Layout); |
|
199
|
1 |
|
$builder |
|
200
|
|
|
->add( |
|
201
|
|
|
'name', |
|
202
|
1 |
|
TextType::class, |
|
203
|
|
|
[ |
|
204
|
|
|
'constraints' => [ |
|
205
|
1 |
|
new NotBlank(), |
|
206
|
1 |
|
], |
|
207
|
|
|
'required' => false, |
|
208
|
1 |
|
'label' => trans('layout.label'), |
|
209
|
1 |
|
] |
|
210
|
1 |
|
)->add( |
|
211
|
1 |
|
'DeviceType', |
|
212
|
1 |
|
DeviceTypeType::class, |
|
213
|
1 |
|
[ |
|
214
|
1 |
|
'constraints' => [ |
|
215
|
1 |
|
new NotBlank(), |
|
216
|
1 |
|
], |
|
217
|
|
|
'required' => false, |
|
218
|
|
|
] |
|
219
|
1 |
|
)->add('Page', EntityType::class, [ |
|
220
|
|
|
'mapped' => false, |
|
221
|
1 |
|
'placeholder' => 'ページを選択してください', |
|
222
|
|
|
'required' => false, |
|
223
|
|
|
'choice_label' => 'Page.name', |
|
224
|
|
|
'choice_value' => 'page_id', |
|
225
|
1 |
|
'class' => PageLayout::class, |
|
226
|
1 |
|
'query_builder' => function (EntityRepository $er) use ($id) { |
|
227
|
1 |
|
return $er->createQueryBuilder('pl') |
|
228
|
|
|
->orderBy('pl.page_id', 'ASC') |
|
229
|
|
|
->where('pl.layout_id = :layout_id') |
|
230
|
|
|
->setParameter('layout_id', $id); |
|
231
|
|
|
}, |
|
232
|
|
|
]); |
|
233
|
|
|
|
|
234
|
|
|
$form = $builder->getForm(); |
|
235
|
|
|
$form->handleRequest($request); |
|
236
|
|
|
|
|
237
|
|
|
if ($form->isSubmitted() && $form->isValid()) { |
|
238
|
|
|
// Layoutの更新 |
|
239
|
|
|
$Layout = $form->getData(); |
|
240
|
|
|
if ($this->isPreview) { |
|
241
|
|
|
$Layout->setName('プレビュー用'); |
|
242
|
|
|
$DeviceType = $this->deviceTypeRepository->find(DeviceType::DEVICE_TYPE_ADMIN); |
|
243
|
|
|
$Layout->setDeviceType($DeviceType); |
|
244
|
|
|
} |
|
245
|
|
|
$this->entityManager->persist($Layout); |
|
246
|
|
|
$this->entityManager->flush($Layout); |
|
|
|
|
|
|
247
|
|
|
|
|
248
|
|
|
// BlockPositionの更新 |
|
249
|
|
|
// delete/insertのため、一度削除する. |
|
250
|
|
|
$BlockPositions = $Layout->getBlockPositions(); |
|
251
|
|
|
foreach ($BlockPositions as $BlockPosition) { |
|
252
|
|
|
$Layout->removeBlockPosition($BlockPosition); |
|
253
|
|
|
$this->entityManager->remove($BlockPosition); |
|
254
|
|
|
$this->entityManager->flush($BlockPosition); |
|
|
|
|
|
|
255
|
|
|
} |
|
256
|
|
|
|
|
257
|
|
|
// ブロックの個数分登録を行う. |
|
258
|
|
|
$max = count($Blocks) + count($UnusedBlocks); |
|
259
|
|
|
$data = $request->request->all(); |
|
260
|
|
|
for ($i = 0; $i < $max; $i++) { |
|
261
|
|
|
// block_idが取得できない場合はinsertしない |
|
262
|
|
|
if (!isset($data['block_id_'.$i])) { |
|
263
|
|
|
continue; |
|
264
|
|
|
} |
|
265
|
|
|
// 未使用ブロックはinsertしない |
|
266
|
|
|
if ($data['section_'.$i] == \Eccube\Entity\Page::TARGET_ID_UNUSED) { |
|
267
|
|
|
continue; |
|
268
|
|
|
} |
|
269
|
|
|
$Block = $this->blockRepository->find($data['block_id_'.$i]); |
|
270
|
|
|
$BlockPosition = new BlockPosition(); |
|
271
|
|
|
$BlockPosition |
|
272
|
|
|
->setBlockId($data['block_id_'.$i]) |
|
273
|
|
|
->setLayoutId($Layout->getId()) |
|
274
|
|
|
->setBlockRow($data['block_row_'.$i]) |
|
275
|
|
|
->setSection($data['section_'.$i]) |
|
276
|
|
|
->setBlock($Block) |
|
|
|
|
|
|
277
|
|
|
->setLayout($Layout); |
|
278
|
|
|
$Layout->addBlockPosition($BlockPosition); |
|
279
|
|
|
$this->entityManager->persist($BlockPosition); |
|
280
|
|
|
$this->entityManager->flush($BlockPosition); |
|
|
|
|
|
|
281
|
|
|
} |
|
282
|
|
|
|
|
283
|
|
|
// プレビューモード |
|
284
|
|
|
if ($this->isPreview) { |
|
285
|
|
|
if ($Page->getEditType() == \Eccube\Entity\Page::EDIT_TYPE_DEFAULT) { |
|
286
|
|
|
if ($Page->getUrl() === 'product_detail') { |
|
287
|
|
|
$products = $this->productRepository->findBy(['Status' => ProductStatus::DISPLAY_SHOW]); |
|
288
|
|
|
$product = null; |
|
289
|
|
|
foreach ($products as $p) { |
|
290
|
|
|
$product = $p; |
|
291
|
|
|
break; |
|
292
|
|
|
} |
|
293
|
|
|
if (is_null($product)) { |
|
294
|
|
|
return ''; |
|
295
|
|
|
} |
|
296
|
|
|
|
|
297
|
|
|
return $this->redirectToRoute($Page->getUrl(), ['preview' => 1, 'id' => $product->getId()]); |
|
298
|
|
|
} else { |
|
299
|
|
|
return $this->redirectToRoute($Page->getUrl(), ['preview' => 1]); |
|
300
|
|
|
} |
|
301
|
|
|
} else { |
|
302
|
|
|
// ユーザー登録画面 |
|
303
|
|
|
return $this->redirectToRoute('user_data', ['route' => $Page->getUrl(), 'preview' => 1]); |
|
304
|
|
|
} |
|
305
|
|
|
} else { |
|
306
|
|
|
$this->addSuccess('admin.register.complete', 'admin'); |
|
307
|
|
|
|
|
308
|
|
|
return $this->redirectToRoute('admin_content_layout_edit', ['id' => $Layout->getId()]); |
|
309
|
|
|
} |
|
310
|
|
|
} |
|
311
|
|
|
|
|
312
|
|
|
return [ |
|
313
|
|
|
'form' => $form->createView(), |
|
314
|
|
|
'Layout' => $Layout, |
|
315
|
|
|
'UnusedBlocks' => $UnusedBlocks, |
|
316
|
|
|
]; |
|
317
|
|
|
} |
|
318
|
|
|
|
|
319
|
|
|
/** |
|
320
|
|
|
* @Method("GET") |
|
321
|
|
|
* @Route("/%eccube_admin_route%/content/layout/view_block", name="admin_content_layout_view_block") |
|
322
|
|
|
* |
|
323
|
|
|
* @param Request $request |
|
324
|
|
|
* @param Twig $twig |
|
325
|
|
|
* |
|
326
|
|
|
* @return JsonResponse |
|
327
|
|
|
*/ |
|
328
|
|
|
public function viewBlock(Request $request, Twig $twig) |
|
329
|
|
|
{ |
|
330
|
|
|
if (!$request->isXmlHttpRequest()) { |
|
331
|
|
|
throw new BadRequestHttpException(); |
|
332
|
|
|
} |
|
333
|
|
|
|
|
334
|
|
|
$id = $request->get('id'); |
|
335
|
|
|
|
|
336
|
|
|
if (is_null($id)) { |
|
337
|
|
|
throw new BadRequestHttpException(); |
|
338
|
|
|
} |
|
339
|
|
|
|
|
340
|
|
|
$Block = $this->blockRepository->find($id); |
|
341
|
|
|
|
|
342
|
|
|
if (null === $Block) { |
|
343
|
|
|
throw new NotFoundHttpException(); |
|
344
|
|
|
} |
|
345
|
|
|
|
|
346
|
|
|
$source = $twig->getLoader() |
|
347
|
|
|
->getSourceContext('Block/'.$Block->getFileName().'.twig') |
|
348
|
|
|
->getCode(); |
|
349
|
|
|
|
|
350
|
|
|
return $this->json([ |
|
351
|
|
|
'id' => $Block->getId(), |
|
352
|
|
|
'source' => $source, |
|
353
|
|
|
]); |
|
354
|
|
|
} |
|
355
|
|
|
|
|
356
|
|
|
/** |
|
357
|
|
|
* @Route("/%eccube_admin_route%/content/layout/{id}/preview", requirements={"id" = "\d+"}, name="admin_content_layout_preview") |
|
358
|
|
|
*/ |
|
359
|
|
|
public function preview(Request $request, $id) |
|
360
|
|
|
{ |
|
361
|
|
|
$form = $request->get('form'); |
|
362
|
|
|
$this->isPreview = true; |
|
363
|
|
|
|
|
364
|
|
|
return $this->edit($request, $id, $form['Page']); |
|
365
|
|
|
} |
|
366
|
|
|
} |
|
367
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignorePhpDoc annotation to the duplicate definition and it will be ignored.