Re-add syntax highlighting to daily emails and

...ATDC lessons
This commit is contained in:
Oliver Davies 2024-02-18 01:35:59 +00:00
parent 0d9bb37503
commit 5fbf48d9ac
48 changed files with 186 additions and 165 deletions

View file

@ -64,7 +64,7 @@ You can also use the `COMPOSE_PROJECT_NAME` variable inside Docker Compose files
For example, if you use Traefik and needed to override the host URL for a service, the string will be interpolated and the project name would be injected as you'd expect.
```yaml
```language-yaml
labels:
- "traefik.http.routers.${COMPOSE_PROJECT_NAME}.rule=Host(
`${COMPOSE_PROJECT_NAME}.docker.localhost`,

View file

@ -15,7 +15,7 @@ A Makefile contains a number of named targets that you can reference, and each h
For example:
```yaml
```language-language-yaml
# Start the project.
start:
docker-compose up -d

View file

@ -15,7 +15,7 @@ By using one of these tools, you can programatically provision a new, blank serv
For example, to [create a DigitalOcean droplet](https://docs.ansible.com/ansible/latest/collections/community/digitalocean/digital_ocean_module.htm):
```yaml
```language-yaml
---
- community.digitalocean.digital_ocean_droplet:
image: ubuntu-20-04-x64
@ -35,7 +35,7 @@ If you needed to create a separate database server or another server for a new e
[Creating an Amazon EC2 instance](https://docs.ansible.com/ansible/latest/collections/amazon/aws/ec2_instance_module.html#ansible-collections-amazon-aws-ec2-instance-module) looks very similar:
```yaml
```language-yaml
---
- amazon.aws.ec2_instance:
image_id: ami-123456

View file

@ -10,7 +10,7 @@ I cloned a fresh version of my [Docker Examples repository](https://github.com/o
I ran `mkdir -p web/modules/custom/example/tests/src/Functional` to create the directory structure that I needed, and then `touch web/modules/custom/example/tests/src/Functional/ExampleTest.php` to create a new test file and populated it with some initial code:
```php
```language-php
<?php
namespace Drupal\Tests\example\Functional;
@ -27,7 +27,7 @@ class ExampleTest extends BrowserTestBase {
For the simplest test, I decided to test some existing Drupal core functionality - that an anonymous user can view the front page:
```php
```language-php
/** @test */
public function the_front_page_loads_for_anonymous_users() {
$this->drupalGet('<front>');
@ -42,7 +42,7 @@ As this is existing functionalty, the test passes. I can change either the path
With the first test working, it's easy to add more for other functionality, such as whether different users should be able to access administration pages:
```php
```language-php
/** @test */
public function the_admin_page_is_not_accessible_to_anonymous_users() {
$this->drupalGet('admin');

View file

@ -15,7 +15,7 @@ I find that these higher-level types of tests are easier and quicker to set up c
For example, this `Device` class which is a data transfer object around Drupal's `NodeInterface`. It ensures that the correct type of node is provided, and includes a named constructor and a helper method to retrieve a device's asset ID from a field:
```php
```language-php
final class Device {
private NodeInterface $node;
@ -47,7 +47,7 @@ I need to specify what value is returned from the `bundle()` method as well as g
I need to mock the `get()` method and specify the field name that I'm getting the value for, which also returns it's own mock for `FieldItemListInterface` with a value set for the `getString()` method.
```php
```language-php
/** @test */
public function should_return_an_asset_id(): void {
// Arrange.
@ -84,7 +84,7 @@ If I was to refactor from using the `get()` and `getString()` methods to a diffe
This is how I could write the same test using a kernel (integration) test:
```php
```language-php
/** @test */
public function should_return_an_asset_id(): void {
// Arrange.

View file

@ -8,7 +8,7 @@ tags: [php]
Here's a snippet of some Drupal code that I wrote last week. It's responsible for converting an array of nodes into a Collection of one of it's field values.
```php
```language-php
return Collection::make($stationNodes)
->map(fn (NodeInterface $station): string => $station->get('field_station_code')->getString())
->values();
@ -28,7 +28,7 @@ It accepts the original node but checks to ensure that the node is the correct t
I've added a helper method to get the field value, encapsulating that logic in a reusable function whilst making the code easier to read and its intent clearer.
```php
```language-php
namespace Drupal\mymodule\ValueObject;
use Drupal\node\NodeInterface;
@ -60,7 +60,7 @@ final class Station implements StationInterface {
This is what my code now looks like:
```php
```language-php
return Collection::make($stationNodes)
->map(fn (NodeInterface $node): StationInterface => Station::fromNode($node))
->map(fn (StationInterface $station): string => $station->getStationCode())

View file

@ -37,7 +37,7 @@ It also makes it more obvious to anyone reading the code that these values are b
It's similar to having this example PHP code:
```php
```language-php
function __invoke(string $type, int $limit): void {};
```

View file

@ -10,7 +10,7 @@ tags:
When writing object-orientated code, particularly in PHP, you usually write method names using camel-case letters - such as:
```php
```language-php
public function doSomething(): void {
// ...
}
@ -18,7 +18,7 @@ public function doSomething(): void {
This is also true when writing methods within a test class - only that the method name is prefixed with the word `test`:
```php
```language-php
public function testSomething(): void {
}
```
@ -27,7 +27,7 @@ This is probably expected and complies with the PSR code style standards like PS
Something that I've seen some PHP developers and some frameworks prefer is to write their test methods using snake-case letters and commonly removing the `test` prefix in favour of using an annotation:
```php
```language-php
/** @test */
public function the_api_should_return_a_200_response_code_if_everything_is_ok(): void {
// ...

View file

@ -14,7 +14,7 @@ As long as a class implements an Interface, it can be decorated.
For example, if I have this PHP interface:
```php
```language-php
interface DoesSomething
{
public function doSomething(): void;
@ -23,7 +23,7 @@ interface DoesSomething
I could have this class that does something:
```php
```language-php
final class FirstClass implements DoesSomething
{
public function doSomething(): void
@ -37,7 +37,7 @@ If I need to do something else, like caching or logging the result, I can decora
To do this, I need another class that implements the same interface and inject the original version.
```php
```language-php
final class SecondClass implements DoesSomething
{
public function __constuct(

View file

@ -19,7 +19,7 @@ A local port needs to be exposed from the database container that Neovim can con
I usually do this with a `docker-compose.override.yaml` file:
```yaml
```language-yaml
services:
database:
ports:

View file

@ -45,7 +45,7 @@ Now I can run `make composer COMPOSER_ARGS="info drupal/core"` and see what I wa
`just`, on the other hand, allows for defining parameters to its recipes:
```yaml
```language-yaml
composer *args:
  docker compose exec php composer {{ args }}
```

View file

@ -14,7 +14,7 @@ If I'm passing arguments into a constructor, I can declare a visibility and it w
Here's an example of a value of a data transfer object that accepts a sort code and account number as strings:
```php
```language-php
class AccountDetails {
public function __construct(
@ -27,7 +27,7 @@ class AccountDetails {
Without promoted constructor properties, I'd need to create the properties and assign them manually, and I'd have this:
```php
```language-php
class AccountDetails {
public string $accountNumber;

View file

@ -10,7 +10,7 @@ tags:
Continuing with yesterday's data transfer object (DTO) example, something that can be done since PHP 8.1 is to make properties read-only:
```php
```language-php
class AccountDetails {
public function __construct(
@ -25,7 +25,7 @@ This means the public properties can be read and used without the need for gette
Without `readonly`, a DTO can be created and the property values can be changed:
```php
```language-php
$accountDetails = new AccountDetails('12345678', '00-00-00');
$accountDetails->accountNumber = 'banana';
```

View file

@ -13,7 +13,7 @@ A data transfer object only stores data but we could also use a value object tha
For example, we could validate that the account number is the correct length and the sort code is the correct format:
```php
```language-php
class AccountDetails {
public function __construct(

View file

@ -12,7 +12,7 @@ Marian Kostadinov ([stochnagara on Twitter](https://twitter.com/stochnagara)) re
Looking at the previous class:
```php
```language-php
class AccountDetails {
public function __construct(
@ -25,7 +25,7 @@ class AccountDetails {
Instead of setting each property as `readonly`, the whole class can instead be marked as `readonly`:
```php
```language-php
readonly class AccountDetails {
public function __construct(

View file

@ -17,7 +17,7 @@ Why? I didn't like the inconsistency of using one approach for variable names an
I'd have had code like this with a mixture of both:
```php
```language-php
class MyClass {
private EntityTypeManagerInterface $entityTypeManager;
@ -31,7 +31,7 @@ class MyClass {
Or even more simply:
```php
```language-php
$entity_type_manager = \Drupal::entityTypeManager();
```

View file

@ -13,7 +13,7 @@ I've seen a lot on social media and posts and videos recently about Laravel Pipe
This is an example from the new documentation:
```php
```language-php
$user = Pipeline::send($user)
->through([
GenerateProfilePhoto::class,

View file

@ -21,7 +21,7 @@ Maybe a user was pending initially, and they're active after running a command o
To help me get started, I'll sometimes write a test like this with placeholders to separate the test into its separate stages:
```php
```language-php
/** @test */
function should_activate_a_pending_user(): void {
// Arrange.
@ -38,7 +38,7 @@ This makes me think about the different stages and what each might need to conta
Or I might write it out in the "Given, When, Then" format:
```php
```language-php
/** @test */
function should_activate_a_pending_user(): void {
// Given I have a user.

View file

@ -16,7 +16,7 @@ For example, the `drupal_set_message()` function was deprecated in Drupal 8.5 an
Once it was deprecated, the function was changed to use the new service to avoid duplicating code and a message was added to notify Developers:
```php
```language-php
function drupal_set_message($message = NULL, $type = 'status', $repeat = FALSE) {
@trigger_error('drupal_set_message() is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\Messenger\MessengerInterface::addMessage() instead. See https://www.drupal.org/node/2774931', E_USER_DEPRECATED);

View file

@ -18,7 +18,7 @@ I'm using PHPUnit's native assertions to check it returns a Collection (I regula
My initial implementation was to loop over each node and use `assertSame` on its bundle before refactoring to create an array of unique bundle names and comparing it to my expected names:
```php
```language-php
self::assertSame(
expected: [$nodeType],
actual: $haystack

View file

@ -13,7 +13,7 @@ Writing custom assertions is a great way to clean up your test code.
Here's an example from one of my client Drupal projects:
```php
```language-php
private static function assertProductVariationHasPrice(ProductVariationInterface $productVariation, string $expectedPrice): void {
self::assertSame(
actual: $productVariation->getPrice()->getNumber(),

View file

@ -14,7 +14,7 @@ In PHP, this is done by throwing an Exception if a condition is met.
For example:
```php
```language-php
if (!is_array(false)) {
throw new \Exception('Not an array');
}
@ -22,13 +22,13 @@ if (!is_array(false)) {
There's also the `assert` construct which, since PHP 8.0, throws an Exception by default:
```php
```language-php
assert(is_array(false));
```
You can also use an assertion library, such as `webmozart/assert` or `beberlei/assert` which provide assertions and guard methods:
```php
```language-php
use Webmozart\Assert\Assert;
Assert::isArray(false);

View file

@ -12,7 +12,7 @@ Following yesterday's email about input validation, guard clauses and assertion
For example:
```php
```language-php
function createJourney(string $from, string $to, int $duration): void {
var_dump($from, $to, $duration);
}
@ -22,13 +22,13 @@ In this code, each parameter has a type, but there's no validation on the values
If I run this:
```plain
```language-plain
createJourney('', '', -10);
```
I would get this output:
```plain
```language-plain
string(0) ""
string(0) ""
int(-10)
@ -44,7 +44,7 @@ I can use an assertion library or throw my own Exceptions if the values pass the
For example:
```php
```language-php
function createJourney(string $from, string $to, int $duration): void {
Assert::stringNotEmpty($from);
Assert::stringNotEmpty($to);

View file

@ -26,7 +26,7 @@ To start, we wrote a test for existing functionality within Drupal core - anonym
This is the whole test:
```php
```language-php
<?php
namespace Drupal\Tests\my_module\Functional;

View file

@ -18,7 +18,7 @@ If I look at some code, I want to see as few indentation levels as possible, mak
Instead, you check for a condition; if that isn't met, you return early.
For example, here is some code I saw recently during a meetup talk:
```php
```language-php
$callingClass = $scope->getClassReflection()->getName();
if ($callingClass === TextMessageQueueProcessor::class) {

View file

@ -23,7 +23,7 @@ Only write comments that add value, and if there are fewer comments, they are ea
This is an example from an open source pull request:
```php
```language-php
/**
* An interface for field access override.
*/

View file

@ -38,7 +38,7 @@ For example, to install Pathauto, you run `composer require drupal/pathauto`.
Within its output, you'll see this:
```plain
```language-plain
Package operations: 3 installs, 0 updates, 0 removals
- Downloading drupal/token (1.12.0)
- Downloading drupal/ctools (4.0.4)

View file

@ -16,7 +16,7 @@ Here's an example (thanks, ChatGPT, for the code).
## The Class to be tested (MyClass.php)
```php
```language-php
<?php
class MyClass {
@ -36,7 +36,7 @@ class MyClass {
## Dependency Interface (DependencyInterface.php)
```php
```language-php
<?php
interface DependencyInterface {
@ -48,7 +48,7 @@ interface DependencyInterface {
## A test class that ends up testing mocks (MyClassTest.php)
```php
```language-php
<?php
use PHPUnit\Framework\TestCase;

View file

@ -16,7 +16,7 @@ In PHPUnit, there are different ways to write test methods.
The standard way is to use camel-case method names with a `test` prefix, for example:
```php
```language-php
public function testTheProjectNameShouldBeAString(): void
{
// ...
@ -25,7 +25,7 @@ public function testTheProjectNameShouldBeAString(): void
Another popular way, particularly in some frameworks, is to use snake-case method names:
```php
```language-php
/** @test */
public function the_project_name_should_be_a_string(): void
{

View file

@ -19,7 +19,7 @@ Unfortunately, they're often overused and are outdated compared to the code they
For example, here's some PHP code:
```php
```language-php
function sayHello(string $name, array $options = ['shout' => false]): void {
     echo 'Hello, ' . $name;
}
@ -53,7 +53,7 @@ Then you'll get this error:
Now, we can use a docblock to provide more information to PHPStan to describe the structure of the `$options` array and that it has strings for keys and boolean values.
```php
```language-php
/**
 * @param array<string, bool> $options
 */
@ -61,7 +61,7 @@ Now, we can use a docblock to provide more information to PHPStan to describe th
Although it's not erroring, we can add the `$name` parameter and declare it as a `string`.
```php
```language-php
/**
 * @param string $name
 * @param array<string, bool> $options
@ -78,7 +78,7 @@ We don't want an empty string for a name and want the correct options and values
Let's change the docblock to this:
```php
```language-php
/**
 * @param non-empty-string $name
 * @param array{shout: bool} $options

View file

@ -16,7 +16,7 @@ As well as different base classes for types of tests - i.e. functional, kernel a
For example, if we have this test:
```php
```language-php
<?php
namespace Drupal\Tests\example\Kernel;
@ -62,7 +62,7 @@ When writing a lot of tests, this can result in duplication and more complex tes
This can be simplified using `EntityKernelTestBase` instead of `KernelTestBase`:
```php
```language-php
<?php
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;

View file

@ -41,7 +41,7 @@ Before adding tests, you must create a module to place them in.
Run `mkdir -p web/modules/custom/atdc` to create an empty module directory, and create an `atdc.info.yml` file within it with this content:
```yaml
```language-yaml
name: Example
type: module
core_version_requirement: ^10
@ -58,7 +58,7 @@ Run `mkdir -p web/modules/custom/atdc/tests/src/Functional && touch web/modules/
Then, add this content.
```php
```language-php
<?php
namespace Drupal\Tests\atdc\Functional;
@ -77,7 +77,7 @@ Note: within a test class, the namespace is `Drupal\Tests\{module_name}` instead
With the boilerplate class added, create a test method within it:
```php
```language-php
public function testBasic(): void {
  self::assertTrue(FALSE);
}
@ -148,7 +148,7 @@ As you're writing functional tests by extending `BrowserTestBase`, you can make
Replace the `testBasic` test method with the following:
```php
```language-php
public function testFrontPage(): void {
$this->drupalGet('/');

View file

@ -15,7 +15,7 @@ In some instances, setting zero will return all items - essentially, an 'unlimit
I imagine the code looks something like this:
```php
```language-php
if ($limit > 0) {
$query->range(0, $limit);
}
@ -31,7 +31,7 @@ It means the value could be either an integer or null, but I think the intent of
This would make the code look like this:
```php
```language-php
if (is_int($limit)) {
$query->range(0, $limit);
}
@ -45,7 +45,7 @@ It wouldn't make sense to set a negative number as the limit or, as the unlimite
This is the end code I'd likely write:
```php
```language-php
if (is_int($limit)) {
if ($limit < 1) {
throw new InvalidArgumentException('A limit must be a positive integer.');

View file

@ -17,14 +17,14 @@ The default approach is that all files can be added, and you specify the files a
For example, if my `.gitignore` file was this, these two directories would be ignored:
```plain
```language-plain
vendor
web
```
The other approach is to ignore everything and unignore the things to add. For example:
```plain
```language-plain
*
!build.yaml
!Dockerfile

View file

@ -27,7 +27,7 @@ Anything that affects multiple users - such as ignoring `vendor` or `node_module
Add this to your `~/.gitconfig` or `~/.config/git/config` file to set the path for your global ignore file:
```plain
```language-plain
[core]
excludesFile = "~/.config/git/ignore"
```

View file

@ -23,7 +23,7 @@ Going forward, I'd like to ensure that each Drupal module only uses its own clas
Here's what I have so far for my [testing course codebase][atdc]:
```php
```language-php
final class ArchitectureTest {
public function test_classes_should_be_final(): Rule {