Skip to content

Instantly share code, notes, and snippets.

@dstollie
Created October 12, 2015 23:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dstollie/6ebd46721d31ed009314 to your computer and use it in GitHub Desktop.
Save dstollie/6ebd46721d31ed009314 to your computer and use it in GitHub Desktop.
Example of adding Twig support to the composer-dist-installer package
<?php
/*----------------------------------------------------*/
// Local environment vars
/*----------------------------------------------------*/
{% set db_name = '{!Database name?[]?|wordpress!}' %}
{% set db_user = '{!Database user []?|=ENV[USER]!}' %}
{% set db_password = '{!Database password?!}' %}
{% set db_host = '{!Database host []?|localhost!}' %}
{% set db_home = '{!Wordpress home url []?|http://mysite.dev/!}' %}
{% set db_siteurl = '{!Wordpress site url []?|http://mysite.dev/cms/!}' %}
return array(
'DB_NAME' => '{{ db_name }}',
'DB_USER' => '{{ db_user }}',
'DB_PASSWORD' => '{{ db_password }}',
'DB_HOST' => '{{ db_host }}',
'WP_HOME' => '{{ db_home }}',
'WP_SITEURL' => '{{ db_siteurl }}',
);
"dist-installer-params": [
{
"type": "Cube\\ComposerDistInstaller\\Processor\\TwigProcessor",
"file": ".env.local.php"
}
}
<?php
/**
* Copyright (c) 2015 Cu.be Solutions
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Cube\ComposerDistInstaller\Processor;
use Composer\IO\IOInterface;
use Twig_Environment;
use Twig_Loader_Array;
/**
* The Twig processor
*
* @package Cube\ComposerDistInstaller
*/
class TwigProcessor implements ProcessorInterface
{
protected $io;
protected $config;
public function __construct(IOInterface $io)
{
$this->setIO($io);
}
public function process(array $config)
{
$this->setConfig($config);
$config = $this->getConfig();
$realFile = $config['file'];
$exists = is_file($realFile);
$action = $exists ? 'Rewriting' : 'Creating';
if ($exists) {
if ($this->getIO()->askConfirmation('Destination file "' . $realFile .'" already exists, overwrite (y/n)? ')) {
$this->getIO()->write(sprintf('<info>%s the "%s" file</info>', $action, $realFile));
$oldFile = $realFile . '.old';
copy($realFile, $oldFile);
$this->getIO()->write(sprintf('A copy of the old configuration file was saved to %s', $oldFile));
} else {
return false;
}
} else {
if (!is_dir($dir = dirname($realFile))) {
mkdir($dir, 0755, true);
}
}
$template = file_get_contents($config['dist-file']);
$templateContents = preg_replace_callback('/\{\!(.*)\!\}/', array($this, '_templateReplace'), $template);
$twig = new Twig_Environment(new Twig_Loader_Array([]));
$template = $twig->createTemplate($templateContents);
$renderedContents = $template->render([]);
print_r($renderedContents);
file_put_contents($realFile, $renderedContents);
return true;
}
/**
* @return IOInterface
*/
public function getIO()
{
return $this->io;
}
/**
* @param IOInterface $io
*/
public function setIO(IOInterface $io)
{
$this->io = $io;
}
/**
* @return mixed
*/
public function getConfig()
{
return $this->config;
}
/**
* @param mixed $config
*/
public function setConfig($config)
{
if (empty($config['file'])) {
throw new \InvalidArgumentException('The extra.dist-installer-params.file setting is required.');
}
if (empty($config['dist-file'])) {
$config['dist-file'] = $config['file'].'.dist';
}
if (!is_file($config['dist-file'])) {
throw new \InvalidArgumentException(sprintf('The dist file "%s" does not exist. Check your dist-file config or create it.', $config['dist-file']));
}
$this->config = $config;
}
/**
* @return array
*/
protected function _getEnvValue($variable)
{
if (isset($this->config['env-map'])) {
$envMap = $this->config['env-map'];
if (isset($envMap[$variable])) {
$variable = $envMap[$variable];
}
}
return getenv($variable);
}
/**
* @param array $matches
* @return string
*/
protected function _templateReplace(array $matches)
{
$result = $matches[0];
if (count($matches) > 1) {
$explode = explode('|', $matches[1]);
$question = $explode[0];
$index = 0;
do {
$default = @$explode[++$index] ?: null;
// if default syntax is =ENV[VARIABLE_NAME] then extract VARIABLE_NAME from the environment as default value
if (strpos($default, '=ENV[') === 0) {
$envMatch = [];
preg_match('/^\=ENV\[(.*)\]$/', $default, $envMatch);
if (isset($envMatch[1])) {
$default = $this->_getEnvValue($envMatch[1]);
}
}
} while( empty($default) && $index < count($explode) );
$question = str_replace('[]', "[$default]", $question);
$result = $this->getIO()->ask(rtrim($question) . ' ', $default);
}
return $result;
}
}
@gsomoza
Copy link

gsomoza commented Oct 13, 2015

This looks great! Haven't tested it though, I'll do that with the PR.

One question: instead of _templateReplace: can we inject environment variables into a variable called something like installer.env or maybe just env?

I think you can do that in the ->render([]) call using $_ENV. Something like that would allow for a 100% Twig-only processor, which would be cleaner IMO.

@dstollie
Copy link
Author

Oh wow, thats a good idea.

Using https://github.com/Incenteev/ParameterHandler first for generating the installer.env file using your console and then using installer.env for populating the twig templates.

We could also make two twig flavours: one which uses the themplateReplace and one which I just described.

What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment