Newer
Older

Angie Byron
committed
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
* Typed data allows you to use shorthand to get data values nested in the
* implicit tree structure of the data. For example, to get the value from
* an entity field item, the Entity Field API allows you to call:
* @code
* $value = $entity->fieldName->propertyName;
* @endcode
* This is really shorthand for:
* @code
* $field_item_list = $entity->get('fieldName');
* $field_item = $field_item_list->get(0);
* $property = $field_item->get('propertyName');
* $value = $property->getValue();
* @endcode
* Some notes:
* - $property, $field_item, and $field_item_list are all typed data objects,
* while $value is a raw PHP value.
* - You can call $property->getParent() to get $field_item,
* $field_item->getParent() to get $field_item_list, or
* $field_item_list->getParent() to get $typed_entity ($entity wrapped in a
* typed data object). $typed_entity->getParent() is NULL.
* - For all of these ->getRoot() returns $typed_entity.
* - The langcode property is on $field_item_list, but you can access it
* on $property as well, so that all items will report the same langcode.
* - When the value of $property is changed by calling $property->setValue(),
* $property->onChange() will fire, which in turn calls the parent object's
* onChange() method and so on. This allows parent objects to react upon
* changes of contained properties or list items.
*
* @section sec_defining Defining data types

Angie Byron
committed
* To define a new data type:
* - Create a class that implements one of the Typed Data interfaces.
* Typically, you will want to extend one of the classes listed in the

Angie Byron
committed
* sections above as a starting point.

Angie Byron
committed
* - Make your class into a DataType plugin. To do that, put it in namespace
* \Drupal\yourmodule\Plugin\DataType (where "yourmodule" is your module's
* short name), and add annotation of type
* \Drupal\Core\TypedData\Annotation\DataType to the documentation header.
* See the @link plugin_api Plugin API topic @endlink and the
* @link annotation Annotations topic @endlink for more information.
*

Angie Byron
committed
* @section sec_using Using data types

Angie Byron
committed
* The data types of the Typed Data API can be used in several ways, once they
* have been defined:
* - In the Field API, data types can be used as the class in the property
* definition of the field. See the @link field Field API topic @endlink for
* more information.
* - In configuration schema files, you can use the unique ID ('id' annotation)
* from any DataType plugin class as the 'type' value for an entry. See the

Alex Pott
committed
* @link config_api Configuration API topic @endlink for more information.

Angie Byron
committed
* - If you need to create a typed data object in code, first get the
* typed_data_manager service from the container or by calling
* \Drupal::typedDataManager(). Then pass the plugin ID to
* $manager::createDataDefinition() to create an appropriate data definition
* object. Then pass the data definition object and the value of the data to
* $manager::create() to create a typed data object.
*
* @see plugin_api
* @see container

Angie Byron
committed
* @}
*/
/**
* @defgroup testing Automated tests
* @{

Alex Pott
committed
* Overview of PHPUnit and Nightwatch automated tests.

Angie Byron
committed
*

Angie Byron
committed
* The Drupal project has embraced a philosophy of using automated tests,
* consisting of both unit tests (which test the functionality of classes at a
* low level) and functional tests (which test the functionality of Drupal
* systems at a higher level, usually involving web output). The goal is to
* have test coverage for all or most of the components and features, and to
* run the automated tests before any code is changed or added, to make sure
* it doesn't break any existing functionality (regression testing).
*
* In order to implement this philosophy, developers need to do the following:
* - When making a patch to fix a bug, make sure that the bug fix patch includes
* a test that fails without the code change and passes with the code change.
* This helps reviewers understand what the bug is, demonstrates that the code
* actually fixes the bug, and ensures the bug will not reappear due to later
* code changes.
* - When making a patch to implement a new feature, include new unit and/or
* functional tests in the patch. This serves to both demonstrate that the
* code actually works, and ensure that later changes do not break the new
* functionality.
*

Alex Pott
committed
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
* @section write_test Writing tests
* All PHP-based tests for Drupal core are written using the industry-standard
* PHPUnit framework, with Drupal extensions. There are several categories of
* tests; each has its own purpose, base class, namespace, and directory:
* - Unit tests:
* - Purpose: Test functionality of a class if the Drupal environment
* (database, settings, etc.) and web browser are not needed for the test,
* or if the Drupal environment can be replaced by a "mock" object.
* - Base class: \Drupal\Tests\UnitTestCase
* - Namespace: \Drupal\Tests\yourmodule\Unit (or a subdirectory)
* - Directory location: yourmodule/tests/src/Unit (or a subdirectory)
* - Kernel tests:
* - Purpose: Test functionality of a class if the full Drupal environment
* and web browser are not needed for the test, but the functionality has
* significant Drupal dependencies that cannot easily be mocked. Kernel
* tests can access services, the database, and a minimal mocked file
* system, and they use an in-memory pseudo-installation. However, modules
* are only installed to the point of having services and hooks, unless you
* install them explicitly.
* - Base class: \Drupal\KernelTests\KernelTestBase
* - Namespace: \Drupal\Tests\yourmodule\Kernel (or a subdirectory)
* - Directory location: yourmodule/tests/src/Kernel (or a subdirectory)
* - Browser tests:
* - Purpose: Test functionality with the full Drupal environment and an
* internal simulated web browser, if JavaScript is not needed.
* - Base class: \Drupal\Tests\BrowserTestBase
* - Namespace: \Drupal\Tests\yourmodule\Functional (or a subdirectory)
* - Directory location: yourmodule/tests/src/Functional (or a subdirectory)
* - Browser tests with JavaScript:
* - Purpose: Test functionality with the full Drupal environment and an
* internal web browser that includes JavaScript execution.
* - Base class: \Drupal\FunctionalJavascriptTests\WebDriverTestBase
* - Namespace: \Drupal\Tests\yourmodule\FunctionalJavascript (or a
* subdirectory)
* - Directory location: yourmodule/tests/src/FunctionalJavascript (or a
* subdirectory)

catch
committed
* - Build tests:
* - Purpose: Test building processes and their outcomes, such as whether a
* live update process actually works, or whether a Composer project
* template actually builds a working site. Provides a temporary build
* workspace and a PHP-native HTTP server to send requests to the site
* you've built.
* - Base class: \Drupal\BuildTests\Framework\BuildTestBase
* - Namespace: \Drupal\Tests\yourmodule\Build (or a
* subdirectory)
* - Directory location: yourmodule/tests/src/Build (or a
* subdirectory)

Alex Pott
committed
*
* Some notes about writing PHP test classes:
* - The class needs a phpDoc comment block with a description and
* @group annotation, which gives information about the test.
* - For unit tests, this comment block should also have @coversDefaultClass
* annotation.
* - When writing tests, put the test code into public methods, each covering a
* logical subset of the functionality that is being tested.
* - The test methods must have names starting with 'test'. For unit tests, the
* test methods need to have a phpDoc block with @covers annotation telling
* which class method they are testing.

Angie Byron
committed
* - In some cases, you may need to write a test module to support your test;
* put such modules under the yourmodule/tests/modules directory.

Alex Pott
committed
*
* Besides the PHPUnit tests described above, Drupal Core also includes a few
* JavaScript-only tests, which use the Nightwatch.js framework to test
* JavaScript code using only JavaScript. These are located in
* core/tests/Drupal/Nightwatch.
*

Angie Byron
committed
* For more details, see:

Alex Pott
committed
* - core/tests/README.md for instructions on running tests
* - https://www.drupal.org/phpunit for full documentation on how to write
* and run PHPUnit tests for Drupal.
* - http://phpunit.de for general information on the PHPUnit framework.

Angie Byron
committed
* - @link oo_conventions Object-oriented programming topic @endlink for more
* on PSR-4, namespaces, and where to place classes.

Alex Pott
committed
* - http://nightwatchjs.org/ for information about Nightwatch testing for
* JavaScript

Angie Byron
committed
* @}
*/

