API Support public-files

This commit is contained in:
Damian Mooyman 2017-12-19 14:03:21 +13:00
parent e5beb23338
commit a959a68e54
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.
- `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.
- `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:
@ -151,9 +154,31 @@ An example recipe:
"project-files": [
"mysite/_config/*.yml",
"mysite/code/MyBlogPage.php"
"client/src/*"
],
"public-files": [
"client/dist/*"
]
},
"prefer-stable": true,
"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": {
"class": "SilverStripe\\RecipePlugin\\RecipePlugin"
"class": "SilverStripe\\RecipePlugin\\RecipePlugin",
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"require": {
"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 $destinationRoot Base of destination directory (no trailing slash)
* @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
$composerFile = new JsonFile(Factory::getComposerFile(), null, $this->io);
$composerData = $composerFile->read();
$installedFiles = isset($composerData['extra'][RecipePlugin::PROJECT_FILES_INSTALLED])
? $composerData['extra'][RecipePlugin::PROJECT_FILES_INSTALLED]
$installedFiles = isset($composerData['extra'][$registrationKey])
? $composerData['extra'][$registrationKey]
: [];
// Load all project files
@ -46,7 +48,7 @@ class RecipeInstaller extends LibraryInstaller {
// Write header
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;
}
@ -85,7 +87,7 @@ class RecipeInstaller extends LibraryInstaller {
if (!isset($composerData['extra'])) {
$composerData['extra'] = [];
}
$composerData['extra'][RecipePlugin::PROJECT_FILES_INSTALLED] = $installedFiles;
$composerData['extra'][$registrationKey] = $installedFiles;
$composerFile->write($composerData);
}
}
@ -143,18 +145,41 @@ class RecipeInstaller extends LibraryInstaller {
return;
}
// Find recipe base dir
$recipePath = $this->getInstallPath($package);
// 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
$name = $package->getName();
$extra = $package->getExtra();
// Install project-files
if (isset($extra[RecipePlugin::PROJECT_FILES])) {
$this->installProjectFiles(
$name,
$this->getInstallPath($package),
$destinationPath,
$extra[RecipePlugin::PROJECT_FILES]
$recipePath,
$projectPath,
$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';
/**
* '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
*/
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
*/
@ -81,8 +96,11 @@ class RecipePlugin implements PluginInterface, EventSubscriberInterface, Capable
$file = new JsonFile(Factory::getComposerFile());
$data = $file->read();
// Remove project-files from project, and any empty extra
unset($data['extra']['project-files']);
// Remove project and public files from project
unset($data['extra'][self::PROJECT_FILES]);
unset($data['extra'][self::PUBLIC_FILES]);
// Remove redundant empty extra
if (empty($data['extra'])) {
unset($data['extra']);
}