scaffold documentation - read the docs · the *.scaffold.phpfile is the configuration file (a...
TRANSCRIPT
Contents
1 Contents 31.1 How to Install . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2 Install Scaffolds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.3 Create Scaffolds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.4 Release Notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191.5 Indices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
i
Scaffold Documentation, Release 1.1
How many times have you been doing the same task, over and over again? Maybe it’s time for you to create somekind of helper that can perform that task for you. Perhaps this tool might be able to help you along the way.
Scaffold is a php-based command line tool for creating and installing various files and directories into your project,based on a configuration file (scaffold).
Key features
• Create desired directory structure
• Copy static files into desired location
• Ask user for input
• Generate files based on templates, compiled with data from the user
In other words, you can perceive this tool as a console wizzard for installing “something” inside your project.
Source is available on GitHub.
Contents 1
CHAPTER 1
Contents
The basics
How to Install
Requirements
• php version > 5.6.4
• composer
This package uses composer. If you do not know what that is or how it works, I recommend that you read a littleabout, before attempting to use this package.
Other than this, you scaffold application requires read / write access to the directories where you use it. Normally thisisn’t a problem. However if you run into these kinds of issues, please review your PHP’s access privileges.
Local Installation
The Scaffold application is intended as a development tool, which is why it should be required via composer as adevelopment dependency.
composer require aedart/scaffold --dev
Global Installation
A global installation allows you to use the scaffold application everywhere.
composer global require aedart/scaffold
3
Scaffold Documentation, Release 1.1
Warning: If you have other packages installed globally, their dependencies might conflict.
You can perhaps resolves this by making use of Consolidation/Cgr, which safely installs each command line toolapplication in it’s own directory.
How to use scaffolds
Install Scaffolds
Require Scaffold
Regardless if you are within a new project or existing, you must first require your desired scaffold(s). This is done viacomposer’s require command or by specifying it in your composer.json.
composer require acme/scaffolds
{"name": "acme/my-project","description": "My Proejct","license": "BSD-3-Clause","type": "library","require": {
"acme/scaffolds": "~1.0"},
}
Global Scaffolds
If you have chosen to require your scaffold(s) globally, then they should already be available and there is no need foryou to perform this.
Install Scaffold
Install Command
The easiest way to install a your desired scaffold, is by invoking the install command
vendor/bin/scaffold install
This command will automatically create an index of all the found scaffolds and start displaying a list of vendors,packages and scaffolds you can chose to install. It should output something similar to this;
Building index==============
! [NOTE] Building new index (.scaffold/index.json)
Searching in /home/Code/my-project/vendor
! [NOTE] Indexing /home/Code/my-project/vendor/acme/scaffolds/my-scaffold.scaffold.→˓php
4 Chapter 1. Contents
Scaffold Documentation, Release 1.1
Searching in /home/.composer/vendor
! [NOTE] No scaffolds found in /home/.composer/vendor
[OK] Indexing completed
Install...==========
Please select a vendor:[0] acme>
Tip: The install command supports several options. See command help for additional information.
vendor/bin/scaffold install -h
Build Command
If you wish to skip the install procedure (listing of vendors, packages ... etc), then you can use the build commandto specify your desired scaffold directly.
vendor/bin/scaffold build other/location/my-scaffold.scaffold.php
Build From File Command
Sometimes it can be useful to automate the building process. For instance, if you want to build several scaffolds atonce, then you can use the build:file command.
vendor/bin/scaffold build:file location/scaffoldsToBuild.php
The command accepts a single argument, file, which is a location to a php file that contains a list of scaffolds to bebuilt.
In other words, this command allows you to build multiple scaffolds in one and the same process.
File Format
The following illustrates the format that the build:file command accepts.
<?php
return [[
// Location to scaffold'location' => __DIR__ . '/MyModel.scaffold.php',
// Input (answers to questions) for that scaffold'input' => [
1.2. Install Scaffolds 5
Scaffold Documentation, Release 1.1
'AEDART/a']
],[
'location' => __DIR__ . '/MyController.scaffold.php','input' => [
'Acme/b']
],[
'location' => __DIR__ . '/MyView.scaffold.php','input' => [
'Punk/c']
],];
Output Location
By default, bot the install and the build commands will output the resulting files and directories into the currentworking directory, form where you invoked the command. This behaviour can be modified by providing the commandswith an optional output directory
vendor/bin/scaffold install -o path/where/to/install/
vendor/bin/scaffold build -o path/where/to/install/ other/location/my-scaffold.→˓scaffold.php
Create your own
Create Scaffolds
Location
The first thing you need to consider is, where to place your scaffold files.
Regardless of your choice, I recommend that you use a version control system !
Note: Make sure that the scaffold application is available a development dependency.
See How to Install
New Project
The “safest” options is to create a new repository in which you only have to deal with the scaffold and it’s resources.Doing so allows you to focus mainly on the structure of the scaffold and there is little risk for you to interfere withexisting files.
6 Chapter 1. Contents
Scaffold Documentation, Release 1.1
Tip: If you are new to using this application, then I recommend that you start off by creating scaffolds in a separateproject.
Existing Project
Alternatively, you can also create scaffolds directly into existing projects. This does have the benefit of having a tightcoupling between your project and associated scaffolds. However, be sure of what you are doing, as it is the nature ofthis application to write files!
Location of (*).scaffold.php
The *.scaffold.php file is covered in the upcoming chapters. For now, you just need to ensure that it is locatedin the project’s root directory, at the same level as your composer.json.
The reason why the scaffold configuration file (*.scaffold.php) needs to be located here, is due to the indexingperformed by the application. By default, it will search for scaffolds inside the local vendor directory, searching eachpackage’s root directory only!
Blank Scaffold
To create a blank scaffold, execute the following command;
vendor/bin/scaffold install -a
Select the Blank Scaffold (aedart/scaffold) scaffold to be installed and follow the onscreen guide.
Once completed, you should have a new empty *.scaffold.php file and a resources directory.
(*).scaffold.php
The *.scaffold.php file is the configuration file (a php array) that the scaffold application will read and executeupon installation. In short, it determines what will happen when an end-user installs it.
<?phpreturn [
'name' => 'My Scaffold',
'description' => 'Creates cool stuff',
'basePath' => __DIR__ . '/resources/',
'tasks' => [],
'folders' => [],
'files' => [],
'templateData' => [],
'templates' => [],
1.3. Create Scaffolds 7
Scaffold Documentation, Release 1.1
'scripts' => [],
'handlers' => [],];
In the following sections, each of the above properties is covered in detail.
Name
required yes
Name of the Scaffold.
The name is displayed in the list of available templates, when the install command is invoked.
<?phpreturn [
'name' => 'My Scaffold',
];
Description
required yes
Description of the scaffold.
The description is displayed in the list of available templates, when the install command is invoked.
<?phpreturn [
'description' => 'Creates a few things...',
];
BasePath
required yes
Location of scaffold’s resources, e.g. static files and templates.
This path tells the scaffold where it can find it’s resource, from which it can build and install one or several folders,files and or templates.
<?phpreturn [
'basePath' => __DIR__ . '/resources/',
];
8 Chapter 1. Contents
Scaffold Documentation, Release 1.1
Tasks
required yes
An ordered list of all the tasks that must be executed. These tasks are responsible for building your project or resource.
By default, several tasks are included in a blank scaffold. You can change these are you see fit, but keep in mind thatthe order does matter.
<?phpreturn [
'tasks' => [\Aedart\Scaffold\Tasks\AskForTemplateData::class,\Aedart\Scaffold\Tasks\AskForTemplateDestination::class,\Aedart\Scaffold\Tasks\CreateDirectories::class,\Aedart\Scaffold\Tasks\CopyFiles::class,\Aedart\Scaffold\Tasks\GenerateFilesFromTemplates::class,
],
];
Note: You can remove all of the default tasks and replace them with your own.
When creating custom tasks, just ensure that you implement the \Aedart\Scaffold\Contracts\Tasks\ConsoleTaskinterface.
You can also just extend the \Aedart\Scaffold\Tasks\BaseTask abstract task, which does some of theground work for you.
Please review the documentation inside the source code for further information.
Folders
required only if \Aedart\Scaffold\Tasks\CreateDirectories::class is used
List of directories (or folders) that will be created.
<?phpreturn [
'folders' => ['app','config','src' => [
'Contracts','Controllers','Events','Models',
],'tmp'
],
];
1.3. Create Scaffolds 9
Scaffold Documentation, Release 1.1
Files
required only if \Aedart\Scaffold\Tasks\CopyFiles::class is used
Copies files from basePath and into the output directory.
See BasePath
<?phpreturn [
'files' => [// Source files (inside 'basePath') => Destination'.gitkeep' => '.gitkeep','logs/default.log' => 'tmp/log.log','docs/LICENSE.txt' => 'LICENSE',
],
];
Warning: You should avoid large files. If your template requires such, then you should perhaps consider a customtask that can download them from an external source!
Alternatively, you can use scripts to perform large file downloads. Just remember to specify a timeout.
See Scripts
TemplateData
required only if the following tasks are useda \Aedart\Scaffold\Tasks\AskForTemplateData::class,b \Aedart\Scaffold\Tasks\AskForTemplateDestination::class,c \Aedart\Scaffold\Tasks\GenerateFilesFromTemplates::class
Data to be used inside Twig templates. Depending upon the template-data’s type, the end-user might be asked in theconsole for an answer.
You can specify as many template data entries as you wish.
<?phpreturn [
'templateData' => [
'myProperty' => ['value' => 'My property value'
],],
];
10 Chapter 1. Contents
Scaffold Documentation, Release 1.1
Syntax
<?phpreturn [
'templateData' => ['name-of-property' => [
'type' =>→˓\Aedart\Scaffold\Contracts\Templates\Data\Type::QUESTION
'question' => 'The question to ask the user''value' => (default value, in case user just hits enter),'validation' => function($answer){return $answer;},'postProcess' => function($answer, array $previousAnswers){return
→˓$answer;},],
]];
The postProcess callback method is automatically provided with eventual previous values. This gives you thepossibility creating computed values that combine previous given answers from the end-user. The postProcess isavailable for all supported types.
In the following sections, an example is shown on each supported type.
Question
<?phpreturn [
'templateData' => [
'myQuestion' => [
'type' =>→˓\Aedart\Scaffold\Contracts\Templates\Data\Type::QUESTION,
'question' => 'What is your vendor name? (used as namespace prefix)',
'value' => 'Acme',
'validation' => function($answer){if(strlen($answer) >= 3){
return $answer;}
throw new \RuntimeException('Vendor name should be at least 3 chars→˓long');
},
'postProcess' => function($answer, array $previousAnswers){return ucfirst($answer);
}],
],];
1.3. Create Scaffolds 11
Scaffold Documentation, Release 1.1
Choice
<?phpreturn [
'templateData' => [
'myChoice' => [
'type' => \Aedart\Scaffold\Contracts\Templates\Data\Type::CHOICE,
'question' => 'In what sub-namespace should your class be located?',
'choices' => ['Controllers','Events','Models'
],
'value' => 'Controllers',],
],];
Confirm
<?phpreturn [
'templateData' => [
'myConfirm' => [
'type' =>→˓\Aedart\Scaffold\Contracts\Templates\Data\Type::CONFIRM,
'question' => 'Add class PHPDoc?',
'value' => true,],
],];
Hidden
<?phpreturn [
'templateData' => [
'myPassword' => [
'type' => \Aedart\Scaffold\Contracts\Templates\Data\Type::HIDDEN,
'question' => 'What password should be stored inside the .env?',
12 Chapter 1. Contents
Scaffold Documentation, Release 1.1
'validation' => function($answer){if(strlen($answer) >= 6){
return $answer;}
throw new \RuntimeException('The password should be at least 6→˓characters long');
},],
],];
Value
When using a simple value, the end-user is not prompted with any questions. Also, the type does not have to bedeclared explicitly.
<?phpreturn [
'templateData' => [
'myValue' => ['value' => 'My Value'
],],
];
It is also possible to perform post-processing of simple values. It can be used to create a computed value which consistsof the given value and perhaps a previously given value.
<?phpreturn [
'templateData' => [
'myValue' => ['value' => 'My Value','postProcess' => function($answer, array $previousAnswers){
return $answer . $previousAnswers['myOtherValue'];}
],],
];
Templates
required only if the following tasks are useda \Aedart\Scaffold\Tasks\AskForTemplateData::class,b \Aedart\Scaffold\Tasks\AskForTemplateDestination::class,c \Aedart\Scaffold\Tasks\GenerateFilesFromTemplates::class
The snippets (or templates) from which one or several files must be generated from.
Each defined template assumes that it’s source Twig template is located inside the basePath.
See BasePath
1.3. Create Scaffolds 13
Scaffold Documentation, Release 1.1
<?phpreturn [
'templates' => ['myTemplate' => [
'source' => 'snippets/env.twig',
'destination' => [
'value' => '.env',],
],],
];
Ask for template destination
The destination property works in the same way as with the templateData, in that you can use it to ask theend user for a file destination. All types are supported.
See TemplateData.
<?phpreturn [
'templates' => ['myTemplate' => [
'source' => 'snippets/markdown.twig',
// Destination of a file - uses a "question" property'destination' => [
'type' =>→˓\Aedart\Scaffold\Contracts\Templates\Data\Type::QUESTION,
'question' => 'Name / location of file? (.md automatically added)→˓',
'value' => 'WIKI',
// Use post processing to add file extension'postProcess' => function($answer, array $previousAnswers){
return $answer . '.md';}
],],
],];
Scripts
required only if \Aedart\Scaffold\Tasks\ExecuteScripts::class is used
CLI scripts (or commands) to be executed
Scripts can be used to perform advanced operations. This could for instance be downloading large files, disk cleanup,running composer commands... etc.
14 Chapter 1. Contents
Scaffold Documentation, Release 1.1
Multiple scripts are allowed and they can be stated in several ways.
Simple Script
<?phpreturn [
'scripts' => ['composer update',
]];
Script with Timeout
If yor expect your script(s) to require more that 60 seconds, then consider specifying a custom timeout.
<?phpreturn [
'scripts' => [[
'timeout' => 75, // Default is 60 seconds'script' => 'composer install && composer update'
],]
];
Advanced Script
If you need to perform very advanced scripts that depends on the scaffold configuration, then you can achieve this viaan anonymous function.
A copy of the scaffold configuration is given as argument.
The function MUST return an instance of \Aedart\Scaffold\Contracts\Scripts\CliScript.
<?phpreturn [
'scripts' => [function(array $config){
$script = 'cd ' . $config['outputPath'] . ' && ls';
return new \Aedart\Scaffold\Scripts\CliScript(['timeout' => 10,'script' => $script
]);},
]];
Error when triggering composer commands
If you trigger some kind of composer script, then you might see that composer’s output is logger to the console asan error. This is due to that composer chooses to write diagnostic output to STDERR instead of STDOUT.
1.3. Create Scaffolds 15
Scaffold Documentation, Release 1.1
You can read more about this in #1905 and #3795 .
Handlers
required no
These handlers are used by some of the default tasks. They provide an additional level of flexibility, in which you canuse the default tasks, yet change the way that each of them handles certain operations.
If you do not plan to change the default tasks’ behaviour, then you can leave out this part of the configuration.
<?phpreturn [
'handlers' => ['directory' => \Aedart\Scaffold\Handlers\DirectoriesHandler::class,'file' => \Aedart\Scaffold\Handlers\FilesHandler::class,'property' => \Aedart\Scaffold\Handlers\PropertyHandler::class,'template' => \Aedart\Scaffold\Handlers\TwigTemplateHandler::class,'script' => \Aedart\Scaffold\Handlers\ScriptsHandler::class,
]];
Note: You can create your own handlers, if the default handlers are insufficient to cover your needs.
Handlers need to implement the \Aedart\Scaffold\Contracts\Handlers\Handler interface.
Alternatively, you can extend the \Aedart\Scaffold\Handlers\BaseHandler abstract handler. It shouldprovide you with a few common methods implementation.
Tip: Currently, only Twig templates are supported. If you do not like working with that engine,then you can implement a different one, by means of creating a new template handler (Please review\Aedart\Scaffold\Handlers\TwigTemplateHandler for inspiration).
If this is the case, please consider if making that handler publicly available for others :)
Testing
Depending on your scaffold complexity, the fastest way of testing it is manually, by building it locally.
vendor/bin/scaffold install -a -o temp/
The above command will first index your scaffold and thereafter install it. All of it’s output will go into the tempdirectory.
Automatic Testing
If your scaffold(s) have become very complex, require lots of user input or perhaps depend on many resources, thenperhaps it is better to write some kind of automatic test for, e.g. via PHPUnit .
The current version of the scaffold application does not offer any testing utilities. However, you can review thetests\integration\InstallCommandTest as inspiration on how to write automatic tests for your scaffold.
Behind the scenes, Symfony’s Command Tester is being used.
16 Chapter 1. Contents
Scaffold Documentation, Release 1.1
In future versions, this package might include better testing utilities.
Helpers
Since version 1.1.0 a helpers.php file is included, which offers a few utility methods that can be used throughoutyour scaffold.
The file is located in {{scaffold application location}}\helpers\helpers.php.
Cache
Available since version 1.1.0
Confronting an end-user with too many questions can quickly become a hassle for them. Therefore, if you find yourselfin a situation where you need a lot of user input, consider caching some of the input.
Caching is made available in a scaffold, by making use of the scaffold_cache_* methods, which are definedinside the helpers.php file.
Behind the Scene
The caching system that is offered by the Scaffold Application, is basically just a wrapper around Laravel’s Cache. It is configured to use the \Illuminate\Cache\FileStore, storing values withing the user provided cachedirectory.
The cache directory is set via a --cache option on each available command that makes use of caching. It defaults.scaffold/cache/ if the option is not provided.
Example
In this example, once a user has answered the question first time, the scaffold will use a cached answer as the defaultvalue. Next time the scaffold is built, the default value will become the cached value.
<?phpreturn [
'templateData' => [
'name' => [
'type' =>→˓\Aedart\Scaffold\Contracts\Templates\Data\Type::QUESTION,
'question' => 'What is your name?',
'value' => scaffold_cache_get('name', 'John Doe'),
'postProcess' => function($answer, array $previousAnswers){// Update the cached value, in case user provides a "new" answerscaffold_cache_put('name', $answer, 60);
return $answer;}
],
1.3. Create Scaffolds 17
Scaffold Documentation, Release 1.1
],];
Available Methods
Please consider Laravel’s documentation for further information and examples of using the cache.
scaffold_cache()
Returns an instance of \Illuminate\Contracts\Cache\Repository.
scaffold_cache_put($key, $value, $minutes = 5)
Store an item in the cache.
scaffold_cache_remember($key, $minutes, Closure $callback)
Get an item from the cache, or store the default value.
scaffold_cache_forever($key, $value)
Store an item in the cache indefinitely.
scaffold_cache_has($key)
Determine if an item exists in the cache.
scaffold_cache_get($key, $default = null)
Retrieve an item from the cache by key.
scaffold_cache_pull($key, $default = null)
Retrieve an item from the cache and delete it.
scaffold_cache_forget($key)
Remove an item from the cache.
scaffold_cache_flush()
Flushes the registered cache directory.
Misc
18 Chapter 1. Contents
Scaffold Documentation, Release 1.1
Release Notes
Within this chapter, you will find a list of the most significant changes.
Version 2.0.x
v2.0.1 (29-10-2017)
Fixed
• Incorrect populate of directories collection inside TwigTemplateHandler
v2.0.0 (15-10-2017)
Added
• Added “build:file” command
Changed
• Changed minimum required PHP version to 7.1.x
• Adapted application to use Laravel 5.5.x. Several interfaces and service providers have changed.
• Adapted application to use Symfony 3.3.x components.
• Deprecated AedartScaffoldTestingConsoleStyleExtendedStyle, replaced by AedartScaffoldConsoleStyleExtend-edStyle.
• Changed build command, now supports setting answers to questions via the input option.
Version 1.2.x
v1.2.0 (08-01-2017)
Changed
• License updated
Version 1.1.x
v1.1.5 (01-10-2016)
Fixed
• Re-fixed indexing order. First fix was correct, yet due to incorrect manual test, the “issue” didn’t seemed fixed.
1.4. Release Notes 19
Scaffold Documentation, Release 1.1
v1.1.4 (01-10-2016)
Fixed
• Re-fixed order of default indexing directories. First fix caused undesired indexing results.
v1.1.3 (01-10-2016)
Fixed
• Fixed order of default index directories.
v1.1.2 (22-09-2016)
Fixed
• Fixed #4 Parse error: syntax error, unexpected ‘->’ (T_OBJECT_OPERATOR) (issue in PHP 5.6.x only)
v1.1.1 (18-09-2016)
Fixed
• Fixed Fatal error: Can’t use function return value in write context (issue in PHP 5.6.x only)
v1.1.0 (18-09-2016)
Added
• Added Cache utility (#3).
• Added release notes documentation
• Added multiple smaller and more maintainable service providers
• Added documentation about why output from composer commands (in scripts) are logged to STDERR
Changed
• Changed ScaffoldServiceProvider, has now become an AggregateServiceProvider instead.It registers a series of smaller service providers.
Version 1.0.x
v1.0.4 (17-09-2016)
Fixed
• Fixed ScriptHandler logging of empty buffer
20 Chapter 1. Contents
Scaffold Documentation, Release 1.1
v1.0.3 (17-09-2016)
Fixed
• Fixed ScriptHandler dual logging of buffered output
v1.0.2 (17-09-2016)
Fixed
• Fixed console logging attempted converting array into string
v1.0.1 (17-09-2016)
Changed
• Changed required dependencies
Fixed
• Fixed property value being cast to string, which caused issue for other types of values, e.g. arrays
• Fixed unstable tests, due to poor generated sample data
v1.0.0 (11-09-2016)
• Release of first stable version
Indices
genindex
1.5. Indices 21
Index
BBasePath
scaffold.php, 8Blank
Empty Scaffold, 7Build
Command, Install, 4Build-File
File Command, 4
CCache, 17CLI, 14Command
Build-File File, 4Install Build, 4
Command TesterSymfony, 16
ComposerSTDERR, 14STDOUT, 14
DDescription
scaffold.php, 8
EEmpty
Scaffold, Blank, 7Scaffold, Location, 6
FFile
Command, Build-File, 4Files
scaffold.php, 9Folders
scaffold.php, 9
GGlobal
Installation, 3
HHandlers
scaffold.php, 16helpers, 17
IInstall
Build Command, 4Installation
Global, 3Local, 3
LLocal
Installation, 3Location
Empty Scaffold, 6Output, 4Scaffold, 6
NName
scaffold.php, 8New
Scaffold, 7
OOutput
Location, 4
PPHPUnit
UnitTest, 16
RRelease Notes, 18
23
Scaffold Documentation, Release 1.1
RequireScaffold, 4
Requirements, 3
SScaffold
Blank Empty, 7Location, 6Location Empty, 6New, 7Require, 4
scaffold.php, 6, 7BasePath, 8Description, 8Files, 9Folders, 9Handlers, 16Name, 8Scripts, 14Tasks, 8TemplateData, 10Templates, 13
Scriptsscaffold.php, 14
Single: Build, 4Single: Build-File, 4Single: Install, 4STDERR
Composer, 14STDOUT
Composer, 14Symfony
Command Tester, 16
TTasks
scaffold.php, 8TemplateData
scaffold.php, 10Templates
scaffold.php, 13Testing, 16
UUnitTest
PHPUnit, 16
24 Index