Alex Pott
committed
/**
* @defgroup php_assert PHP Runtime Assert Statements
* @{
* Use of the assert() statement in Drupal.
*
* Unit tests also use the term "assertion" to refer to test conditions, so to
* avoid confusion the term "runtime assertion" will be used for the assert()
* statement throughout the documentation.
*
* A runtime assertion is a statement that is expected to always be true at
* the point in the code it appears at. They are tested using PHP's internal
* @link http://php.net/assert assert() @endlink statement. If an

Alex Pott
committed
* assertion is ever FALSE it indicates an error in the code or in module or
* theme configuration files. User-provided configuration files should be
* verified with standard control structures at all times, not just checked in
* development environments with assert() statements on.
*
* The Drupal project primarily uses runtime assertions to enforce the
* expectations of the API by failing when incorrect calls are made by code
* under development. While PHP type hinting does this for objects and arrays,
* runtime assertions do this for scalars (strings, integers, floats, etc.) and
* complex data structures such as cache and render arrays. They ensure that
* methods' return values are the documented data types. They also verify that

Alex Pott
committed
* objects have been properly configured and set up by the service container.

Lee Rowlands
committed
* They supplement unit tests by checking scenarios that do not have unit tests
* written for them.
*
* There are two php settings which affect runtime assertions. The first,
* assert.exception, should always be set to 1. The second is zend.assertions.
* Set this to -1 in production and 1 in development.

Alex Pott
committed
*
* See https://www.drupal.org/node/2492225 for more information on runtime
* assertions.
* @}
*/

