lexide / pro-forma
A library for managing and installing templated files for auto-generated code
Installs: 327
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 2
Forks: 0
Open Issues: 0
Type:composer-plugin
Requires
- php: >=8.0
- composer-plugin-api: ^2.0
- lexide/puzzle-di: ~3.0.2
Requires (Dev)
- composer/composer: ^2.0
- mikey179/vfsstream: ^1.6.0
- mockery/mockery: ^1.6.0
- phpunit/phpunit: ^9.6.0
This package is auto-updated.
Last update: 2024-12-01 00:09:56 UTC
README
This library allows other libraries to configure templates for auto-generated code, allowing for quick bootstrapping of projects, using a composer plugin.
Once the Pro Forma plugin is enabled, the templating process is seamless from an end-user perspective, so installing a library that is configured with Pro Forma templates will automatically generate those files if they don't already exist.
Project installation
To use Pro Forma in a project, enable the plugin in the composer.json
file and allow PuzzleDI to use the library
containing the code templates:
{ "config": { "allow-plugins": { "lexide/pro-forma": true, "lexide/puzzle-di": true } }, "extra": { "lexide/puzzle-di": { "whitelist": { "lexide/pro-forma": [ "target/library" ] } } } }
Running install
or update
Composer commands will invoke Pro Forma code generation.
Composer may also ask if the Pro Forma plugin should be enabled, if it is not already.
It is recommended that the auto-generated files be added to version control, however this is not required.
IMPORTANT! Only whitelisted libraries will have their templates generated. This includes any other libraries that whitelisted libraries have added to the whitelist trust chain. This is intended to prevent unintentional code generation when adding a new library to a project. If Pro Forma does not generate the expected files, it is advised to check that the library is correctly whitelisted.
Template Providers
Pro Forma works by having libraries register template providers with it, using lexide/puzzle-di
, then processing the template config provided
by those classes to convert template files into generated code.
Pro Forma uses lexide/puzzle-di
to collect a list of TemplateProviderInterface
class names.
Composer configuration
Each library can register a single template provider, that implements the
Lexide\ProForm\Template\TemplateProviderInterface
interface, by adding the following configuration to the library's
composer.json
file:
{ "extra": { "lexide/puzzle-di": { "files": { "lexide/pro-forma": { "class": "Fully\\Qualified\\Template\\Provider\\Class\\Name" } } } } }
If this library uses dependencies that should also use Pro Forma to auto-generate code, those dependent libraries can be
added to the whitelist chain for PuzzleDI in this library's composer.json
file, much the same as when
configuring a project:
{ "extra": { "lexide/puzzle-di": { "whitelist": { "lexide/pro-forma": [ "dependent/library" ] } } } }
Templates
The purpose of a template provider is to return an array of instances of the Lexide\ProForm\Template\Template
class.
These instances need to contain all the information required to template the generated code.
In order to customise which templated files are returned, the providers are passed two config objects; a
Lexide\ProForm\Template\ProviderConfig\ProjectConfig
instance, which contains the project name, namespace and a list of
installed packages, and a Lexide\ProForm\Template\ProviderConfig\LibraryConfig
instance, which contains configuration
for the current provider, taken from the project's composer.json
. This allows the providers to make decisions such as
adding a particular template if a package is installed or setting the value of a replacement based on project config
options, for example.
The values contained in the LibraryConfig
instance for a provider is defined only for its library and is configured as
follows:
{ "extra": { "lexide/pro-forma": { "config": { "target/library": { "foo": "bar" } } } } }
In this example, the LibraryConfig
instance would contain the value bar
under the key foo
.
$value = $libraryConfig->getValue("foo"); // value is set to 'bar'
TemplateProvider Messages
TemplateProviders have the ability to pass messages back to Pro Forma, in order to relay information to the user. This is useful when a provider has made a decision based on installed packages or config that ths user need to be informed about, such as skipping templates if a package is not installed or notifying about invalid configuration.
The TemplateProvider is responsible for implementing the getMessages()
method, which should return an array of strings
representing the messages that need to be displayed. If a provider doesn't supply any messages, an empty array should be
returned.
Template class
The template class, Lexide\ProForma\Template\Template
, has four properties:
- name - the name of the template.
- templatePath - the path, relative to the library root, of the template file to process.
- outputPath - the path, relative to the project root, of the file to be generated.
- replacements - an array of key/value pairs to substitute into the template.
These properties can be set via setters on a manually created template instance, or via the factory method:
Lexide\ProForma\Template\TemplateFactory::create()
.
Replacements
Template files can contain placeholder values that will be substituted when the output file is generated. The substitutions array is determined by the template providers and is custom per template. Pro Forma doesn't know beforehand which placeholder values exist for a template, it will blindly attempt to replace them based on the key that the provider supplies, therefore if placeholders are used, there must always be a replacement added to the template instance for each one.
Placeholder keys are wrapped in double curly braces, {{ key }}
; spaces inside the braces are optional. When defining
the replacements, only use the key name, no braces are required:
$template->setReplacements(["key" => "value"]);
IMPORTANT! For consistency, replacement values must always be strings; any value that is not a string will be ignored, and a message will be outputted describing the value as invalid. This includes values that are "stringable" or that PHP would naturally convert to a string.
Regenerating files
On occasion, it may be necessary to regenerate files if a library has had an update that changes a template's behaviour.
In order to do this, temporarily add the following value to the lexide/pro-forma
section in extra
:
{ "extra": { "lexide/pro-forma": { "overwrite": true } } }
Please note that Pro Forma will continue to overwrite files while this value is set to true; it is not intended to be used permanently, to avoid unexpected changes in behaviour after a composer update or install.
Also, this setting tells Pro Forma to overwrite all files, so any customisations that aren't in version control will be removed.
Finally, Pro Forma will never delete files; if a library is uninstalled, it's auto-generated code will need deleting manually.