Newer
Older
<?php
namespace LakeDrops\Docker4Drupal;
use Composer\Composer;
use Composer\IO\IOInterface;
use LakeDrops\Component\Dotenv\Dotenv;
use LakeDrops\DockerTraefik\Traefik;

jurgenhaas
committed
use Symfony\Component\Yaml\Yaml;
/**
* Class Handler.
*
* @package LakeDrops\Docker4Drupal
*/
* @var \Composer\Composer
*/
protected $composer;
/**
* @var \Composer\IO\IOInterface
*/
protected $io;
/**
* The Drupal core package.
*
* @var \Composer\Package\PackageInterface
*/
protected $drupalCorePackage;
/**
* Handler constructor.
*
* @param \Composer\Composer $composer
* The composer object of this session.
* @param \Composer\IO\IOInterface $io
* The input-output object of the composer session.
*/
public function __construct(Composer $composer, IOInterface $io) {
$this->composer = $composer;
$this->io = $io;
}
/**
* @return \Composer\Package\PackageInterface
* The Drupal core package.
*/
protected function getDrupalCorePackage() {
if (!isset($this->drupalCorePackage)) {
$this->drupalCorePackage = $this->getPackage('drupal/core');
}
return $this->drupalCorePackage;
}
/**
* Retrieve a package from the current composer process.
*
* @param string $name
* Name of the package to get from the current composer installation.
*
* @return \Composer\Package\PackageInterface
* The package.
*/
protected function getPackage($name) {
return $this->composer->getRepositoryManager()->getLocalRepository()->findPackage($name, '*');
}
/**
* Configure Drupal Project for Docker.
*
* @param \Composer\Script\Event $event
* The event that triggered the call of this function.
* @param bool $overwrite
public function configureProject(Event $event, $overwrite = FALSE) {
if (!$event->isDevMode()) {
return;
}
$options = $this->getOptions();
$fs = new Filesystem();
$installationManager = $this->composer->getInstallationManager();
if (isset($options['webroot'])) {
if (!$fs->exists($options['webroot'])) {
return;
}
$webRoot = $options['webroot'];
}
else {
$drupalCorePackage = $this->getDrupalCorePackage();
if (!$drupalCorePackage) {
// We are called too early, Drupal core is not available yet.
return;
}
$corePath = $installationManager->getInstallPath($drupalCorePackage);
$webRoot = dirname($corePath);
$pluginRoot = $installationManager->getInstallPath($this->getPackage('lakedrops/docker4drupal'));

jurgenhaas
committed
// If the d8-project-scaffold plugin is present we only execute this one
// if $force is TRUE. This way we can make sure that we get executed after
// d8-project-scaffold.
$settingsPath = $webRoot . '/sites/default';
if ($this->getPackage('lakedrops/d8-project-scaffold')) {
if (!$fs->exists($projectRoot . '/settings/default')) {
return;
}
$settingsPath = 'settings/default';
}
// Check if SSH auth sockets are supported.
$ssh_auth_sock = getenv('SSH_AUTH_SOCK');
$options['php']['ssh'] = !empty($ssh_auth_sock);
$twig_loader = new \Twig_Loader_Array([]);
$twig = new \Twig_Environment($twig_loader);

jurgenhaas
committed
foreach ($this->getFiles($projectRoot, $webRoot, $settingsPath) as $template => $def) {
if (!$fs->exists($def['dest'])) {
$fs->mkdir($def['dest']);
}
$twig_loader->setTemplate($template, $template);
$filename = $twig->render($template, $options);
$file = $def['dest'] . '/' . $filename;
if ($overwrite || !$fs->exists($file)) {
$twig_loader->setTemplate($filename, file_get_contents($pluginRoot . '/templates/' . $template . '.twig'));
$rendered = $twig->render($filename, $options);
if (!empty($def['add2yaml']) && isset($options[$filename])) {
$yaml = Yaml::parse($rendered);
$yaml = array_merge_recursive($yaml, $options[$filename]);
$rendered = Yaml::dump($yaml, 9, 2);
}
if ($fs->exists($file)) {
if (md5_file($file) == md5($rendered)) {
continue;
}
$orig_file = $file . '.orig';
if ($fs->exists($orig_file)) {
$fs->remove($orig_file);
}
$fs->rename($file, $orig_file);
if (!$orig_ignored) {
$this->git('ignore *.orig');
$orig_ignored = TRUE;
}
}
else {
$this->git('ignore ' . $filename);

jurgenhaas
committed
if (isset($def['link']) && ($def['link'] != $settingsPath)) {
$link = $def['link'] . '/' . $filename;
if (!$fs->exists($link)) {
$rel = substr($fs->makePathRelative($file, $projectRoot . '/' . $link), 3, -1);
$fs->symlink($rel, $link);
}
}
$fs->chmod($file, 0664);
}
// Make sure that settings.docker.php gets called from settings.php.

jurgenhaas
committed
$settingsPhpFile = $settingsPath . '/settings.php';
if ($fs->exists(($settingsPhpFile))) {
$settingsPhp = file_get_contents($settingsPhpFile);
if (strpos($settingsPhp, 'settings.docker.php') === FALSE) {

jurgenhaas
committed
$settingsPhp .= "\n\nif (file_exists(__DIR__ . '/settings.docker.php')) {\n include __DIR__ . '/settings.docker.php';\n}\n";

jurgenhaas
committed
file_put_contents($settingsPhpFile, $settingsPhp);
}
$traefik = new Traefik($options['projectname']);
$traefik->update();
// Set permissions, see https://wodby.com/stacks/drupal/docs/local/permissions
exec('setfacl -dR -m u:$(whoami):rwX -m u:82:rwX -m u:100:rX' . $projectRoot);
exec('setfacl -R -m u:$(whoami):rwX -m u:82:rwX -m u:100:rX' . $projectRoot);
/**
* List of files and settings on how to handle them.
*
* @param string $projectRoot
* Name of the project's root directory.
* @param string $webRoot
* Name of the web's root directory.
* @param string $settingsPath
* Name of the settings directory.
*
* @return array
* List of files.
*/

