Failed Conditions
Pull Request — experimental/sf (#3236)
by Kentaro
144:19 queued 116:23
created

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

Labels
Severity

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) 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\Master\DeviceType;
18
use Eccube\Form\Type\Admin\TemplateType;
19
use Eccube\Repository\Master\DeviceTypeRepository;
20
use Eccube\Repository\TemplateRepository;
21
use Eccube\Util\CacheUtil;
22
use Eccube\Util\StringUtil;
23
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
24
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
25
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
26
use Symfony\Component\Filesystem\Filesystem;
27
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
28
use Symfony\Component\Form\FormError;
29
use Symfony\Component\HttpFoundation\BinaryFileResponse;
30
use Symfony\Component\HttpFoundation\Request;
31
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
32
use Symfony\Component\HttpKernel\KernelEvents;
33
34
class TemplateController extends AbstractController
35
{
36
    /**
37
     * @var TemplateRepository
38
     */
39
    protected $templateRepository;
40
41
    /**
42
     * @var DeviceTypeRepository
43
     */
44
    protected $deviceTypeRepository;
45
46
    /**
47
     * TemplateController constructor.
48
     *
49
     * @param TemplateRepository $templateRepository
50
     * @param DeviceTypeRepository $deviceTypeRepository
51
     */
52 4
    public function __construct(
53
        TemplateRepository $templateRepository,
54
        DeviceTypeRepository $deviceTypeRepository
55
    ) {
56 4
        $this->templateRepository = $templateRepository;
57 4
        $this->deviceTypeRepository = $deviceTypeRepository;
58
    }
59
60
    /**
61
     * テンプレート一覧画面
62
     *
63
     * @Route("/%eccube_admin_route%/store/template", name="admin_store_template")
64
     * @Template("@admin/Store/template.twig")
65
     *
66
     * @param Request $request
67
     *
68
     * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
69
     */
70 1
    public function index(Request $request, CacheUtil $cacheUtil)
71
    {
72 1
        $DeviceType = $this->deviceTypeRepository->find(DeviceType::DEVICE_TYPE_PC);
73
74 1
        $Templates = $this->templateRepository->findBy(['DeviceType' => $DeviceType]);
75
76 1
        $form = $this->formFactory->createBuilder()
77 1
            ->add('selected', HiddenType::class)
78 1
            ->getForm();
79 1
        $form->handleRequest($request);
80
81 1
        if ($form->isSubmitted() && $form->isValid()) {
82
            $Template = $this->templateRepository->find($form['selected']->getData());
83
84
            $envFile = $this->getParameter('kernel.project_dir').'/.env';
85
            $env = file_exists($envFile) ? file_get_contents($envFile) : '';
86
87
            $env = StringUtil::replaceOrAddEnv($env, [
88
                'ECCUBE_TEMPLATE_CODE' => $Template->getCode(),
89
            ]);
90
91
            file_put_contents($envFile, $env);
92
93
            $this->addSuccess('admin.content.template.save.complete', 'admin');
94
95
            $cacheUtil->clearCache();
96
97
            return $this->redirectToRoute('admin_store_template');
98
        }
99
100
        return [
101 1
            'form' => $form->createView(),
102 1
            'Templates' => $Templates,
103
        ];
104
    }
105
106
    /**
107
     * テンプレート一覧からのダウンロード
108
     *
109
     * @Route("/%eccube_admin_route%/store/template/{id}/download", name="admin_store_template_download", requirements={"id" = "\d+"})
110
     *
111
     * @param Request $request
112
     * @param \Eccube\Entity\Template $Template
113
     *
114
     * @return BinaryFileResponse
115
     */
116
    public function download(Request $request, \Eccube\Entity\Template $Template)
117
    {
118
        // 該当テンプレートのディレクトリ
119
        $templateCode = $Template->getCode();
120
        $targetRealDir = $this->getParameter('kernel.project_dir').'/app/template/'.$templateCode;
121
        $targetHtmlRealDir = $this->getParameter('kernel.project_dir').'/html/template/'.$templateCode;
122
123
        // 一時ディレクトリ
124
        $uniqId = sha1(StringUtil::random(32));
125
        $tmpDir = \sys_get_temp_dir().'/'.$uniqId;
126
        $appDir = $tmpDir.'/app';
127
        $htmlDir = $tmpDir.'/html';
128
129
        // ファイル名
130
        $tarFile = $tmpDir.'.tar';
131
        $tarGzFile = $tarFile.'.gz';
132
        $downloadFileName = $Template->getCode().'.tar.gz';
133
134
        // 該当テンプレートを一時ディレクトリへコピーする.
135
        $fs = new Filesystem();
136
        $fs->mkdir([$appDir, $htmlDir]);
137
        $fs->mirror($targetRealDir, $appDir);
138
        $fs->mirror($targetHtmlRealDir, $htmlDir);
139
140
        // tar.gzファイルに圧縮する.
141
        $phar = new \PharData($tarFile);
142
        $phar->buildFromDirectory($tmpDir);
143
        // appディレクトリがない場合は, 空ディレクトリを追加
144
        // @see https://github.com/EC-CUBE/ec-cube/issues/742
145
        if (empty($phar['app'])) {
146
            $phar->addEmptyDir('app');
147
        }
148
        $phar->compress(\Phar::GZ);
149
150
        // ダウンロード完了後にファイルを削除する.
151
        // http://stackoverflow.com/questions/15238897/removing-file-after-delivering-response-with-silex-symfony
152
        $this->eventDispatcher->addListener(KernelEvents::TERMINATE, function () use (
153
            $tmpDir,
154
            $tarFile,
155
            $tarGzFile
156
        ) {
157
            log_debug('remove temp file: '.$tmpDir);
158
            log_debug('remove temp file: '.$tarFile);
159
            log_debug('remove temp file: '.$tarGzFile);
160
            $fs = new Filesystem();
161
            $fs->remove($tmpDir);
162
            $fs->remove($tarFile);
163
            $fs->remove($tarGzFile);
164
        });
165
166
        $response = new BinaryFileResponse($tarGzFile);
167
        $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $downloadFileName);
168
169
        return $response;
170
    }
