Completed
Push — experimental/sf ( 62d5bb...ebcb49 )
by Ryo
935:43 queued 928:36
created

TemplateController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 7
ccs 0
cts 3
cp 0
crap 2
rs 10
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\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
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
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
0 ignored issues
show
introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
50
     * @param DeviceTypeRepository $deviceTypeRepository
51
     */
52
    public function __construct(
53
        TemplateRepository $templateRepository,
54
        DeviceTypeRepository $deviceTypeRepository
55
    ) {
56
        $this->templateRepository = $templateRepository;
57
        $this->deviceTypeRepository = $deviceTypeRepository;
58
    }
59
60
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$cacheUtil" missing
Loading history...
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
    public function index(Request $request, CacheUtil $cacheUtil)
71
    {
72
        $DeviceType = $this->deviceTypeRepository->find(DeviceType::DEVICE_TYPE_PC);
73
74
        $Templates = $this->templateRepository->findBy(['DeviceType' => $DeviceType]);
75
76
        $form = $this->formFactory->createBuilder()
77
            ->add('selected', HiddenType::class)
78
            ->getForm();
79
        $form->handleRequest($request);
80
81
        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_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
            'form' => $form->createView(),
102
            '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
0 ignored issues
show
introduced by
Expected 17 spaces after parameter type; 1 found
Loading history...
112
     * @param \Eccube\Entity\Template $Template
113
     *
114
     * @return mixed
115
     */
116
    public function download(Request $request, \Eccube\Entity\Template $Template)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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]);
0 ignored issues
show
Documentation introduced by
array($appDir, $htmlDir) is of type array<integer,string,{"0":"string","1":"string"}>, but the function expects a string|object<Symfony\Co...nt\Filesystem\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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
        ) {
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 12 spaces, but found 8.
Loading history...
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
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$request" missing
Loading history...
introduced by
Doc comment for parameter "$Template" missing
Loading history...
173
     * @Route("/%eccube_admin_route%/store/template/{id}/delete", name="admin_store_template_delete", requirements={"id" = "\d+"})
174
     * @Method("DELETE")
175
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
176
    public function delete(Request $request, \Eccube\Entity\Template $Template)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
177
    {
178
        $this->isTokenValid();
179
180
        // デフォルトテンプレート
181
        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
        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
        $templateCode = $Template->getCode();
196
        $targetRealDir = $this->container->getParameter('kernel.project_dir').'/app/template/'.$templateCode;
197
        $targetHtmlRealDir = $this->container->getParameter('kernel.project_dir').'/html/template/'.$templateCode;
198
199
        $fs = new Filesystem();
200
        $fs->remove($targetRealDir);
201
        $fs->remove($targetHtmlRealDir);
202
203
        // テーブルからも削除
204
        $this->entityManager->remove($Template);
205
        $this->entityManager->flush();
206
207
        $this->addSuccess('admin.content.template.delete.complete', 'admin');
208
209
        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
    public function install(Request $request)
223
    {
224
        $form = $this->formFactory
225
            ->createBuilder(TemplateType::class)
226
            ->getForm();
227
        $form->handleRequest($request);
228
229
        if ($form->isSubmitted() && $form->isValid()) {
230
            /** @var $Template \Eccube\Entity\Template */
231
            $Template = $form->getData();
232
233
            $TemplateExists = $this->templateRepository->findByCode($Template->getCode());
0 ignored issues
show
Documentation Bug introduced by
The method findByCode does not exist on object<Eccube\Repository\TemplateRepository>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
234
235
            // テンプレートコードの重複チェック.
236
            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
            $templateCode = $Template->getCode();
246
            $targetRealDir = $this->getParameter('kernel.project_dir').'/app/template/'.$templateCode;
247
            $targetHtmlRealDir = $this->getParameter('kernel.project_dir').'/html/template/'.$templateCode;
248
249
            // 一時ディレクトリ
250
            $uniqId = sha1(StringUtil::random(32));
251
            $tmpDir = \sys_get_temp_dir().'/'.$uniqId;
252
            $appDir = $tmpDir.'/app';
253
            $htmlDir = $tmpDir.'/html';
254
255
            $formFile = $form['file']->getData();
256
            // ファイル名
257
            $archive = $templateCode.'.'.$formFile->getClientOriginalExtension();
258
259
            // ファイルを一時ディレクトリへ移動.
260
            $formFile->move($tmpDir, $archive);
261
262
            // 一時ディレクトリへ解凍する.
263
            try {
264
                if ($formFile->getClientOriginalExtension() === 'zip') {
265
                    $zip = new \ZipArchive();
266
                    $zip->open($tmpDir.'/'.$archive);
267
                    $zip->extractTo($tmpDir);
268
                    $zip->close();
269
                } else {
270
                    $phar = new \PharData($tmpDir.'/'.$archive);
271
                    $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
            $fs = new Filesystem();
282
283
            // appディレクトリの存在チェック.
284
            if (!file_exists($appDir)) {
285
                $fs->mkdir($appDir);
286
            }
287
288
            // htmlディレクトリの存在チェック.
289
            if (!file_exists($htmlDir)) {
290
                $fs->mkdir($htmlDir);
291
            }
292
293
            // 一時ディレクトリから該当テンプレートのディレクトリへコピーする.
294
            $fs->mirror($appDir, $targetRealDir);
295
            $fs->mirror($htmlDir, $targetHtmlRealDir);
296
297
            // 一時ディレクトリを削除.
298
            $fs->remove($tmpDir);
299
300
            $DeviceType = $this->deviceTypeRepository->find(DeviceType::DEVICE_TYPE_PC);
301
302
            $Template->setDeviceType($DeviceType);
303
304
            $this->entityManager->persist($Template);
305
            $this->entityManager->flush();
306
307
            $this->addSuccess('admin.content.template.add.complete', 'admin');
308
309
            return $this->redirectToRoute('admin_store_template');
310
        }
311
312
        return [
313
            'form' => $form->createView(),
314
        ];
315
    }
316
}
317