Merge pull request #4 from open-sausages/pulls/1/throwing-a-public

API Support `public-files`
This commit is contained in:
Aaron Carlino 2018-01-12 14:33:30 +13:00 committed by GitHub
commit 3e16a5b138
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 12 deletions

View File

@ -133,6 +133,9 @@ Recipe types should follow the following rules:
- The `require` must have `silverstripe/recipe-plugin` as a dependency. - The `require` must have `silverstripe/recipe-plugin` as a dependency.
- `extra.project-files` must be declared as a list of wildcard patterns, matching the files in the recipe root - `extra.project-files` must be declared as a list of wildcard patterns, matching the files in the recipe root
as they should be copied to the root project. The relative paths of these resources are equivalent. as they should be copied to the root project. The relative paths of these resources are equivalent.
- `extra.public-files` must be declared for any files which should be copied to the `public` web folder. If the project
in question doesn't have any public folder, these will be copied to root instead. Note that all public files
must be committed to the recipe `public` folder.
An example recipe: An example recipe:
@ -151,9 +154,31 @@ An example recipe:
"project-files": [ "project-files": [
"mysite/_config/*.yml", "mysite/_config/*.yml",
"mysite/code/MyBlogPage.php" "mysite/code/MyBlogPage.php"
"client/src/*"
],
"public-files": [
"client/dist/*"
] ]
}, },
"prefer-stable": true, "prefer-stable": true,
"minimum-stability": "dev" "minimum-stability": "dev"
} }
``` ```
The files within this recipe would be organised in the structure:
```
client/
src/
blog.scss
mysite/
_config/
settings.yml
code/
MyBlogPage.php
public/
client/
dist/
blog.css
composer.json
```

View File

@ -15,7 +15,10 @@
} }
}, },
"extra": { "extra": {
"class": "SilverStripe\\RecipePlugin\\RecipePlugin" "class": "SilverStripe\\RecipePlugin\\RecipePlugin",
"branch-alias": {
"dev-master": "1.x-dev"
}
}, },
"require": { "require": {
"composer-plugin-api": "^1.1" "composer-plugin-api": "^1.1"

View File

@ -27,14 +27,16 @@ class RecipeInstaller extends LibraryInstaller {
* @param string $sourceRoot Base of source files (no trailing slash) * @param string $sourceRoot Base of source files (no trailing slash)
* @param string $destinationRoot Base of destination directory (no trailing slash) * @param string $destinationRoot Base of destination directory (no trailing slash)
* @param array $filePatterns List of file patterns in wildcard format (e.g. `code/My*.php`) * @param array $filePatterns List of file patterns in wildcard format (e.g. `code/My*.php`)
* @param string $registrationKey Registration key for installed files
* @param string $name Name of project file type being installed
*/ */
protected function installProjectFiles($recipe, $sourceRoot, $destinationRoot, $filePatterns) protected function installProjectFiles($recipe, $sourceRoot, $destinationRoot, $filePatterns, $registrationKey, $name = 'project')
{ {
// load composer json data // load composer json data
$composerFile = new JsonFile(Factory::getComposerFile(), null, $this->io); $composerFile = new JsonFile(Factory::getComposerFile(), null, $this->io);
$composerData = $composerFile->read(); $composerData = $composerFile->read();
$installedFiles = isset($composerData['extra'][RecipePlugin::PROJECT_FILES_INSTALLED]) $installedFiles = isset($composerData['extra'][$registrationKey])
? $composerData['extra'][RecipePlugin::PROJECT_FILES_INSTALLED] ? $composerData['extra'][$registrationKey]
: []; : [];
// Load all project files // Load all project files
@ -46,7 +48,7 @@ class RecipeInstaller extends LibraryInstaller {
// Write header // Write header
if (!$any) { if (!$any) {
$this->io->write("Installing project files for recipe <info>{$recipe}</info>:"); $this->io->write("Installing {$name} files for recipe <info>{$recipe}</info>:");
$any = true; $any = true;
} }
@ -85,7 +87,7 @@ class RecipeInstaller extends LibraryInstaller {
if (!isset($composerData['extra'])) { if (!isset($composerData['extra'])) {
$composerData['extra'] = []; $composerData['extra'] = [];
} }
$composerData['extra'][RecipePlugin::PROJECT_FILES_INSTALLED] = $installedFiles; $composerData['extra'][$registrationKey] = $installedFiles;
$composerFile->write($composerData); $composerFile->write($composerData);
} }
} }
@ -143,18 +145,41 @@ class RecipeInstaller extends LibraryInstaller {
return; return;
} }
// Find recipe base dir
$recipePath = $this->getInstallPath($package);
// Find project path // Find project path
$destinationPath = dirname(realpath(Factory::getComposerFile())); $projectPath = dirname(realpath(Factory::getComposerFile()));
// Find public path
$candidatePublicPath = $projectPath . DIRECTORY_SEPARATOR . RecipePlugin::PUBLIC_PATH;
$publicPath = is_dir($candidatePublicPath) ? $candidatePublicPath : $projectPath;
// Copy project files to root // Copy project files to root
$name = $package->getName(); $name = $package->getName();
$extra = $package->getExtra(); $extra = $package->getExtra();
// Install project-files
if (isset($extra[RecipePlugin::PROJECT_FILES])) { if (isset($extra[RecipePlugin::PROJECT_FILES])) {
$this->installProjectFiles( $this->installProjectFiles(
$name, $name,
$this->getInstallPath($package), $recipePath,
$destinationPath, $projectPath,
$extra[RecipePlugin::PROJECT_FILES] $extra[RecipePlugin::PROJECT_FILES],
RecipePlugin::PROJECT_FILES_INSTALLED,
'project'
);
}
// Install public-files
if (isset($extra[RecipePlugin::PUBLIC_FILES])) {
$this->installProjectFiles(
$name,
$recipePath . '/' . RecipePlugin::PUBLIC_PATH,
$publicPath,
$extra[RecipePlugin::PUBLIC_FILES],
RecipePlugin::PUBLIC_FILES_INSTALLED,
'public'
); );
} }
} }

View File

@ -34,11 +34,26 @@ class RecipePlugin implements PluginInterface, EventSubscriberInterface, Capable
*/ */
const PROJECT_FILES = 'project-files'; const PROJECT_FILES = 'project-files';
/**
* 'extra' key for public files
*/
const PUBLIC_FILES = 'public-files';
/**
* Hard-coded 'public' web-root folder
*/
const PUBLIC_PATH = 'public';
/** /**
* 'extra' key for list of project files installed * 'extra' key for list of project files installed
*/ */
const PROJECT_FILES_INSTALLED = 'project-files-installed'; const PROJECT_FILES_INSTALLED = 'project-files-installed';
/**
* 'extra' key for list of public files installed
*/
const PUBLIC_FILES_INSTALLED = 'public-files-installed';
/** /**
* 'extra' key for project dependencies installed * 'extra' key for project dependencies installed
*/ */
@ -81,8 +96,11 @@ class RecipePlugin implements PluginInterface, EventSubscriberInterface, Capable
$file = new JsonFile(Factory::getComposerFile()); $file = new JsonFile(Factory::getComposerFile());
$data = $file->read(); $data = $file->read();
// Remove project-files from project, and any empty extra // Remove project and public files from project
unset($data['extra']['project-files']); unset($data['extra'][self::PROJECT_FILES]);
unset($data['extra'][self::PUBLIC_FILES]);
// Remove redundant empty extra
if (empty($data['extra'])) { if (empty($data['extra'])) {
unset($data['extra']); unset($data['extra']);
} }