1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of EC-CUBE |
5
|
|
|
* |
6
|
|
|
* Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. |
7
|
|
|
* |
8
|
|
|
* http://www.ec-cube.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\Command; |
15
|
|
|
|
16
|
|
|
use Symfony\Component\Console\Command\Command; |
17
|
|
|
use Symfony\Component\Console\Exception\InvalidArgumentException; |
18
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
19
|
|
|
use Symfony\Component\Console\Input\InputOption; |
20
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
21
|
|
|
use Symfony\Component\Console\Style\SymfonyStyle; |
22
|
|
|
use Symfony\Component\DependencyInjection\Container; |
23
|
|
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
24
|
|
|
use Symfony\Component\Filesystem\Filesystem; |
25
|
|
|
|
26
|
|
|
class PluginGenerateCommand extends Command |
27
|
|
|
{ |
28
|
|
|
protected static $defaultName = 'eccube:plugin:generate'; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @var SymfonyStyle |
32
|
|
|
*/ |
33
|
|
|
protected $io; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var Filesystem |
37
|
|
|
*/ |
38
|
|
|
protected $fs; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @var ContainerInterface |
42
|
|
|
*/ |
43
|
|
|
protected $container; |
44
|
|
|
|
45
|
|
|
public function __construct(ContainerInterface $container) |
46
|
|
|
{ |
47
|
|
|
parent::__construct(); |
48
|
|
|
$this->container = $container; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
protected function configure() |
52
|
|
|
{ |
53
|
|
|
$this |
54
|
|
|
->addArgument('name', InputOption::VALUE_REQUIRED, 'plugin name') |
55
|
|
|
->addArgument('code', InputOption::VALUE_REQUIRED, 'plugin code') |
56
|
|
|
->addArgument('ver', InputOption::VALUE_REQUIRED, 'plugin version') |
57
|
|
|
->setDescription('Generate plugin skeleton.'); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
protected function initialize(InputInterface $input, OutputInterface $output) |
61
|
|
|
{ |
62
|
|
|
$this->io = new SymfonyStyle($input, $output); |
63
|
|
|
$this->fs = new Filesystem(); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
protected function interact(InputInterface $input, OutputInterface $output) |
67
|
|
|
{ |
68
|
|
|
if (null !== $input->getArgument('name') && null !== $input->getArgument('code') && null !== $input->getArgument('ver')) { |
69
|
|
|
return; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
$this->io->title('EC-CUBE Plugin Generator Interactive Wizard'); |
73
|
|
|
|
74
|
|
|
// Plugin name. |
75
|
|
|
$name = $input->getArgument('name'); |
76
|
|
View Code Duplication |
if (null !== $name) { |
|
|
|
|
77
|
|
|
$this->io->text(' > <info>name</info>: '.$name); |
78
|
|
|
} else { |
79
|
|
|
$name = $this->io->ask('name', 'EC-CUBE Sample Plugin'); |
80
|
|
|
$input->setArgument('name', $name); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
// Plugin code. |
84
|
|
|
$code = $input->getArgument('code'); |
85
|
|
View Code Duplication |
if (null !== $code) { |
|
|
|
|
86
|
|
|
$this->io->text(' > <info>code</info>: '.$code); |
87
|
|
|
} else { |
88
|
|
|
$code = $this->io->ask('code', 'Sample', [$this, 'validateCode']); |
89
|
|
|
$input->setArgument('code', $code); |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
// Plugin version. |
93
|
|
|
$version = $input->getArgument('ver'); |
94
|
|
View Code Duplication |
if (null !== $version) { |
|
|
|
|
95
|
|
|
$this->io->text(' > <info>ver</info>: '.$version); |
96
|
|
|
} else { |
97
|
|
|
$version = $this->io->ask('ver', '1.0.0', [$this, 'validateVersion']); |
98
|
|
|
$input->setArgument('ver', $version); |
99
|
|
|
} |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
103
|
|
|
{ |
104
|
|
|
$name = $input->getArgument('name'); |
105
|
|
|
$code = $input->getArgument('code'); |
106
|
|
|
$version = $input->getArgument('ver'); |
107
|
|
|
|
108
|
|
|
$this->validateCode($code); |
109
|
|
|
$this->validateVersion($version); |
|
|
|
|
110
|
|
|
|
111
|
|
|
$pluginDir = $this->container->getParameter('kernel.project_dir').'/app/Plugin/'.$code; |
112
|
|
|
|
113
|
|
|
$this->createDirectories($pluginDir); |
114
|
|
|
$this->createConfig($pluginDir, $name, $code, $version); |
115
|
|
|
$this->createEvent($pluginDir, $code); |
116
|
|
|
$this->createMessages($pluginDir); |
117
|
|
|
$this->createNav($pluginDir, $code); |
118
|
|
|
$this->createTwigBlock($pluginDir, $code); |
119
|
|
|
$this->createConfigController($pluginDir, $code); |
120
|
|
|
$this->createGithubActions($pluginDir); |
121
|
|
|
|
122
|
|
|
$this->io->success(sprintf('Plugin was successfully created: %s %s %s', $name, $code, $version)); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
public function validateCode($code) |
126
|
|
|
{ |
127
|
|
|
if (empty($code)) { |
128
|
|
|
throw new InvalidArgumentException('The code can not be empty.'); |
129
|
|
|
} |
130
|
|
|
if (strlen($code) > 255) { |
131
|
|
|
throw new InvalidArgumentException('The code can enter up to 255 characters'); |
132
|
|
|
} |
133
|
|
|
if (1 !== preg_match('/^\w+$/', $code)) { |
134
|
|
|
throw new InvalidArgumentException('The code [a-zA-Z_] is available.'); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
$pluginDir = $this->container->getParameter('kernel.project_dir').'/app/Plugin/'.$code; |
138
|
|
|
if (file_exists($pluginDir)) { |
139
|
|
|
throw new InvalidArgumentException('Plugin directory exists.'); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
return $code; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
public function validateVersion($version) |
146
|
|
|
{ |
147
|
|
|
// TODO |
148
|
|
|
return $version; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* @param string $pluginDir |
153
|
|
|
*/ |
154
|
|
|
protected function createDirectories($pluginDir) |
155
|
|
|
{ |
156
|
|
|
$dirs = [ |
157
|
|
|
'Controller/Admin', |
158
|
|
|
'Entity', |
159
|
|
|
'Repository', |
160
|
|
|
'Form/Type', |
161
|
|
|
'Form/Extension', |
162
|
|
|
'Resource/doctrine', |
163
|
|
|
'Resource/locale', |
164
|
|
|
'Resource/template/admin', |
165
|
|
|
'.github/workflows', |
166
|
|
|
]; |
167
|
|
|
|
168
|
|
|
foreach ($dirs as $dir) { |
169
|
|
|
$this->fs->mkdir($pluginDir.'/'.$dir); |
170
|
|
|
} |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* @param string $pluginDir |
175
|
|
|
*/ |
176
|
|
|
protected function createConfig($pluginDir, $name, $code, $version) |
177
|
|
|
{ |
178
|
|
|
$source = <<<EOL |
179
|
|
|
{ |
180
|
|
|
"name": "ec-cube/$code", |
181
|
|
|
"version": "$version", |
182
|
|
|
"description": "$name", |
183
|
|
|
"type": "eccube-plugin", |
184
|
|
|
"require": { |
185
|
|
|
"ec-cube/plugin-installer": "~0.0.7" |
186
|
|
|
}, |
187
|
|
|
"extra": { |
188
|
|
|
"code": "$code" |
189
|
|
|
} |
190
|
|
|
} |
191
|
|
|
EOL; |
192
|
|
|
|
193
|
|
|
$this->fs->dumpFile($pluginDir.'/composer.json', $source); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* @param string $pluginDir |
199
|
|
|
*/ |
200
|
|
|
protected function createGithubActions($pluginDir) |
201
|
|
|
{ |
202
|
|
|
$source = ' |
203
|
|
|
name: Packaging for EC-CUBE Plugin |
204
|
|
|
on: |
205
|
|
|
release: |
206
|
|
|
types: [ published ] |
207
|
|
|
jobs: |
208
|
|
|
deploy: |
209
|
|
|
name: Build |
210
|
|
|
runs-on: ubuntu-18.04 |
211
|
|
|
steps: |
212
|
|
|
- name: Checkout |
213
|
|
|
uses: actions/checkout@v2 |
214
|
|
|
- name: Packaging |
215
|
|
|
working-directory: ../ |
216
|
|
|
run: | |
217
|
|
|
rm -rf $GITHUB_WORKSPACE/.github |
218
|
|
|
find $GITHUB_WORKSPACE -name "dummy" -delete |
219
|
|
|
find $GITHUB_WORKSPACE -name ".git*" -and ! -name ".gitkeep" -print0 | xargs -0 rm -rf |
220
|
|
|
chmod -R o+w $GITHUB_WORKSPACE |
221
|
|
|
cd $GITHUB_WORKSPACE |
222
|
|
|
tar cvzf ../${{ github.event.repository.name }}-${{ github.event.release.tag_name }}.tar.gz ./* |
223
|
|
|
- name: Upload binaries to release of TGZ |
224
|
|
|
uses: svenstaro/upload-release-action@v1-release |
225
|
|
|
with: |
226
|
|
|
repo_token: ${{ secrets.GITHUB_TOKEN }} |
227
|
|
|
file: ${{ runner.workspace }}/${{ github.event.repository.name }}-${{ github.event.release.tag_name }}.tar.gz |
228
|
|
|
asset_name: ${{ github.event.repository.name }}-${{ github.event.release.tag_name }}.tar.gz |
229
|
|
|
tag: ${{ github.ref }} |
230
|
|
|
overwrite: true |
231
|
|
|
'; |
232
|
|
|
|
233
|
|
|
$this->fs->dumpFile($pluginDir.'/.github/workflows/release.yml', $source); |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
|
237
|
|
|
/** |
238
|
|
|
* @param string $pluginDir |
239
|
|
|
*/ |
240
|
|
|
protected function createMessages($pluginDir) |
241
|
|
|
{ |
242
|
|
|
$this->fs->dumpFile($pluginDir.'/Resource/locale/messages.ja.yaml', ''); |
243
|
|
|
$this->fs->dumpFile($pluginDir.'/Resource/locale/validators.ja.yaml', ''); |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
/** |
247
|
|
|
* @param string $pluginDir |
248
|
|
|
*/ |
249
|
|
|
protected function createTwigBlock($pluginDir, $code) |
250
|
|
|
{ |
251
|
|
|
$source = <<<EOL |
252
|
|
|
<?php |
253
|
|
|
|
254
|
|
|
namespace Plugin\\${code}; |
255
|
|
|
|
256
|
|
|
use Eccube\\Common\\EccubeTwigBlock; |
257
|
|
|
|
258
|
|
|
class TwigBlock implements EccubeTwigBlock |
259
|
|
|
{ |
260
|
|
|
/** |
261
|
|
|
* @return array |
262
|
|
|
*/ |
263
|
|
|
public static function getTwigBlock() |
264
|
|
|
{ |
265
|
|
|
return []; |
266
|
|
|
} |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
EOL; |
270
|
|
|
$this->fs->dumpFile($pluginDir.'/TwigBlock.php', $source); |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* @param string $pluginDir |
275
|
|
|
*/ |
276
|
|
|
protected function createNav($pluginDir, $code) |
277
|
|
|
{ |
278
|
|
|
$source = <<<EOL |
279
|
|
|
<?php |
280
|
|
|
|
281
|
|
|
namespace Plugin\\${code}; |
282
|
|
|
|
283
|
|
|
use Eccube\\Common\\EccubeNav; |
284
|
|
|
|
285
|
|
|
class Nav implements EccubeNav |
286
|
|
|
{ |
287
|
|
|
/** |
288
|
|
|
* @return array |
289
|
|
|
*/ |
290
|
|
|
public static function getNav() |
291
|
|
|
{ |
292
|
|
|
return []; |
293
|
|
|
} |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
EOL; |
297
|
|
|
$this->fs->dumpFile($pluginDir.'/Nav.php', $source); |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
/** |
301
|
|
|
* @param string $pluginDir |
302
|
|
|
*/ |
303
|
|
|
protected function createEvent($pluginDir, $code) |
304
|
|
|
{ |
305
|
|
|
$source = <<<EOL |
306
|
|
|
<?php |
307
|
|
|
|
308
|
|
|
namespace Plugin\\${code}; |
309
|
|
|
|
310
|
|
|
use Symfony\\Component\\EventDispatcher\\EventSubscriberInterface; |
311
|
|
|
|
312
|
|
|
class Event implements EventSubscriberInterface |
313
|
|
|
{ |
314
|
|
|
/** |
315
|
|
|
* @return array |
316
|
|
|
*/ |
317
|
|
|
public static function getSubscribedEvents() |
318
|
|
|
{ |
319
|
|
|
return []; |
320
|
|
|
} |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
EOL; |
324
|
|
|
$this->fs->dumpFile($pluginDir.'/Event.php', $source); |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
/** |
328
|
|
|
* @param string $pluginDir |
329
|
|
|
*/ |
330
|
|
|
protected function createConfigController($pluginDir, $code) |
331
|
|
|
{ |
332
|
|
|
$snakecased = Container::underscore($code); |
333
|
|
|
|
334
|
|
|
$source = <<<EOL |
335
|
|
|
<?php |
336
|
|
|
|
337
|
|
|
namespace Plugin\\${code}\\Controller\\Admin; |
338
|
|
|
|
339
|
|
|
use Eccube\\Controller\\AbstractController; |
340
|
|
|
use Plugin\\${code}\\Form\\Type\\Admin\\ConfigType; |
341
|
|
|
use Plugin\\${code}\\Repository\\ConfigRepository; |
342
|
|
|
use Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Template; |
343
|
|
|
use Symfony\\Component\\HttpFoundation\\Request; |
344
|
|
|
use Symfony\\Component\\Routing\\Annotation\\Route; |
345
|
|
|
|
346
|
|
|
class ConfigController extends AbstractController |
347
|
|
|
{ |
348
|
|
|
/** |
349
|
|
|
* @var ConfigRepository |
350
|
|
|
*/ |
351
|
|
|
protected \$configRepository; |
352
|
|
|
|
353
|
|
|
/** |
354
|
|
|
* ConfigController constructor. |
355
|
|
|
* |
356
|
|
|
* @param ConfigRepository \$configRepository |
357
|
|
|
*/ |
358
|
|
|
public function __construct(ConfigRepository \$configRepository) |
359
|
|
|
{ |
360
|
|
|
\$this->configRepository = \$configRepository; |
361
|
|
|
} |
362
|
|
|
|
363
|
|
|
/** |
364
|
|
|
* @Route("/%eccube_admin_route%/${snakecased}/config", name="${snakecased}_admin_config") |
365
|
|
|
* @Template("@${code}/admin/config.twig") |
366
|
|
|
*/ |
367
|
|
|
public function index(Request \$request) |
368
|
|
|
{ |
369
|
|
|
\$Config = \$this->configRepository->get(); |
370
|
|
|
\$form = \$this->createForm(ConfigType::class, \$Config); |
371
|
|
|
\$form->handleRequest(\$request); |
372
|
|
|
|
373
|
|
|
if (\$form->isSubmitted() && \$form->isValid()) { |
374
|
|
|
\$Config = \$form->getData(); |
375
|
|
|
\$this->entityManager->persist(\$Config); |
376
|
|
|
\$this->entityManager->flush(\$Config); |
377
|
|
|
\$this->addSuccess('登録しました。', 'admin'); |
378
|
|
|
|
379
|
|
|
return \$this->redirectToRoute('${snakecased}_admin_config'); |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
return [ |
383
|
|
|
'form' => \$form->createView(), |
384
|
|
|
]; |
385
|
|
|
} |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
EOL; |
389
|
|
|
|
390
|
|
|
$this->fs->dumpFile($pluginDir.'/Controller/Admin/ConfigController.php', $source); |
391
|
|
|
|
392
|
|
|
$source = <<<EOL |
393
|
|
|
<?php |
394
|
|
|
|
395
|
|
|
namespace Plugin\\${code}\\Entity; |
396
|
|
|
|
397
|
|
|
use Doctrine\\ORM\\Mapping as ORM; |
398
|
|
|
|
399
|
|
|
/** |
400
|
|
|
* Config |
401
|
|
|
* |
402
|
|
|
* @ORM\Table(name="plg_${snakecased}_config") |
403
|
|
|
* @ORM\Entity(repositoryClass="Plugin\\${code}\\Repository\\ConfigRepository") |
404
|
|
|
*/ |
405
|
|
|
class Config |
406
|
|
|
{ |
407
|
|
|
/** |
408
|
|
|
* @var int |
409
|
|
|
* |
410
|
|
|
* @ORM\Column(name="id", type="integer", options={"unsigned":true}) |
411
|
|
|
* @ORM\Id |
412
|
|
|
* @ORM\GeneratedValue(strategy="IDENTITY") |
413
|
|
|
*/ |
414
|
|
|
private \$id; |
415
|
|
|
|
416
|
|
|
/** |
417
|
|
|
* @var string |
418
|
|
|
* |
419
|
|
|
* @ORM\Column(name="name", type="string", length=255) |
420
|
|
|
*/ |
421
|
|
|
private \$name; |
422
|
|
|
|
423
|
|
|
/** |
424
|
|
|
* @return int |
425
|
|
|
*/ |
426
|
|
|
public function getId() |
427
|
|
|
{ |
428
|
|
|
return \$this->id; |
429
|
|
|
} |
430
|
|
|
|
431
|
|
|
/** |
432
|
|
|
* @return string |
433
|
|
|
*/ |
434
|
|
|
public function getName() |
435
|
|
|
{ |
436
|
|
|
return \$this->name; |
437
|
|
|
} |
438
|
|
|
|
439
|
|
|
/** |
440
|
|
|
* @param string \$name |
441
|
|
|
* |
442
|
|
|
* @return \$this; |
443
|
|
|
*/ |
444
|
|
|
public function setName(\$name) |
445
|
|
|
{ |
446
|
|
|
\$this->name = \$name; |
447
|
|
|
|
448
|
|
|
return \$this; |
449
|
|
|
} |
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
EOL; |
453
|
|
|
|
454
|
|
|
$this->fs->dumpFile($pluginDir.'/Entity/Config.php', $source); |
455
|
|
|
|
456
|
|
|
$source = <<<EOL |
457
|
|
|
<?php |
458
|
|
|
|
459
|
|
|
namespace Plugin\\${code}\\Repository; |
460
|
|
|
|
461
|
|
|
use Eccube\\Repository\\AbstractRepository; |
462
|
|
|
use Plugin\\${code}\\Entity\\Config; |
463
|
|
|
use Symfony\\Bridge\\Doctrine\\RegistryInterface; |
464
|
|
|
|
465
|
|
|
/** |
466
|
|
|
* ConfigRepository |
467
|
|
|
* |
468
|
|
|
* This class was generated by the Doctrine ORM. Add your own custom |
469
|
|
|
* repository methods below. |
470
|
|
|
*/ |
471
|
|
|
class ConfigRepository extends AbstractRepository |
472
|
|
|
{ |
473
|
|
|
/** |
474
|
|
|
* ConfigRepository constructor. |
475
|
|
|
* |
476
|
|
|
* @param RegistryInterface \$registry |
477
|
|
|
*/ |
478
|
|
|
public function __construct(RegistryInterface \$registry) |
479
|
|
|
{ |
480
|
|
|
parent::__construct(\$registry, Config::class); |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
/** |
484
|
|
|
* @param int \$id |
485
|
|
|
* |
486
|
|
|
* @return null|Config |
487
|
|
|
*/ |
488
|
|
|
public function get(\$id = 1) |
489
|
|
|
{ |
490
|
|
|
return \$this->find(\$id); |
491
|
|
|
} |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
EOL; |
495
|
|
|
|
496
|
|
|
$this->fs->dumpFile($pluginDir.'/Repository/ConfigRepository.php', $source); |
497
|
|
|
|
498
|
|
|
$source = <<<EOL |
499
|
|
|
<?php |
500
|
|
|
|
501
|
|
|
namespace Plugin\\${code}\\Form\\Type\\Admin; |
502
|
|
|
|
503
|
|
|
use Plugin\\${code}\\Entity\\Config; |
504
|
|
|
use Symfony\\Component\\Form\\AbstractType; |
505
|
|
|
use Symfony\\Component\\Form\\Extension\\Core\\Type\\TextType; |
506
|
|
|
use Symfony\\Component\\Form\\FormBuilderInterface; |
507
|
|
|
use Symfony\\Component\\OptionsResolver\\OptionsResolver; |
508
|
|
|
use Symfony\Component\Validator\Constraints\Length; |
509
|
|
|
use Symfony\Component\Validator\Constraints\NotBlank; |
510
|
|
|
|
511
|
|
|
class ConfigType extends AbstractType |
512
|
|
|
{ |
513
|
|
|
/** |
514
|
|
|
* {@inheritdoc} |
515
|
|
|
*/ |
516
|
|
|
public function buildForm(FormBuilderInterface \$builder, array \$options) |
517
|
|
|
{ |
518
|
|
|
\$builder->add('name', TextType::class, [ |
519
|
|
|
'constraints' => [ |
520
|
|
|
new NotBlank(), |
521
|
|
|
new Length(['max' => 255]), |
522
|
|
|
], |
523
|
|
|
]); |
524
|
|
|
} |
525
|
|
|
|
526
|
|
|
/** |
527
|
|
|
* {@inheritdoc} |
528
|
|
|
*/ |
529
|
|
|
public function configureOptions(OptionsResolver \$resolver) |
530
|
|
|
{ |
531
|
|
|
\$resolver->setDefaults([ |
532
|
|
|
'data_class' => Config::class, |
533
|
|
|
]); |
534
|
|
|
} |
535
|
|
|
} |
536
|
|
|
|
537
|
|
|
EOL; |
538
|
|
|
|
539
|
|
|
$this->fs->dumpFile($pluginDir.'/Form/Type/Admin/ConfigType.php', $source); |
540
|
|
|
|
541
|
|
|
$source = <<<EOL |
542
|
|
|
{% extends '@admin/default_frame.twig' %} |
543
|
|
|
|
544
|
|
|
{% set menus = ['store', 'plugin', 'plugin_list'] %} |
545
|
|
|
|
546
|
|
|
{% block title %}${code}{% endblock %} |
547
|
|
|
{% block sub_title %}プラグイン一覧{% endblock %} |
548
|
|
|
|
549
|
|
|
{% form_theme form '@admin/Form/bootstrap_4_horizontal_layout.html.twig' %} |
550
|
|
|
|
551
|
|
|
{% block stylesheet %}{% endblock stylesheet %} |
552
|
|
|
|
553
|
|
|
{% block javascript %}{% endblock javascript %} |
554
|
|
|
|
555
|
|
|
{% block main %} |
556
|
|
|
<form role="form" method="post"> |
557
|
|
|
|
558
|
|
|
{{ form_widget(form._token) }} |
559
|
|
|
|
560
|
|
|
<div class="c-contentsArea__cols"> |
561
|
|
|
<div class="c-contentsArea__primaryCol"> |
562
|
|
|
<div class="c-primaryCol"> |
563
|
|
|
<div class="card rounded border-0 mb-4"> |
564
|
|
|
<div class="card-header"><span>設定</span></div> |
565
|
|
|
<div class="card-body"> |
566
|
|
|
<div class="row"> |
567
|
|
|
<div class="col-3"><span>名前</span><span |
568
|
|
|
class="badge badge-primary ml-1">必須</span></div> |
569
|
|
|
<div class="col mb-2"> |
570
|
|
|
{{ form_widget(form.name) }} |
571
|
|
|
{{ form_errors(form.name) }} |
572
|
|
|
</div> |
573
|
|
|
</div> |
574
|
|
|
</div> |
575
|
|
|
</div> |
576
|
|
|
</div> |
577
|
|
|
</div> |
578
|
|
|
</div> |
579
|
|
|
<div class="c-conversionArea"> |
580
|
|
|
<div class="c-conversionArea__container"> |
581
|
|
|
<div class="row justify-content-between align-items-center"> |
582
|
|
|
<div class="col-6"> |
583
|
|
|
<div class="c-conversionArea__leftBlockItem"> |
584
|
|
|
<a class="c-baseLink" |
585
|
|
|
href="{{ url('admin_store_plugin') }}"> |
586
|
|
|
<i class="fa fa-backward" aria-hidden="true"></i> |
587
|
|
|
<span>プラグイン一覧</span> |
588
|
|
|
</a> |
589
|
|
|
</div> |
590
|
|
|
</div> |
591
|
|
|
<div class="col-6"> |
592
|
|
|
<div class="row align-items-center justify-content-end"> |
593
|
|
|
<div class="col-auto"> |
594
|
|
|
<button class="btn btn-ec-conversion px-5" |
595
|
|
|
type="submit">登録</button> |
596
|
|
|
</div> |
597
|
|
|
</div> |
598
|
|
|
</div> |
599
|
|
|
</div> |
600
|
|
|
</div> |
601
|
|
|
</div> |
602
|
|
|
</form> |
603
|
|
|
{% endblock %} |
604
|
|
|
|
605
|
|
|
EOL; |
606
|
|
|
$this->fs->dumpFile($pluginDir.'/Resource/template/admin/config.twig', $source); |
607
|
|
|
} |
608
|
|
|
} |
609
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.