Skip to content

Commit

Permalink
Fix and properly implement module folder scoping.
Browse files Browse the repository at this point in the history
  • Loading branch information
jesseleite committed Nov 11, 2024
1 parent 889d6db commit a0b42b1
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 33 deletions.
32 changes: 28 additions & 4 deletions src/StarterKits/InstallableModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
final class InstallableModule extends Module
{
protected $installer;
protected $relativePath;

/**
* Set installer instance.
Expand All @@ -26,6 +27,16 @@ public function installer(?Installer $installer): self
return $this;
}

/**
* Set relative module path.
*/
public function setRelativePath(string $path): self
{
$this->relativePath = $path;

return $this;
}

/**
* Validate starter kit module is installable.
*
Expand Down Expand Up @@ -125,8 +136,10 @@ protected function installableFiles(): Collection
*/
protected function expandExportDirectoriesToFiles(string $to, ?string $from = null): Collection
{
$from = $this->relativePath($from ?? $to);

$from = Path::tidy($this->starterKitPath($from));
$to = Path::tidy($this->starterKitPath($to));
$from = Path::tidy($from ? $this->starterKitPath($from) : $to);

$paths = collect([$from => $to]);

Expand Down Expand Up @@ -184,9 +197,8 @@ protected function installableDependencies(string $configKey): array
protected function ensureInstallableFilesExist(): self
{
$this
->exportPaths()
->merge($this->exportAsPaths())
->reject(fn ($path) => $this->files->exists($this->starterKitPath($path)))
->installableFiles()
->reject(fn ($to, $from) => $this->files->exists($from))
->each(function ($path) {
throw new StarterKitException("Starter kit path [{$path}] does not exist.");
});
Expand Down Expand Up @@ -238,6 +250,18 @@ protected function starterKitPath(?string $path = null): string
return collect([base_path("vendor/{$package}"), $path])->filter()->implode('/');
}

/**
* Get relative module path.
*/
protected function relativePath(string $path): string
{
if (! $this->relativePath) {
return $path;
}

return Str::ensureRight($this->relativePath, '/').$path;
}

/**
* Normalize packages array to require args, with version handling if `package => version` array structure is passed.
*/
Expand Down
44 changes: 30 additions & 14 deletions src/StarterKits/InstallableModules.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,22 @@ public function instantiate(): self
/**
* Recursively instantiate module and its nested modules.
*/
protected function instantiateModuleRecursively(Collection|array|string $config, string $key): InstallableModule
protected function instantiateModuleRecursively(Collection|array|string $config, string $key, ?string $moduleScope = null): InstallableModule
{
if ($config === '@import') {
if ($imported = $config === '@import') {
$config = $this->importModuleConfig($key);
}

if (Arr::get($config, 'import') === '@config') {
} elseif ($imported = Arr::get($config, 'import') === '@config') {
$config = $this->importModuleConfig($key)->merge($config);
}

$moduleScope = $imported ? $key : $moduleScope;

if ($options = Arr::get($config, 'options')) {
$config['options'] = collect($options)
->map(fn ($optionConfig, $optionKey) => $this->instantiateModuleRecursively(
$optionConfig,
$this->normalizeModuleKey($key, $optionKey),
$moduleScope,
));
}

Expand All @@ -96,10 +97,17 @@ protected function instantiateModuleRecursively(Collection|array|string $config,
->map(fn ($childConfig, $childKey) => $this->instantiateModuleRecursively(
$childConfig,
$this->normalizeModuleKey($key, $childKey),
$moduleScope,
));
}

return (new InstallableModule($config, $key))->installer($this->installer);
$module = (new InstallableModule($config, $key))->installer($this->installer);

if ($moduleScope) {
$this->scopeInstallableFiles($module, $moduleScope);
}

return $module;
}

/**
Expand All @@ -109,19 +117,15 @@ protected function instantiateModuleRecursively(Collection|array|string $config,
*/
protected function importModuleConfig(string $key): Collection
{
$moduleConfig = $this->relativeModulePath('module.yaml', $key);
$moduleConfig = $this->relativeModulePath($key, 'module.yaml');

$absolutePath = $this->starterKitPath($moduleConfig);

if (! $this->files->exists($absolutePath)) {
throw new StarterKitException("Starter kit module config [$moduleConfig] does not exist.");
}

$config = collect(YAML::parse($this->files->get($absolutePath)));

// TODO: prefix from in export paths

return $config;
return collect(YAML::parse($this->files->get($absolutePath)));
}

/**
Expand Down Expand Up @@ -157,9 +161,21 @@ protected function starterKitPath(?string $path = null): string
/**
* Assemble relative imported module path.
*/
protected function relativeModulePath(string $path, string $key): string
protected function relativeModulePath(string $key, ?string $path = null): string
{
$base = 'modules/'.str_replace('.', '/', $key);

return $path
? $base.Str::ensureLeft($path, '/')
: $base;
}

/**
* Scope installable files to imported module.
*/
protected function scopeInstallableFiles(InstallableModule $module, string $scope): void
{
return 'modules/'.str_replace('.', '/', $key).Str::ensureLeft($path, '/');
$module->setRelativePath($this->relativeModulePath($scope));
}

/**
Expand Down
1 change: 0 additions & 1 deletion src/StarterKits/Installer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Facades\Statamic\StarterKits\Hook;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Http;
use Statamic\Console\NullConsole;
use Statamic\Console\Please\Application as PleaseApplication;
Expand Down
38 changes: 24 additions & 14 deletions tests/StarterKits/InstallTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -973,7 +973,7 @@ public function it_installs_imported_modules_confirmed_interactively_via_prompt(
path: 'modules/seo/module.yaml',
config: [
'export_paths' => [
'resources/css/seo.css',
$this->moveKitRepoFile('modules/seo', 'resources/css/seo.css'),
],
'dependencies' => [
'statamic/seo-pro' => '^0.2.0',
Expand All @@ -987,13 +987,13 @@ public function it_installs_imported_modules_confirmed_interactively_via_prompt(
'options' => [
'react' => [
'export_paths' => [
'resources/js/react.js',
$this->moveKitRepoFile('modules/js', 'resources/js/react.js'),
],
],
'vue' => '@import', // import option as separate module!
'svelte' => [
'export_paths' => [
'resources/js/svelte.js',
$this->moveKitRepoFile('modules/js', 'resources/js/svelte.js'),
],
],
],
Expand All @@ -1004,7 +1004,7 @@ public function it_installs_imported_modules_confirmed_interactively_via_prompt(
path: 'modules/js/vue/module.yaml',
config: [
'export_paths' => [
'resources/js/vue.js',
$this->moveKitRepoFile('modules/js/vue', 'resources/js/vue.js'),
],
'dependencies' => [
'bobsled/vue-components' => '^1.5',
Expand Down Expand Up @@ -1154,7 +1154,7 @@ public function it_can_merge_imported_module_config_with_starter_kit_config()
config: [
'label' => 'This should not get used, because prompt config in starter-kit.yaml takes precedence!',
'export_paths' => [
'resources/js/react.js',
$this->moveKitRepoFile('modules/js/react', 'resources/js/react.js'),
],
],
);
Expand Down Expand Up @@ -1656,7 +1656,7 @@ public function it_installs_nested_imported_modules_confirmed_interactively_via_
path: 'modules/seo/module.yaml',
config: [
'export_paths' => [
'resources/css/seo.css',
$this->moveKitRepoFile('modules/seo', 'resources/css/seo.css'),
],
'dependencies' => [
'statamic/seo-pro' => '^0.2.0',
Expand All @@ -1666,19 +1666,19 @@ public function it_installs_nested_imported_modules_confirmed_interactively_via_
'options' => [
'react' => [
'export_paths' => [
'resources/js/react.js',
$this->moveKitRepoFile('modules/seo', 'resources/js/react.js'),
],
'modules' => [
'testing_tools' => [
'export_paths' => [
'resources/js/react-testing-tools.js',
$this->moveKitRepoFile('modules/seo', 'resources/js/react-testing-tools.js'),
],
],
],
],
'vue' => [
'export_paths' => [
'resources/js/vue.js',
$this->moveKitRepoFile('modules/seo', 'resources/js/vue.js'),
],
'dependencies_dev' => [
'i-love-vue/test-helpers' => '^1.5',
Expand All @@ -1689,7 +1689,7 @@ public function it_installs_nested_imported_modules_confirmed_interactively_via_
],
'svelte' => [
'export_paths' => [
'resources/js/svelte.js',
$this->moveKitRepoFile('modules/seo', 'resources/js/svelte.js'),
],
],
],
Expand All @@ -1698,12 +1698,12 @@ public function it_installs_nested_imported_modules_confirmed_interactively_via_
'options' => [
'jquery' => [
'export_paths' => [
'resources/js/jquery.js',
$this->moveKitRepoFile('modules/seo', 'resources/js/jquery.js'),
],
],
'mootools' => [
'export_paths' => [
'resources/js/jquery.js',
$this->moveKitRepoFile('modules/seo', 'resources/js/mootools.js'),
],
],
],
Expand All @@ -1716,7 +1716,7 @@ public function it_installs_nested_imported_modules_confirmed_interactively_via_
path: 'modules/seo/js/vue/testing_tools/module.yaml',
config: [
'export_paths' => [
'resources/js/vue-testing-tools.js',
$this->moveKitRepoFile('modules/seo/js/vue/testing_tools', 'resources/js/vue-testing-tools.js'),
],
],
);
Expand All @@ -1725,7 +1725,7 @@ public function it_installs_nested_imported_modules_confirmed_interactively_via_
path: 'modules/jamaica/bobsled/module.yaml',
config: [
'export_paths' => [
'resources/css/bobsled.css',
$this->moveKitRepoFile('modules/jamaica/bobsled', 'resources/css/bobsled.css'),
],
'dependencies' => [
'bobsled/speed-calculator' => '^1.0.0',
Expand Down Expand Up @@ -1798,6 +1798,16 @@ private function setConfig($config, $path = 'starter-kit.yaml')
$this->files->put($this->preparePath($this->kitRepoPath($path)), YAML::dump($config));
}

private function moveKitRepoFile($relativeModulePath, $relativeFilePath)
{
$this->files->move(
$this->kitRepoPath($relativeFilePath),
$this->preparePath($this->kitRepoPath(Str::ensureRight($relativeModulePath, '/').$relativeFilePath)),
);

return $relativeFilePath;
}

private function preparePath($path)
{
$folder = preg_replace('/(.*)\/[^\/]+\.[^\/]+/', '$1', $path);
Expand Down

0 comments on commit a0b42b1

Please sign in to comment.