Angie Byron
committed
/**

Angie Byron
committed
* @defgroup info_types Information types

Angie Byron
committed
* @{

Angie Byron
committed
* Types of information in Drupal.

Angie Byron
committed
*

Angie Byron
committed
* Drupal has several distinct types of information, each with its own methods
* for storage and retrieval:
* - Content: Information meant to be displayed on your site: articles, basic
* pages, images, files, custom blocks, etc. Content is stored and accessed
* using @link entity_api Entities @endlink.
* - Session: Information about individual users' interactions with the site,
* such as whether they are logged in. This is really "state" information, but
* it is not stored the same way so it's a separate type here. Session data is
* accessed via \Symfony\Component\HttpFoundation\Request::getSession(), which
* returns an instance of

Alex Pott
committed
* \Symfony\Component\HttpFoundation\Session\SessionInterface.
* See the @link session Sessions topic @endlink for more information.

Angie Byron
committed
* - State: Information of a temporary nature, generally machine-generated and
* not human-edited, about the current state of your site. Examples: the time
* when Cron was last run, whether node access permissions need rebuilding,
* etc. See @link state_api the State API topic @endlink for more information.
* - Configuration: Information about your site that is generally (or at least
* can be) human-edited, but is not Content, and is meant to be relatively
* permanent. Examples: the name of your site, the content types and views
* you have defined, etc. See
* @link config_api the Configuration API topic @endlink for more information.
*

Angie Byron
committed
* @see cache
* @see i18n

Angie Byron
committed
* @}
*/
/**

Angie Byron
committed
* @defgroup extending Extending and altering Drupal

Angie Byron
committed
* @{

Alex Pott
committed
* Overview of extensions and alteration methods for Drupal.

Angie Byron
committed
*

Alex Pott
committed
* @section sec_types Types of extensions

Angie Byron
committed
* Drupal's core behavior can be extended and altered via these three basic

Alex Pott
committed
* types of extensions:

Angie Byron
committed
* - Themes: Themes alter the appearance of Drupal sites. They can include
* template files, which alter the HTML markup and other raw output of the
* site; CSS files, which alter the styling applied to the HTML; and
* JavaScript, Flash, images, and other files. For more information, see the
* @link theme_render Theme system and render API topic @endlink and
* https://www.drupal.org/docs/8/theming

Angie Byron
committed
* - Modules: Modules add to or alter the behavior and functionality of Drupal,
* by using one or more of the methods listed below. For more information
* about creating modules, see https://www.drupal.org/developing/modules/8

Angie Byron
committed
* - Installation profiles: Installation profiles can be used to
* create distributions, which are complete specific-purpose packages of
* Drupal including additional modules, themes, and data. For more

Alex Pott
committed
* information, see https://www.drupal.org/developing/distributions.

Angie Byron
committed
*

Alex Pott
committed
* @section sec_alter Alteration methods for modules

Angie Byron
committed
* Here is a list of the ways that modules can alter or extend Drupal's core
* behavior, or the behavior of other modules:
* - Hooks: Specially-named functions that a module defines, which are
* discovered and called at specific times, usually to alter behavior or data.
* See the @link hooks Hooks topic @endlink for more information.
* - Plugins: Classes that a module defines, which are discovered and
* instantiated at specific times to add functionality. See the

Angie Byron
committed
* @link plugin_api Plugin API topic @endlink for more information.

Angie Byron
committed
* - Entities: Special plugins that define entity types for storing new types
* of content or configuration in Drupal. See the
* @link entity_api Entity API topic @endlink for more information.
* - Services: Classes that perform basic operations within Drupal, such as
* accessing the database and sending email. See the

Angie Byron
committed
* @link container Dependency Injection Container and Services topic @endlink
* for more information.
* - Routing: Providing or altering "routes", which are URLs that Drupal
* responds to, or altering routing behavior with event listener classes.
* See the @link menu Routing and menu topic @endlink for more information.

Jennifer Hodgdon
committed
* - Events: Modules can register as event subscribers; when an event is
* dispatched, a method is called on each registered subscriber, allowing each
* one to react. See the @link events Events topic @endlink for more
* information.

Alex Pott
committed
*
* @section sec_sample *.info.yml files
* Extensions must each be located in a directory whose name matches the short
* name (or machine name) of the extension, and this directory must contain a
* file named machine_name.info.yml (where machine_name is the machine name of
* the extension). See \Drupal\Core\Extension\InfoParserInterface::parse() for
* documentation of the format of .info.yml files.

Angie Byron
committed
* @}
*/
/**

Angie Byron
committed
* @defgroup plugin_api Plugin API

Angie Byron
committed
* @{

Angie Byron
committed
* Using the Plugin API

Angie Byron
committed
*

Angie Byron
committed
* @section sec_overview Overview and terminology
*

Angie Byron
committed
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
* The basic idea of plugins is to allow a particular module or subsystem of
* Drupal to provide functionality in an extensible, object-oriented way. The
* controlling module or subsystem defines the basic framework (interface) for
* the functionality, and other modules can create plugins (implementing the
* interface) with particular behaviors. The controlling module instantiates
* existing plugins as needed, and calls methods to invoke their functionality.
* Examples of functionality in Drupal Core that use plugins include: the block
* system (block types are plugins), the entity/field system (entity types,
* field types, field formatters, and field widgets are plugins), the image
* manipulation system (image effects and image toolkits are plugins), and the
* search system (search page types are plugins).
*
* Plugins are grouped into plugin types, each generally defined by an
* interface. Each plugin type is managed by a plugin manager service, which
* uses a plugin discovery method to discover provided plugins of that type and
* instantiate them using a plugin factory.
*
* Some plugin types make use of the following concepts or components:
* - Plugin derivatives: Allows a single plugin class to present itself as
* multiple plugins. Example: the Menu module provides a block for each
* defined menu via a block plugin derivative.
* - Plugin mapping: Allows a plugin class to map a configuration string to an
* instance, and have the plugin automatically instantiated without writing
* additional code.

Alex Pott
committed
* - Plugin collections: Provide a way to lazily instantiate a set of plugin

Angie Byron
committed
* instances from a single plugin definition.
*
* There are several things a module developer may need to do with plugins:
* - Define a completely new plugin type: see @ref sec_define below.
* - Create a plugin of an existing plugin type: see @ref sec_create below.
* - Perform tasks that involve plugins: see @ref sec_use below.
*
* See https://www.drupal.org/developing/api/8/plugins for more detailed

Angie Byron
committed
* documentation on the plugin system. There are also topics for a few
* of the many existing types of plugins:
* - @link block_api Block API @endlink
* - @link entity_api Entity API @endlink
* - @link field Various types of field-related plugins @endlink
* - @link views_plugins Views plugins @endlink (has links to topics covering
* various specific types of Views plugins).
* - @link search Search page plugins @endlink
*
* @section sec_define Defining a new plugin type
* To define a new plugin type:
* - Define an interface for the plugin. This describes the common set of
* behavior, and the methods you will call on each plugin class that is
* instantiated. Usually this interface will extend one or more of the
* following interfaces:
* - \Drupal\Component\Plugin\PluginInspectionInterface
* - \Drupal\Component\Plugin\ConfigurableInterface
* - \Drupal\Component\Plugin\DependentPluginInterface

Angie Byron
committed
* - \Drupal\Component\Plugin\ContextAwarePluginInterface
* - \Drupal\Core\Plugin\PluginFormInterface
* - \Drupal\Core\Executable\ExecutableInterface
* - (optional) Create a base class that provides a partial implementation of
* the interface, for the convenience of developers wishing to create plugins
* of your type. The base class usually extends
* \Drupal\Core\Plugin\PluginBase, or one of the base classes that extends
* this class.
* - Choose a method for plugin discovery, and define classes as necessary.
* See @ref sub_discovery below.
* - Create a plugin manager/factory class and service, which will discover and
* instantiate plugins. See @ref sub_manager below.
* - Use the plugin manager to instantiate plugins. Call methods on your plugin
* interface to perform the tasks of your plugin type.

Alex Pott
committed
* - (optional) If appropriate, define a plugin collection. See @ref
* sub_collection below for more information.

Angie Byron
committed
*

Angie Byron
committed
* @subsection sub_discovery Plugin discovery
* Plugin discovery is the process your plugin manager uses to discover the
* individual plugins of your type that have been defined by your module and
* other modules. Plugin discovery methods are classes that implement
* \Drupal\Component\Plugin\Discovery\DiscoveryInterface. Most plugin types use
* one of the following discovery mechanisms:
* - Annotation: Plugin classes are annotated and placed in a defined namespace
* subdirectory. Most Drupal Core plugins use this method of discovery.
* - Hook: Plugin modules need to implement a hook to tell the manager about
* their plugins.

Alex Pott
committed
* - YAML: Plugins are listed in YAML files. Drupal Core uses this method for

Angie Byron
committed
* discovering local tasks and local actions. This is mainly useful if all
* plugins use the same class, so it is kind of like a global derivative.
* - Static: Plugin classes are registered within the plugin manager class
* itself. Static discovery is only useful if modules cannot define new
* plugins of this type (if the list of available plugins is static).
*
* It is also possible to define your own custom discovery mechanism or mix
* methods together. And there are many more details, such as annotation
* decorators, that apply to some of the discovery methods. See
* https://www.drupal.org/developing/api/8/plugins for more details.

Angie Byron
committed
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
*
* The remainder of this documentation will assume Annotation-based discovery,
* since this is the most common method.
*
* @subsection sub_manager Defining a plugin manager class and service
* To define an annotation-based plugin manager:
* - Choose a namespace subdirectory for your plugin. For example, search page
* plugins go in directory Plugin/Search under the module namespace.
* - Define an annotation class for your plugin type. This class should extend
* \Drupal\Component\Annotation\Plugin, and for most plugin types, it should
* contain member variables corresponding to the annotations plugins will
* need to provide. All plugins have at least $id: a unique string
* identifier.
* - Define an alter hook for altering the discovered plugin definitions. You
* should document the hook in a *.api.php file.
* - Define a plugin manager class. This class should implement
* \Drupal\Component\Plugin\PluginManagerInterface; most plugin managers do
* this by extending \Drupal\Core\Plugin\DefaultPluginManager. If you do
* extend the default plugin manager, the only method you will probably need
* to define is the class constructor, which will need to call the parent
* constructor to provide information about the annotation class and plugin
* namespace for discovery, set up the alter hook, and possibly set up
* caching. See classes that extend DefaultPluginManager for examples.
* - Define a service for your plugin manager. See the
* @link container Services topic for more information. @endlink Your service
* definition should look something like this, referencing your manager
* class and the parent (default) plugin manager service to inherit
* constructor arguments:
* @code
* plugin.manager.mymodule:
* class: Drupal\mymodule\MyPluginManager
* parent: default_plugin_manager
* @endcode
* - If your plugin is configurable, you will also need to define the
* configuration schema and possibly a configuration entity type. See the
* @link config_api Configuration API topic @endlink for more information.
*

Alex Pott
committed
* @subsection sub_collection Defining a plugin collection

Angie Byron
committed
* Some configurable plugin types allow administrators to create zero or more
* instances of each plugin, each with its own configuration. For example,
* a single block plugin can be configured several times, to display in
* different regions of a theme, with different visibility settings, a
* different title, or other plugin-specific settings. To make this possible,

Alex Pott
committed
* a plugin type can make use of what's known as a plugin collection.
*
* A plugin collection is a class that extends
* \Drupal\Component\Plugin\LazyPluginCollection or one of its subclasses; there
* are several examples in Drupal Core. If your plugin type uses a plugin
* collection, it will usually also have a configuration entity, and the entity
* class should implement
* \Drupal\Core\Entity\EntityWithPluginCollectionInterface. Again, there are
* several examples in Drupal Core; see also the @link config_api Configuration
* API topic @endlink for more information about configuration entities.

Angie Byron
committed
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
*
* @section sec_create Creating a plugin of an existing type
* Assuming the plugin type uses annotation-based discovery, in order to create
* a plugin of an existing type, you will be creating a class. This class must:
* - Implement the plugin interface, so that it has the required methods
* defined. Usually, you'll want to extend the plugin base class, if one has
* been provided.
* - Have the right annotation in its documentation header. See the
* @link annotation Annotation topic @endlink for more information about
* annotation.
* - Be in the right plugin namespace, in order to be discovered.
* Often, the easiest way to make sure this happens is to find an existing
* example of a working plugin class of the desired type, and copy it into your
* module as a starting point.
*
* You can also create a plugin derivative, which allows your plugin class
* to present itself to the user interface as multiple plugins. To do this,
* in addition to the plugin class, you'll need to create a separate plugin
* derivative class implementing
* \Drupal\Component\Plugin\Derivative\DerivativeInterface. The classes
* \Drupal\system\Plugin\Block\SystemMenuBlock (plugin class) and
* \Drupal\system\Plugin\Derivative\SystemMenuBlock (derivative class) are a
* good example to look at.
*

Jennifer Hodgdon
committed
* @section sec_use Performing tasks involving plugins

Angie Byron
committed
* Here are the steps to follow to perform a task that involves plugins:
* - Locate the machine name of the plugin manager service, and instantiate the
* service. See the @link container Services topic @endlink for more
* information on how to do this.
* - On the plugin manager class, use methods like getDefinition(),
* getDefinitions(), or other methods specific to particular plugin managers
* to retrieve information about either specific plugins or the entire list of
* defined plugins.
* - Call the createInstance() method on the plugin manager to instantiate
* individual plugin objects.
* - Call methods on the plugin objects to perform the desired tasks.

Angie Byron
committed
*
* @see annotation

Angie Byron
committed
* @}
*/
/**
* @defgroup oo_conventions Objected-oriented programming conventions
* @{
* PSR-4, namespaces, class naming, and other conventions.
*

Angie Byron
committed
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
* A lot of the PHP code in Drupal is object oriented (OO), making use of
* @link http://php.net/manual/language.oop5.php PHP classes, interfaces, and traits @endlink
* (which are loosely referred to as "classes" in the rest of this topic). The
* following conventions and standards apply to this version of Drupal:
* - Each class must be in its own file.
* - Classes must be namespaced. If a module defines a class, the namespace
* must start with \Drupal\module_name. If it is defined by Drupal Core for
* use across many modules, the namespace should be \Drupal\Core or
* \Drupal\Component, with the exception of the global class \Drupal. See
* https://www.drupal.org/node/1353118 for more about namespaces.
* - In order for the PSR-4-based class auto-loader to find the class, it must
* be located in a directory corresponding to the namespace. For
* module-defined classes, if the namespace is \Drupal\module_name\foo\bar,
* then the class goes under the main module directory in directory
* src/foo/bar. For Drupal-wide classes, if the namespace is
* \Drupal\Core\foo\bar, then it goes in directory
* core/lib/Drupal/Core/foo/bar. See https://www.drupal.org/node/2156625 for
* more information about PSR-4.
* - Some classes have annotations added to their documentation headers. See
* the @link annotation Annotation topic @endlink for more information.
* - Standard plugin discovery requires particular namespaces and annotation
* for most plugin classes. See the
* @link plugin_api Plugin API topic @endlink for more information.
* - There are project-wide coding standards for OO code, including naming:
* https://www.drupal.org/node/608152

Angie Byron
committed
* - Documentation standards for classes are covered on:
* https://www.drupal.org/coding-standards/docs#classes

Angie Byron
committed
* @}
*/

Angie Byron
committed
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
/**
* @defgroup listing_page_class Page header for Classes page
* @{
* Introduction to classes
*
* A lot of the PHP code in Drupal is object oriented (OO), making use of
* @link http://php.net/manual/language.oop5.php PHP classes, interfaces, and traits. @endlink
* See the
* @link oo_conventions Objected-oriented programming conventions @endlink
* for more information.
*
* @see oo_conventions
*
* @}
*/
/**
* @defgroup listing_page_namespace Page header for Namespaces page
* @{
* Introduction to namespaces
*
* PHP classes, interfaces, and traits in Drupal are
* @link http://php.net/manual/language.namespaces.rationale.php namespaced. @endlink

Angie Byron
committed
* See the
* @link oo_conventions Objected-oriented programming conventions @endlink
* for more information.
*
* @see oo_conventions
*
* @}
*/

Angie Byron
committed
/**
* @defgroup best_practices Best practices for developers
* @{

Angie Byron
committed
* Overview of standards and best practices for developers
*
* Ideally, all code that is included in Drupal Core and contributed modules,
* themes, and distributions will be secure, internationalized, maintainable,
* and efficient. In order to facilitate this, the Drupal community has
* developed a set of guidelines and standards for developers to follow. Most of
* these standards can be found under
* @link https://www.drupal.org/developing/best-practices Best practices on Drupal.org @endlink

Angie Byron
committed
*
* Standards and best practices that developers should be aware of include:
* - Security: https://www.drupal.org/writing-secure-code and the

Angie Byron
committed
* @link sanitization Sanitization functions topic @endlink
* - Coding standards: https://www.drupal.org/coding-standards
* and https://www.drupal.org/coding-standards/docs
* - Accessibility: https://www.drupal.org/node/1637990 (modules) and
* https://www.drupal.org/node/464472 (themes)
* - Usability: https://www.drupal.org/ui-standards

Angie Byron
committed
* - Internationalization: @link i18n Internationalization topic @endlink
* - Automated testing: @link testing Automated tests topic @endlink

Angie Byron
committed
* @}
*/

