Skip to content

Commit c4535ea

Browse files
committed
Merge branch '8.x-1.x' of ssh://git.drupal.org/project/examples into 8.x-1.x
2 parents 8a07af0 + 21f436a commit c4535ea

21 files changed

+768
-31
lines changed

Diff for: STANDARDS.md

+11-7
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@ Examples uses mostly the same coding standards as Drupal core.
66
If you see a discrepancy between the coding standards tools used by core and
77
those used by Examples, please file an issue so that Examples can follow core.
88

9-
Examples uses the phpcs tool to allow for checking PHP coding standards. We also
10-
use eslint for JavaScript coding standards.
9+
Examples uses the `phpcs` tool to allow for checking PHP coding standards. We
10+
use the `drupal/coder` project for Drupal-specific coding standards.
1111

12-
Examples has a `phpcs.xml.dist` file at the root of the project. This file
13-
specifies the current coding standards 'sniffs' which code in the project must
14-
pass.
12+
We also use `eslint` for JavaScript coding standards.
1513

16-
The `phpcs.xml.dist` file is used by a tool called PHP_CodeSniffer (`phpcs`).
14+
Examples has a `phpcs.xml.dist` file at the root of the project. phpcs uses this
15+
file to specify the current coding standards 'sniffs' which code in the project
16+
must pass.
1717

1818
Contributors should install `phpcs` in their local Drupal installation, and then
1919
use that to run `phpcs` against Examples as part of their development and review
20-
process.
20+
process. (See details below on how to install and run this tool.)
2121

2222
Contributors can also patch the `phpcs.xml.dist` file itself, in order to fix
2323
the codebase to pass a given rule or sniff. Patches which do this should be
@@ -47,6 +47,10 @@ Like this:
4747
$ ../vendor/bin/phpcs -e --standard=Drupal
4848
// Shows you a bunch of Drupal-related sniffs.
4949

50+
Note that there is an issue to require Coder and phpcs as part of Drupal core:
51+
https://www.drupal.org/node/2744463 Once this issue is fixed, you shouldn't need
52+
to install phpcs before using it.
53+
5054
Running phpcs
5155
-------------
5256

Diff for: TESTING.md

+67-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ the testbot's behavior.
1515
You can find information on how to run `run-tests.sh` locally here:
1616
https://www.drupal.org/node/645286
1717

18+
Examples is always targeted to the dev branch of Drupal core for the latest
19+
release. As of this writing, the latest release of Drupal core is 8.2.5, which
20+
means development for Examples should be against the Drupal 8.2.x development
21+
branch. When Drupal 8.3.0 is released, we'll start targeting Examples to 8.3.x,
22+
and so on.
23+
1824
You should at least run `run-tests.sh` locally against all the changes in your
1925
patch before uploading it.
2026

@@ -27,8 +33,68 @@ suggested workaround for this, since there is no best practice to demonstrate as
2733
an example. There is, however, this issue in core:
2834
https://www.drupal.org/node/2499239
2935

36+
How To Run The Tests In The Drupal UI
37+
-------------------------------------
38+
39+
Generally, you should run tests from the command line. This is generally easier
40+
than using Drupal's testing UI. However, here's how you can do it that way:
41+
42+
Enable the Testing module.
43+
44+
Visit the test list page at `admin/config/development/testing`.
45+
46+
Since the tests are organized by module, you can search for a module name and
47+
get all the tests for that module. For instance, type in 'node_type_example' for
48+
all the tests related to that module.
49+
50+
Click the check boxes next to the tests you want to run. If you find this
51+
tedious, it's time to learn to use the command line. :-)
52+
53+
Click 'Run Tests.' You're now running the tests.
54+
55+
Step-by-step: How To Run The Tests.
56+
-----------------------------------
57+
58+
Begin with an installed Drupal codebase. Make a codebase, set up the database,
59+
etc. Note that you can use an existing Drupal instance but the best practice is
60+
to start fresh. Something not working right? Try a new installation.
61+
62+
Use the dev branch of core for the latest release of Drupal. As of this writing,
63+
it's 8.2.x. When Drupal 8.3.0 is released, we'll target 8.3.x.
64+
65+
Open the terminal window and move to the root directory of the Drupal
66+
installation:
67+
68+
$ cd path/to/drupal
69+
70+
Put Examples into the `modules/` folder of the Drupal installation. If you are
71+
doing development on Examples, you should have already checked out the git
72+
repository into `modules/`, like this:
73+
74+
$ git clone --branch 8.x-1.x https://git.drupal.org/project/examples.git modules/examples
75+
76+
Now you can run `run-tests.sh`, which, despite having a `.sh` suffix is not a
77+
shell script. It's a PHP script.
78+
79+
You'll use the `--directory` option to have the test runner scan the Examples
80+
module directory for tests.
81+
82+
Also, importantly, if your test site has its own URL, you'll need to supply that
83+
with the `--url` option. For instance, under MAMP, you must specify
84+
`--url http://localhost:8888/`.
85+
86+
You can also use `--concurrency` to speed up the test run, and `--browser` to
87+
see detailed test results in a web browser instead of just text output in the
88+
terminal.
89+
90+
$ php ./core/scripts/run-tests.sh --browser --concurrency 10 --url http://localhost:8888/ --directory modules/examples
91+
92+
This should run all the tests present in Examples. If you add a test and it
93+
doesn't appear in the list of tests to run, then you'll need to double-check
94+
that it's in the proper test namespace and that the class name (and thus the
95+
file name) ends in Test.
3096

31-
What Tests Should An Example Project Have?
97+
What Tests Should An Example Module Have?
3298
------------------------------------------
3399

34100
Examples has a checklist for each module:

Diff for: events_example/events_example.info.yml

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
name: Events example
2+
type: module
3+
description: Provides an example of subscribing to and dispatching events.
4+
package: Example modules
5+
core: 8.x
6+
dependencies:
7+
- examples

Diff for: events_example/events_example.links.menu.yml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
events_example.description:
2+
title: 'Events Example'
3+
description: 'Example of dispatching and subscribing to events.'
4+
route_name: events_example.description

Diff for: events_example/events_example.module

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
/**
4+
* @file
5+
* Demonstrates how to subscribe to and dispatch events.
6+
*/
7+
8+
/**
9+
* @defgroup events_example Example: Events
10+
* @ingroup examples
11+
* @{
12+
* Demonstrates subscribing to, and dispatching, events.
13+
*
14+
* Events allow for different components of the system to interact and
15+
* communicate with each other. Modules can either dispatch events, subscribe to
16+
* events, or both.
17+
*
18+
* Subscribing to an event allows a module to declare that it would like to be
19+
* notified anytime a specific event happens. A module can subscribe to any
20+
* number of events, and can even subscribe to the same event more than once.
21+
*
22+
* Dispatching an event allows a module, or Drupal core subsystem, to notify any
23+
* registered subscribers that a specific event has just taken place. When an
24+
* event is dispatched the registered code for each subscriber is executed. For
25+
* example, whenever a configuration entity is updated the Configuration API
26+
* dispatches a new event allowing all subscribers to react to the change.
27+
*
28+
* This allows modules to extend other systems without the need to modify the
29+
* original code.
30+
*
31+
* Each event has a unique string name. This string is often referred to as "the
32+
* event", or "the event name". This string is how you identify which event(s)
33+
* you are interested in. A complete list of events dispatched by core is
34+
* available at
35+
* https://api.drupal.org/api/drupal/core%21core.api.php/group/events/
36+
*
37+
* Drupal's event system is an extension of the
38+
* @link http://symfony.com/doc/current/components/event_dispatcher.html Symfony
39+
* EventDispatcher component @endlink, and implements the Mediator pattern.
40+
*
41+
* Subscribing to an event requires:
42+
* - Defining a service in your module, tagged with 'event_subscriber'.
43+
* - Defining a class for your subscriber service that implements
44+
* \Symfony\Component\EventDispatcher\EventSubscriberInterface
45+
* - Using the getSubscribedEvents method to return a list of the events you
46+
* want to subscribe to, and which methods on the class should be called for
47+
* each one.
48+
*
49+
* For an example of subscribing to an event see the events_example.services.yml
50+
* file. And the \Drupal\events_example\EventSubscriber\EventsExampleSubscriber
51+
* class.
52+
*
53+
* Dispatching an event requires:
54+
* - Defining a new static class with constants for unique event names and
55+
* documentation. Example: \Drupal\events_exampl\Event\IncidentEvents
56+
* - Defining an event class that extends
57+
* \Symfony\Component\EventDispatcher\Event
58+
* Example: \Drupal\events_example\Event\IncidentReportEvent
59+
* - Use the 'event_dispatcher' service in your code to dispatch an event and
60+
* provide an event object as an argument. Example:
61+
* \Drupal\events_example\Form\EventsExampleForm::submitForm()
62+
*
63+
* This example code is based off of the article @link
64+
* https://drupalize.me/blog/201502/responding-events-drupal-8 Responding to
65+
* Events in Drupal 8 @endlink.
66+
*
67+
* @see events
68+
* @see \Symfony\Component\EventDispatcher\EventDispatcherInterface
69+
* @see \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher
70+
* @see service_tag
71+
*/
72+
73+
/**
74+
* @} End of "defgroup events_example".
75+
*/

Diff for: events_example/events_example.routing.yml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Define a route for our event dispatching example.
2+
events_example.description:
3+
path: 'examples/events-example'
4+
defaults:
5+
_form: '\Drupal\events_example\Form\EventsExampleForm'
6+
_title: 'Events Example'
7+
requirements:
8+
_permission: 'access content'

Diff for: events_example/events_example.services.yml

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Subscribing to an event requires you to create a new service tagged with the
2+
# 'event_subscriber' tag. This tells the service container, and by proxy the
3+
# event dispatcher service, that the class registered here can be queried to get
4+
# a list of events that it would like to be notified about.
5+
#
6+
# For more on defining and tagging services see
7+
# https://api.drupal.org/api/drupal/core%21core.api.php/group/container/8.2.x
8+
services:
9+
# Give your service a unique name, convention is to prefix service names with
10+
# the name of the module that implements them.
11+
events_example_subscriber:
12+
# Point to the class that will contain your implementation of
13+
# \Symfony\Component\EventDispatcher\EventSubscriberInterface
14+
class: Drupal\events_example\EventSubscriber\EventsExampleSubscriber
15+
tags:
16+
- {name: event_subscriber}

Diff for: events_example/src/Event/IncidentEvents.php

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace Drupal\events_example\Event;
4+
5+
/**
6+
* Defines events for the events_example module.
7+
*
8+
* It is best practice define the unique names for events as constants on a
9+
* class. This provides a place for documentation of the events. As well as
10+
* allowing the event dispatcher to use the constants instead of hard coding a
11+
* string.
12+
*
13+
* In this example we're defining one new event:
14+
* 'events_example.new_incident_report'. This event will be dispatched by the
15+
* form controller \Drupal\events_example\Form\EventsExampleForm whenever a new
16+
* incident is reported. If your application dispatches more than one event
17+
* you can use a single class to document multiple events. Just add a new
18+
* constant for each. Group related events together with a single class, define
19+
* another class for unrelated events.
20+
*
21+
* The docblock for each event constant should contain an "@Event" tag. This is
22+
* used to ensure documentation parsing tools can gather and list all events.
23+
* For example,
24+
* https://api.drupal.org/api/drupal/core%21core.api.php/group/events/
25+
*
26+
* The docblock should also contain a description of when, and
27+
* under what conditions, the event is triggered. A module developer should be
28+
* able to read this description in order to determine whether or not this is
29+
* the event that they want to subscribe to.
30+
*
31+
* This class is declared as final so that it can not be extended. It should
32+
* only ever be used to provide unique event names, and documentation.
33+
*
34+
* In core \Drupal\Core\Config\ConfigCrudEvent is a good example of defining and
35+
* documenting new events.
36+
*
37+
* @see \Drupal\Core\Config\ConfigCrudEvent
38+
*
39+
* @ingroup events_example
40+
*/
41+
final class IncidentEvents {
42+
43+
/**
44+
* Name of the event fired when a new incident is reported.
45+
*
46+
* This event allows modules to perform an action whenever a new incident is
47+
* reported via the incident report form. The event listener method receives a
48+
* \Drupal\events_example\Event\IncidentReportEvent instance.
49+
*
50+
* @Event
51+
*
52+
* @see \Drupal\events_example\Event\IncidentReportEvent
53+
*
54+
* @var string
55+
*/
56+
const NEW_REPORT = 'events_example.new_incident_report';
57+
58+
}

Diff for: events_example/src/Event/IncidentReportEvent.php

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
namespace Drupal\events_example\Event;
4+
5+
use Symfony\Component\EventDispatcher\Event;
6+
7+
/**
8+
* Wraps a incident report event for event subscribers.
9+
*
10+
* Whenever there is additional contextual data that you want to provide to the
11+
* event subscribers when dispatching an event you should create a new class
12+
* that extends \Symfony\Component\EventDispatcher\Event.
13+
*
14+
* See \Drupal\Core\Config\ConfigCrudEvent for an example of this in core.
15+
*
16+
* @see \Drupal\Core\Config\ConfigCrudEvent
17+
*
18+
* @ingroup events_example
19+
*/
20+
class IncidentReportEvent extends Event {
21+
22+
/**
23+
* Incident type.
24+
*
25+
* @var string
26+
*/
27+
protected $type;
28+
29+
/**
30+
* Detailed incident report.
31+
*
32+
* @var string
33+
*/
34+
protected $report;
35+
36+
/**
37+
* Constructs an incident report event object.
38+
*
39+
* @param string $type
40+
* The incident report type.
41+
* @param string $report
42+
* A detailed description of the incident provided by the reporter.
43+
*/
44+
public function __construct($type, $report) {
45+
$this->type = $type;
46+
$this->report = $report;
47+
}
48+
49+
/**
50+
* Get the incident type.
51+
*
52+
* @return string
53+
* The type of report.
54+
*/
55+
public function getType() {
56+
return $this->type;
57+
}
58+
59+
/**
60+
* Get the detailed incident report.
61+
*
62+
* @return string
63+
* The text of the report.
64+
*/
65+
public function getReport() {
66+
return $this->report;
67+
}
68+
69+
}

0 commit comments

Comments
 (0)