Skip to content

[StimulusBundle] AssetMapper compiler doesn't handle controllers in subdirectory correctly #1422

Closed
@tamcy

Description

@tamcy

I am probably referring to this code segement (this is my first trial on AssetMapper):

foreach ($this->controllersMapGenerator->getControllersMap() as $name => $mappedControllerAsset) {
// @legacy: backwards compatibility with Symfony 6.3
if (class_exists(AssetDependency::class)) {
$loaderPublicPath = $asset->publicPathWithoutDigest;
$controllerPublicPath = $mappedControllerAsset->asset->publicPathWithoutDigest;
$relativeImportPath = Path::makeRelative($controllerPublicPath, \dirname($loaderPublicPath));
} else {
$relativeImportPath = Path::makeRelative($mappedControllerAsset->asset->sourcePath, \dirname($asset->sourcePath));
}
$relativeImportPath = json_encode($relativeImportPath, \JSON_THROW_ON_ERROR | \JSON_UNESCAPED_SLASHES);
/*
* The AssetDependency will already be added by AssetMapper itself when
* it processes this file. However, due to the "stimulusFetch: 'lazy'"
* that may appear inside the controllers, this file is dependent on
* the "contents" of each controller. So, we add the dependency here
* and mark it as a "content" dependency so that this file's contents
* will be recalculated when the contents of any controller changes.
*/
if (class_exists(AssetDependency::class)) {
// @legacy: Backwards compatibility with Symfony 6.3
$asset->addDependency(new AssetDependency(
$mappedControllerAsset->asset,
$mappedControllerAsset->isLazy,
true,
));
} else {
$asset->addDependency($mappedControllerAsset->asset);
}
$autoImportPaths = [];
foreach ($mappedControllerAsset->autoImports as $autoImport) {
if ($autoImport->isBareImport) {
$autoImportPaths[] = json_encode($autoImport->path, \JSON_THROW_ON_ERROR | \JSON_UNESCAPED_SLASHES);
} else {
$autoImportPaths[] = json_encode(Path::makeRelative($autoImport->path, \dirname($asset->sourcePath)), \JSON_THROW_ON_ERROR | \JSON_UNESCAPED_SLASHES);
}
}
if ($mappedControllerAsset->isLazy) {
if (!$mappedControllerAsset->autoImports) {
$lazyControllers[] = sprintf('%s: () => import(%s)', json_encode($name), $relativeImportPath);
} else {
// import $relativeImportPath and also the auto-imports
// and use a Promise.all() to wait for all of them
$lazyControllers[] = sprintf('%s: () => Promise.all([import(%s), %s]).then((ret) => ret[0])', json_encode($name), $relativeImportPath, implode(', ', array_map(fn ($path) => "import($path)", $autoImportPaths)));
}
continue;
}
$controllerNameForVariable = sprintf('controller_%s', \count($eagerControllerParts));
$importLines[] = sprintf(
'import %s from %s;',
$controllerNameForVariable,
$relativeImportPath
);
foreach ($autoImportPaths as $autoImportRelativePath) {
$importLines[] = sprintf(
'import %s;',
$autoImportRelativePath
);
}
$eagerControllerParts[] = sprintf('"%s": %s', $name, $controllerNameForVariable);
}
$importCode = implode("\n", $importLines);
$eagerControllersJson = sprintf('{%s}', implode(', ', $eagerControllerParts));
$lazyControllersExpression = sprintf('{%s}', implode(', ', $lazyControllers));
$isDebugString = $this->isDebug ? 'true' : 'false';
return <<<EOF
$importCode
export const eagerControllers = $eagerControllersJson;
export const lazyControllers = $lazyControllersExpression;
export const isApplicationDebug = $isDebugString;
EOF;
}

Where the $name variable in the foreach loop is the controller name. But when the Stimulus controller javascript file is placed under a subdirectory (e.g. in assets/controllers/admin/user_controller.js, when assets/controllers is the root dir) this code doesn't replace the directory separater with a double-dash (--) according to the naming convention, which causes the resultant controller array to look like this (I am using Windows, thus the backslash):

export const eagerControllers = {"admin\users": controller_0};

The result is that calling {{ stimulus_controller('admin/users') }} fails to work.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions