Initial commit

This commit is contained in:
Oliver Davies 2024-11-20 13:23:17 +00:00
commit 5036f657b3
37 changed files with 13223 additions and 0 deletions

2
.dockerignore Normal file
View file

@ -0,0 +1,2 @@
/README.md
/.github/

18
.env.example Normal file
View file

@ -0,0 +1,18 @@
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
export DOCKER_UID=1000
export COMPOSE_PROJECT_NAME=drupal-london-meetup
export COMPOSE_PROFILES=web,php,database
export DOCKER_WEB_VOLUME=.:/app
export DRUSH_OPTIONS_URI="https://${COMPOSE_PROJECT_NAME}.docker.localhost"
export MYSQL_DATABASE=app
export MYSQL_PASSWORD=app
export MYSQL_USER=app
export DB_NAME="$MYSQL_DATABASE"
export DB_PASSWORD="$MYSQL_PASSWORD"
export DB_USER="$MYSQL_USER"

3
.envrc Normal file
View file

@ -0,0 +1,3 @@
source_url "https://raw.githubusercontent.com/cachix/devenv/82c0147677e510b247d8b9165c54f73d32dfd899/direnvrc" "sha256-7u4iDd1nZpxL4tCzmPG0dQgC5V+/44Ba+tHkPob1v2k="
use devenv

9
.githooks/pre-push Executable file
View file

@ -0,0 +1,9 @@
#!/usr/bin/env bash
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
set -o errexit
export TTY="-T"
./run test:commit

27
.githooks/prepare-commit-msg Executable file
View file

@ -0,0 +1,27 @@
#!/usr/bin/env bash
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
# Load the issue ID from an `.issue-id` file within the project and replace the
# `ISSUE_ID` placeholder within a Git commit message.
#
# For example, running `echo "OD-123" > .issue-id` will add `Refs: OD-123` to
# the commit message.
#
# This also works with multiple issue IDs in the same string, e.g.
# "OD-123 OD-456", or IDs on multiple lines.
set -o errexit
set -o nounset
set -o pipefail
PROJECT_DIR=$(git rev-parse --show-toplevel)
ISSUE_FILE="$PROJECT_DIR/.issue-id"
if [ -f "${ISSUE_FILE}" ]; then
ISSUE_IDS=$(cat "${ISSUE_FILE}" | tr '\n' ',' | tr ' ' ',' | sed 's/,$//' | sed 's/,/, /g')
if [ -n "${ISSUE_IDS}" ]; then
sed -i.bak "s/# Refs:/Refs: $ISSUE_IDS/" "$1"
fi
fi

41
.gitignore vendored Normal file
View file

@ -0,0 +1,41 @@
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
.editorconfig
.env
.gitattributes
.phpunit.result.cache
vendor/
web/.csslintrc
web/.eslintignore
web/.eslintrc.json
web/.ht.router.php
web/.htaccess
web/INSTALL.txt
web/README.md
web/autoload.php
web/core/
web/example.gitignore
web/index.php
web/modules/README.txt
web/modules/contrib/
web/profiles/README.txt
web/robots.txt
web/sites/*/files/
web/sites/*/private/
web/sites/*/services*.yml
web/sites/*/settings*.php
web/sites/README.txt
web/sites/default/default.services.yml
web/sites/default/default.settings.php
web/sites/development.services.yml
web/sites/example.settings.local.php
web/sites/example.sites.php
web/sites/simpletest/
web/themes/README.txt
web/themes/contrib/
web/update.php
web/web.config
# Docker.
.env
docker-compose.override.yaml

2
.hadolint.yaml Normal file
View file

@ -0,0 +1,2 @@
ignore:
- DL3059

30
.tmux Executable file
View file

@ -0,0 +1,30 @@
#!/usr/bin/env bash
open() {
tmux new-window -dn shell
tmux new-window -dn server
tmux send-keys -t server "devenv up" Enter
tmux split-window -h
tmux send-keys -t .right "watchexec --exts php,module,theme,yml phpunit --testdox web/modules/custom/opdavies_talks/tests/src" Enter
tmux select-pane -t .left
}
close() {
tmux send-keys -t server C-c
tmux send-keys -t server Enter
tmux kill-pane -t .right
tmux kill-window -t shell
tmux kill-window -t server
}
if [[ "${DRUPAL_LONDON:-0}" == "1" ]]; then
close
export DRUPAL_LONDON=0
else
open
export DRUPAL_LONDON=1
fi

12
CHANGELOG.md Normal file
View file

@ -0,0 +1,12 @@
# Changelog
## 2023-12-16
### Added
* Add CHANGELOG.md.
### Changed
* Update PHP to 8.2.
* Update Drupal to 10.2.0.

64
Dockerfile Normal file
View file

@ -0,0 +1,64 @@
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
FROM php:8.3-fpm-bullseye AS base
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
RUN which composer && composer -V
ARG DOCKER_UID=1000
ENV DOCKER_UID="${DOCKER_UID}"
WORKDIR /app
RUN adduser --disabled-password --uid "${DOCKER_UID}" app \
&& chown app:app -R /app
USER app
ENV PATH="${PATH}:/app/bin:/app/vendor/bin"
COPY --chown=app:app composer.* ./
################################################################################
FROM base AS build
USER root
RUN apt-get update -yqq \
&& apt-get install -yqq --no-install-recommends \
git libpng-dev libjpeg-dev libzip-dev mariadb-client unzip \
&& rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man \
&& apt-get clean
RUN docker-php-ext-configure gd --with-jpeg
RUN docker-php-ext-install gd opcache pdo_mysql zip
COPY --chown=app:app phpunit.xml* ./
USER app
RUN composer validate --strict
RUN composer install
COPY --chown=app:app tools/docker/images/php/root /
ENTRYPOINT ["/usr/local/bin/docker-entrypoint-php"]
CMD ["php-fpm"]
################################################################################
FROM nginx:1 as web
EXPOSE 8080
WORKDIR /app
COPY tools/docker/images/web/root /

1
README.md Normal file
View file

@ -0,0 +1 @@
# drupal-london-meetup

31
build-configs.yaml Normal file
View file

@ -0,0 +1,31 @@
name: drupal-london-meetup
template: drupal
web:
type: nginx
database:
type: mariadb
version: 10
php:
version: 8.3-fpm-bullseye
phpcs:
paths:
- web/modules/custom
standards:
- Drupal
- DrupalPractice
phpstan: false
drupal:
docroot: web
docker-compose:
services:
- database
- php
- web
dockerfile:
stages:
build:
commands:
- composer validate --strict
- composer install
experimental:
createGitHubActionsConfiguration: false

117
composer.json Normal file
View file

@ -0,0 +1,117 @@
{
"name": "drupal/recommended-project",
"description": "Project template for Drupal 9 projects with a relocated document root",
"type": "project",
"license": "GPL-2.0-or-later",
"homepage": "https://www.drupal.org/project/drupal",
"support": {
"docs": "https://www.drupal.org/docs/user_guide/en/index.html",
"chat": "https://www.drupal.org/node/314178"
},
"repositories": [
{
"type": "composer",
"url": "https://packages.drupal.org/8"
}
],
"require": {
"composer/installers": "^1.9",
"drupal/core-composer-scaffold": "^10.3",
"drupal/core-project-message": "^10.3",
"drupal/core-recommended": "^10.3",
"drush/drush": "^13"
},
"conflict": {
"drupal/drupal": "*"
},
"minimum-stability": "stable",
"prefer-stable": true,
"config": {
"sort-packages": true,
"allow-plugins": {
"composer/installers": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"drupal/core-composer-scaffold": true,
"drupal/core-project-message": true,
"php-http/discovery": true,
"phpstan/extension-installer": true,
"tbachert/spi": true
}
},
"extra": {
"drupal-scaffold": {
"locations": {
"web-root": "web/"
}
},
"installer-paths": {
"web/core": [
"type:drupal-core"
],
"web/libraries/{$name}": [
"type:drupal-library"
],
"web/modules/contrib/{$name}": [
"type:drupal-module"
],
"web/profiles/contrib/{$name}": [
"type:drupal-profile"
],
"web/themes/contrib/{$name}": [
"type:drupal-theme"
],
"drush/Commands/contrib/{$name}": [
"type:drupal-drush"
],
"web/modules/custom/{$name}": [
"type:drupal-custom-module"
],
"web/profiles/custom/{$name}": [
"type:drupal-custom-profile"
],
"web/themes/custom/{$name}": [
"type:drupal-custom-theme"
]
},
"drupal-core-project-message": {
"include-keys": [
"homepage",
"support"
],
"post-create-project-cmd-message": [
"<bg=blue;fg=white> </>",
"<bg=blue;fg=white> Congratulations, youve installed the Drupal codebase </>",
"<bg=blue;fg=white> from the drupal/recommended-project template! </>",
"<bg=blue;fg=white> </>",
"",
"<bg=yellow;fg=black>Next steps</>:",
" * Install the site: https://www.drupal.org/docs/8/install",
" * Read the user guide: https://www.drupal.org/docs/user_guide/en/index.html",
" * Get support: https://www.drupal.org/support",
" * Get involved with the Drupal community:",
" https://www.drupal.org/getting-involved",
" * Remove the plugin that prints this message:",
" composer remove drupal/core-project-message"
]
},
"violinist": {
"automerge": 1,
"bundled_packages": {
"drupal/core-recommended": [
"drupal/core-composer-scaffold",
"drupal/core-dev",
"drupal/core-project-message"
]
},
"blocklist": [
"drupal/core-composer-scaffold",
"drupal/core-dev",
"drupal/core-project-message"
]
}
},
"require-dev": {
"drupal/core-dev": "^10.3",
"phpspec/prophecy-phpunit": "^2"
}
}

12000
composer.lock generated Normal file

File diff suppressed because it is too large Load diff

116
devenv.lock Normal file
View file

@ -0,0 +1,116 @@
{
"nodes": {
"devenv": {
"locked": {
"dir": "src/modules",
"lastModified": 1731679695,
"owner": "cachix",
"repo": "devenv",
"rev": "9f6cadacb9db82f541bbadd67e0189a2b850937e",
"type": "github"
},
"original": {
"dir": "src/modules",
"owner": "cachix",
"repo": "devenv",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1716977621,
"owner": "cachix",
"repo": "devenv-nixpkgs",
"rev": "4267e705586473d3e5c8d50299e71503f16a6fb6",
"type": "github"
},
"original": {
"owner": "cachix",
"ref": "rolling",
"repo": "devenv-nixpkgs",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1731386116,
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "689fed12a013f56d4c4d3f612489634267d86529",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1731363552,
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"devenv": "devenv",
"nixpkgs": "nixpkgs",
"pre-commit-hooks": "pre-commit-hooks"
}
}
},
"root": "root",
"version": 7
}

72
devenv.nix Normal file
View file

@ -0,0 +1,72 @@
{ pkgs, ... }:
let
drupalRoot = "web";
in
{
packages = [
pkgs.git
];
dotenv.disableHint = true;
languages = {
php = {
enable = true;
version = "8.2";
ini = ''
memory_limit = 256M
'';
fpm.pools.web = {
listen = "127.0.0.1:9000";
settings = {
"pm" = "dynamic";
"pm.max_children" = 75;
"pm.max_requests" = 500;
"pm.max_spare_servers" = 20;
"pm.min_spare_servers" = 5;
"pm.start_servers" = 10;
};
};
};
};
processes = { };
services = {
caddy = {
enable = true;
config = ''
{
http_port 8080
}
localhost:8080 {
root * ${drupalRoot}
encode gzip
php_fastcgi localhost:9000
file_server
}
'';
};
mysql = {
enable = true;
initialDatabases = [ { name = "app"; } ];
};
};
enterShell = ''
if [[ ! -d vendor ]]; then
composer install
fi
'';
enterTest = ''
phpunit --testdox
'';
}

15
devenv.yaml Normal file
View file

@ -0,0 +1,15 @@
# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
inputs:
nixpkgs:
url: github:cachix/devenv-nixpkgs/rolling
# If you're using non-OSS software, you can set allowUnfree to true.
# allowUnfree: true
# If you're willing to use a package that's vulnerable
# permittedInsecurePackages:
# - "openssl-1.1.1w"
# If you have more than one devenv you can merge them
#imports:
# - ./backend

View file

@ -0,0 +1,8 @@
services:
php-fpm:
extra_hosts:
- "host.docker.internal:host-gateway"
web:
ports:
- "80:80"

79
docker-compose.yaml Normal file
View file

@ -0,0 +1,79 @@
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
x-proxy: &default-proxy
networks:
- default
- proxy
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_proxy"
- "traefik.http.routers.${COMPOSE_PROJECT_NAME}.rule=Host(
`${COMPOSE_PROJECT_NAME}.docker.localhost`,
)"
- "traefik.http.routers.${COMPOSE_PROJECT_NAME}.tls=true"
x-app: &default-app
volumes:
- "${DOCKER_WEB_VOLUME:-./web:/app/web}"
env_file:
- .env
restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
networks:
- default
deploy:
resources:
limits:
cpus: "${DOCKER_MYSQL_CPUS:-0}"
memory: "${DOCKER_MYSQL_MEMORY:-0}"
labels:
- "traefik.enable=false"
tty: true
services:
web:
<<: [*default-proxy, *default-app]
build:
context: .
target: web
depends_on:
- php
profiles: [web]
php:
<<: [*default-app]
build:
context: .
target: build
args:
- "DOCKER_UID=${DOCKER_UID:-1000}"
volumes:
- .:/app
depends_on:
- database
profiles: [php]
database:
image: mariadb:10
deploy:
resources:
limits:
cpus: "${DOCKER_MYSQL_CPUS:-0}"
memory: "${DOCKER_MYSQL_MEMORY:-0}"
volumes:
- db-data:/var/lib/mysql
env_file:
- .env
labels:
- "traefik.enable=false"
environment:
MYSQL_RANDOM_ROOT_PASSWORD: true
profiles: [database]
volumes:
db-data: {}
networks:
proxy:
external: true
name: traefik_proxy

32
phpcs.xml.dist Normal file
View file

@ -0,0 +1,32 @@
<?xml version="1.0"?>
<!-- Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs. -->
<ruleset name="drupal-london-meetup coding standards">
<description>PHPCS configuration file for drupal-london-meetup.</description>
<file>web/modules/custom</file>
<arg value="np"/>
<rule ref="DrupalPractice"/>
<rule ref="Drupal">
<exclude name="Drupal.Commenting.ClassComment.Missing"/>
<exclude name="Drupal.Commenting.DataTypeNamespace.DataTypeNamespace"/>
<exclude name="Drupal.Commenting.Deprecated"/>
<exclude name="Drupal.Commenting.DocComment.ContentAfterOpen"/>
<exclude name="Drupal.Commenting.DocComment.MissingShort"/>
<exclude name="Drupal.Commenting.FunctionComment.IncorrectParamVarName"/>
<exclude name="Drupal.Commenting.FunctionComment.IncorrectTypeHint"/>
<exclude name="Drupal.Commenting.FunctionComment.InvalidReturn"/>
<exclude name="Drupal.Commenting.FunctionComment.Missing"/>
<exclude name="Drupal.Commenting.FunctionComment.MissingParamComment"/>
<exclude name="Drupal.Commenting.FunctionComment.MissingReturnComment"/>
<exclude name="Drupal.Commenting.FunctionComment.ParamTypeSpaces"/>
<exclude name="Drupal.Commenting.FunctionComment.TypeHintMissing"/>
<exclude name="Drupal.Commenting.InlineComment.DocBlock"/>
<exclude name="Drupal.Commenting.VariableComment.Missing"/>
<exclude name="Drupal.NamingConventions.ValidFunctionName.ScopeNotCamelCaps"/>
<exclude name="DrupalPractice.Objects.StrictSchemaDisabled.StrictConfigSchema"/>
</rule>
</ruleset>

37
phpunit.xml.dist Normal file
View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs. -->
<phpunit
beStrictAboutChangesToGlobalState="true"
beStrictAboutOutputDuringTests="false"
beStrictAboutTestsThatDoNotTestAnything="true"
bootstrap="web/core/tests/bootstrap.php"
cacheResult="false"
colors="true"
failOnWarning="true"
printerClass="\Drupal\Tests\Listeners\HtmlOutputPrinter"
>
<php>
<env name="BROWSERTEST_OUTPUT_BASE_URL" value=""/>
<env name="BROWSERTEST_OUTPUT_DIRECTORY" value=""/>
<env name="MINK_DRIVER_ARGS" value=''/>
<env name="MINK_DRIVER_ARGS_WEBDRIVER" value=''/>
<env name="MINK_DRIVER_CLASS" value=''/>
<env name="SIMPLETEST_BASE_URL" value="http://localhost:8080"/>
<env name="SIMPLETEST_DB" value="sqlite://localhost//dev/shm/test.sqlite"/>
<ini name="error_reporting" value="32767"/>
<ini name="memory_limit" value="-1"/>
</php>
<testsuites>
<testsuite name="functional">
<directory>./web/modules/custom/**/tests/**/Functional</directory>
</testsuite>
<testsuite name="kernel">
<directory>./web/modules/custom/**/tests/**/Kernel</directory>
</testsuite>
<testsuite name="unit">
<directory>./web/modules/custom/**/tests/**/Unit</directory>
</testsuite>
</testsuites>
</phpunit>

141
run Executable file
View file

@ -0,0 +1,141 @@
#!/usr/bin/env bash
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
set -o errexit
set -o pipefail
# If we're running in CI we need to disable TTY allocation for docker compose
# commands that enable it by default, such as exec and run.
TTY="${TTY:-}"
if [[ ! -t 1 ]]; then
TTY="-T"
fi
# Run automated tests as part of the Continuous Integration (CI) pipeline.
function ci:test {
lint:dockerfile
docker compose version
docker network create traefik_proxy || true
cp --no-clobber .env.example .env || true
docker compose build --progress plain
docker compose up --detach
docker compose logs
composer install --quiet --no-progress
test --testdox
}
# Run a command within the php container.
function cmd {
docker compose exec php "${@}"
}
# Run coding standards checks.
function coding-standards {
cmd phpcs "${@}"
}
# Execute any Composer command.
function composer {
_exec php composer "${@}"
}
# Connect to the database.
function db {
[[ -f ".env" ]] && source .env
docker compose exec database mysql -u"$DB_USER" -p"$DB_PASSWORD" "$DB_NAME"
}
# Execute any Drush command.
function drush {
_exec php drush "${@}"
}
# Disable Git hooks.
function git-hooks:off {
git config --unset core.hooksPath
}
# Enable Git hooks.
function git-hooks:on {
git config core.hooksPath .githooks
}
# Display a list of all available commands.
function help {
printf "%s <task> [args]\n\nTasks:\n" "${0}"
compgen -A function | grep -v "^_" | cat -n
printf "\nExtended help:\n Each task has comments for general usage\n"
}
# Install Drupal.
function install {
drush site:install -y "${@}"
}
# Lint the Dockerfile.
function lint:dockerfile {
docker container run --rm -i \
hadolint/hadolint hadolint --ignore DL3008 --ignore DL3022 --ignore DL3059 -t style "${@}" - < Dockerfile
}
# Start the project.
function start {
cp -v --no-clobber .env.example .env || true
docker compose up -d
}
function stop {
docker compose down
}
function test {
_exec php phpunit --colors=always "${@}"
}
function test:commit {
test --testdox --testsuite functional
test --testdox --testsuite kernel
test --testdox --testsuite unit
quality
}
function _exec {
docker compose exec ${TTY} "${@}"
}
function _run {
local service="${1}"
local command="${2}"
docker compose run \
--entrypoint "${command}" \
--no-deps \
--rm \
${TTY} \
"${service}" "${@}"
}
# Include any local tasks.
# https://stackoverflow.com/a/6659698
[[ -e "${BASH_SOURCE%/*}/run.local" ]] && source "${BASH_SOURCE%/*}/run.local"
TIMEFORMAT=$'\nTask completed in %3lR'
time "${@:-help}"
# vim: ft=bash

204
snippets.lua Normal file
View file

@ -0,0 +1,204 @@
require("luasnip.session.snippet_collection").clear_snippets("php")
require("luasnip.session.snippet_collection").clear_snippets("yaml")
local ls = require("luasnip")
local s = ls.snippet
local t = ls.text_node
local fmt = require("luasnip.extras.fmt").fmt
local fmta = require("luasnip.extras.fmt").fmta
ls.add_snippets("php", {
s(
"createnodes",
fmt(
[[
$this->createNode(['type' => 'talk']);
$this->createNode(['type' => 'talk']);
]],
{}
)
),
s(
"pagecontroller",
fmta(
[[
<<?php
declare(strict_types=1);
namespace Drupal\opdavies_talks\Controller;
final class TalksPageController {
public function __invoke(): array {
return [];
}
}
]],
{}
)
),
s(
"repocount",
fmt(
[[
public function __construct(private EntityTypeManagerInterface $entityTypeManager) {{
}}
public function getCount(): int {{
$talks = $this->entityTypeManager->getStorage('node')->loadByProperties();
return count($talks);
}}
]],
{}
)
),
s(
"repotestclass",
fmta(
[[
<<?php
namespace Drupal\Tests\opdavies_talks\Kernel\Repository;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
final class TalkNodeRepositoryTest extends EntityKernelTestBase {
protected static $modules = ['opdavies_talks'];
}
]],
{}
)
),
s(
"repotestcount",
fmt(
[[
public function test_it_returns_a_count(): void {{
$talkRepository = $this->container->get(TalkNodeRepository::class);
self::assertSame(2, $talkRepository->getCount());
}}
]],
{}
)
),
s(
"showconstructor",
fmta(
[[
public function __construct(private TalkNodeRepository $talkRepository) {
}
]],
{}
)
),
s(
"showcount",
fmt(
[[
$talkCount = 2;
return ['#markup' => $this->t('<span data-talk-count>:count talks</span>', [':count' => $talkCount])];
]],
{}
)
),
s("showrepository", t("$talkCount = $this->talkRepository->getCount();")),
s(
"test200response",
fmt(
[[
public function test_it_returns_a_200_response_code(): void {{
$this->drupalGet('/talks');
$session = $this->assertSession();
$session->statusCodeEquals(Response::HTTP_OK);
}}
]],
{}
)
),
s(
"testclass",
fmt(
[[
<?php
namespace Drupal\Tests\opdavies_talks\Functional;
use Drupal\Tests\BrowserTestBase;
class TalksPageTest extends BrowserTestBase {{
public $defaultTheme = 'stark';
}}
]],
{}
)
),
s(
"testcount",
fmt(
[[
public function test_it_displays_the_talk_count(): void {{
$this->drupalGet('/talks');
$session = $this->assertSession();
$session->responseContains('<span data-talk-count>2 talks</span>');
}}
]],
{}
)
),
s("testmodules", t("protected static $modules = ['opdavies_talks'];")),
})
ls.add_snippets("yaml", {
s(
"talkpage",
fmt(
[[
opdavies_talks.page:
path: /talks
defaults:
_controller: Drupal\opdavies_talks\Controller\TalksPageController
_title: Talks
requirements:
_permission: access content
]],
{}
)
),
s(
"talkservices",
fmt(
[[
services:
Drupal\opdavies_talks\Controller\TalksPageController:
autowire: true
Drupal\opdavies_talks\Repository\TalkNodeRepository: []
]],
{}
)
),
})

View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
[[ -f composer.json && ! -d vendor ]] && composer install
eval "$@"

View file

@ -0,0 +1,6 @@
xdebug.mode=develop,debug
xdebug.client_host=host.docker.internal
xdebug.discover_client_host=0
xdebug.output_dir=/tmp/xdebug
xdebug.log=/tmp/xdebug/xdebug-docker-drupal-example.log
xdebug.start_with_request=yes

View file

@ -0,0 +1,7 @@
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
max_vars_input = 1000
memory_limit = 128M
post_max_size = 2M
upload_max_filesize = 2M

View file

@ -0,0 +1,22 @@
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
server {
server_name _;
root /app/web;
location / {
try_files $uri /index.php?$query_string;
}
location ~ \.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
try_files $fastcgi_script_name =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param QUERY_STRING $query_string;
fastcgi_intercept_errors on;
fastcgi_pass php:9000;
}
}

2
web/modules/custom/example/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/composer.lock
/vendor/

View file

@ -0,0 +1,5 @@
{
"require": {
"symfony/config": "^6.1"
}
}

View file

@ -0,0 +1,5 @@
name: Example module
description: TODO
type: module
core_version_requirement: ^9 || ^10 || ^11
package: Example

View file

@ -0,0 +1,7 @@
drupal-module-template.example:
path: /@opdavies/drupal-module-template
defaults:
_controller: Drupal\example\Controller\ExamplePageController
_title: Example page
requirements:
_permission: access content

View file

@ -0,0 +1,7 @@
services:
Drupal\Core\Logger\LoggerChannelFactoryInterface:
alias: logger.factory
private: true
Drupal\example\Controller\ExamplePageController:
autowire: true

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="phpcs-standard">
<description>Codestyle ruleset for Drupal</description>
<rule ref="Drupal"/>
<rule ref="DrupalPractice"/>
<arg name="ignore" value="*.css,*.md,*.txt"/>
<arg name="colors"/>
<arg value="np"/>
<file>./src</file>
<rule ref="Drupal">
<exclude name="Drupal.Commenting.ClassComment.Missing"/>
<exclude name="Drupal.NamingConventions.ValidFunctionName.ScopeNotCamelCaps"/>
<exclude name="Drupal.Commenting.DataTypeNamespace.DataTypeNamespace"/>
<exclude name="Drupal.Commenting.DocComment.MissingShort"/>
<exclude name="Drupal.Commenting.FunctionComment.IncorrectParamVarName"/>
<exclude name="Drupal.Commenting.FunctionComment.IncorrectTypeHint"/>
<exclude name="Drupal.Commenting.FunctionComment.InvalidReturn"/>
<exclude name="Drupal.Commenting.FunctionComment.Missing"/>
<exclude name="Drupal.Commenting.FunctionComment.MissingParamComment"/>
<exclude name="Drupal.Commenting.FunctionComment.MissingReturnComment"/>
<exclude name="Drupal.Commenting.FunctionComment.ParamTypeSpaces"/>
<exclude name="Drupal.Commenting.InlineComment.DocBlock"/>
<exclude name="Drupal.Commenting.VariableComment.Missing"/>
<exclude name="DrupalPractice.Objects.StrictSchemaDisabled.StrictConfigSchema"/>
</rule>
</ruleset>

View file

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Drupal\example\Controller;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
final class ExamplePageController {
use StringTranslationTrait;
public function __construct(
private LoggerChannelFactoryInterface $logger,
) {}
/**
* @return array<string,mixed>
*/
public function __invoke(): array {
$this->logger->get('example')->info('Example page viewed.');
return [
'#markup' => $this->t(
'This is an example page from the <a href="@url">Drupal Module Template</a>.',
['@url' => 'https://github.com/opdavies/drupal-module-template']
),
];
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace Drupal\Tests\example\Functional;
use Drupal\Tests\BrowserTestBase;
use Symfony\Component\HttpFoundation\Response;
final class ExamplePageTest extends BrowserTestBase {
public $defaultTheme = 'stark';
protected static $modules = [
// Core.
'node',
// Custom.
"example"
];
/** @test */
public function should_load_the_example_page_for_anonymous_users(): void {
// Arrange.
// Act.
$this->drupalGet('/@opdavies/drupal-module-template');
// Assert.
$this->assertSession()->statusCodeEquals(Response::HTTP_OK);
}
}