• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

heimrichhannot / contao-encore-bundle / 27198996514

09 Jun 2026 10:07AM UTC coverage: 75.679% (-1.9%) from 77.539%
27198996514

push

github

web-flow
Allow extension from App, various enhancements (#38)

28 of 68 new or added lines in 11 files covered. (41.18%)

3 existing lines in 2 files now uncovered.

641 of 847 relevant lines covered (75.68%)

2.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Command/PrepareCommand.php
1
<?php
2

3
/*
4
 * Copyright (c) 2023 Heimrich & Hannot GmbH
5
 *
6
 * @license LGPL-3.0-or-later
7
 */
8

9
namespace HeimrichHannot\EncoreBundle\Command;
10

11
use HeimrichHannot\EncoreBundle\Collection\ExtensionCollection;
12
use HeimrichHannot\EncoreBundle\EncoreExtension\EncoreExtensionWrapperFactory;
13
use Psr\Cache\CacheItemPoolInterface;
14
use Symfony\Component\Console\Attribute\AsCommand;
15
use Symfony\Component\Console\Command\Command;
16
use Symfony\Component\Console\Input\InputInterface;
17
use Symfony\Component\Console\Input\InputOption;
18
use Symfony\Component\Console\Output\OutputInterface;
19
use Symfony\Component\Console\Style\SymfonyStyle;
20
use Symfony\Component\Filesystem\Filesystem;
21
use Symfony\Component\HttpKernel\KernelInterface;
22
use Twig\Environment;
23

24
#[AsCommand(
25
    name: 'huh:encore:prepare',
×
26
    description: 'Does the necessary preparation for contao encore bundle. Needs to be called after changes to bundle encore entries.',
×
27
    aliases: ['encore:prepare'],
×
28
    hidden: false
×
29
)]
×
30
class PrepareCommand extends Command
31
{
32
    public const DEPENDENCY_PREFIX = '@huh/encore-bundle--';
33

34
    private SymfonyStyle $io;
35

36
    public function __construct(
37
        private readonly CacheItemPoolInterface $encoreCache,
38
        private readonly KernelInterface $kernel,
39
        private readonly Environment $twig,
40
        private readonly ExtensionCollection $extensionCollection,
41
        private readonly EncoreExtensionWrapperFactory $wrapperFactory,
42
    ) {
43
        parent::__construct();
×
44
    }
45

46
    protected function configure()
47
    {
48
        $this
×
49
            ->addOption('skip-entries', null, InputOption::VALUE_OPTIONAL, 'Add a comma separated list of entries to skip their generation.', false);
×
50
    }
51

52
    protected function execute(InputInterface $input, OutputInterface $output): int
53
    {
54
        $this->io = new SymfonyStyle($input, $output);
×
55

56
        $this->io->title('Update project encore data');
×
57

58
        $resultFile = $this->kernel->getProjectDir() . \DIRECTORY_SEPARATOR . 'encore.bundles.js';
×
59

60
        $skipEntries = $input->getOption('skip-entries') ? explode(',', (string) $input->getOption('skip-entries')) : [];
×
61

62
        $this->io->writeln('Using <fg=green>' . $this->kernel->getEnvironment() . '</> environment. (Use --env=[ENV] to change environment. See --help for more information!)');
×
63

64
        @unlink($resultFile);
×
65

66
        $this->encoreCache->clear();
×
67

68
        $this->io->text(['', ' // Collect entries', '']);
×
69

70
        $this->io->writeln('> Collect entries from yaml config');
×
71

72
        $encoreJsEntries = [];
×
73

74
        $this->io->writeln(['', '> Collect entries from encore extensions']);
×
75
        $extensionDependencies = [];
×
76
        $extensionList = [];
×
77

78
        foreach ($this->extensionCollection->getExtensions() as $extension) {
×
NEW
79
            $wrapper = $this->wrapperFactory->wrap($extension);
×
80
            try {
NEW
81
                $bundlePath = $wrapper->getBundlePath();
×
NEW
82
            } catch (\RuntimeException $e) {
×
NEW
83
                $this->io->warning($e->getMessage());
×
NEW
84
                continue;
×
85
            }
86

87
            $preparedEntry = [];
×
UNCOV
88
            foreach ($extension->getEntries() as $entry) {
×
89
                $preparedEntry['name'] = $entry->getName();
×
NEW
90
                $filePath = '.' . \DIRECTORY_SEPARATOR;
×
NEW
91
                if ('.' !== $bundlePath) {
×
NEW
92
                    $filePath .= $bundlePath . \DIRECTORY_SEPARATOR;
×
93
                }
NEW
94
                $preparedEntry['file'] = $filePath . ltrim($entry->getPath(), \DIRECTORY_SEPARATOR);
×
UNCOV
95
                $encoreJsEntries[] = $preparedEntry;
×
96
            }
97

NEW
98
            if (!$wrapper->isAppExtension() && file_exists($bundlePath . \DIRECTORY_SEPARATOR . 'package.json')) {
×
99
                $packageData = json_decode(file_get_contents($bundlePath . \DIRECTORY_SEPARATOR . 'package.json'), true);
×
100
                $extensionDependencies = array_merge($extensionDependencies, $packageData['dependencies'] ?? []);
×
101
            }
102

NEW
103
            $extensionList[] = [$wrapper->getBundleShortName(), $extension::class, $bundlePath];
×
104
        }
105

106
        $this->io->newLine();
×
107
        $this->io->writeln('Found <fg=green>' . \count($this->extensionCollection->getExtensions()) . '</> registered encore extensions.');
×
108

109
        if ($this->io->isVerbose()) {
×
110
            $this->io->table(['Bundle', 'Extension', 'Bundle path'], $extensionList);
×
111
        }
112

113
        $this->io->text(['', ' // Update encore entry dependencies', '']);
×
114

115
        $projectPackageJsonPath = $this->kernel->getProjectDir() . \DIRECTORY_SEPARATOR . 'package.json';
×
116
        if (!file_exists($projectPackageJsonPath)) {
×
117
            throw new \Exception('No package.json could be found in your project. This file must be present for encore to work!');
×
118
        }
119

120
        $this->io->writeln('Collect encore entry dependencies ');
×
121
        $encorePackageData = [
×
122
            'name' => '@hundh/encore-entry-dependencies',
×
123
            'version' => date('Ymd') . '.' . date('Hi') . '.' . time(),
×
124
            'dependencies' => $extensionDependencies,
×
125
        ];
×
126
        $encoreAssetsPath = 'vendor' . \DIRECTORY_SEPARATOR . 'heimrichhannot' . \DIRECTORY_SEPARATOR . 'encore-entry-dependencies';
×
127

128
        (new Filesystem())->dumpFile(
×
129
            $this->kernel->getProjectDir() . \DIRECTORY_SEPARATOR . $encoreAssetsPath . \DIRECTORY_SEPARATOR . 'package.json',
×
130
            json_encode($encorePackageData, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES)
×
131
        );
×
132

133
        $this->io->writeln('Register dependencies in project');
×
134
        $packageData = json_decode(file_get_contents($projectPackageJsonPath), true, 512, \JSON_THROW_ON_ERROR);
×
135

136
        $packageData['dependencies'] = array_merge(
×
137
            [
×
138
                '@hundh/encore-entry-dependencies' => 'file:.' . \DIRECTORY_SEPARATOR . $encoreAssetsPath . \DIRECTORY_SEPARATOR,
×
139
            ],
×
140
            $packageData['dependencies'] ?? []
×
141
        );
×
142

143
        (new Filesystem())->dumpFile(
×
144
            $projectPackageJsonPath,
×
145
            json_encode($packageData, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES)
×
146
        );
×
147

148
        if (!empty($encoreJsEntries)) {
×
149
            $this->io->text(['', ' // Output encore_bundles.js', '']);
×
150

151
            $content = $this->twig->render('@HeimrichHannotEncore/encore_bundles.js.twig', [
×
152
                'entries' => $encoreJsEntries,
×
153
                'skipEntries' => $skipEntries,
×
154
            ]);
×
155

156
            file_put_contents($resultFile, $content);
×
157

158
            $this->io->writeln('Created encore.bundles.js in your project root. You can now require it in your webpack.config.js');
×
159
        } else {
160
            $this->io->warning('Found no registered encore entries. Skipped encore.bundles.js creation.');
×
161
        }
162

163
        $this->io->success('Finished updating your project encore data.');
×
164

165
        $this->io->text([
×
166
            'Next steps:',
×
167
            '1. If your dependencies have changed, run <fg=black;bg=cyan> yarn upgrade </>.',
×
168
            '2. Compile your asset with <fg=black;bg=cyan> yarn encore dev </>, <fg=black;bg=cyan> yarn encore dev --watch </> or <fg=black;bg=cyan> yarn encore prod </>',
×
169
            '',
×
170
        ]);
×
171

172
        return Command::SUCCESS;
×
173
    }
174
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc