Skip to content

Commit 88b6ecd

Browse files
authored
Consolidate scaffolding
* Consolidate scaffolding into this project. * Add consolidated scaffold files. * Fix typo. * Add missing path to file existance check. * Fixed incorrectly named function. * Add missing filesystem dep, refactor to use. * Changing docker-compose.yml file to copy only if absent. * Add static function back in to enable calling script manually. * Fixed RoboFile.php to include default install profile. * Add bin dir config to composer.json.
1 parent 6e8914b commit 88b6ecd

File tree

5 files changed

+289
-24
lines changed

5 files changed

+289
-24
lines changed

RoboFile.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
/**
3+
* @file
4+
* Contains \Robo\RoboFile.
5+
*
6+
* Implementation of class for Robo - http://robo.li/
7+
*
8+
* You may override methods provided by RoboFileBase.php in this file.
9+
* Configuration overrides should be made in the constructor.
10+
*/
11+
12+
include_once 'RoboFileBase.php';
13+
14+
/**
15+
* Class RoboFile.
16+
*/
17+
class RoboFile extends RoboFileBase
18+
{
19+
20+
/**
21+
* {@inheritdoc}
22+
*/
23+
public function __construct()
24+
{
25+
parent::__construct();
26+
// Put project specific overrides here, below the parent constructor.
27+
}
28+
29+
/**
30+
* {@inheritdoc}
31+
*/
32+
protected function getDrupalProfile()
33+
{
34+
// Replace this with the profile of your choice.
35+
return "standard";
36+
}
37+
}

composer.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
"require": {
77
"php": ">=5.4.5",
88
"composer-plugin-api": "^1.0.0",
9-
"drupal-composer/drupal-scaffold": "^2.2"
9+
"drupal-composer/drupal-scaffold": "^2.2",
10+
"symfony/filesystem": "~2.8|~3.0"
11+
},
12+
"config": {
13+
"bin-dir": "bin/"
1014
},
1115
"autoload": {
1216
"psr-4": {

docker-compose.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
version: '2'
2+
services:
3+
web:
4+
image: uofa/apache2-php7-dev:shepherd
5+
hostname: ${PROJECT}
6+
environment:
7+
SITE_TITLE: Drupal site
8+
SITE_MAIL: [email protected]
9+
SITE_ADMIN_EMAIL: [email protected]
10+
SITE_ADMIN_USERNAME: admin
11+
SITE_ADMIN_PASSWORD: password
12+
VIRTUAL_HOST: ${PROJECT}.${DOMAIN}
13+
SSH_AUTH_SOCK: ${CONTAINER_SSH_AUTH_SOCK}
14+
DATABASE_HOST: db
15+
DATABASE_PORT: 3306
16+
DATABASE_NAME: drupal
17+
DATABASE_USER: user
18+
DATABASE_PASSWORD: password
19+
PRIVATE_DIR: /shared/private
20+
PUBLIC_DIR: web/sites/default/files
21+
HASH_SALT: random-hash
22+
CONFIG_SYNC_DIRECTORY: /shared/private/random-hash/sync
23+
volumes:
24+
- .:/code
25+
- shared:/shared
26+
- ${HOST_SSH_AUTH_SOCK_DIR}:/ssh
27+
db:
28+
image: mariadb
29+
environment:
30+
MYSQL_DATABASE: drupal
31+
MYSQL_USER: user
32+
MYSQL_PASSWORD: password
33+
MYSQL_ROOT_PASSWORD: super-secret-password
34+
mail:
35+
image: helder/mailcatcher
36+
environment:
37+
- VIRTUAL_HOST=mail.${PROJECT}.${DOMAIN}
38+
volumes:
39+
shared:
40+
ssh:

src/Handler.php

Lines changed: 204 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44

55
use Composer\Composer;
66
use Composer\IO\IOInterface;
7-
use Composer\Util\Filesystem;
8-
use Composer\Util\RemoteFilesystem;
9-
use DrupalComposer\DrupalScaffold\FileFetcher;
10-
use Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem;
7+
use Composer\Util\Filesystem as ComposerFilesystem;
8+
use Symfony\Component\Filesystem\Filesystem;
119

1210
class Handler
1311
{
@@ -22,6 +20,11 @@ class Handler
2220
*/
2321
protected $io;
2422

23+
/**
24+
* @var \Symfony\Component\Filesystem\Filesystem
25+
*/
26+
protected $filesystem;
27+
2528
/**
2629
* Handler constructor.
2730
*
@@ -32,6 +35,7 @@ public function __construct(Composer $composer, IOInterface $io)
3235
{
3336
$this->composer = $composer;
3437
$this->io = $io;
38+
$this->filesystem = new Filesystem();
3539
}
3640

3741
/**
@@ -41,28 +45,207 @@ public function __construct(Composer $composer, IOInterface $io)
4145
*/
4246
public function onPostCmdEvent(\Composer\Script\Event $event)
4347
{
44-
$this->downloadScaffold();
48+
$event->getIO()->write("Updating Shepherd scaffold files.");
49+
$this->updateShepherdScaffoldFiles();
50+
$event->getIO()->write("Creating necessary directories.");
51+
$this->createDirectories();
52+
$event->getIO()->write("Creating settings.php file if not present.");
53+
$this->createSettingsFile();
54+
$event->getIO()->write("Creating services.yml file if not present.");
55+
$this->createServicesFile();
4556
}
4657

4758
/**
48-
* Downloads Shepherd Drupal scaffold files.
59+
* Update the Shepherd scaffold files.
4960
*/
50-
public function downloadScaffold()
61+
public function updateShepherdScaffoldFiles()
5162
{
52-
$source = 'https://raw.githubusercontent.com/universityofadelaide/shepherd-drupal-scaffold/{version}/{path}';
53-
$filenames = [
54-
'dsh',
55-
'RoboFileBase.php',
56-
];
57-
$version = 'master';
58-
$destination = dirname($this->composer->getConfig()
59-
->get('vendor-dir'));
60-
61-
$fetcher = new FileFetcher(
62-
new RemoteFilesystem($this->io),
63-
$source,
64-
$filenames
63+
$packagePath = $this->getPackagePath();
64+
$projectPath = $this->getProjectPath();
65+
66+
// Always copy and replace these files.
67+
$this->copyFiles(
68+
$packagePath,
69+
$projectPath,
70+
[
71+
'dsh',
72+
'RoboFileBase.php',
73+
],
74+
true
6575
);
66-
$fetcher->fetch($version, $destination);
76+
77+
// Only copy these files if they do not exist at the destination.
78+
$this->copyFiles(
79+
$packagePath,
80+
$projectPath,
81+
[
82+
'docker-compose.yml',
83+
'RoboFile.php',
84+
]
85+
);
86+
}
87+
88+
/**
89+
* Ensure necessary directories exist.
90+
*/
91+
public function createDirectories()
92+
{
93+
$root = $this->getDrupalRootPath();
94+
$dirs = [
95+
'modules',
96+
'profiles',
97+
'themes',
98+
];
99+
100+
// Required for unit testing.
101+
foreach ($dirs as $dir) {
102+
if (!$this->filesystem->exists($root . '/'. $dir)) {
103+
$this->filesystem->mkdir($root . '/'. $dir);
104+
$this->filesystem->touch($root . '/'. $dir . '/.gitkeep');
105+
}
106+
}
107+
}
108+
109+
/**
110+
* Create settings.php file and inject Shepherd-specific settings.
111+
*
112+
* Note: does nothing if the file already exists.
113+
*/
114+
public function createSettingsFile()
115+
{
116+
$root = $this->getDrupalRootPath();
117+
118+
// If the settings.php is not present, and the default version is...
119+
if (!$this->filesystem->exists($root . '/sites/default/settings.php') && $this->filesystem->exists($root . '/sites/default/default.settings.php')) {
120+
$this->filesystem->copy($root . '/sites/default/default.settings.php', $root . '/sites/default/settings.php');
121+
$this->filesystem->chmod($root . '/sites/default/settings.php', 0666);
122+
123+
$shepherdSettings = "\n/**\n * START SHEPHERD CONFIG\n */\n" .
124+
"\$databases['default']['default'] = array (\n" .
125+
" 'database' => getenv('DATABASE_NAME'),\n" .
126+
" 'username' => getenv('DATABASE_USER'),\n" .
127+
" 'password' => getenv('DATABASE_PASSWORD_FILE') ? file_get_contents(getenv('DATABASE_PASSWORD_FILE')) : getenv('DATABASE_PASSWORD'),\n" .
128+
" 'host' => getenv('DATABASE_HOST'),\n" .
129+
" 'port' => getenv('DATABASE_PORT') ?: '3306',\n" .
130+
" 'driver' => getenv('DATABASE_DRIVER') ?: 'mysql',\n" .
131+
" 'prefix' => getenv('DATABASE_PREFIX') ?: '',\n" .
132+
" 'collation' => getenv('DATABASE_COLLATION') ?: 'utf8mb4_general_ci',\n" .
133+
" 'namespace' => getenv('DATABASE_NAMESPACE') ?: 'Drupal\\\\Core\\\\Database\\\\Driver\\\\mysql',\n" .
134+
");\n" .
135+
"\$settings['file_private_path'] = getenv('PRIVATE_DIR');\n" .
136+
"\$settings['hash_salt'] = getenv('HASH_SALT') ?: '" . str_replace(['+', '/', '='], ['-', '_', ''], base64_encode(random_bytes(55))) . "';\n" .
137+
"\$config_directories['sync'] = getenv('CONFIG_SYNC_DIRECTORY') ?: 'sites/default/files/config_" . str_replace(['+', '/', '='], ['-', '_', ''], base64_encode(random_bytes(55))) . "/sync';\n" .
138+
"if (! is_dir(\$app_root . '/' . \$config_directories['sync'])) mkdir(\$app_root . '/' . \$config_directories['sync'], 0777, true);\n" .
139+
"\$settings['shepherd_site_id'] = getenv('SHEPHERD_SITE_ID');\n" .
140+
"\$settings['shepherd_url'] = getenv('SHEPHERD_URL');\n" .
141+
"\$settings['shepherd_token'] = getenv('SHEPHERD_TOKEN_FILE') ? file_get_contents(getenv('SHEPHERD_TOKEN_FILE')) : getenv('SHEPHERD_TOKEN');\n" .
142+
"/**\n * END SHEPHERD CONFIG\n */\n" .
143+
"\n" .
144+
"/**\n * START LOCAL CONFIG\n */\n" .
145+
"if (file_exists(__DIR__ . '/settings.local.php')) {\n" .
146+
" include __DIR__ . '/settings.local.php';\n" .
147+
"}\n" .
148+
"/**\n * END LOCAL CONFIG\n */\n"
149+
;
150+
151+
// Append Shepherd-specific environment variable settings to settings.php.
152+
file_put_contents(
153+
$root . '/sites/default/settings.php',
154+
$shepherdSettings,
155+
FILE_APPEND
156+
);
157+
}
158+
}
159+
160+
/**
161+
* Create services.yml file if not present.
162+
*/
163+
public function createServicesFile()
164+
{
165+
$root = $this->getDrupalRootPath();
166+
167+
if (!$this->filesystem->exists($root . '/sites/default/services.yml') && $this->filesystem->exists($root . '/sites/default/default.services.yml')) {
168+
$this->filesystem->copy($root . '/sites/default/default.services.yml', $root . '/sites/default/services.yml');
169+
$this->filesystem->chmod($root . '/sites/default/services.yml', 0666);
170+
}
171+
}
172+
173+
/**
174+
* Copy files from origin to destination, optionally overwritting existing.
175+
*
176+
* @param bool $overwriteExisting
177+
* If true, replace existing files. Defaults to false.
178+
*/
179+
public function copyFiles($origin, $destination, $filenames, $overwriteExisting = false)
180+
{
181+
foreach ($filenames as $filename) {
182+
// Skip copying files that already exist at the destination.
183+
if (! $overwriteExisting && $this->filesystem->exists($destination . '/' . $filename)) {
184+
continue;
185+
}
186+
$this->filesystem->copy(
187+
$origin . '/' . $filename,
188+
$destination . '/' . $filename,
189+
true
190+
);
191+
}
192+
}
193+
194+
/**
195+
* Get the path to the vendor directory.
196+
*
197+
* E.g. /home/user/code/project/vendor
198+
*
199+
* @return string
200+
*/
201+
public function getVendorPath()
202+
{
203+
// Load ComposerFilesystem to get access to path normalisation.
204+
$composerFilesystem = new ComposerFilesystem();
205+
206+
$config = $this->composer->getConfig();
207+
$composerFilesystem->ensureDirectoryExists($config->get('vendor-dir'));
208+
$vendorPath = $composerFilesystem->normalizePath(realpath($config->get('vendor-dir')));
209+
210+
return $vendorPath;
211+
}
212+
213+
/**
214+
* Get the path to the project directory.
215+
*
216+
* E.g. /home/user/code/project
217+
*
218+
* @return string
219+
*/
220+
public function getProjectPath()
221+
{
222+
$projectPath = dirname($this->getVendorPath());
223+
return $projectPath;
224+
}
225+
226+
/**
227+
* Get the path to the package directory.
228+
*
229+
* E.g. /home/user/code/project/vendor/universityofadelaide/shepherd-drupal-scaffold
230+
*
231+
* @return string
232+
*/
233+
public function getPackagePath()
234+
{
235+
$packagePath = $this->getVendorPath() . '/universityofadelaide/shepherd-drupal-scaffold';
236+
return $packagePath;
237+
}
238+
239+
/**
240+
* Get the path to the Drupal root directory.
241+
*
242+
* E.g. /home/user/code/project/web
243+
*
244+
* @return string
245+
*/
246+
public function getDrupalRootPath()
247+
{
248+
$drupalRootPath = $this->getProjectPath() . '/web';
249+
return $drupalRootPath;
67250
}
68251
}

src/Plugin.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public function activate(Composer $composer, IOInterface $io)
3838
public static function getSubscribedEvents()
3939
{
4040
return array(
41+
ScriptEvents::POST_INSTALL_CMD => 'postCmd',
4142
ScriptEvents::POST_UPDATE_CMD => 'postCmd',
4243
);
4344
}
@@ -58,10 +59,10 @@ public function postCmd(\Composer\Script\Event $event)
5859
* scaffold files.
5960
*
6061
* @param \Composer\Script\Event $event
61-
*/
62+
*/
6263
public static function scaffold(\Composer\Script\Event $event)
6364
{
6465
$handler = new Handler($event->getComposer(), $event->getIO());
65-
$handler->downloadScaffold();
66+
$handler->onPostCmdEvent($event);
6667
}
6768
}

0 commit comments

Comments
 (0)