171
172
    /**
173
     * @Route("/%eccube_admin_route%/store/template/{id}/delete", name="admin_store_template_delete", requirements={"id" = "\d+"})
174
     * @Method("DELETE")
175
     */
176 1
    public function delete(Request $request, \Eccube\Entity\Template $Template)
177
    {
178 1
        $this->isTokenValid();
179
180
        // デフォルトテンプレート
181 1
        if ($Template->isDefaultTemplate()) {
182
            $this->addError('admin.content.template.delete.default.error', 'admin');
183
184
            return $this->redirectToRoute('admin_store_template');
185
        }
186
187
        // 設定中のテンプレート
188 1
        if ($this->eccubeConfig['eccube.theme'] === $Template->getCode()) {
189
            $this->addError('admin.content.template.delete.current.error', 'admin');
190
191
            return $this->redirectToRoute('admin_store_template');
192
        }
193
194
        // テンプレートディレクトリの削除
195 1
        $templateCode = $Template->getCode();
196 1
        $targetRealDir = $this->container->getParameter('kernel.project_dir').'/app/template/'.$templateCode;
197 1
        $targetHtmlRealDir = $this->container->getParameter('kernel.project_dir').'/html/template/'.$templateCode;
198
199 1
        $fs = new Filesystem();
200 1
        $fs->remove($targetRealDir);
201 1
        $fs->remove($targetHtmlRealDir);
202
203
        // テーブルからも削除
204 1
        $this->entityManager->remove($Template);
205 1
        $this->entityManager->flush();
206
207 1
        $this->addSuccess('admin.content.template.delete.complete', 'admin');
208
209 1
        return $this->redirectToRoute('admin_store_template');
210
    }
211
212
    /**
213
     * テンプレートの追加画面.
214
     *
215
     * @Route("/%eccube_admin_route%/store/template/install", name="admin_store_template_install")
216
     * @Template("@admin/Store/template_add.twig")
217
     *
218
     * @param Request $request
219
     *
220
     * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
221
     */
222 3
    public function install(Request $request)
223
    {
224 3
        $form = $this->formFactory
225 3
            ->createBuilder(TemplateType::class)
226 3
            ->getForm();
227 3
        $form->handleRequest($request);
228
229 3
        if ($form->isSubmitted() && $form->isValid()) {
230
            /** @var $Template \Eccube\Entity\Template */
231 2
            $Template = $form->getData();
232
233 2
            $TemplateExists = $this->templateRepository->findByCode($Template->getCode());
234
235
            // テンプレートコードの重複チェック.
236 2
            if ($TemplateExists) {
237
                $form['code']->addError(new FormError(trans('template.text.error.code_not_available')));
238
239
                return [
240
                    'form' => $form->createView(),
241
                ];
242
            }
243
244
            // 該当テンプレートのディレクトリ
245 2
            $templateCode = $Template->getCode();
246 2
            $targetRealDir = $this->getParameter('kernel.project_dir').'/app/template/'.$templateCode;
247 2
            $targetHtmlRealDir = $this->getParameter('kernel.project_dir').'/html/template/'.$templateCode;
248
249
            // 一時ディレクトリ
250 2
            $uniqId = sha1(StringUtil::random(32));
251 2
            $tmpDir = \sys_get_temp_dir().'/'.$uniqId;
252 2
            $appDir = $tmpDir.'/app';
253 2
            $htmlDir = $tmpDir.'/html';
254
255 2
            $formFile = $form['file']->getData();
256
            // ファイル名
257 2
            $archive = $templateCode.'.'.$formFile->getClientOriginalExtension();
258
259
            // ファイルを一時ディレクトリへ移動.
260 2
            $formFile->move($tmpDir, $archive);
261
262
            // 一時ディレクトリへ解凍する.
263
            try {
264 2
                if ($formFile->getClientOriginalExtension() === 'zip') {
265 2
                    $zip = new \ZipArchive();
266 2
                    $zip->open($tmpDir.'/'.$archive);
267 2
                    $zip->extractTo($tmpDir);
268 2
                    $zip->close();
269
                } else {
270
                    $phar = new \PharData($tmpDir.'/'.$archive);
271 2
                    $phar->extractTo($tmpDir, null, true);
272
                }
273
            } catch (\Exception $e) {
274
                $form['file']->addError(new FormError(trans('template.text.error.upload_failuer')));
275
276
                return [
277
                    'form' => $form->createView(),
278
                ];
279
            }
280
281 2
            $fs = new Filesystem();
282
283
            // appディレクトリの存在チェック.
284 2
            if (!file_exists($appDir)) {
285
                $fs->mkdir($appDir);
286
            }
287
288
            // htmlディレクトリの存在チェック.
289 2
            if (!file_exists($htmlDir)) {
290
                $fs->mkdir($htmlDir);
291
            }
292
293
            // 一時ディレクトリから該当テンプレートのディレクトリへコピーする.
294 2
            $fs->mirror($appDir, $targetRealDir);
295 2
            $fs->mirror($htmlDir, $targetHtmlRealDir);
296
297
            // 一時ディレクトリを削除.
298 2
            $fs->remove($tmpDir);
299
300 2
            $DeviceType = $this->deviceTypeRepository->find(DeviceType::DEVICE_TYPE_PC);
301
302 2
            $Template->setDeviceType($DeviceType);
0 ignored issues
show
It seems like $DeviceType defined by $this->deviceTypeReposit...ceType::DEVICE_TYPE_PC) on line 300 can also be of type object; however, Eccube\Entity\Template::setDeviceType() does only seem to accept null|object<Eccube\Entity\Master\DeviceType>, 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...
303
304 2
            $this->entityManager->persist($Template);
305 2
            $this->entityManager->flush();
306
307 2
            $this->addSuccess('admin.content.template.add.complete', 'admin');
308
309 2
            return $this->redirectToRoute('admin_store_template');
310
        }
311
312
        return [
313 1
            'form' => $form->createView(),
314
        ];
315
    }
316
}
317