jurgenhaas
committed
protected function getFiles($projectRoot, $webRoot, $settingsPath) {

jurgenhaas
committed
'dest' => $projectRoot . '/' . $settingsPath,
'add2yaml' => TRUE,

jurgenhaas
committed
'aliases.drushrc.php' => [
'dest' => $projectRoot . '/drush',
],
'drushrc.php' => [
'dest' => $projectRoot . '/drush',
],
'default.site.yml' => [
'dest' => $projectRoot . '/drush/sites',
'add2yaml' => TRUE,
],
'drush.yml' => [
'dest' => $projectRoot . '/drush',
'add2yaml' => TRUE,
* Retrieve options from composer.json "extra" configuration.
$projectname = str_replace([' ', '-', '_', '.'], '', basename(getcwd()));
$env = new Dotenv('docker4drupal', $this->io);
$env->put('COMPOSE_PROJECT_NAME', $projectname);
$extra = $this->composer->getPackage()->getExtra() + ['docker4drupal' => []];
$options = NestedArray::mergeDeep([
'projectname' => $projectname,
'docker0' => [
'ip' => $this->getLocalIpv4('docker0'),
],
'live' => [
'root' => '',
'uri' => '',
'host' => '',
'user' => $env->receive('live_host_username', 'Remote username for host of the live site', getenv('USER')),
],
'drush' => [
'sql' => [
'tables' => [
'structure' => [
'cache',
'cache_*',
'history',
'search_*',
'sessions',
'watchdog',
],
'skip' => [
'migration_*',
],
],
],
],
'drupal' => [
'version' => '8',
],
'php' => [
'version' => '7.0',
'xdebug' => 1,
],
'webserver' => [
],
'varnish' => [
'enable' => 0,
],
'redis' => [
'version' => '4.0',
],
'dbbrowser' => [
'type' => 'pma',
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
],
'solr' => [
'enable' => 0,
'version' => '6.6',
],
'node' => [
'enable' => 0,
'key' => '',
'path' => '',
],
'memcached' => [
'enable' => 0,
],
'rsyslog' => [
'enable' => 0,
],
'athenapdf' => [
'enable' => 0,
'key' => '',
],
'blackfire' => [
'enable' => 0,
'id' => '',
'token' => '',
],
'webgrind' => [
'enable' => 0,
],
], $extra['docker4drupal']);
return $options;
}
/**
* Wrapper for git command in the root directory.
*
* Git command name, arguments and/or options.
*/
protected function git($command) {
passthru(escapeshellcmd('git -c "user.email=d8-project@lakedrops.com" ' . $command));
/**
* Determine local ipv4 address.
*
* @param string|null $interface
* The name of the interface for which to determine the ipv4 address.
*
* @return string|array
* The ipv4 address(es).
*/
private function getLocalIpv4($interface = NULL) {
$out = explode(PHP_EOL, shell_exec('LC_ALL=C /sbin/ifconfig'));
$local_addrs = array();
$ifname = 'unknown';
foreach ($out as $str) {
$matches = array();
if (preg_match('/^([a-z0-9]+)(:\d{1,2})?(\s)+Link/', $str, $matches)) {
$ifname = $matches[1];
}
elseif (preg_match('/inet addr:((?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:[.](?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3})\s/', $str, $matches)) {
$local_addrs[$ifname] = $matches[1];
}
}
if (!isset($interface)) {
return $local_addrs;
}
return isset($local_addrs[$interface]) ? $local_addrs[$interface] : '127.0.0.1';
}