Jennifer Hodgdon
committed
/**
* @defgroup utility Utility classes and functions
* @{
* Overview of utility classes and functions for developers.
*
* Drupal provides developers with a variety of utility functions that make it
* easier and more efficient to perform tasks that are either really common,
* tedious, or difficult. Utility functions help to reduce code duplication and
* should be used in place of one-off code whenever possible.
*
* @see common.inc
* @see file
* @see format
* @see php_wrappers
* @see sanitization
* @see transliteration
* @see validation
* @}
*/

Angie Byron
committed

Jennifer Hodgdon
committed
/**
* @defgroup hooks Hooks
* @{
* Define functions that alter the behavior of Drupal core.
*
* One way for modules to alter the core behavior of Drupal (or another module)
* is to use hooks. Hooks are specially-named functions that a module defines
* (this is known as "implementing the hook"), which are discovered and called
* at specific times to alter or add to the base behavior or data (this is
* known as "invoking the hook"). Each hook has a name (example:
* hook_batch_alter()), a defined set of parameters, and a defined return value.
* Your modules can implement hooks that are defined by Drupal core or other
* modules that they interact with. Your modules can also define their own
* hooks, in order to let other modules interact with them.
*
* To implement a hook:
* - Locate the documentation for the hook. Hooks are documented in *.api.php
* files, by defining functions whose name starts with "hook_" (these
* files and their functions are never loaded by Drupal -- they exist solely
* for documentation). The function should have a documentation header, as
* well as a sample function body. For example, in the core file form.api.php,
* you can find hooks such as hook_batch_alter(). Also, if you are viewing
* this documentation on an API reference site, the Core hooks will be listed
* in this topic.

Jennifer Hodgdon
committed
* - Copy the function to your module's .module file.
* - Change the name of the function, substituting your module's short name
* (name of the module's directory, and .info.yml file without the extension)

Alex Pott
committed
* for the "hook" part of the sample function name. For instance, to implement

Jennifer Hodgdon
committed
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
* hook_batch_alter(), you would rename it to my_module_batch_alter().
* - Edit the documentation for the function (normally, your implementation
* should just have one line saying "Implements hook_batch_alter().").
* - Edit the body of the function, substituting in what you need your module
* to do.
*
* To define a hook:
* - Choose a unique name for your hook. It should start with "hook_", followed
* by your module's short name.
* - Provide documentation in a *.api.php file in your module's main
* directory. See the "implementing" section above for details of what this
* should contain (parameters, return value, and sample function body).
* - Invoke the hook in your module's code.
*
* To invoke a hook, use methods on
* \Drupal\Core\Extension\ModuleHandlerInterface such as alter(), invoke(),
* and invokeAll(). You can obtain a module handler by calling
* \Drupal::moduleHandler(), or getting the 'module_handler' service on an
* injected container.
*
* @see extending
* @see themeable
* @see callbacks
* @see \Drupal\Core\Extension\ModuleHandlerInterface
* @see \Drupal::moduleHandler()
*
* @}
*/
/**
* @defgroup callbacks Callbacks
* @{
* Callback function signatures.
*
* Drupal's API sometimes uses callback functions to allow you to define how
* some type of processing happens. A callback is a function with a defined
* signature, which you define in a module. Then you pass the function name as
* a parameter to a Drupal API function or return it as part of a hook
* implementation return value, and your function is called at an appropriate
* time. For instance, when setting up batch processing you might need to
* provide a callback function for each processing step and/or a callback for
* when processing is finished; you would do that by defining these functions
* and passing their names into the batch setup function.
*
* Callback function signatures, like hook definitions, are described by
* creating and documenting dummy functions in a *.api.php file; normally, the
* dummy callback function's name should start with "callback_", and you should
* document the parameters and return value and provide a sample function body.
* Then your API documentation can refer to this callback function in its
* documentation. A user of your API can usually name their callback function
* anything they want, although a standard name would be to replace "callback_"
* with the module name.
*
* @see hooks
* @see themeable
*
* @}
*/
/**
* @defgroup form_api Form generation
* @{
* Describes how to generate and manipulate forms and process form submissions.
*
* Drupal provides a Form API in order to achieve consistency in its form
* processing and presentation, while simplifying code and reducing the amount
* of HTML that must be explicitly generated by a module.
*
* @section generating_forms Creating forms
* Forms are defined as classes that implement the
* \Drupal\Core\Form\FormInterface and are built using the
* \Drupal\Core\Form\FormBuilder class. Drupal provides a couple of utility
* classes that can be extended as a starting point for most basic forms, the
* most commonly used of which is \Drupal\Core\Form\FormBase. FormBuilder
* handles the low level processing of forms such as rendering the necessary
* HTML, initial processing of incoming $_POST data, and delegating to your
* implementation of FormInterface for validation and processing of submitted
* data.
*
* Here is an example of a Form class:
* @code
* namespace Drupal\mymodule\Form;
*
* use Drupal\Core\Form\FormBase;
* use Drupal\Core\Form\FormStateInterface;

Jennifer Hodgdon
committed
*
* class ExampleForm extends FormBase {
* public function getFormId() {
* // Unique ID of the form.
* return 'example_form';
* }
*

Dries Buytaert
committed
* public function buildForm(array $form, FormStateInterface $form_state) {

Jennifer Hodgdon
committed
* // Create a $form API array.
* $form['phone_number'] = array(
* '#type' => 'tel',

Alex Pott
committed
* '#title' => $this->t('Your phone number'),
* );
* $form['save'] = array(
* '#type' => 'submit',
* '#value' => $this->t('Save'),

Jennifer Hodgdon
committed
* );
* return $form;
* }
*

Dries Buytaert
committed
* public function validateForm(array &$form, FormStateInterface $form_state) {

Jennifer Hodgdon
committed
* // Validate submitted form data.
* }
*

Dries Buytaert
committed
* public function submitForm(array &$form, FormStateInterface $form_state) {

Jennifer Hodgdon
committed
* // Handle submitted form data.
* }
* }
* @endcode
*
* @section retrieving_forms Retrieving and displaying forms
* \Drupal::formBuilder()->getForm() should be used to handle retrieving,
* processing, and displaying a rendered HTML form. Given the ExampleForm
* defined above,
* \Drupal::formBuilder()->getForm('Drupal\mymodule\Form\ExampleForm') would
* return the rendered HTML of the form defined by ExampleForm::buildForm(), or
* call the validateForm() and submitForm(), methods depending on the current
* processing state.
*
* The argument to \Drupal::formBuilder()->getForm() is the name of a class that
* implements FormInterface. Any additional arguments passed to the getForm()
* method will be passed along as additional arguments to the

Jennifer Hodgdon
committed
* ExampleForm::buildForm() method.
*
* For example:
* @code
* $extra = '612-123-4567';
* $form = \Drupal::formBuilder()->getForm('Drupal\mymodule\Form\ExampleForm', $extra);
* ...

Dries Buytaert
committed
* public function buildForm(array $form, FormStateInterface $form_state, $extra = NULL)

Jennifer Hodgdon
committed
* $form['phone_number'] = array(
* '#type' => 'tel',
* '#title' => $this->t('Your phone number'),
* '#value' => $extra,
* );
* return $form;
* }
* @endcode
*
* Alternatively, forms can be built directly via the routing system which will
* take care of calling \Drupal::formBuilder()->getForm(). The following example

Alex Pott
committed
* demonstrates the use of a routing.yml file to display a form at the given
* route.

Jennifer Hodgdon
committed
*
* @code
* example.form:
* path: '/example-form'
* defaults:
* _title: 'Example form'
* _form: '\Drupal\mymodule\Form\ExampleForm'
* @endcode
*

Angie Byron
committed
* The $form argument to form-related functions is a specialized render array
* containing the elements and properties of the form. For more about render
* arrays, see the @link theme_render Render API topic. @endlink For more
* detailed explanations of the Form API workflow, see the
* @link https://www.drupal.org/node/2117411 Form API documentation section. @endlink

Angie Byron
committed
* In addition, there is a set of Form API tutorials in the
* @link https://www.drupal.org/project/examples Examples for Developers project. @endlink

Jennifer Hodgdon
committed
*
* In the form builder, validation, submission, and other form methods,
* $form_state is the primary influence on the processing of the form and is
* passed to most methods, so they can use it to communicate with the form
* system and each other. $form_state is an object that implements
* \Drupal\Core\Form\FormStateInterface.
* @}

Jennifer Hodgdon
committed
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
*/
/**
* @defgroup queue Queue operations
* @{
* Queue items to allow later processing.
*
* The queue system allows placing items in a queue and processing them later.
* The system tries to ensure that only one consumer can process an item.
*
* Before a queue can be used it needs to be created by
* Drupal\Core\Queue\QueueInterface::createQueue().
*
* Items can be added to the queue by passing an arbitrary data object to
* Drupal\Core\Queue\QueueInterface::createItem().
*
* To process an item, call Drupal\Core\Queue\QueueInterface::claimItem() and
* specify how long you want to have a lease for working on that item.
* When finished processing, the item needs to be deleted by calling
* Drupal\Core\Queue\QueueInterface::deleteItem(). If the consumer dies, the
* item will be made available again by the Drupal\Core\Queue\QueueInterface
* implementation once the lease expires. Another consumer will then be able to
* receive it when calling Drupal\Core\Queue\QueueInterface::claimItem().
* Due to this, the processing code should be aware that an item might be handed
* over for processing more than once.
*
* The $item object used by the Drupal\Core\Queue\QueueInterface can contain
* arbitrary metadata depending on the implementation. Systems using the
* interface should only rely on the data property which will contain the
* information passed to Drupal\Core\Queue\QueueInterface::createItem().
* The full queue item returned by Drupal\Core\Queue\QueueInterface::claimItem()
* needs to be passed to Drupal\Core\Queue\QueueInterface::deleteItem() once
* processing is completed.
*
* There are two kinds of queue backends available: reliable, which preserves
* the order of messages and guarantees that every item will be executed at
* least once. The non-reliable kind only does a best effort to preserve order
* in messages and to execute them at least once but there is a small chance
* that some items get lost. For example, some distributed back-ends like
* Amazon SQS will be managing jobs for a large set of producers and consumers
* where a strict FIFO ordering will likely not be preserved. Another example
* would be an in-memory queue backend which might lose items if it crashes.
* However, such a backend would be able to deal with significantly more writes
* than a reliable queue and for many tasks this is more important. See

Alex Pott
committed
* aggregator_cron() for an example of how to effectively use a non-reliable
* queue. Another example is doing Twitter statistics -- the small possibility
* of losing a few items is insignificant next to power of the queue being able
* to keep up with writes. As described in the processing section, regardless
* of the queue being reliable or not, the processing code should be aware that
* an item might be handed over for processing more than once (because the
* processing code might time out before it finishes).
* @}

Angie Byron
committed
*/
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
/**
* @defgroup annotation Annotations
* @{
* Annotations for class discovery and metadata description.
*
* The Drupal plugin system has a set of reusable components that developers
* can use, override, and extend in their modules. Most of the plugins use
* annotations, which let classes register themselves as plugins and describe
* their metadata. (Annotations can also be used for other purposes, though
* at the moment, Drupal only uses them for the plugin system.)
*
* To annotate a class as a plugin, add code similar to the following to the
* end of the documentation block immediately preceding the class declaration:
* @code
* * @ContentEntityType(
* * id = "comment",
* * label = @Translation("Comment"),
* * ...
* * base_table = "comment"
* * )
* @endcode
*
* Note that you must use double quotes; single quotes will not work in
* annotations.
*
* Some annotation types, which extend the "@ PluginID" annotation class, have
* only a single 'id' key in their annotation. For these, it is possible to use
* a shorthand annotation. For example:
* @code
* * @ViewsArea("entity")
* @endcode
* in place of
* @code
* * @ViewsArea(
* * id = "entity"
* *)
* @endcode
*
* The available annotation classes are listed in this topic, and can be
* identified when you are looking at the Drupal source code by having
* "@ Annotation" in their documentation blocks (without the space after @). To
* find examples of annotation for a particular annotation class, such as
* EntityType, look for class files that have an @ annotation section using the
* annotation class.
*
* @see plugin_translatable
* @see plugin_context
*
* @}
*/
/**
* @addtogroup hooks
* @{
*/
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
/**
* Perform periodic actions.
*
* Modules that require some commands to be executed periodically can
* implement hook_cron(). The engine will then call the hook whenever a cron
* run happens, as defined by the administrator. Typical tasks managed by
* hook_cron() are database maintenance, backups, recalculation of settings
* or parameters, automated mailing, and retrieving remote data.
*
* Short-running or non-resource-intensive tasks can be executed directly in
* the hook_cron() implementation.
*
* Long-running tasks and tasks that could time out, such as retrieving remote
* data, sending email, and intensive file tasks, should use the queue API
* instead of executing the tasks directly. To do this, first define one or
* more queues via a \Drupal\Core\Annotation\QueueWorker plugin. Then, add items
* that need to be processed to the defined queues.
*/
function hook_cron() {
// Short-running operation example, not using a queue:
// Delete all expired records since the last cron run.
$expires = \Drupal::state()->get('mymodule.last_check', 0);
\Drupal::database()->delete('mymodule_table')
->condition('expires', $expires, '>=')
->execute();
\Drupal::state()->set('mymodule.last_check', REQUEST_TIME);
// Long-running operation example, leveraging a queue:
// Queue news feeds for updates once their refresh interval has elapsed.
$queue = \Drupal::queue('aggregator_feeds');
$ids = \Drupal::entityTypeManager()->getStorage('aggregator_feed')->getFeedIdsToRefresh();
foreach (Feed::loadMultiple($ids) as $feed) {
if ($queue->createItem($feed)) {
// Add timestamp to avoid queueing item more than once.
$feed->setQueuedTime(REQUEST_TIME);
$feed->save();
}
}
$ids = \Drupal::entityQuery('aggregator_feed')
->condition('queued', REQUEST_TIME - (3600 * 6), '<')
->execute();
if ($ids) {
$feeds = Feed::loadMultiple($ids);
foreach ($feeds as $feed) {
$feed->setQueuedTime(0);
$feed->save();
}
}
}
/**
* Alter available data types for typed data wrappers.
*
* @param array $data_types
* An array of data type information.
*
* @see hook_data_type_info()
*/
function hook_data_type_info_alter(&$data_types) {
$data_types['email']['class'] = '\Drupal\mymodule\Type\Email';
}
/**
* Alter cron queue information before cron runs.
*
* Called by \Drupal\Core\Cron to allow modules to alter cron queue settings
* before any jobs are processed.
*
* @param array $queues
* An array of cron queue information.
*
* @see \Drupal\Core\Queue\QueueWorkerInterface
* @see \Drupal\Core\Annotation\QueueWorker
* @see \Drupal\Core\Cron
*/
function hook_queue_info_alter(&$queues) {
// This site has many feeds so let's spend 90 seconds on each cron run
// updating feeds instead of the default 60.
$queues['aggregator_feeds']['cron']['time'] = 90;
}
/**
* Alter an email message created with MailManagerInterface->mail().
*
* Hook hook_mail_alter() allows modification of email messages created and sent
* with MailManagerInterface->mail(). Usage examples include adding and/or
* changing message text, message fields, and message headers.
*
* Email messages sent using functions other than MailManagerInterface->mail()
* will not invoke hook_mail_alter(). For example, a contributed module directly
* calling the MailInterface->mail() or PHP mail() function will not invoke
* this hook. All core modules use MailManagerInterface->mail() for messaging,
* it is best practice but not mandatory in contributed modules.
*
* @param $message
* An array containing the message data. Keys in this array include:
* The MailManagerInterface->mail() id of the message. Look at module source
* code or MailManagerInterface->mail() for possible id values.
* The address or addresses the message will be sent to. The
* formatting of this string must comply with RFC 2822.