-
-
Notifications
You must be signed in to change notification settings - Fork 540
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[5.x] Starter kit modules and other misc improvements (#10559)
Co-authored-by: Jason Varga <[email protected]>
- Loading branch information
1 parent
52ee6a0
commit c6180f6
Showing
27 changed files
with
2,598 additions
and
664 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<?php | ||
|
||
namespace Statamic\StarterKits\Concerns; | ||
|
||
use Illuminate\Console\Command; | ||
use Illuminate\Filesystem\Filesystem; | ||
use Statamic\Console\NullConsole; | ||
use Statamic\Facades\Path; | ||
|
||
trait InteractsWithFilesystem | ||
{ | ||
/** | ||
* Install starter kit file. | ||
*/ | ||
protected function installFile(string $fromPath, string $toPath, Command|NullConsole $console): self | ||
{ | ||
$displayPath = str_replace(Path::tidy(base_path().'/'), '', $toPath); | ||
|
||
$console->line("Installing file [{$displayPath}]"); | ||
|
||
app(Filesystem::class)->copy($fromPath, $this->preparePath($toPath)); | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Export starter kit path. | ||
*/ | ||
protected function exportPath(string $starterKitPath, string $from, ?string $to = null): void | ||
{ | ||
$to = $to | ||
? "{$starterKitPath}/{$to}" | ||
: "{$starterKitPath}/{$from}"; | ||
|
||
$from = base_path($from); | ||
|
||
$this->preparePath($to); | ||
|
||
$files = app(Filesystem::class); | ||
|
||
$files->isDirectory($from) | ||
? $files->copyDirectory($from, $to) | ||
: $files->copy($from, $to); | ||
} | ||
|
||
/** | ||
* Prepare path directory. | ||
*/ | ||
protected function preparePath(string $path): string | ||
{ | ||
$files = app(Filesystem::class); | ||
|
||
$directory = $files->isDirectory($path) | ||
? $path | ||
: preg_replace('/(.*)\/[^\/]*/', '$1', Path::tidy($path)); | ||
|
||
if (! $files->exists($directory)) { | ||
$files->makeDirectory($directory, 0755, true); | ||
} | ||
|
||
return Path::tidy($path); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
<?php | ||
|
||
namespace Statamic\StarterKits; | ||
|
||
use Exception; | ||
use Illuminate\Support\Collection; | ||
use Statamic\StarterKits\Exceptions\StarterKitException; | ||
use Statamic\Support\Str; | ||
|
||
class ExportableModule extends Module | ||
{ | ||
/** | ||
* Validate starter kit module is exportable. | ||
* | ||
* @throws Exception|StarterKitException | ||
*/ | ||
public function validate(): void | ||
{ | ||
$this | ||
->ensureModuleConfigNotEmpty() | ||
->ensureNotExportingComposerJson() | ||
->ensureExportablePathsExist() | ||
->ensureExportableDependenciesExist(); | ||
} | ||
|
||
/** | ||
* Export starter kit module. | ||
* | ||
* @throws Exception|StarterKitException | ||
*/ | ||
public function export(string $starterKitPath): void | ||
{ | ||
$this | ||
->exportPaths() | ||
->each(fn ($path) => $this->exportPath( | ||
from: $path, | ||
starterKitPath: $starterKitPath, | ||
)); | ||
|
||
$this | ||
->exportAsPaths() | ||
->each(fn ($to, $from) => $this->exportPath( | ||
from: $from, | ||
to: $to, | ||
starterKitPath: $starterKitPath, | ||
)); | ||
} | ||
|
||
public function versionDependencies(): self | ||
{ | ||
$exportableDependencies = $this->exportableDependencies(); | ||
|
||
$this->config->forget('dependencies'); | ||
$this->config->forget('dependencies_dev'); | ||
|
||
if ($dependencies = $this->exportDependenciesFromComposerRequire('require', $exportableDependencies)) { | ||
$this->config->put('dependencies', $dependencies->all()); | ||
} | ||
|
||
if ($devDependencies = $this->exportDependenciesFromComposerRequire('require-dev', $exportableDependencies)) { | ||
$this->config->put('dependencies_dev', $devDependencies->all()); | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Get exportable dependencies without versions from module config. | ||
*/ | ||
protected function exportableDependencies(): Collection | ||
{ | ||
$config = $this->config(); | ||
|
||
return collect() | ||
->merge($config->get('dependencies') ?? []) | ||
->merge($config->get('dependencies_dev') ?? []) | ||
->map(function ($value, $key) { | ||
return Str::contains($key, '/') | ||
? $key | ||
: $value; | ||
}); | ||
} | ||
|
||
/** | ||
* Export dependencies from composer.json using specific require key. | ||
*/ | ||
protected function exportDependenciesFromComposerRequire(string $requireKey, Collection $exportableDependencies): mixed | ||
{ | ||
$composerJson = json_decode($this->files->get(base_path('composer.json')), true); | ||
|
||
$dependencies = collect($composerJson[$requireKey] ?? []) | ||
->filter(function ($version, $dependency) use ($exportableDependencies) { | ||
return $exportableDependencies->contains($dependency); | ||
}); | ||
|
||
return $dependencies->isNotEmpty() | ||
? $dependencies | ||
: false; | ||
} | ||
|
||
/** | ||
* Ensure composer.json is not one of the export paths. | ||
* | ||
* @throws StarterKitException | ||
*/ | ||
protected function ensureNotExportingComposerJson(): self | ||
{ | ||
// Here we'll ensure both `export_as` values and keys are included, | ||
// because we want to make sure `composer.json` is referenced on either end. | ||
$flattenedExportPaths = $this | ||
->exportPaths() | ||
->merge($this->exportAsPaths()) | ||
->merge($this->exportAsPaths()->keys()); | ||
|
||
if ($flattenedExportPaths->contains('composer.json')) { | ||
throw new StarterKitException('Cannot export [composer.json]. Please use `dependencies` array!'); | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Ensure export paths exist. | ||
* | ||
* @throws StarterKitException | ||
*/ | ||
protected function ensureExportablePathsExist(): self | ||
{ | ||
$this | ||
->exportPaths() | ||
->merge($this->exportAsPaths()->keys()) | ||
->reject(fn ($path) => $this->files->exists(base_path($path))) | ||
->each(function ($path) { | ||
throw new StarterKitException("Cannot export [{$path}], because it does not exist in your app!"); | ||
}); | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Ensure export dependencies exist in app's composer.json. | ||
* | ||
* @throws StarterKitException | ||
*/ | ||
protected function ensureExportableDependenciesExist(): self | ||
{ | ||
$installedDependencies = collect(json_decode($this->files->get(base_path('composer.json')), true)) | ||
->only(['require', 'require-dev']) | ||
->map(fn ($dependencies) => array_keys($dependencies)) | ||
->flatten(); | ||
|
||
$this | ||
->exportableDependencies() | ||
->reject(fn ($dependency) => $installedDependencies->contains($dependency)) | ||
->each(function ($dependency) { | ||
throw new StarterKitException("Cannot export [{$dependency}], because it does not exist in your composer.json!"); | ||
}); | ||
|
||
return $this; | ||
} | ||
} |
Oops, something went wrong.