Failed Conditions
Pull Request — experimental/sf (#3445)
by
unknown
206:10 queued 141:04
created

LayoutController::delete()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2.0185

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 18
ccs 10
cts 12
cp 0.8333
crap 2.0185
rs 9.6666
c 0
b 0
f 0
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);
0 ignored issues
show
Unused Code introduced by
The call to EntityManagerInterface::flush() has too many arguments starting with $Layout.

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 @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
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);
0 ignored issues
show
Unused Code introduced by
The call to EntityManagerInterface::flush() has too many arguments starting with $Layout.

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 @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
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);
0 ignored issues
show
Unused Code introduced by
The call to EntityManagerInterface::flush() has too many arguments starting with $BlockPosition.

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 @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
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)
0 ignored issues
show
Bug introduced by
It seems like $Block defined by $this->blockRepository->...data['block_id_' . $i]) on line 269 can also be of type object; however, Eccube\Entity\BlockPosition::setBlock() does only seem to accept null|object<Eccube\Entity\Block>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
277
                    ->setLayout($Layout);
278
                $Layout->addBlockPosition($BlockPosition);
279
                $this->entityManager->persist($BlockPosition);
280
                $this->entityManager->flush($BlockPosition);
0 ignored issues
show
Unused Code introduced by
The call to EntityManagerInterface::flush() has too many arguments starting with $BlockPosition.

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 @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
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