Skip to content
Snippets Groups Projects
Commit ef44e288 authored by jurgenhaas's avatar jurgenhaas
Browse files

Move developer related parts over from drupal-8-scaffold

parents
No related branches found
No related tags found
No related merge requests found
Pipeline #
# Drupal editor configuration normalization
# @see http://editorconfig.org/
# This is the top-most .editorconfig file; do not search in parent directories.
root = true
# All files.
[*]
end_of_line = LF
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{composer.json,composer.lock}]
indent_size = 4
vendor
composer.lock
Deploy:
script:
- curl -XPOST -H'content-type:application/json' "https://packagist.org/api/update-package?username=${PACKAGIST_USERNAME}&apiToken=${PACKAGIST_API_TOKEN}" -d'{"repository":{"url":"'${CI_PROJECT_URL}'"}}'
only:
- tags
- triggers
- schedules
# Guidelines for developers
It is important to use the following command for updates:
```bash
composer update --no-plugins
```
# Drupal 8 Project Developer Plugin
This is a composer plugin which is utilized by the [Drupal 8 Project Template](https://gitlab.lakedrops.com/composer/project/drupal-8) project. Detailed documentation can be found there.
{
"name": "lakedrops/d8-project-scaffold-developer",
"description": "Composer Plugin for Drupal 8 Project Developers",
"type": "composer-plugin",
"keywords": [
"Drupal",
"Development",
"Install",
"Update"
],
"homepage": "https://gitlab.lakedrops.com/composer/plugin/drupal-8-scaffold-developer",
"license": "GPL-2.0-or-later",
"authors": [
{
"name": "Jürgen Haas",
"email": "juergen@paragon-es.de",
"homepage": "https://www.paragon-es.de",
"role": "Drupal Expert"
},
{
"name": "Richard Papp",
"email": "richard.papp@boromino.com",
"homepage": "http://www.boromino.com",
"role": "Drupal Expert"
}
],
"support": {
"issues": "https://gitlab.lakedrops.com/composer/plugin/drupal-8-scaffold-developer/issues",
"source": "https://gitlab.lakedrops.com/composer/plugin/drupal-8-scaffold-developer/tree/master"
},
"repositories": [
{
"type": "composer",
"url": "https://packages.drupal.org/8"
}
],
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.3",
"drupal-code-builder/drupal-code-builder-drush": "^9.0",
"drupal/coder": "^8.2",
"lakedrops/composer-scripts": "^1.0.0",
"lakedrops/docker4drupal": "^1.0.0",
"lakedrops/dorgflow": "^1.0.0"
},
"require-dev": {
"composer/composer": "^1.5.0",
"phpunit/phpunit": "^4.8.0"
},
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"LakeDrops\\Drupal8ScaffoldDeveloper\\": "src/"
}
},
"extra": {
"class": "LakeDrops\\Drupal8ScaffoldDeveloper\\Plugin",
"lakedrops": {
"scripts": {
"lakedrops": {
"callback": "LakeDrops\\Drupal8ScaffoldDeveloper\\Plugin::scaffold",
"description": "(Re-)Configure this project for developers."
}
}
}
},
"scripts": {
"install-codestandards": ["Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run"],
"post-install-cmd": ["@install-codestandards"],
"post-update-cmd": ["@install-codestandards"]
}
}
<?php
namespace LakeDrops\Drupal8ScaffoldDeveloper;
use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\Script\Event;
use LakeDrops\Docker4Drupal\Handler as D4D;
use Symfony\Component\Filesystem\Filesystem;
/**
* Class Handler.
*
* @package LakeDrops\Drupal8ScaffoldDeveloper
*/
class Handler {
/**
* The composer object running this session.
*
* @var \Composer\Composer
*/
protected $composer;
/**
* The input-output object for the composer session.
*
* @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.
* @param \Composer\IO\IOInterface $io
* The input-output object.
*/
public function __construct(Composer $composer, IOInterface $io) {
$this->composer = $composer;
$this->io = $io;
}
/**
* Get the Drupal Core package.
*
* Look up the Drupal core package object, or return it from where we cached
* it in the $drupalCorePackage field.
*
* @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, '*');
}
/**
* Post project create event to execute the scaffolding.
*
* @param \Composer\Script\Event $event
* The event that triggered the plugin.
*/
public function setupLakeDropsProject(Event $event) {
// We only do the fancy stuff for developers.
if (!$event->isDevMode()) {
return;
}
$options = $this->getOptions();
$fs = new Filesystem();
$installationManager = $this->composer->getInstallationManager();
$drupalCorePackage = $this->getDrupalCorePackage();
$corePath = $installationManager->getInstallPath($drupalCorePackage);
// Directory where the root project is being created.
$projectRoot = getcwd();
// Directory where Drupal's index.php is located.
$webRoot = dirname($corePath);
// Directory where this plugin is being installed.
$pluginRoot = $installationManager->getInstallPath($this->getPackage('lakedrops/d8-project-scaffold'));
// Create contrib/custom dirs for modules, profiles, themes and drush.
foreach ([
$webRoot . '/modules',
$webRoot . '/profiles',
$webRoot . '/themes',
'drush',
] as $dir) {
foreach (['contrib', 'custom'] as $subdir) {
$path = $dir . '/' . $subdir;
if (!$fs->exists($path)) {
$fs->mkdir($path, 0775);
}
if ($options['chg-acl']) {
$fs->chgrp($path, $options['webserver-groupname'], TRUE);
}
}
}
// Create and protect config, settings and files directories.
foreach ([
'config/default/sync',
'settings/default',
'files/default/files',
'files/default/private',
] as $dir) {
$path = $projectRoot . '/' . $dir;
if (!$fs->exists($path)) {
$fs->mkdir($path);
$fs->copy($pluginRoot . '/templates/.htaccess', $path . '/.htaccess');
}
if ($options['chg-acl']) {
$fs->chgrp($path, $options['webserver-groupname'], TRUE);
}
}
// Link Drupal site's files and private directory.
foreach (['files', 'private'] as $dir) {
if (!$fs->exists($webRoot . '/sites/default/' . $dir)) {
$rel = substr($fs->makePathRelative($projectRoot . '/files/default/' . $dir, $projectRoot . '/' . $webRoot . '/sites/default/' . $dir), 3, -1);
$fs->symlink($rel, $webRoot . '/sites/default/' . $dir);
$fs->chmod($webRoot . '/sites/default/' . $dir, 0775);
}
}
// Link Drupal site's settings files.
$options['hash'] = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode(random_bytes(55)));
$twig_loader = new \Twig_Loader_Array([]);
$twig = new \Twig_Environment($twig_loader);
foreach ([
'settings.php',
'services.yml',
'development.services.yml',
'settings.local.php',
] as $template) {
$file = $projectRoot . '/settings/default/' . $template;
$link = $webRoot . '/sites/default/' . $template;
if (!$fs->exists($link)) {
$twig_loader->setTemplate($template, file_get_contents($pluginRoot . '/templates/' . $template));
$rendered = $twig->render($template, $options);
file_put_contents($file, $rendered);
$rel = substr($fs->makePathRelative($file, $projectRoot . '/' . $link), 3, -1);
$fs->symlink($rel, $link);
}
$fs->chmod($file, 0664);
if ($options['chg-acl']) {
$fs->chgrp($file, $options['webserver-groupname']);
}
}
// Copy Drush policy and readme.
foreach (['policy.drush.inc', 'README.md'] as $template) {
$fs->copy($pluginRoot . '/templates/drush/' . $template, 'drush/' . $template);
}
// Link Drupal site's config directory.
if (!$fs->exists($webRoot . '/sites/default/files/config')) {
$rel = substr($fs->makePathRelative($projectRoot . '/config/default', $projectRoot . '/files/default/files/config'), 3, -1);
$fs->symlink($rel, $webRoot . '/sites/default/files/config');
}
// Tasks we only do the first time this is run.
if (!$fs->exists($projectRoot . '/.git')) {
// Remove template files.
foreach (['.gitlab-ci.yml', 'README.md'] as $file) {
$fs->remove($file);
}
// Initialize local git working copy.
try {
$this->git('init');
$this->git('add *');
$this->git('commit -m "Initial commit"');
}
catch (\Exception $ex) {
// We're ignoring this for now.
}
}
// If available, also configure Docker4Drupal.
if ($this->getPackage('lakedrops/docker4drupal')) {
$handler = new D4D($event->getComposer(), $event->getIO());
$handler->configureProject($event);
}
}
/**
* Retrieve configuration for this package.
*
* @return array
* The settings from the extra configuration.
*/
protected function getOptions() {
$extra = $this->composer->getPackage()->getExtra() + ['d8-project-scaffold' => []];
$options = $extra['d8-project-scaffold'] + [
'chg-acl' => FALSE,
'webserver-username' => 'www-data',
'webserver-groupname' => 'www-data',
'filter_protocols' => [
'http',
'https',
'ftp',
'news',
'nntp',
'tel',
'telnet',
'mailto',
'irc',
'ssh',
'sftp',
'webcal',
'rtsp',
],
];
return $options;
}
/**
* Wrapper for git command in the root directory.
*
* @param string $command
* Git command name, arguments and/or options.
*
* @throws \Exception
*/
protected function git($command) {
passthru(escapeshellcmd('git -c "user.email=d8-project@lakedrops.com" ' . $command), $exit_code);
if ($exit_code !== 0) {
throw new \Exception('Git returned a non-zero exit code');
}
}
}
<?php
namespace LakeDrops\Drupal8ScaffoldDeveloper;
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Script\Event;
use Composer\Script\ScriptEvents;
/**
* Composer plugin for handling drupal scaffold.
*/
class Plugin implements PluginInterface, EventSubscriberInterface {
/**
* The handler object for events.
*
* @var \LakeDrops\Drupal8ScaffoldDeveloper\Handler
*/
protected $handler;
/**
* {@inheritdoc}
*/
public function activate(Composer $composer, IOInterface $io) {
$this->handler = new Handler($composer, $io);
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return array(
ScriptEvents::POST_CREATE_PROJECT_CMD => 'postCreateProject',
);
}
/**
* Post create project event callback.
*
* @param \Composer\Script\Event $event
* The event that triggered the plugin.
*/
public function postCreateProject(Event $event) {
$this->handler->setupLakeDropsProject($event);
}
/**
* Callback to setup the project.
*
* @param \Composer\Script\Event $event
* The event that triggered the plugin.
*/
public static function scaffold(Event $event) {
$handler = new Handler($event->getComposer(), $event->getIO());
$handler->setupLakeDropsProject($event);
}
}
# Deny all requests from Apache 2.4+.
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
# Deny all requests from Apache 2.0-2.2.
<IfModule !mod_authz_core.c>
Deny from all
</IfModule>
# Turn off all options we don't need.
Options -Indexes -ExecCGI -Includes -MultiViews
# Set the catch-all handler to prevent scripts from being executed.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>
# Override the handler again if we're run later in the evaluation list.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>
# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php5.c>
php_flag engine off
</IfModule>
\ No newline at end of file
# Local development services.
#
# To activate this feature, follow the instructions at the top of the
# 'example.settings.local.php' file, which sits next to this file.
services:
cache.backend.null:
class: Drupal\Core\Cache\NullBackendFactory
This directory contains commands, configuration and site aliases for Drush. See http://packages.drush.org/ for a directory of Drush commands installable via Composer.
<?php
/*
* Customize this file as desired. See https://github.com/drush-ops/drush/blob/8.x/examples/policy.drush.inc for documentation.
*/
/**
* Implements drush_hook_COMMAND_validate().
*
* Encourage folks to use `composer` instead of Drush pm commands
*/
function drush_policy_pm_updatecode_validate() {
return _deny_message();
}
function drush_policy_pm_update_validate() {
return _deny_message();
}
function drush_policy_pm_download_validate() {
return _deny_message();
}
function _deny_message() {
if (!drush_get_option('pm-force')) {
$msg = 'This codebase is assembled with Composer instead of Drush. Use `composer update` and `composer require` instead of `drush pm-updatecode` and `drush pm-download`. You may override this error by using the --pm-force option.';
return drush_set_error('POLICY_PM_DENY', dt($msg));
}
}
/**
* Implements hook_drush_help_alter().
*/
function policy_drush_help_alter(&$command) {
if (in_array($command['command'], array('pm-updatecode', 'pm-update', 'pm-download'))) {
$command['options']['pm-force'] = 'Override site policy and allow Drush codebase management (pm-* commands)';
}
}
parameters:
session.storage.options:
gc_probability: 1
gc_divisor: 100
gc_maxlifetime: 200000
cookie_lifetime: 2000000
twig.config:
debug: true
auto_reload: null
cache: false
renderer.config:
required_cache_contexts: ['languages:language_interface', 'theme', 'user.permissions']
auto_placeholder_conditions:
max-age: 0
contexts: ['session', 'user']
tags: []
http.response.debug_cacheability_headers: false
factory.keyvalue:
{}
factory.keyvalue.expirable:
{}
filter_protocols:
{% for filter_protocol in filter_protocols %}
- {{ filter_protocol }}
{% endfor %}
<?php
$localCache = FALSE;
$config['config_split.config_split.develop']['status'] = TRUE;
$config['config_split.config_split.live']['status'] = FALSE;
assert_options(ASSERT_ACTIVE, TRUE);
\Drupal\Component\Assertion\Handle::register();
$config['system.logging']['error_level'] = 'verbose';
$config['system.performance']['css']['preprocess'] = FALSE;
$config['system.performance']['js']['preprocess'] = FALSE;
$config['config_auto_export.settings']['enabled'] = FALSE;
$settings['extension_discovery_scan_tests'] = TRUE;
$settings['rebuild_access'] = TRUE;
$settings['skip_permissions_hardening'] = TRUE;
if ($localCache) {
$settings['redis.connection']['interface'] = 'PhpRedis';
$settings['redis.connection']['host'] = 'redis';
$settings['cache']['default'] = 'cache.backend.redis';
$settings['container_yamls'][] = 'modules/redis/example.services.yml';
$settings['queue_default'] = 'queue.redis';
}
else {
$settings['container_yamls'][] = __DIR__ . '/development.services.yml';
$settings['cache']['bins']['render'] = 'cache.backend.null';
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null';
}
<?php
$databases = array (
'default' => array (
'default' => array (
'driver' => 'mysql',
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'database' => 'example',
'username' => 'username',
'password' => 'password',
'host' => '127.0.0.1',
'port' => '3306',
'prefix' => '',
),
),
);
$settings['update_free_access'] = FALSE;
$settings['container_yamls'][] = __DIR__ . '/services.yml';
$settings['file_public_path'] = 'sites/default/files';
$settings['file_private_path'] = 'sites/default/private';
$settings['hash_salt'] = '{{ hash }}';
$settings['trusted_host_patterns'] = array(
'^www\.example\.com$',
);
$config['system.file']['path']['temporary'] = '/tmp';
$config_directories['sync'] = 'sites/default/files/config/sync';
if (file_exists(__DIR__ . '/settings.local.php')) {
include __DIR__ . '/settings.local.php';
}
if (file_exists(__DIR__ . '/settings.docker.php')) {
include __DIR__ . '/settings.docker.php';
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment