annotate core/core.api.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 1fec387a4317
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /**
Chris@0 4 * @file
Chris@0 5 * Documentation landing page and topics, plus core library hooks.
Chris@0 6 */
Chris@0 7
Chris@0 8 /**
Chris@0 9 * @mainpage
Chris@0 10 * Welcome to the Drupal API Documentation!
Chris@0 11 *
Chris@0 12 * This site is an API reference for Drupal, generated from comments embedded
Chris@0 13 * in the source code. More in-depth documentation can be found at
Chris@0 14 * https://www.drupal.org/developing/api.
Chris@0 15 *
Chris@0 16 * Here are some topics to help you get started developing with Drupal.
Chris@0 17 *
Chris@0 18 * @section essentials Essential background concepts
Chris@0 19 *
Chris@0 20 * - @link oo_conventions Object-oriented conventions used in Drupal @endlink
Chris@0 21 * - @link extending Extending and altering Drupal @endlink
Chris@0 22 * - @link best_practices Security and best practices @endlink
Chris@0 23 * - @link info_types Types of information in Drupal @endlink
Chris@0 24 *
Chris@0 25 * @section interface User interface
Chris@0 26 *
Chris@0 27 * - @link menu Menu entries, local tasks, and other links @endlink
Chris@0 28 * - @link routing Routing API and page controllers @endlink
Chris@0 29 * - @link form_api Forms @endlink
Chris@0 30 * - @link block_api Blocks @endlink
Chris@0 31 * - @link ajax Ajax @endlink
Chris@0 32 *
Chris@0 33 * @section store_retrieve Storing and retrieving data
Chris@0 34 *
Chris@0 35 * - @link entity_api Entities @endlink
Chris@0 36 * - @link field Fields @endlink
Chris@0 37 * - @link config_api Configuration API @endlink
Chris@0 38 * - @link state_api State API @endlink
Chris@0 39 * - @link views_overview Views @endlink
Chris@0 40 * - @link database Database abstraction layer @endlink
Chris@0 41 *
Chris@0 42 * @section other_essentials Other essential APIs
Chris@0 43 *
Chris@0 44 * - @link plugin_api Plugins @endlink
Chris@0 45 * - @link container Services and the Dependency Injection Container @endlink
Chris@0 46 * - @link events Events @endlink
Chris@0 47 * - @link i18n Internationalization @endlink
Chris@0 48 * - @link cache Caching @endlink
Chris@0 49 * - @link utility Utility classes and functions @endlink
Chris@0 50 * - @link user_api User accounts, permissions, and roles @endlink
Chris@0 51 * - @link theme_render Render API @endlink
Chris@0 52 * - @link themeable Theme system @endlink
Chris@0 53 * - @link update_api Update API @endlink
Chris@0 54 * - @link migration Migration @endlink
Chris@0 55 *
Chris@0 56 * @section additional Additional topics
Chris@0 57 *
Chris@0 58 * - @link batch Batch API @endlink
Chris@0 59 * - @link queue Queue API @endlink
Chris@0 60 * - @link typed_data Typed Data @endlink
Chris@0 61 * - @link testing Automated tests @endlink
Chris@0 62 * - @link php_assert PHP Runtime Assert Statements @endlink
Chris@0 63 * - @link third_party Integrating third-party applications @endlink
Chris@0 64 *
Chris@0 65 * @section more_info Further information
Chris@0 66 *
Chris@0 67 * - @link https://api.drupal.org/api/drupal/groups/8 All topics @endlink
Chris@0 68 * - @link https://www.drupal.org/project/examples Examples project (sample modules) @endlink
Chris@0 69 * - @link https://www.drupal.org/list-changes API change notices @endlink
Chris@0 70 * - @link https://www.drupal.org/developing/api/8 Drupal 8 API longer references @endlink
Chris@0 71 */
Chris@0 72
Chris@0 73 /**
Chris@0 74 * @defgroup third_party REST and Application Integration
Chris@0 75 * @{
Chris@0 76 * Integrating third-party applications using REST and related operations.
Chris@0 77 *
Chris@0 78 * @section sec_overview Overview of web services
Chris@0 79 * Web services make it possible for applications and web sites to read and
Chris@0 80 * update information from other web sites. There are several standard
Chris@0 81 * techniques for providing web services, including:
Chris@0 82 * - SOAP: http://wikipedia.org/wiki/SOAP
Chris@0 83 * - XML-RPC: http://wikipedia.org/wiki/XML-RPC
Chris@0 84 * - REST: http://wikipedia.org/wiki/Representational_state_transfer
Chris@0 85 * Drupal sites can both provide web services and integrate third-party web
Chris@0 86 * services.
Chris@0 87 *
Chris@0 88 * @section sec_rest_overview Overview of REST
Chris@0 89 * The REST technique uses basic HTTP requests to obtain and update data, where
Chris@0 90 * each web service defines a specific API (HTTP GET and/or POST parameters and
Chris@0 91 * returned response) for its HTTP requests. REST requests are separated into
Chris@0 92 * several types, known as methods, including:
Chris@0 93 * - GET: Requests to obtain data.
Chris@0 94 * - POST: Requests to update or create data.
Chris@0 95 * - PUT: Requests to update or create data (limited support, currently unused
Chris@0 96 * by entity resources).
Chris@0 97 * - PATCH: Requests to update a subset of data, such as one field.
Chris@0 98 * - DELETE: Requests to delete data.
Chris@0 99 * The Drupal Core REST module provides support for GET, POST, PATCH, and DELETE
Chris@0 100 * quests on entities, GET requests on the database log from the Database
Chris@0 101 * Logging module, and a plugin framework for providing REST support for other
Chris@0 102 * data and other methods.
Chris@0 103 *
Chris@0 104 * REST requests can be authenticated. The Drupal Core Basic Auth module
Chris@0 105 * provides authentication using the HTTP Basic protocol; the contributed module
Chris@0 106 * OAuth (https://www.drupal.org/project/oauth) implements the OAuth
Chris@0 107 * authentication protocol. You can also use cookie-based authentication, which
Chris@0 108 * would require users to be logged into the Drupal site while using the
Chris@0 109 * application on the third-party site that is using the REST service.
Chris@0 110 *
Chris@0 111 * @section sec_rest Enabling REST for entities and the log
Chris@0 112 * Here are the steps to take to use the REST operations provided by Drupal
Chris@0 113 * Core:
Chris@0 114 * - Enable the REST module, plus Basic Auth (or another authentication method)
Chris@0 115 * and HAL.
Chris@0 116 * - Node entity support is configured by default. If you would like to support
Chris@0 117 * other types of entities, you can copy
Chris@0 118 * core/modules/rest/config/install/rest.settings.yml to your sync
Chris@0 119 * configuration directory, appropriately modified for other entity types,
Chris@0 120 * and import it. Support for GET on the log from the Database Logging module
Chris@0 121 * can also be enabled in this way; in this case, the 'entity:node' line
Chris@0 122 * in the configuration would be replaced by the appropriate plugin ID,
Chris@0 123 * 'dblog'.
Chris@0 124 * - Set up permissions to allow the desired REST operations for a role, and set
Chris@0 125 * up one or more user accounts to perform the operations.
Chris@0 126 * - To perform a REST operation, send a request to either the canonical URL
Chris@0 127 * for an entity (such as node/12345 for a node), or if the entity does not
Chris@0 128 * have a canonical URL, a URL like entity/(type)/(ID). The URL for a log
Chris@0 129 * entry is dblog/(ID). The request must have the following properties:
Chris@0 130 * - The request method must be set to the REST method you are using (POST,
Chris@0 131 * GET, PATCH, etc.).
Chris@0 132 * - The content type for the data you send, or the accept type for the
Chris@0 133 * data you are receiving, must be set to 'application/hal+json'.
Chris@0 134 * - If you are sending data, it must be JSON-encoded.
Chris@0 135 * - You'll also need to make sure the authentication information is sent
Chris@0 136 * with the request, unless you have allowed access to anonymous users.
Chris@0 137 *
Chris@0 138 * For more detailed information on setting up REST, see
Chris@0 139 * https://www.drupal.org/documentation/modules/rest.
Chris@0 140 *
Chris@0 141 * @section sec_plugins Defining new REST plugins
Chris@0 142 * The REST framework in the REST module has support built in for entities, but
Chris@0 143 * it is also an extensible plugin-based system. REST plugins implement
Chris@0 144 * interface \Drupal\rest\Plugin\ResourceInterface, and generally extend base
Chris@0 145 * class \Drupal\rest\Plugin\ResourceBase. They are annotated with
Chris@0 146 * \Drupal\rest\Annotation\RestResource annotation, and must be in plugin
Chris@0 147 * namespace subdirectory Plugin\rest\resource. For more information on how to
Chris@0 148 * create plugins, see the @link plugin_api Plugin API topic. @endlink
Chris@0 149 *
Chris@0 150 * If you create a new REST plugin, you will also need to enable it by
Chris@0 151 * providing default configuration or configuration import, as outlined in
Chris@0 152 * @ref sec_rest above.
Chris@0 153 *
Chris@0 154 * @section sec_integrate Integrating data from other sites into Drupal
Chris@0 155 * If you want to integrate data from other web sites into Drupal, here are
Chris@0 156 * some notes:
Chris@0 157 * - There are contributed modules available for integrating many third-party
Chris@0 158 * sites into Drupal. Search on https://www.drupal.org/project/project_module
Chris@0 159 * - If there is not an existing module, you will need to find documentation on
Chris@0 160 * the specific web services API for the site you are trying to integrate.
Chris@0 161 * - There are several classes and functions that are useful for interacting
Chris@0 162 * with web services:
Chris@0 163 * - You should make requests using the 'http_client' service, which
Chris@0 164 * implements \GuzzleHttp\ClientInterface. See the
Chris@0 165 * @link container Services topic @endlink for more information on
Chris@0 166 * services. If you cannot use dependency injection to retrieve this
Chris@0 167 * service, the \Drupal::httpClient() method is available. A good example
Chris@0 168 * of how to use this service can be found in
Chris@0 169 * \Drupal\aggregator\Plugin\aggregator\fetcher\DefaultFetcher
Chris@0 170 * - \Drupal\Component\Serialization\Json (JSON encoding and decoding).
Chris@0 171 * - PHP has functions and classes for parsing XML; see
Chris@0 172 * http://php.net/manual/refs.xml.php
Chris@0 173 * @}
Chris@0 174 */
Chris@0 175
Chris@0 176 /**
Chris@0 177 * @defgroup state_api State API
Chris@0 178 * @{
Chris@0 179 * Information about the State API.
Chris@0 180 *
Chris@0 181 * The State API is one of several methods in Drupal for storing information.
Chris@0 182 * See the @link info_types Information types topic @endlink for an
Chris@0 183 * overview of the different types of information.
Chris@0 184 *
Chris@0 185 * The basic entry point into the State API is \Drupal::state(), which returns
Chris@0 186 * an object of class \Drupal\Core\State\StateInterface. This class has
Chris@0 187 * methods for storing and retrieving state information; each piece of state
Chris@0 188 * information is associated with a string-valued key. Example:
Chris@0 189 * @code
Chris@0 190 * // Get the state class.
Chris@0 191 * $state = \Drupal::state();
Chris@0 192 * // Find out when cron was last run; the key is 'system.cron_last'.
Chris@0 193 * $time = $state->get('system.cron_last');
Chris@0 194 * // Set the cron run time to the current request time.
Chris@0 195 * $state->set('system.cron_last', REQUEST_TIME);
Chris@0 196 * @endcode
Chris@0 197 *
Chris@0 198 * For more on the State API, see https://www.drupal.org/developing/api/8/state
Chris@0 199 * @}
Chris@0 200 */
Chris@0 201
Chris@0 202 /**
Chris@0 203 * @defgroup config_api Configuration API
Chris@0 204 * @{
Chris@0 205 * Information about the Configuration API.
Chris@0 206 *
Chris@0 207 * The Configuration API is one of several methods in Drupal for storing
Chris@0 208 * information. See the @link info_types Information types topic @endlink for
Chris@0 209 * an overview of the different types of information. The sections below have
Chris@0 210 * more information about the configuration API; see
Chris@0 211 * https://www.drupal.org/developing/api/8/configuration for more details.
Chris@0 212 *
Chris@0 213 * @section sec_storage Configuration storage
Chris@0 214 * In Drupal, there is a concept of the "active" configuration, which is the
Chris@0 215 * configuration that is currently in use for a site. The storage used for the
Chris@0 216 * active configuration is configurable: it could be in the database, in files
Chris@0 217 * in a particular directory, or in other storage backends; the default storage
Chris@0 218 * is in the database. Module developers must use the configuration API to
Chris@0 219 * access the active configuration, rather than being concerned about the
Chris@0 220 * details of where and how it is stored.
Chris@0 221 *
Chris@0 222 * Configuration is divided into individual objects, each of which has a
Chris@0 223 * unique name or key. Some modules will have only one configuration object,
Chris@0 224 * typically called 'mymodule.settings'; some modules will have many. Within
Chris@0 225 * a configuration object, configuration settings have data types (integer,
Chris@0 226 * string, Boolean, etc.) and settings can also exist in a nested hierarchy,
Chris@0 227 * known as a "mapping".
Chris@0 228 *
Chris@0 229 * Configuration can also be overridden on a global, per-language, or
Chris@0 230 * per-module basis. See https://www.drupal.org/node/1928898 for more
Chris@0 231 * information.
Chris@0 232 *
Chris@0 233 * @section sec_yaml Configuration YAML files
Chris@0 234 * Whether or not configuration files are being used for the active
Chris@0 235 * configuration storage on a particular site, configuration files are always
Chris@0 236 * used for:
Chris@0 237 * - Defining the default configuration for an extension (module, theme, or
Chris@0 238 * profile), which is imported to the active storage when the extension is
Chris@0 239 * enabled. These configuration items are located in the config/install
Chris@0 240 * sub-directory of the extension. Note that changes to this configuration
Chris@0 241 * after a module or theme is already enabled have no effect; to make a
Chris@0 242 * configuration change after a module or theme is enabled, you would need to
Chris@0 243 * uninstall/reinstall or use a hook_update_N() function.
Chris@0 244 * - Defining optional configuration for a module or theme. Optional
Chris@0 245 * configuration items are located in the config/optional sub-directory of the
Chris@0 246 * extension. These configuration items have dependencies that are not
Chris@0 247 * explicit dependencies of the extension, so they are only installed if all
Chris@0 248 * dependencies are met. For example, in the scenario that module A defines a
Chris@0 249 * dependency which requires module B, but module A is installed first and
Chris@0 250 * module B some time later, then module A's config/optional directory will be
Chris@0 251 * scanned at that time for newly met dependencies, and the configuration will
Chris@0 252 * be installed then. If module B is never installed, the configuration item
Chris@0 253 * will not be installed either.
Chris@0 254 * - Exporting and importing configuration.
Chris@0 255 *
Chris@0 256 * The file storage format for configuration information in Drupal is
Chris@0 257 * @link http://wikipedia.org/wiki/YAML YAML files. @endlink Configuration is
Chris@0 258 * divided into files, each containing one configuration object. The file name
Chris@0 259 * for a configuration object is equal to the unique name of the configuration,
Chris@0 260 * with a '.yml' extension. The default configuration files for each module are
Chris@0 261 * placed in the config/install directory under the top-level module directory,
Chris@0 262 * so look there in most Core modules for examples.
Chris@0 263 *
Chris@0 264 * @section sec_schema Configuration schema and translation
Chris@0 265 * Each configuration file has a specific structure, which is expressed as a
Chris@0 266 * YAML-based configuration schema. The configuration schema details the
Chris@0 267 * structure of the configuration, its data types, and which of its values need
Chris@0 268 * to be translatable. Each module needs to define its configuration schema in
Chris@0 269 * files in the config/schema directory under the top-level module directory, so
Chris@0 270 * look there in most Core modules for examples.
Chris@0 271 *
Chris@0 272 * Configuration can be internationalized; see the
Chris@0 273 * @link i18n Internationalization topic @endlink for more information. Data
Chris@0 274 * types label, text, and date_format in configuration schema are translatable;
Chris@0 275 * string is non-translatable text (the 'translatable' property on a schema
Chris@0 276 * data type definition indicates that it is translatable).
Chris@0 277 *
Chris@0 278 * @section sec_simple Simple configuration
Chris@0 279 * The simple configuration API should be used for information that will always
Chris@0 280 * have exactly one copy or version. For instance, if your module has a
Chris@0 281 * setting that is either on or off, then this is only defined once, and it
Chris@0 282 * would be a Boolean-valued simple configuration setting.
Chris@0 283 *
Chris@0 284 * The first task in using the simple configuration API is to define the
Chris@0 285 * configuration file structure, file name, and schema of your settings (see
Chris@0 286 * @ref sec_yaml above). Once you have done that, you can retrieve the active
Chris@0 287 * configuration object that corresponds to configuration file mymodule.foo.yml
Chris@0 288 * with a call to:
Chris@0 289 * @code
Chris@0 290 * $config = \Drupal::config('mymodule.foo');
Chris@0 291 * @endcode
Chris@0 292 *
Chris@0 293 * This will be an object of class \Drupal\Core\Config\Config, which has methods
Chris@0 294 * for getting configuration information. For instance, if your YAML file
Chris@0 295 * structure looks like this:
Chris@0 296 * @code
Chris@0 297 * enabled: '0'
Chris@0 298 * bar:
Chris@0 299 * baz: 'string1'
Chris@0 300 * boo: 34
Chris@0 301 * @endcode
Chris@0 302 * you can make calls such as:
Chris@0 303 * @code
Chris@0 304 * // Get a single value.
Chris@0 305 * $enabled = $config->get('enabled');
Chris@0 306 * // Get an associative array.
Chris@0 307 * $bar = $config->get('bar');
Chris@0 308 * // Get one element of the array.
Chris@0 309 * $bar_baz = $config->get('bar.baz');
Chris@0 310 * @endcode
Chris@0 311 *
Chris@0 312 * The Config object that was obtained and used in the previous examples does
Chris@0 313 * not allow you to change configuration. If you want to change configuration,
Chris@0 314 * you will instead need to get the Config object by making a call to
Chris@0 315 * getEditable() on the config factory:
Chris@0 316 * @code
Chris@0 317 * $config =\Drupal::service('config.factory')->getEditable('mymodule.foo');
Chris@0 318 * @endcode
Chris@0 319 *
Chris@0 320 * Individual configuration values can be changed or added using the set()
Chris@0 321 * method and saved using the save() method:
Chris@0 322 * @code
Chris@0 323 * // Set a scalar value.
Chris@0 324 * $config->set('enabled', 1);
Chris@0 325 * // Save the configuration.
Chris@0 326 * $config->save();
Chris@0 327 * @endcode
Chris@0 328 *
Chris@0 329 * Configuration values can also be unset using the clear() method, which is
Chris@0 330 * also chainable:
Chris@0 331 * @code
Chris@0 332 * $config->clear('bar.boo')->save();
Chris@0 333 * $config_data = $config->get('bar');
Chris@0 334 * @endcode
Chris@0 335 * In this example $config_data would return an array with one key - 'baz' -
Chris@0 336 * because 'boo' was unset.
Chris@0 337 *
Chris@0 338 * @section sec_entity Configuration entities
Chris@0 339 * In contrast to the simple configuration settings described in the previous
Chris@0 340 * section, if your module allows users to create zero or more items (where
Chris@0 341 * "items" are things like content type definitions, view definitions, and the
Chris@0 342 * like), then you need to define a configuration entity type to store your
Chris@0 343 * configuration. Creating an entity type, loading entities, and querying them
Chris@0 344 * are outlined in the @link entity_api Entity API topic. @endlink Here are a
Chris@0 345 * few additional steps and notes specific to configuration entities:
Chris@0 346 * - For examples, look for classes that implement
Chris@0 347 * \Drupal\Core\Config\Entity\ConfigEntityInterface -- one good example is
Chris@0 348 * the \Drupal\user\Entity\Role entity type.
Chris@0 349 * - In the entity type annotation, you will need to define a 'config_prefix'
Chris@0 350 * string. When Drupal stores a configuration item, it will be given a name
Chris@0 351 * composed of your module name, your chosen config prefix, and the ID of
Chris@0 352 * the individual item, separated by '.'. For example, in the Role entity,
Chris@0 353 * the config prefix is 'role', so one configuration item might be named
Chris@0 354 * user.role.anonymous, with configuration file user.role.anonymous.yml.
Chris@0 355 * - You will need to define the schema for your configuration in your
Chris@0 356 * modulename.schema.yml file, with an entry for 'modulename.config_prefix.*'.
Chris@0 357 * For example, for the Role entity, the file user.schema.yml has an entry
Chris@0 358 * user.role.*; see @ref sec_yaml above for more information.
Chris@0 359 * - Your module can provide default/optional configuration entities in YAML
Chris@0 360 * files; see @ref sec_yaml above for more information.
Chris@0 361 * - Some configuration entities have dependencies on other configuration
Chris@0 362 * entities, and module developers need to consider this so that configuration
Chris@0 363 * can be imported, uninstalled, and synchronized in the right order. For
Chris@0 364 * example, a field display configuration entity would need to depend on
Chris@0 365 * field configuration, which depends on field and bundle configuration.
Chris@0 366 * Configuration entity classes expose dependencies by overriding the
Chris@0 367 * \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies()
Chris@0 368 * method.
Chris@0 369 * - On routes for paths starting with '/admin' or otherwise designated as
Chris@0 370 * administration paths (such as node editing when it is set as an admin
Chris@0 371 * operation), if they have configuration entity placeholders, configuration
Chris@0 372 * entities are normally loaded in their original language, without
Chris@0 373 * translations or other overrides. This is usually desirable, because most
Chris@0 374 * admin paths are for editing configuration, and you need that to be in the
Chris@0 375 * source language and to lack possibly dynamic overrides. If for some reason
Chris@0 376 * you need to have your configuration entity loaded in the currently-selected
Chris@0 377 * language on an admin path (for instance, if you go to
Chris@0 378 * example.com/es/admin/your_path and you need the entity to be in Spanish),
Chris@0 379 * then you can add a 'with_config_overrides' parameter option to your route.
Chris@0 380 * The same applies if you need to load the entity with overrides (or
Chris@0 381 * translated) on an admin path like '/node/add/article' (when configured to
Chris@0 382 * be an admin path). Here's an example using the configurable_language config
Chris@0 383 * entity:
Chris@0 384 * @code
Chris@0 385 * mymodule.myroute:
Chris@0 386 * path: '/admin/mypath/{configurable_language}'
Chris@0 387 * defaults:
Chris@0 388 * _controller: '\Drupal\mymodule\MyController::myMethod'
Chris@0 389 * options:
Chris@0 390 * parameters:
Chris@0 391 * configurable_language:
Chris@0 392 * type: entity:configurable_language
Chris@0 393 * with_config_overrides: TRUE
Chris@0 394 * @endcode
Chris@0 395 * With the route defined this way, the $configurable_language parameter to
Chris@0 396 * your controller method will come in translated to the current language.
Chris@0 397 * Without the parameter options section, it would be in the original
Chris@0 398 * language, untranslated.
Chris@0 399 *
Chris@0 400 * @see i18n
Chris@0 401 *
Chris@0 402 * @}
Chris@0 403 */
Chris@0 404
Chris@0 405 /**
Chris@0 406 * @defgroup cache Cache API
Chris@0 407 * @{
Chris@0 408 * Information about the Drupal Cache API
Chris@0 409 *
Chris@0 410 * @section basics Basics
Chris@0 411 *
Chris@0 412 * Note: If not specified, all of the methods mentioned here belong to
Chris@0 413 * \Drupal\Core\Cache\CacheBackendInterface.
Chris@0 414 *
Chris@0 415 * The Cache API is used to store data that takes a long time to compute.
Chris@0 416 * Caching can either be permanent or valid only for a certain timespan, and
Chris@0 417 * the cache can contain any type of data.
Chris@0 418 *
Chris@0 419 * To use the Cache API:
Chris@0 420 * - Request a cache object through \Drupal::cache() or by injecting a cache
Chris@0 421 * service.
Chris@0 422 * - Define a Cache ID (cid) value for your data. A cid is a string, which must
Chris@0 423 * contain enough information to uniquely identify the data. For example, if
Chris@0 424 * your data contains translated strings, then your cid value must include the
Chris@0 425 * interface text language selected for page.
Chris@0 426 * - Call the get() method to attempt a cache read, to see if the cache already
Chris@0 427 * contains your data.
Chris@0 428 * - If your data is not already in the cache, compute it and add it to the
Chris@0 429 * cache using the set() method. The third argument of set() can be used to
Chris@0 430 * control the lifetime of your cache item.
Chris@0 431 *
Chris@0 432 * Example:
Chris@0 433 * @code
Chris@0 434 * $cid = 'mymodule_example:' . \Drupal::languageManager()->getCurrentLanguage()->getId();
Chris@0 435 *
Chris@0 436 * $data = NULL;
Chris@0 437 * if ($cache = \Drupal::cache()->get($cid)) {
Chris@0 438 * $data = $cache->data;
Chris@0 439 * }
Chris@0 440 * else {
Chris@0 441 * $data = my_module_complicated_calculation();
Chris@0 442 * \Drupal::cache()->set($cid, $data);
Chris@0 443 * }
Chris@0 444 * @endcode
Chris@0 445 *
Chris@0 446 * Note the use of $data and $cache->data in the above example. Calls to
Chris@0 447 * \Drupal::cache()->get() return a record that contains the information stored
Chris@0 448 * by \Drupal::cache()->set() in the data property as well as additional meta
Chris@0 449 * information about the cached data. In order to make use of the cached data
Chris@0 450 * you can access it via $cache->data.
Chris@0 451 *
Chris@0 452 * @section bins Cache bins
Chris@0 453 *
Chris@0 454 * Cache storage is separated into "bins", each containing various cache items.
Chris@0 455 * Each bin can be configured separately; see @ref configuration.
Chris@0 456 *
Chris@0 457 * When you request a cache object, you can specify the bin name in your call to
Chris@0 458 * \Drupal::cache(). Alternatively, you can request a bin by getting service
Chris@0 459 * "cache.nameofbin" from the container. The default bin is called "default", with
Chris@0 460 * service name "cache.default", it is used to store common and frequently used
Chris@0 461 * caches.
Chris@0 462 *
Chris@0 463 * Other common cache bins are the following:
Chris@0 464 * - bootstrap: Data needed from the beginning to the end of most requests,
Chris@0 465 * that has a very strict limit on variations and is invalidated rarely.
Chris@0 466 * - render: Contains cached HTML strings like cached pages and blocks, can
Chris@0 467 * grow to large size.
Chris@0 468 * - data: Contains data that can vary by path or similar context.
Chris@0 469 * - discovery: Contains cached discovery data for things such as plugins,
Chris@0 470 * views_data, or YAML discovered data such as library info.
Chris@0 471 *
Chris@0 472 * A module can define a cache bin by defining a service in its
Chris@0 473 * modulename.services.yml file as follows (substituting the desired name for
Chris@0 474 * "nameofbin"):
Chris@0 475 * @code
Chris@0 476 * cache.nameofbin:
Chris@0 477 * class: Drupal\Core\Cache\CacheBackendInterface
Chris@0 478 * tags:
Chris@0 479 * - { name: cache.bin }
Chris@0 480 * factory: cache_factory:get
Chris@0 481 * arguments: [nameofbin]
Chris@0 482 * @endcode
Chris@0 483 * See the @link container Services topic @endlink for more on defining
Chris@0 484 * services.
Chris@0 485 *
Chris@0 486 * @section delete Deletion
Chris@0 487 *
Chris@0 488 * There are two ways to remove an item from the cache:
Chris@0 489 * - Deletion (using delete(), deleteMultiple() or deleteAll()) permanently
Chris@0 490 * removes the item from the cache.
Chris@0 491 * - Invalidation (using invalidate(), invalidateMultiple() or invalidateAll())
Chris@0 492 * is a "soft" delete that only marks items as "invalid", meaning "not fresh"
Chris@0 493 * or "not fresh enough". Invalid items are not usually returned from the
Chris@0 494 * cache, so in most ways they behave as if they have been deleted. However,
Chris@0 495 * it is possible to retrieve invalid items, if they have not yet been
Chris@0 496 * permanently removed by the garbage collector, by passing TRUE as the second
Chris@0 497 * argument for get($cid, $allow_invalid).
Chris@0 498 *
Chris@0 499 * Use deletion if a cache item is no longer useful; for instance, if the item
Chris@0 500 * contains references to data that has been deleted. Use invalidation if the
Chris@0 501 * cached item may still be useful to some callers until it has been updated
Chris@0 502 * with fresh data. The fact that it was fresh a short while ago may often be
Chris@0 503 * sufficient.
Chris@0 504 *
Chris@0 505 * Invalidation is particularly useful to protect against stampedes. Rather than
Chris@0 506 * having multiple concurrent requests updating the same cache item when it
Chris@0 507 * expires or is deleted, there can be one request updating the cache, while the
Chris@0 508 * other requests can proceed using the stale value. As soon as the cache item
Chris@0 509 * has been updated, all future requests will use the updated value.
Chris@0 510 *
Chris@0 511 * @section tags Cache Tags
Chris@0 512 *
Chris@0 513 * The fourth argument of the set() method can be used to specify cache tags,
Chris@0 514 * which are used to identify which data is included in each cache item. A cache
Chris@0 515 * item can have multiple cache tags (an array of cache tags), and each cache
Chris@0 516 * tag is a string. The convention is to generate cache tags of the form
Chris@0 517 * [prefix]:[suffix]. Usually, you'll want to associate the cache tags of
Chris@0 518 * entities, or entity listings. You won't have to manually construct cache tags
Chris@0 519 * for them — just get their cache tags via
Chris@0 520 * \Drupal\Core\Cache\CacheableDependencyInterface::getCacheTags() and
Chris@0 521 * \Drupal\Core\Entity\EntityTypeInterface::getListCacheTags().
Chris@0 522 * Data that has been tagged can be invalidated as a group: no matter the Cache
Chris@0 523 * ID (cid) of the cache item, no matter in which cache bin a cache item lives;
Chris@0 524 * as long as it is tagged with a certain cache tag, it will be invalidated.
Chris@0 525 *
Chris@0 526 * Because of that, cache tags are a solution to the cache invalidation problem:
Chris@0 527 * - For caching to be effective, each cache item must only be invalidated when
Chris@0 528 * absolutely necessary. (i.e. maximizing the cache hit ratio.)
Chris@0 529 * - For caching to be correct, each cache item that depends on a certain thing
Chris@0 530 * must be invalidated whenever that certain thing is modified.
Chris@0 531 *
Chris@0 532 * A typical scenario: a user has modified a node that appears in two views,
Chris@0 533 * three blocks and on twelve pages. Without cache tags, we couldn't possibly
Chris@0 534 * know which cache items to invalidate, so we'd have to invalidate everything:
Chris@0 535 * we had to sacrifice effectiveness to achieve correctness. With cache tags, we
Chris@0 536 * can have both.
Chris@0 537 *
Chris@0 538 * Example:
Chris@0 539 * @code
Chris@0 540 * // A cache item with nodes, users, and some custom module data.
Chris@0 541 * $tags = array(
Chris@0 542 * 'my_custom_tag',
Chris@0 543 * 'node:1',
Chris@0 544 * 'node:3',
Chris@0 545 * 'user:7',
Chris@0 546 * );
Chris@0 547 * \Drupal::cache()->set($cid, $data, CacheBackendInterface::CACHE_PERMANENT, $tags);
Chris@0 548 *
Chris@0 549 * // Invalidate all cache items with certain tags.
Chris@0 550 * \Drupal\Core\Cache\Cache::invalidateTags(array('user:1'));
Chris@0 551 * @endcode
Chris@0 552 *
Chris@0 553 * Drupal is a content management system, so naturally you want changes to your
Chris@0 554 * content to be reflected everywhere, immediately. That's why we made sure that
Chris@0 555 * every entity type in Drupal 8 automatically has support for cache tags: when
Chris@0 556 * you save an entity, you can be sure that the cache items that have the
Chris@0 557 * corresponding cache tags will be invalidated.
Chris@0 558 * This also is the case when you define your own entity types: you'll get the
Chris@0 559 * exact same cache tag invalidation as any of the built-in entity types, with
Chris@0 560 * the ability to override any of the default behavior if needed.
Chris@0 561 * See \Drupal\Core\Cache\CacheableDepenencyInterface::getCacheTags(),
Chris@0 562 * \Drupal\Core\Entity\EntityTypeInterface::getListCacheTags(),
Chris@0 563 * \Drupal\Core\Entity\Entity::invalidateTagsOnSave() and
Chris@0 564 * \Drupal\Core\Entity\Entity::invalidateTagsOnDelete().
Chris@0 565 *
Chris@0 566 * @section context Cache contexts
Chris@0 567 *
Chris@0 568 * Some computed data depends on contextual data, such as the user roles of the
Chris@0 569 * logged-in user who is viewing a page, the language the page is being rendered
Chris@0 570 * in, the theme being used, etc. When caching the output of such a calculation,
Chris@0 571 * you must cache each variation separately, along with information about which
Chris@0 572 * variation of the contextual data was used in the calculatation. The next time
Chris@0 573 * the computed data is needed, if the context matches that for an existing
Chris@0 574 * cached data set, the cached data can be reused; if no context matches, a new
Chris@0 575 * data set can be calculated and cached for later use.
Chris@0 576 *
Chris@0 577 * Cache contexts are services tagged with 'cache.context', whose classes
Chris@0 578 * implement \Drupal\Core\Cache\Context\CacheContextInterface. See
Chris@0 579 * https://www.drupal.org/developing/api/8/cache/contexts for more information
Chris@0 580 * on cache contexts, including a list of the contexts that exist in Drupal
Chris@0 581 * core, and information on how to define your own contexts. See the
Chris@0 582 * @link container Services and the Dependency Injection Container @endlink
Chris@0 583 * topic for more information about services.
Chris@0 584 *
Chris@0 585 * Typically, the cache context is specified as part of the #cache property
Chris@0 586 * of a render array; see the Caching section of the
Chris@0 587 * @link theme_render Render API overview topic @endlink for details.
Chris@0 588 *
Chris@0 589 * @section configuration Configuration
Chris@0 590 *
Chris@0 591 * By default cached data is stored in the database. This can be configured
Chris@0 592 * though so that all cached data, or that of an individual cache bin, uses a
Chris@0 593 * different cache backend, such as APCu or Memcache, for storage.
Chris@0 594 *
Chris@0 595 * In a settings.php file, you can override the service used for a particular
Chris@0 596 * cache bin. For example, if your service implementation of
Chris@0 597 * \Drupal\Core\Cache\CacheBackendInterface was called cache.custom, the
Chris@0 598 * following line would make Drupal use it for the 'cache_render' bin:
Chris@0 599 * @code
Chris@0 600 * $settings['cache']['bins']['render'] = 'cache.custom';
Chris@0 601 * @endcode
Chris@0 602 *
Chris@0 603 * Additionally, you can register your cache implementation to be used by
Chris@0 604 * default for all cache bins with:
Chris@0 605 * @code
Chris@0 606 * $settings['cache']['default'] = 'cache.custom';
Chris@0 607 * @endcode
Chris@0 608 *
Chris@0 609 * For cache bins that are stored in the database, the number of rows is limited
Chris@0 610 * to 5000 by default. This can be changed for all database cache bins. For
Chris@0 611 * example, to instead limit the number of rows to 50000:
Chris@0 612 * @code
Chris@0 613 * $settings['database_cache_max_rows']['default'] = 50000;
Chris@0 614 * @endcode
Chris@0 615 *
Chris@0 616 * Or per bin (in this example we allow infinite entries):
Chris@0 617 * @code
Chris@0 618 * $settings['database_cache_max_rows']['bins']['dynamic_page_cache'] = -1;
Chris@0 619 * @endcode
Chris@0 620 *
Chris@0 621 * For monitoring reasons it might be useful to figure out the amount of data
Chris@0 622 * stored in tables. The following SQL snippet can be used for that:
Chris@0 623 * @code
Chris@0 624 * SELECT table_name AS `Table`, table_rows AS 'Num. of Rows',
Chris@0 625 * ROUND(((data_length + index_length) / 1024 / 1024), 2) `Size in MB` FROM
Chris@0 626 * information_schema.TABLES WHERE table_schema = '***DATABASE_NAME***' AND
Chris@0 627 * table_name LIKE 'cache_%' ORDER BY (data_length + index_length) DESC
Chris@0 628 * LIMIT 10;
Chris@0 629 * @endcode
Chris@0 630 *
Chris@0 631 * @see \Drupal\Core\Cache\DatabaseBackend
Chris@0 632 *
Chris@0 633 * Finally, you can chain multiple cache backends together, see
Chris@0 634 * \Drupal\Core\Cache\ChainedFastBackend and \Drupal\Core\Cache\BackendChain.
Chris@0 635 *
Chris@0 636 * @see https://www.drupal.org/node/1884796
Chris@0 637 * @}
Chris@0 638 */
Chris@0 639
Chris@0 640 /**
Chris@0 641 * @defgroup user_api User accounts, permissions, and roles
Chris@0 642 * @{
Chris@0 643 * API for user accounts, access checking, roles, and permissions.
Chris@0 644 *
Chris@0 645 * @section sec_overview Overview and terminology
Chris@0 646 * Drupal's permission system is based on the concepts of accounts, roles,
Chris@0 647 * and permissions.
Chris@0 648 *
Chris@0 649 * Users (site visitors) have accounts, which include a user name, an email
Chris@0 650 * address, a password (or some other means of authentication), and possibly
Chris@0 651 * other fields (if defined on the site). Anonymous users have an implicit
Chris@0 652 * account that does not have a real user name or any account information.
Chris@0 653 *
Chris@0 654 * Each user account is assigned one or more roles. The anonymous user account
Chris@0 655 * automatically has the anonymous user role; real user accounts
Chris@0 656 * automatically have the authenticated user role, plus any roles defined on
Chris@0 657 * the site that they have been assigned.
Chris@0 658 *
Chris@0 659 * Each role, including the special anonymous and authenticated user roles, is
Chris@0 660 * granted one or more named permissions, which allow them to perform certain
Chris@0 661 * tasks or view certain content on the site. It is possible to designate a
Chris@0 662 * role to be the "administrator" role; if this is set up, this role is
Chris@0 663 * automatically granted all available permissions whenever a module is
Chris@0 664 * enabled that defines permissions.
Chris@0 665 *
Chris@0 666 * All code in Drupal that allows users to perform tasks or view content must
Chris@0 667 * check that the current user has the correct permission before allowing the
Chris@0 668 * action. In the standard case, access checking consists of answering the
Chris@0 669 * question "Does the current user have permission 'foo'?", and allowing or
Chris@0 670 * denying access based on the answer. Note that access checking should nearly
Chris@0 671 * always be done at the permission level, not by checking for a particular role
Chris@0 672 * or user ID, so that site administrators can set up user accounts and roles
Chris@0 673 * appropriately for their particular sites.
Chris@0 674 *
Chris@0 675 * @section sec_define Defining permissions
Chris@0 676 * Modules define permissions via a $module.permissions.yml file. See
Chris@0 677 * \Drupal\user\PermissionHandler for documentation of permissions.yml files.
Chris@0 678 *
Chris@0 679 * @section sec_access Access permission checking
Chris@0 680 * Depending on the situation, there are several methods for ensuring that
Chris@0 681 * access checks are done properly in Drupal:
Chris@0 682 * - Routes: When you register a route, include a 'requirements' section that
Chris@0 683 * either gives the machine name of the permission that is needed to visit the
Chris@0 684 * URL of the route, or tells Drupal to use an access check method or service
Chris@0 685 * to check access. See the @link menu Routing topic @endlink for more
Chris@0 686 * information.
Chris@0 687 * - Entities: Access for various entity operations is designated either with
Chris@0 688 * simple permissions or access control handler classes in the entity
Chris@0 689 * annotation. See the @link entity_api Entity API topic @endlink for more
Chris@0 690 * information.
Chris@0 691 * - Other code: There is a 'current_user' service, which can be injected into
Chris@0 692 * classes to provide access to the current user account (see the
Chris@0 693 * @link container Services and Dependency Injection topic @endlink for more
Chris@0 694 * information on dependency injection). In code that cannot use dependency
Chris@0 695 * injection, you can access this service and retrieve the current user
Chris@0 696 * account object by calling \Drupal::currentUser(). Once you have a user
Chris@0 697 * object for the current user (implementing \Drupal\user\UserInterface), you
Chris@0 698 * can call inherited method
Chris@0 699 * \Drupal\Core\Session\AccountInterface::hasPermission() to check
Chris@0 700 * permissions, or pass this object into other functions/methods.
Chris@0 701 * - Forms: Each element of a form array can have a Boolean '#access' property,
Chris@0 702 * which determines whether that element is visible and/or usable. This is a
Chris@0 703 * common need in forms, so the current user service (described above) is
Chris@0 704 * injected into the form base class as method
Chris@0 705 * \Drupal\Core\Form\FormBase::currentUser().
Chris@0 706 *
Chris@0 707 * @section sec_entities User and role objects
Chris@0 708 * User objects in Drupal are entity items, implementing
Chris@0 709 * \Drupal\user\UserInterface. Role objects in Drupal are also entity items,
Chris@0 710 * implementing \Drupal\user\RoleInterface. See the
Chris@0 711 * @link entity_api Entity API topic @endlink for more information about
Chris@0 712 * entities in general (including how to load, create, modify, and query them).
Chris@0 713 *
Chris@0 714 * Roles often need to be manipulated in automated test code, such as to add
Chris@0 715 * permissions to them. Here's an example:
Chris@0 716 * @code
Chris@0 717 * $role = \Drupal\user\Entity\Role::load('authenticated');
Chris@0 718 * $role->grantPermission('access comments');
Chris@0 719 * $role->save();
Chris@0 720 * @endcode
Chris@0 721 *
Chris@0 722 * Other important interfaces:
Chris@0 723 * - \Drupal\Core\Session\AccountInterface: The part of UserInterface that
Chris@0 724 * deals with access checking. In writing code that checks access, your
Chris@0 725 * method parameters should use this interface, not UserInterface.
Chris@0 726 * - \Drupal\Core\Session\AccountProxyInterface: The interface for the
Chris@0 727 * current_user service (described above).
Chris@0 728 * @}
Chris@0 729 */
Chris@0 730
Chris@0 731 /**
Chris@0 732 * @defgroup container Services and Dependency Injection Container
Chris@0 733 * @{
Chris@0 734 * Overview of the Dependency Injection Container and Services.
Chris@0 735 *
Chris@0 736 * @section sec_overview Overview of container, injection, and services
Chris@0 737 * The Services and Dependency Injection Container concepts have been adopted by
Chris@0 738 * Drupal from the @link http://symfony.com/ Symfony framework. @endlink A
Chris@0 739 * "service" (such as accessing the database, sending email, or translating user
Chris@0 740 * interface text) is defined (given a name and an interface or at least a
Chris@0 741 * class that defines the methods that may be called), and a default class is
Chris@0 742 * designated to provide the service. These two steps must be done together, and
Chris@0 743 * can be done by Drupal Core or a module. Other modules can then define
Chris@0 744 * alternative classes to provide the same services, overriding the default
Chris@0 745 * classes. Classes and functions that need to use the service should always
Chris@0 746 * instantiate the class via the dependency injection container (also known
Chris@0 747 * simply as the "container"), rather than instantiating a particular service
Chris@0 748 * provider class directly, so that they get the correct class (default or
Chris@0 749 * overridden).
Chris@0 750 *
Chris@0 751 * See https://www.drupal.org/node/2133171 for more detailed information on
Chris@0 752 * services and the dependency injection container.
Chris@0 753 *
Chris@0 754 * @section sec_discover Discovering existing services
Chris@0 755 * Drupal core defines many core services in the core.services.yml file (in the
Chris@0 756 * top-level core directory). Some Drupal Core modules and contributed modules
Chris@0 757 * also define services in modulename.services.yml files. API reference sites
Chris@0 758 * (such as https://api.drupal.org) generate lists of all existing services from
Chris@0 759 * these files. Look for the Services link in the API Navigation block.
Chris@0 760 * Alternatively you can look through the individual files manually.
Chris@0 761 *
Chris@0 762 * A typical service definition in a *.services.yml file looks like this:
Chris@0 763 * @code
Chris@0 764 * path.alias_manager:
Chris@0 765 * class: Drupal\Core\Path\AliasManager
Chris@0 766 * arguments: ['@path.crud', '@path.alias_whitelist', '@language_manager']
Chris@0 767 * @endcode
Chris@0 768 * Some services use other services as factories; a typical service definition
Chris@0 769 * is:
Chris@0 770 * @code
Chris@0 771 * cache.entity:
Chris@0 772 * class: Drupal\Core\Cache\CacheBackendInterface
Chris@0 773 * tags:
Chris@0 774 * - { name: cache.bin }
Chris@0 775 * factory: cache_factory:get
Chris@0 776 * arguments: [entity]
Chris@0 777 * @endcode
Chris@0 778 *
Chris@0 779 * The first line of a service definition gives the unique machine name of the
Chris@0 780 * service. This is often prefixed by the module name if provided by a module;
Chris@0 781 * however, by convention some service names are prefixed by a group name
Chris@0 782 * instead, such as cache.* for cache bins and plugin.manager.* for plugin
Chris@0 783 * managers.
Chris@0 784 *
Chris@0 785 * The class line either gives the default class that provides the service, or
Chris@0 786 * if the service uses a factory class, the interface for the service. If the
Chris@0 787 * class depends on other services, the arguments line lists the machine
Chris@0 788 * names of the dependencies (preceded by '@'); objects for each of these
Chris@0 789 * services are instantiated from the container and passed to the class
Chris@0 790 * constructor when the service class is instantiated. Other arguments can also
Chris@0 791 * be passed in; see the section at https://www.drupal.org/node/2133171 for more
Chris@0 792 * detailed information.
Chris@0 793 *
Chris@0 794 * Services using factories can be defined as shown in the above example, if the
Chris@0 795 * factory is itself a service. The factory can also be a class; details of how
Chris@0 796 * to use service factories can be found in the section at
Chris@0 797 * https://www.drupal.org/node/2133171.
Chris@0 798 *
Chris@0 799 * @section sec_container Accessing a service through the container
Chris@0 800 * As noted above, if you need to use a service in your code, you should always
Chris@0 801 * instantiate the service class via a call to the container, using the machine
Chris@0 802 * name of the service, so that the default class can be overridden. There are
Chris@0 803 * several ways to make sure this happens:
Chris@0 804 * - For service-providing classes, see other sections of this documentation
Chris@0 805 * describing how to pass services as arguments to the constructor.
Chris@0 806 * - Plugin classes, controllers, and similar classes have create() or
Chris@0 807 * createInstance() methods that are used to create an instance of the class.
Chris@0 808 * These methods come from different interfaces, and have different
Chris@0 809 * arguments, but they all include an argument $container of type
Chris@0 810 * \Symfony\Component\DependencyInjection\ContainerInterface.
Chris@0 811 * If you are defining one of these classes, in the create() or
Chris@0 812 * createInstance() method, call $container->get('myservice.name') to
Chris@0 813 * instantiate a service. The results of these calls are generally passed to
Chris@0 814 * the class constructor and saved as member variables in the class.
Chris@0 815 * - For functions and class methods that do not have access to either of
Chris@0 816 * the above methods of dependency injection, you can use service location to
Chris@0 817 * access services, via a call to the global \Drupal class. This class has
Chris@0 818 * special methods for accessing commonly-used services, or you can call a
Chris@0 819 * generic method to access any service. Examples:
Chris@0 820 * @code
Chris@0 821 * // Retrieve the entity.manager service object (special method exists).
Chris@0 822 * $manager = \Drupal::entityManager();
Chris@0 823 * // Retrieve the service object for machine name 'foo.bar'.
Chris@0 824 * $foobar = \Drupal::service('foo.bar');
Chris@0 825 * @endcode
Chris@0 826 *
Chris@0 827 * As a note, you should always use dependency injection (via service arguments
Chris@0 828 * or create()/createInstance() methods) if possible to instantiate services,
Chris@0 829 * rather than service location (via the \Drupal class), because:
Chris@0 830 * - Dependency injection facilitates writing unit tests, since the container
Chris@0 831 * argument can be mocked and the create() method can be bypassed by using
Chris@0 832 * the class constructor. If you use the \Drupal class, unit tests are much
Chris@0 833 * harder to write and your code has more dependencies.
Chris@0 834 * - Having the service interfaces on the class constructor and member variables
Chris@0 835 * is useful for IDE auto-complete and self-documentation.
Chris@0 836 *
Chris@0 837 * @section sec_define Defining a service
Chris@0 838 * If your module needs to define a new service, here are the steps:
Chris@0 839 * - Choose a unique machine name for your service. Typically, this should
Chris@0 840 * start with your module name. Example: mymodule.myservice.
Chris@0 841 * - Create a PHP interface to define what your service does.
Chris@0 842 * - Create a default class implementing your interface that provides your
Chris@0 843 * service. If your class needs to use existing services (such as database
Chris@0 844 * access), be sure to make these services arguments to your class
Chris@0 845 * constructor, and save them in member variables. Also, if the needed
Chris@0 846 * services are provided by other modules and not Drupal Core, you'll want
Chris@0 847 * these modules to be dependencies of your module.
Chris@0 848 * - Add an entry to a modulename.services.yml file for the service. See
Chris@0 849 * @ref sec_discover above, or existing *.services.yml files in Core, for the
Chris@0 850 * syntax; it will start with your machine name, refer to your default class,
Chris@0 851 * and list the services that need to be passed into your constructor.
Chris@0 852 *
Chris@0 853 * Services can also be defined dynamically, as in the
Chris@0 854 * \Drupal\Core\CoreServiceProvider class, but this is less common for modules.
Chris@0 855 *
Chris@0 856 * @section sec_tags Service tags
Chris@0 857 * Some services have tags, which are defined in the service definition. See
Chris@0 858 * @link service_tag Service Tags @endlink for usage.
Chris@0 859 *
Chris@0 860 * @section sec_injection Overriding the default service class
Chris@0 861 * Modules can override the default classes used for services. Here are the
Chris@0 862 * steps:
Chris@0 863 * - Define a class in the top-level namespace for your module
Chris@0 864 * (Drupal\my_module), whose name is the camel-case version of your module's
Chris@0 865 * machine name followed by "ServiceProvider" (for example, if your module
Chris@0 866 * machine name is my_module, the class must be named
Chris@0 867 * MyModuleServiceProvider).
Chris@0 868 * - The class needs to implement
Chris@0 869 * \Drupal\Core\DependencyInjection\ServiceModifierInterface, which is
Chris@0 870 * typically done by extending
Chris@0 871 * \Drupal\Core\DependencyInjection\ServiceProviderBase.
Chris@0 872 * - The class needs to contain one method: alter(). This method does the
Chris@0 873 * actual work of telling Drupal to use your class instead of the default.
Chris@0 874 * Here's an example:
Chris@0 875 * @code
Chris@0 876 * public function alter(ContainerBuilder $container) {
Chris@0 877 * // Override the language_manager class with a new class.
Chris@0 878 * $definition = $container->getDefinition('language_manager');
Chris@0 879 * $definition->setClass('Drupal\my_module\MyLanguageManager');
Chris@0 880 * }
Chris@0 881 * @endcode
Chris@0 882 * Note that $container here is an instance of
Chris@0 883 * \Drupal\Core\DependencyInjection\ContainerBuilder.
Chris@0 884 *
Chris@0 885 * @see https://www.drupal.org/node/2133171
Chris@0 886 * @see core.services.yml
Chris@0 887 * @see \Drupal
Chris@0 888 * @see \Symfony\Component\DependencyInjection\ContainerInterface
Chris@0 889 * @see plugin_api
Chris@0 890 * @see menu
Chris@0 891 * @}
Chris@0 892 */
Chris@0 893
Chris@0 894 /**
Chris@0 895 * @defgroup listing_page_service Page header for Services page
Chris@0 896 * @{
Chris@0 897 * Introduction to services
Chris@0 898 *
Chris@0 899 * A "service" (such as accessing the database, sending email, or translating
Chris@0 900 * user interface text) can be defined by a module or Drupal core. Defining a
Chris@0 901 * service means giving it a name and designating a default class to provide the
Chris@0 902 * service; ideally, there should also be an interface that defines the methods
Chris@0 903 * that may be called. Services are collected into the Dependency Injection
Chris@0 904 * Container, and can be overridden to use different classes or different
Chris@0 905 * instantiation by modules. See the
Chris@0 906 * @link container Services and Dependency Injection Container topic @endlink
Chris@0 907 * for details.
Chris@0 908 *
Chris@0 909 * Some services have tags, which are defined in the service definition. Tags
Chris@0 910 * are used to define a group of related services, or to specify some aspect of
Chris@0 911 * how the service behaves. See the
Chris@0 912 * @link service_tag Service Tags topic @endlink for more information.
Chris@0 913 *
Chris@0 914 * @see container
Chris@0 915 * @see service_tag
Chris@0 916 *
Chris@0 917 * @}
Chris@0 918 */
Chris@0 919
Chris@0 920 /**
Chris@0 921 * @defgroup typed_data Typed Data API
Chris@0 922 * @{
Chris@0 923 * API for describing data based on a set of available data types.
Chris@0 924 *
Chris@0 925 * PHP has data types, such as int, string, float, array, etc., and it is an
Chris@0 926 * object-oriented language that lets you define classes and interfaces.
Chris@0 927 * However, in some cases, it is useful to be able to define an abstract
Chris@0 928 * type (as in an interface, free of implementation details), that still has
Chris@0 929 * properties (which an interface cannot) as well as meta-data. The Typed Data
Chris@0 930 * API provides this abstraction.
Chris@0 931 *
Chris@0 932 * @section sec_overview Overview
Chris@0 933 * Each data type in the Typed Data API is a plugin class (annotation class
Chris@0 934 * example: \Drupal\Core\TypedData\Annotation\DataType); these plugins are
Chris@0 935 * managed by the typed_data_manager service (by default
Chris@0 936 * \Drupal\Core\TypedData\TypedDataManager). Each data object encapsulates a
Chris@0 937 * single piece of data, provides access to the metadata, and provides
Chris@0 938 * validation capability. Also, the typed data plugins have a shorthand
Chris@0 939 * for easily accessing data values, described in @ref sec_tree.
Chris@0 940 *
Chris@0 941 * The metadata of a data object is defined by an object based on a class called
Chris@0 942 * the definition class (see \Drupal\Core\TypedData\DataDefinitionInterface).
Chris@0 943 * The class used can vary by data type and can be specified in the data type's
Chris@0 944 * plugin definition, while the default is set in the $definition_class property
Chris@0 945 * of the annotation class. The default class is
Chris@0 946 * \Drupal\Core\TypedData\DataDefinition. For data types provided by a plugin
Chris@0 947 * deriver, the plugin deriver can set the definition_class property too.
Chris@0 948 * The metadata object provides information about the data, such as the data
Chris@0 949 * type, whether it is translatable, the names of its properties (for complex
Chris@0 950 * types), and who can access it.
Chris@0 951 *
Chris@0 952 * See https://www.drupal.org/node/1794140 for more information about the Typed
Chris@0 953 * Data API.
Chris@0 954 *
Chris@0 955 * @section sec_varieties Varieties of typed data
Chris@0 956 * There are three kinds of typed data: primitive, complex, and list.
Chris@0 957 *
Chris@0 958 * @subsection sub_primitive Primitive data types
Chris@0 959 * Primitive data types wrap PHP data types and also serve as building blocks
Chris@0 960 * for complex and list typed data. Each primitive data type has an interface
Chris@0 961 * that extends \Drupal\Core\TypedData\PrimitiveInterface, with getValue()
Chris@0 962 * and setValue() methods for accessing the data value, and a default plugin
Chris@0 963 * implementation. Here's a list:
Chris@0 964 * - \Drupal\Core\TypedData\Type\IntegerInterface: Plugin ID integer,
Chris@0 965 * corresponds to PHP type int.
Chris@0 966 * - \Drupal\Core\TypedData\Type\StringInterface: Plugin ID string,
Chris@0 967 * corresponds to PHP type string.
Chris@0 968 * - \Drupal\Core\TypedData\Type\FloatInterface: Plugin ID float,
Chris@0 969 * corresponds to PHP type float.
Chris@0 970 * - \Drupal\Core\TypedData\Type\BooleanInterface: Plugin ID bool,
Chris@0 971 * corresponds to PHP type bool.
Chris@0 972 * - \Drupal\Core\TypedData\Type\BinaryInterface: Plugin ID binary,
Chris@0 973 * corresponds to a PHP file resource.
Chris@0 974 * - \Drupal\Core\TypedData\Type\UriInterface: Plugin ID uri.
Chris@0 975 *
Chris@0 976 * @subsection sec_complex Complex data
Chris@0 977 * Complex data types, with interface
Chris@0 978 * \Drupal\Core\TypedData\ComplexDataInterface, represent data with named
Chris@0 979 * properties; the properties can be accessed with get() and set() methods.
Chris@0 980 * The value of each property is itself a typed data object, which can be
Chris@0 981 * primitive, complex, or list data.
Chris@0 982 *
Chris@0 983 * The base type for most complex data is the
Chris@0 984 * \Drupal\Core\TypedData\Plugin\DataType\Map class, which represents an
Chris@0 985 * associative array. Map provides its own definition class in the annotation,
Chris@0 986 * \Drupal\Core\TypedData\MapDataDefinition, and most complex data classes
Chris@0 987 * extend this class. The getValue() and setValue() methods on the Map class
Chris@0 988 * enforce the data definition and its property structure.
Chris@0 989 *
Chris@0 990 * The Drupal Field API uses complex typed data for its field items, with
Chris@0 991 * definition class \Drupal\Core\Field\TypedData\FieldItemDataDefinition.
Chris@0 992 *
Chris@0 993 * @section sec_list Lists
Chris@0 994 * List data types, with interface \Drupal\Core\TypedData\ListInterface,
Chris@0 995 * represent data that is an ordered list of typed data, all of the same type.
Chris@0 996 * More precisely, the plugins in the list must have the same base plugin ID;
Chris@0 997 * however, some types (for example field items and entities) are provided by
Chris@0 998 * plugin derivatives and the sub IDs can be different.
Chris@0 999 *
Chris@0 1000 * @section sec_tree Tree handling
Chris@0 1001 * Typed data allows you to use shorthand to get data values nested in the
Chris@0 1002 * implicit tree structure of the data. For example, to get the value from
Chris@0 1003 * an entity field item, the Entity Field API allows you to call:
Chris@0 1004 * @code
Chris@0 1005 * $value = $entity->fieldName->propertyName;
Chris@0 1006 * @endcode
Chris@0 1007 * This is really shorthand for:
Chris@0 1008 * @code
Chris@0 1009 * $field_item_list = $entity->get('fieldName');
Chris@0 1010 * $field_item = $field_item_list->get(0);
Chris@0 1011 * $property = $field_item->get('propertyName');
Chris@0 1012 * $value = $property->getValue();
Chris@0 1013 * @endcode
Chris@0 1014 * Some notes:
Chris@0 1015 * - $property, $field_item, and $field_item_list are all typed data objects,
Chris@0 1016 * while $value is a raw PHP value.
Chris@0 1017 * - You can call $property->getParent() to get $field_item,
Chris@0 1018 * $field_item->getParent() to get $field_item_list, or
Chris@0 1019 * $field_item_list->getParent() to get $typed_entity ($entity wrapped in a
Chris@0 1020 * typed data object). $typed_entity->getParent() is NULL.
Chris@0 1021 * - For all of these ->getRoot() returns $typed_entity.
Chris@0 1022 * - The langcode property is on $field_item_list, but you can access it
Chris@0 1023 * on $property as well, so that all items will report the same langcode.
Chris@0 1024 * - When the value of $property is changed by calling $property->setValue(),
Chris@0 1025 * $property->onChange() will fire, which in turn calls the parent object's
Chris@0 1026 * onChange() method and so on. This allows parent objects to react upon
Chris@0 1027 * changes of contained properties or list items.
Chris@0 1028 *
Chris@0 1029 * @section sec_defining Defining data types
Chris@0 1030 * To define a new data type:
Chris@0 1031 * - Create a class that implements one of the Typed Data interfaces.
Chris@0 1032 * Typically, you will want to extend one of the classes listed in the
Chris@0 1033 * sections above as a starting point.
Chris@0 1034 * - Make your class into a DataType plugin. To do that, put it in namespace
Chris@0 1035 * \Drupal\yourmodule\Plugin\DataType (where "yourmodule" is your module's
Chris@0 1036 * short name), and add annotation of type
Chris@0 1037 * \Drupal\Core\TypedData\Annotation\DataType to the documentation header.
Chris@0 1038 * See the @link plugin_api Plugin API topic @endlink and the
Chris@0 1039 * @link annotation Annotations topic @endlink for more information.
Chris@0 1040 *
Chris@0 1041 * @section sec_using Using data types
Chris@0 1042 * The data types of the Typed Data API can be used in several ways, once they
Chris@0 1043 * have been defined:
Chris@0 1044 * - In the Field API, data types can be used as the class in the property
Chris@0 1045 * definition of the field. See the @link field Field API topic @endlink for
Chris@0 1046 * more information.
Chris@0 1047 * - In configuration schema files, you can use the unique ID ('id' annotation)
Chris@0 1048 * from any DataType plugin class as the 'type' value for an entry. See the
Chris@0 1049 * @link config_api Confuration API topic @endlink for more information.
Chris@0 1050 * - If you need to create a typed data object in code, first get the
Chris@0 1051 * typed_data_manager service from the container or by calling
Chris@0 1052 * \Drupal::typedDataManager(). Then pass the plugin ID to
Chris@0 1053 * $manager::createDataDefinition() to create an appropriate data definition
Chris@0 1054 * object. Then pass the data definition object and the value of the data to
Chris@0 1055 * $manager::create() to create a typed data object.
Chris@0 1056 *
Chris@0 1057 * @see plugin_api
Chris@0 1058 * @see container
Chris@0 1059 * @}
Chris@0 1060 */
Chris@0 1061
Chris@0 1062 /**
Chris@0 1063 * @defgroup testing Automated tests
Chris@0 1064 * @{
Chris@0 1065 * Overview of PHPUnit tests and Simpletest tests.
Chris@0 1066 *
Chris@0 1067 * The Drupal project has embraced a philosophy of using automated tests,
Chris@0 1068 * consisting of both unit tests (which test the functionality of classes at a
Chris@0 1069 * low level) and functional tests (which test the functionality of Drupal
Chris@0 1070 * systems at a higher level, usually involving web output). The goal is to
Chris@0 1071 * have test coverage for all or most of the components and features, and to
Chris@0 1072 * run the automated tests before any code is changed or added, to make sure
Chris@0 1073 * it doesn't break any existing functionality (regression testing).
Chris@0 1074 *
Chris@0 1075 * In order to implement this philosophy, developers need to do the following:
Chris@0 1076 * - When making a patch to fix a bug, make sure that the bug fix patch includes
Chris@0 1077 * a test that fails without the code change and passes with the code change.
Chris@0 1078 * This helps reviewers understand what the bug is, demonstrates that the code
Chris@0 1079 * actually fixes the bug, and ensures the bug will not reappear due to later
Chris@0 1080 * code changes.
Chris@0 1081 * - When making a patch to implement a new feature, include new unit and/or
Chris@0 1082 * functional tests in the patch. This serves to both demonstrate that the
Chris@0 1083 * code actually works, and ensure that later changes do not break the new
Chris@0 1084 * functionality.
Chris@0 1085 *
Chris@0 1086 * @section write_unit Writing PHPUnit tests for classes
Chris@0 1087 * PHPUnit tests for classes are written using the industry-standard PHPUnit
Chris@0 1088 * framework. Use a PHPUnit test to test functionality of a class if the Drupal
Chris@0 1089 * environment (database, settings, etc.) and web browser are not needed for the
Chris@0 1090 * test, or if the Drupal environment can be replaced by a "mock" object. To
Chris@0 1091 * write a PHPUnit test:
Chris@0 1092 * - Define a class that extends \Drupal\Tests\UnitTestCase.
Chris@0 1093 * - The class name needs to end in the word Test.
Chris@0 1094 * - The namespace must be a subspace/subdirectory of \Drupal\yourmodule\Tests,
Chris@0 1095 * where yourmodule is your module's machine name.
Chris@0 1096 * - The test class file must be named and placed under the
Chris@0 1097 * yourmodule/tests/src/Unit directory, according to the PSR-4 standard.
Chris@0 1098 * - Your test class needs a phpDoc comment block with a description and
Chris@0 1099 * a @group annotation, which gives information about the test.
Chris@0 1100 * - Add test cases by adding method names that start with 'test' and have no
Chris@0 1101 * arguments, for example testYourTestCase(). Each one should test a logical
Chris@0 1102 * subset of the functionality.
Chris@0 1103 * For more details, see:
Chris@0 1104 * - https://www.drupal.org/phpunit for full documentation on how to write
Chris@0 1105 * PHPUnit tests for Drupal.
Chris@0 1106 * - http://phpunit.de for general information on the PHPUnit framework.
Chris@0 1107 * - @link oo_conventions Object-oriented programming topic @endlink for more
Chris@0 1108 * on PSR-4, namespaces, and where to place classes.
Chris@0 1109 *
Chris@0 1110 * @section write_functional Writing functional tests
Chris@0 1111 * Functional tests are written using a Drupal-specific framework that is, for
Chris@0 1112 * historical reasons, known as "Simpletest". Use a Simpletest test to test the
Chris@0 1113 * functionality of sub-system of Drupal, if the functionality depends on the
Chris@0 1114 * Drupal database and settings, or to test the web output of Drupal. To
Chris@0 1115 * write a Simpletest test:
Chris@0 1116 * - For functional tests of the web output of Drupal, define a class that
Chris@0 1117 * extends \Drupal\simpletest\WebTestBase, which contains an internal web
Chris@0 1118 * browser and defines many helpful test assertion methods that you can use
Chris@0 1119 * in your tests. You can specify modules to be enabled by defining a
Chris@0 1120 * $modules member variable -- keep in mind that by default, WebTestBase uses
Chris@0 1121 * a "testing" install profile, with a minimal set of modules enabled.
Chris@0 1122 * - For functional tests that do not test web output, define a class that
Chris@0 1123 * extends \Drupal\KernelTests\KernelTestBase. This class is much faster
Chris@0 1124 * than WebTestBase, because instead of making a full install of Drupal, it
Chris@0 1125 * uses an in-memory pseudo-installation (similar to what the installer and
Chris@0 1126 * update scripts use). To use this test class, you will need to create the
Chris@0 1127 * database tables you need and install needed modules manually.
Chris@0 1128 * - The namespace must be a subspace/subdirectory of \Drupal\yourmodule\Tests,
Chris@0 1129 * where yourmodule is your module's machine name.
Chris@0 1130 * - The test class file must be named and placed under the yourmodule/src/Tests
Chris@0 1131 * directory, according to the PSR-4 standard.
Chris@0 1132 * - Your test class needs a phpDoc comment block with a description and
Chris@0 1133 * a @group annotation, which gives information about the test.
Chris@0 1134 * - You may also override the default setUp() method, which can set be used to
Chris@0 1135 * set up content types and similar procedures.
Chris@0 1136 * - In some cases, you may need to write a test module to support your test;
Chris@0 1137 * put such modules under the yourmodule/tests/modules directory.
Chris@0 1138 * - Add test cases by adding method names that start with 'test' and have no
Chris@0 1139 * arguments, for example testYourTestCase(). Each one should test a logical
Chris@0 1140 * subset of the functionality. Each method runs in a new, isolated test
Chris@0 1141 * environment, so it can only rely on the setUp() method, not what has
Chris@0 1142 * been set up by other test methods.
Chris@0 1143 * For more details, see:
Chris@0 1144 * - https://www.drupal.org/simpletest for full documentation on how to write
Chris@0 1145 * functional tests for Drupal.
Chris@0 1146 * - @link oo_conventions Object-oriented programming topic @endlink for more
Chris@0 1147 * on PSR-4, namespaces, and where to place classes.
Chris@0 1148 *
Chris@0 1149 * @section write_functional_phpunit Write functional PHP tests (phpunit)
Chris@0 1150 * Functional tests extend the BrowserTestBase base class, and use PHPUnit as
Chris@0 1151 * their underlying framework. They use a simulated browser, in which the test
Chris@0 1152 * can click links, visit URLs, post to forms, etc. To write a functional test:
Chris@0 1153 * - Extend \Drupal\Tests\BrowserTestBase.
Chris@0 1154 * - Place the test in the yourmodule/tests/src/Functional/ directory and use
Chris@0 1155 * the \Drupal\Tests\yourmodule\Functional namespace.
Chris@0 1156 * - Add a @group annotation. For example, if the test is for a Drupal 6
Chris@0 1157 * migration process, the group core uses is migrate_drupal_6. Use yourmodule
Chris@0 1158 * as the group name if the test does not belong to another larger group.
Chris@0 1159 * - You may also override the default setUp() method, which can be used to set
Chris@0 1160 * up content types and similar procedures. Don't forget to call the parent
Chris@0 1161 * method.
Chris@0 1162 * - In some cases, you may need to write a test module to support your test;
Chris@0 1163 * put such modules under the yourmodule/tests/modules directory.
Chris@0 1164 * - Add test cases by adding method names that start with 'test' and have no
Chris@0 1165 * arguments, for example testYourTestCase(). Each one should test a logical
Chris@0 1166 * subset of the functionality. Each method runs in a new, isolated test
Chris@0 1167 * environment, so it can only rely on the setUp() method, not what has
Chris@0 1168 * been set up by other test methods.
Chris@0 1169 * For more details, see:
Chris@0 1170 * - https://www.drupal.org/docs/8/phpunit/phpunit-browser-test-tutorial for
Chris@0 1171 * a full tutorial on how to write functional PHPUnit tests for Drupal.
Chris@0 1172 * - https://www.drupal.org/phpunit for the full documentation on how to write
Chris@0 1173 * PHPUnit tests for Drupal.
Chris@0 1174 *
Chris@0 1175 * @section write_jsfunctional_phpunit Write functional JavaScript tests (phpunit)
Chris@0 1176 * To write a functional test that relies on JavaScript:
Chris@0 1177 * - Extend \Drupal\FunctionalJavaScriptTests\JavascriptTestBase.
Chris@0 1178 * - Place the test into the yourmodule/tests/src/FunctionalJavascript/
Chris@0 1179 * directory and use the \Drupal\Tests\yourmodule\FunctionalJavascript
Chris@0 1180 * namespace.
Chris@0 1181 * - Add a @group annotation. Use yourmodule as the group name if the test does
Chris@0 1182 * not belong to another larger group.
Chris@0 1183 * - Set up PhantomJS; see http://phantomjs.org/download.html.
Chris@0 1184 * - To run tests, see core/tests/README.md.
Chris@0 1185 * - When clicking a link/button with Ajax behavior attached, keep in mind that
Chris@0 1186 * the underlying browser might take time to deliver changes to the HTML. Use
Chris@0 1187 * $this->assertSession()->assertWaitOnAjaxRequest() to wait for the Ajax
Chris@0 1188 * request to finish.
Chris@0 1189 * For more details, see:
Chris@0 1190 * - https://www.drupal.org/docs/8/phpunit/phpunit-javascript-testing-tutorial
Chris@0 1191 * for a full tutorial on how to write PHPUnit JavaScript tests for Drupal.
Chris@0 1192 * - https://www.drupal.org/phpunit for the full documentation on how to write
Chris@0 1193 * PHPUnit tests for Drupal.
Chris@0 1194 *
Chris@0 1195 * @section running Running tests
Chris@0 1196 * You can run both Simpletest and PHPUnit tests by enabling the core Testing
Chris@0 1197 * module (core/modules/simpletest). Once that module is enabled, tests can be
Chris@0 1198 * run using the core/scripts/run-tests.sh script, using
Chris@0 1199 * @link https://www.drupal.org/project/drush Drush @endlink, or from the
Chris@0 1200 * Testing module user interface.
Chris@0 1201 *
Chris@0 1202 * PHPUnit tests can also be run from the command line, using the PHPUnit
Chris@0 1203 * framework. See https://www.drupal.org/node/2116263 for more information.
Chris@0 1204 * @}
Chris@0 1205 */
Chris@0 1206
Chris@0 1207 /**
Chris@0 1208 * @defgroup php_assert PHP Runtime Assert Statements
Chris@0 1209 * @{
Chris@0 1210 * Use of the assert() statement in Drupal.
Chris@0 1211 *
Chris@0 1212 * Unit tests also use the term "assertion" to refer to test conditions, so to
Chris@0 1213 * avoid confusion the term "runtime assertion" will be used for the assert()
Chris@0 1214 * statement throughout the documentation.
Chris@0 1215 *
Chris@0 1216 * A runtime assertion is a statement that is expected to always be true at
Chris@0 1217 * the point in the code it appears at. They are tested using PHP's internal
Chris@0 1218 * @link http://php.net/assert assert() @endlink statement. If an
Chris@0 1219 * assertion is ever FALSE it indicates an error in the code or in module or
Chris@0 1220 * theme configuration files. User-provided configuration files should be
Chris@0 1221 * verified with standard control structures at all times, not just checked in
Chris@0 1222 * development environments with assert() statements on.
Chris@0 1223 *
Chris@0 1224 * When runtime assertions fail in PHP 7 an \AssertionError is thrown.
Chris@0 1225 * Drupal uses an assertion callback to do the same in PHP 5.x so that unit
Chris@0 1226 * tests involving runtime assertions will work uniformly across both versions.
Chris@0 1227 *
Chris@0 1228 * The Drupal project primarily uses runtime assertions to enforce the
Chris@0 1229 * expectations of the API by failing when incorrect calls are made by code
Chris@0 1230 * under development. While PHP type hinting does this for objects and arrays,
Chris@0 1231 * runtime assertions do this for scalars (strings, integers, floats, etc.) and
Chris@0 1232 * complex data structures such as cache and render arrays. They ensure that
Chris@0 1233 * methods' return values are the documented datatypes. They also verify that
Chris@0 1234 * objects have been properly configured and set up by the service container.
Chris@0 1235 * Runtime assertions are checked throughout development. They supplement unit
Chris@0 1236 * tests by checking scenarios that do not have unit tests written for them,
Chris@0 1237 * and by testing the API calls made by all the code in the system.
Chris@0 1238 *
Chris@0 1239 * When using assert() keep the following in mind:
Chris@0 1240 * - Runtime assertions are disabled by default in production and enabled in
Chris@0 1241 * development, so they can't be used as control structures. Use exceptions
Chris@0 1242 * for errors that can occur in production no matter how unlikely they are.
Chris@0 1243 * - Assert() functions in a buggy manner prior to PHP 7. If you do not use a
Chris@0 1244 * string for the first argument of the statement but instead use a function
Chris@0 1245 * call or expression then that code will be evaluated even when runtime
Chris@0 1246 * assertions are turned off. To avoid this you must use a string as the
Chris@0 1247 * first argument, and assert will pass this string to the eval() statement.
Chris@0 1248 * - Since runtime assertion strings are parsed by eval() use caution when
Chris@0 1249 * using them to work with data that may be unsanitized.
Chris@0 1250 *
Chris@0 1251 * See https://www.drupal.org/node/2492225 for more information on runtime
Chris@0 1252 * assertions.
Chris@0 1253 * @}
Chris@0 1254 */
Chris@0 1255
Chris@0 1256 /**
Chris@0 1257 * @defgroup info_types Information types
Chris@0 1258 * @{
Chris@0 1259 * Types of information in Drupal.
Chris@0 1260 *
Chris@0 1261 * Drupal has several distinct types of information, each with its own methods
Chris@0 1262 * for storage and retrieval:
Chris@0 1263 * - Content: Information meant to be displayed on your site: articles, basic
Chris@0 1264 * pages, images, files, custom blocks, etc. Content is stored and accessed
Chris@0 1265 * using @link entity_api Entities @endlink.
Chris@0 1266 * - Session: Information about individual users' interactions with the site,
Chris@0 1267 * such as whether they are logged in. This is really "state" information, but
Chris@0 1268 * it is not stored the same way so it's a separate type here. Session
Chris@0 1269 * information is available from the Request object. The session implements
Chris@0 1270 * \Symfony\Component\HttpFoundation\Session\SessionInterface.
Chris@0 1271 * - State: Information of a temporary nature, generally machine-generated and
Chris@0 1272 * not human-edited, about the current state of your site. Examples: the time
Chris@0 1273 * when Cron was last run, whether node access permissions need rebuilding,
Chris@0 1274 * etc. See @link state_api the State API topic @endlink for more information.
Chris@0 1275 * - Configuration: Information about your site that is generally (or at least
Chris@0 1276 * can be) human-edited, but is not Content, and is meant to be relatively
Chris@0 1277 * permanent. Examples: the name of your site, the content types and views
Chris@0 1278 * you have defined, etc. See
Chris@0 1279 * @link config_api the Configuration API topic @endlink for more information.
Chris@0 1280 *
Chris@0 1281 * @see cache
Chris@0 1282 * @see i18n
Chris@0 1283 * @}
Chris@0 1284 */
Chris@0 1285
Chris@0 1286 /**
Chris@0 1287 * @defgroup extending Extending and altering Drupal
Chris@0 1288 * @{
Chris@0 1289 * Overview of extensions and alteration methods for Drupal.
Chris@0 1290 *
Chris@0 1291 * @section sec_types Types of extensions
Chris@0 1292 * Drupal's core behavior can be extended and altered via these three basic
Chris@0 1293 * types of extensions:
Chris@0 1294 * - Themes: Themes alter the appearance of Drupal sites. They can include
Chris@0 1295 * template files, which alter the HTML markup and other raw output of the
Chris@0 1296 * site; CSS files, which alter the styling applied to the HTML; and
Chris@0 1297 * JavaScript, Flash, images, and other files. For more information, see the
Chris@0 1298 * @link theme_render Theme system and render API topic @endlink and
Chris@0 1299 * https://www.drupal.org/docs/8/theming
Chris@0 1300 * - Modules: Modules add to or alter the behavior and functionality of Drupal,
Chris@0 1301 * by using one or more of the methods listed below. For more information
Chris@0 1302 * about creating modules, see https://www.drupal.org/developing/modules/8
Chris@0 1303 * - Installation profiles: Installation profiles can be used to
Chris@0 1304 * create distributions, which are complete specific-purpose packages of
Chris@0 1305 * Drupal including additional modules, themes, and data. For more
Chris@0 1306 * information, see https://www.drupal.org/developing/distributions.
Chris@0 1307 *
Chris@0 1308 * @section sec_alter Alteration methods for modules
Chris@0 1309 * Here is a list of the ways that modules can alter or extend Drupal's core
Chris@0 1310 * behavior, or the behavior of other modules:
Chris@0 1311 * - Hooks: Specially-named functions that a module defines, which are
Chris@0 1312 * discovered and called at specific times, usually to alter behavior or data.
Chris@0 1313 * See the @link hooks Hooks topic @endlink for more information.
Chris@0 1314 * - Plugins: Classes that a module defines, which are discovered and
Chris@0 1315 * instantiated at specific times to add functionality. See the
Chris@0 1316 * @link plugin_api Plugin API topic @endlink for more information.
Chris@0 1317 * - Entities: Special plugins that define entity types for storing new types
Chris@0 1318 * of content or configuration in Drupal. See the
Chris@0 1319 * @link entity_api Entity API topic @endlink for more information.
Chris@0 1320 * - Services: Classes that perform basic operations within Drupal, such as
Chris@0 1321 * accessing the database and sending email. See the
Chris@0 1322 * @link container Dependency Injection Container and Services topic @endlink
Chris@0 1323 * for more information.
Chris@0 1324 * - Routing: Providing or altering "routes", which are URLs that Drupal
Chris@0 1325 * responds to, or altering routing behavior with event listener classes.
Chris@0 1326 * See the @link menu Routing and menu topic @endlink for more information.
Chris@0 1327 * - Events: Modules can register as event subscribers; when an event is
Chris@0 1328 * dispatched, a method is called on each registered subscriber, allowing each
Chris@0 1329 * one to react. See the @link events Events topic @endlink for more
Chris@0 1330 * information.
Chris@0 1331 *
Chris@0 1332 * @section sec_sample *.info.yml files
Chris@0 1333 * Extensions must each be located in a directory whose name matches the short
Chris@0 1334 * name (or machine name) of the extension, and this directory must contain a
Chris@0 1335 * file named machine_name.info.yml (where machine_name is the machine name of
Chris@0 1336 * the extension). See \Drupal\Core\Extension\InfoParserInterface::parse() for
Chris@0 1337 * documentation of the format of .info.yml files.
Chris@0 1338 * @}
Chris@0 1339 */
Chris@0 1340
Chris@0 1341 /**
Chris@0 1342 * @defgroup plugin_api Plugin API
Chris@0 1343 * @{
Chris@0 1344 * Using the Plugin API
Chris@0 1345 *
Chris@0 1346 * @section sec_overview Overview and terminology
Chris@0 1347 *
Chris@0 1348 * The basic idea of plugins is to allow a particular module or subsystem of
Chris@0 1349 * Drupal to provide functionality in an extensible, object-oriented way. The
Chris@0 1350 * controlling module or subsystem defines the basic framework (interface) for
Chris@0 1351 * the functionality, and other modules can create plugins (implementing the
Chris@0 1352 * interface) with particular behaviors. The controlling module instantiates
Chris@0 1353 * existing plugins as needed, and calls methods to invoke their functionality.
Chris@0 1354 * Examples of functionality in Drupal Core that use plugins include: the block
Chris@0 1355 * system (block types are plugins), the entity/field system (entity types,
Chris@0 1356 * field types, field formatters, and field widgets are plugins), the image
Chris@0 1357 * manipulation system (image effects and image toolkits are plugins), and the
Chris@0 1358 * search system (search page types are plugins).
Chris@0 1359 *
Chris@0 1360 * Plugins are grouped into plugin types, each generally defined by an
Chris@0 1361 * interface. Each plugin type is managed by a plugin manager service, which
Chris@0 1362 * uses a plugin discovery method to discover provided plugins of that type and
Chris@0 1363 * instantiate them using a plugin factory.
Chris@0 1364 *
Chris@0 1365 * Some plugin types make use of the following concepts or components:
Chris@0 1366 * - Plugin derivatives: Allows a single plugin class to present itself as
Chris@0 1367 * multiple plugins. Example: the Menu module provides a block for each
Chris@0 1368 * defined menu via a block plugin derivative.
Chris@0 1369 * - Plugin mapping: Allows a plugin class to map a configuration string to an
Chris@0 1370 * instance, and have the plugin automatically instantiated without writing
Chris@0 1371 * additional code.
Chris@0 1372 * - Plugin collections: Provide a way to lazily instantiate a set of plugin
Chris@0 1373 * instances from a single plugin definition.
Chris@0 1374 *
Chris@0 1375 * There are several things a module developer may need to do with plugins:
Chris@0 1376 * - Define a completely new plugin type: see @ref sec_define below.
Chris@0 1377 * - Create a plugin of an existing plugin type: see @ref sec_create below.
Chris@0 1378 * - Perform tasks that involve plugins: see @ref sec_use below.
Chris@0 1379 *
Chris@0 1380 * See https://www.drupal.org/developing/api/8/plugins for more detailed
Chris@0 1381 * documentation on the plugin system. There are also topics for a few
Chris@0 1382 * of the many existing types of plugins:
Chris@0 1383 * - @link block_api Block API @endlink
Chris@0 1384 * - @link entity_api Entity API @endlink
Chris@0 1385 * - @link field Various types of field-related plugins @endlink
Chris@0 1386 * - @link views_plugins Views plugins @endlink (has links to topics covering
Chris@0 1387 * various specific types of Views plugins).
Chris@0 1388 * - @link search Search page plugins @endlink
Chris@0 1389 *
Chris@0 1390 * @section sec_define Defining a new plugin type
Chris@0 1391 * To define a new plugin type:
Chris@0 1392 * - Define an interface for the plugin. This describes the common set of
Chris@0 1393 * behavior, and the methods you will call on each plugin class that is
Chris@0 1394 * instantiated. Usually this interface will extend one or more of the
Chris@0 1395 * following interfaces:
Chris@0 1396 * - \Drupal\Component\Plugin\PluginInspectionInterface
Chris@0 1397 * - \Drupal\Component\Plugin\ConfigurablePluginInterface
Chris@0 1398 * - \Drupal\Component\Plugin\ContextAwarePluginInterface
Chris@0 1399 * - \Drupal\Core\Plugin\PluginFormInterface
Chris@0 1400 * - \Drupal\Core\Executable\ExecutableInterface
Chris@0 1401 * - (optional) Create a base class that provides a partial implementation of
Chris@0 1402 * the interface, for the convenience of developers wishing to create plugins
Chris@0 1403 * of your type. The base class usually extends
Chris@0 1404 * \Drupal\Core\Plugin\PluginBase, or one of the base classes that extends
Chris@0 1405 * this class.
Chris@0 1406 * - Choose a method for plugin discovery, and define classes as necessary.
Chris@0 1407 * See @ref sub_discovery below.
Chris@0 1408 * - Create a plugin manager/factory class and service, which will discover and
Chris@0 1409 * instantiate plugins. See @ref sub_manager below.
Chris@0 1410 * - Use the plugin manager to instantiate plugins. Call methods on your plugin
Chris@0 1411 * interface to perform the tasks of your plugin type.
Chris@0 1412 * - (optional) If appropriate, define a plugin collection. See @ref
Chris@0 1413 * sub_collection below for more information.
Chris@0 1414 *
Chris@0 1415 * @subsection sub_discovery Plugin discovery
Chris@0 1416 * Plugin discovery is the process your plugin manager uses to discover the
Chris@0 1417 * individual plugins of your type that have been defined by your module and
Chris@0 1418 * other modules. Plugin discovery methods are classes that implement
Chris@0 1419 * \Drupal\Component\Plugin\Discovery\DiscoveryInterface. Most plugin types use
Chris@0 1420 * one of the following discovery mechanisms:
Chris@0 1421 * - Annotation: Plugin classes are annotated and placed in a defined namespace
Chris@0 1422 * subdirectory. Most Drupal Core plugins use this method of discovery.
Chris@0 1423 * - Hook: Plugin modules need to implement a hook to tell the manager about
Chris@0 1424 * their plugins.
Chris@0 1425 * - YAML: Plugins are listed in YAML files. Drupal Core uses this method for
Chris@0 1426 * discovering local tasks and local actions. This is mainly useful if all
Chris@0 1427 * plugins use the same class, so it is kind of like a global derivative.
Chris@0 1428 * - Static: Plugin classes are registered within the plugin manager class
Chris@0 1429 * itself. Static discovery is only useful if modules cannot define new
Chris@0 1430 * plugins of this type (if the list of available plugins is static).
Chris@0 1431 *
Chris@0 1432 * It is also possible to define your own custom discovery mechanism or mix
Chris@0 1433 * methods together. And there are many more details, such as annotation
Chris@0 1434 * decorators, that apply to some of the discovery methods. See
Chris@0 1435 * https://www.drupal.org/developing/api/8/plugins for more details.
Chris@0 1436 *
Chris@0 1437 * The remainder of this documentation will assume Annotation-based discovery,
Chris@0 1438 * since this is the most common method.
Chris@0 1439 *
Chris@0 1440 * @subsection sub_manager Defining a plugin manager class and service
Chris@0 1441 * To define an annotation-based plugin manager:
Chris@0 1442 * - Choose a namespace subdirectory for your plugin. For example, search page
Chris@0 1443 * plugins go in directory Plugin/Search under the module namespace.
Chris@0 1444 * - Define an annotation class for your plugin type. This class should extend
Chris@0 1445 * \Drupal\Component\Annotation\Plugin, and for most plugin types, it should
Chris@0 1446 * contain member variables corresponding to the annotations plugins will
Chris@0 1447 * need to provide. All plugins have at least $id: a unique string
Chris@0 1448 * identifier.
Chris@0 1449 * - Define an alter hook for altering the discovered plugin definitions. You
Chris@0 1450 * should document the hook in a *.api.php file.
Chris@0 1451 * - Define a plugin manager class. This class should implement
Chris@0 1452 * \Drupal\Component\Plugin\PluginManagerInterface; most plugin managers do
Chris@0 1453 * this by extending \Drupal\Core\Plugin\DefaultPluginManager. If you do
Chris@0 1454 * extend the default plugin manager, the only method you will probably need
Chris@0 1455 * to define is the class constructor, which will need to call the parent
Chris@0 1456 * constructor to provide information about the annotation class and plugin
Chris@0 1457 * namespace for discovery, set up the alter hook, and possibly set up
Chris@0 1458 * caching. See classes that extend DefaultPluginManager for examples.
Chris@0 1459 * - Define a service for your plugin manager. See the
Chris@0 1460 * @link container Services topic for more information. @endlink Your service
Chris@0 1461 * definition should look something like this, referencing your manager
Chris@0 1462 * class and the parent (default) plugin manager service to inherit
Chris@0 1463 * constructor arguments:
Chris@0 1464 * @code
Chris@0 1465 * plugin.manager.mymodule:
Chris@0 1466 * class: Drupal\mymodule\MyPluginManager
Chris@0 1467 * parent: default_plugin_manager
Chris@0 1468 * @endcode
Chris@0 1469 * - If your plugin is configurable, you will also need to define the
Chris@0 1470 * configuration schema and possibly a configuration entity type. See the
Chris@0 1471 * @link config_api Configuration API topic @endlink for more information.
Chris@0 1472 *
Chris@0 1473 * @subsection sub_collection Defining a plugin collection
Chris@0 1474 * Some configurable plugin types allow administrators to create zero or more
Chris@0 1475 * instances of each plugin, each with its own configuration. For example,
Chris@0 1476 * a single block plugin can be configured several times, to display in
Chris@0 1477 * different regions of a theme, with different visibility settings, a
Chris@0 1478 * different title, or other plugin-specific settings. To make this possible,
Chris@0 1479 * a plugin type can make use of what's known as a plugin collection.
Chris@0 1480 *
Chris@0 1481 * A plugin collection is a class that extends
Chris@0 1482 * \Drupal\Component\Plugin\LazyPluginCollection or one of its subclasses; there
Chris@0 1483 * are several examples in Drupal Core. If your plugin type uses a plugin
Chris@0 1484 * collection, it will usually also have a configuration entity, and the entity
Chris@0 1485 * class should implement
Chris@0 1486 * \Drupal\Core\Entity\EntityWithPluginCollectionInterface. Again, there are
Chris@0 1487 * several examples in Drupal Core; see also the @link config_api Configuration
Chris@0 1488 * API topic @endlink for more information about configuration entities.
Chris@0 1489 *
Chris@0 1490 * @section sec_create Creating a plugin of an existing type
Chris@0 1491 * Assuming the plugin type uses annotation-based discovery, in order to create
Chris@0 1492 * a plugin of an existing type, you will be creating a class. This class must:
Chris@0 1493 * - Implement the plugin interface, so that it has the required methods
Chris@0 1494 * defined. Usually, you'll want to extend the plugin base class, if one has
Chris@0 1495 * been provided.
Chris@0 1496 * - Have the right annotation in its documentation header. See the
Chris@0 1497 * @link annotation Annotation topic @endlink for more information about
Chris@0 1498 * annotation.
Chris@0 1499 * - Be in the right plugin namespace, in order to be discovered.
Chris@0 1500 * Often, the easiest way to make sure this happens is to find an existing
Chris@0 1501 * example of a working plugin class of the desired type, and copy it into your
Chris@0 1502 * module as a starting point.
Chris@0 1503 *
Chris@0 1504 * You can also create a plugin derivative, which allows your plugin class
Chris@0 1505 * to present itself to the user interface as multiple plugins. To do this,
Chris@0 1506 * in addition to the plugin class, you'll need to create a separate plugin
Chris@0 1507 * derivative class implementing
Chris@0 1508 * \Drupal\Component\Plugin\Derivative\DerivativeInterface. The classes
Chris@0 1509 * \Drupal\system\Plugin\Block\SystemMenuBlock (plugin class) and
Chris@0 1510 * \Drupal\system\Plugin\Derivative\SystemMenuBlock (derivative class) are a
Chris@0 1511 * good example to look at.
Chris@0 1512 *
Chris@0 1513 * @section sec_use Performing tasks involving plugins
Chris@0 1514 * Here are the steps to follow to perform a task that involves plugins:
Chris@0 1515 * - Locate the machine name of the plugin manager service, and instantiate the
Chris@0 1516 * service. See the @link container Services topic @endlink for more
Chris@0 1517 * information on how to do this.
Chris@0 1518 * - On the plugin manager class, use methods like getDefinition(),
Chris@0 1519 * getDefinitions(), or other methods specific to particular plugin managers
Chris@0 1520 * to retrieve information about either specific plugins or the entire list of
Chris@0 1521 * defined plugins.
Chris@0 1522 * - Call the createInstance() method on the plugin manager to instantiate
Chris@0 1523 * individual plugin objects.
Chris@0 1524 * - Call methods on the plugin objects to perform the desired tasks.
Chris@0 1525 *
Chris@0 1526 * @see annotation
Chris@0 1527 * @}
Chris@0 1528 */
Chris@0 1529
Chris@0 1530 /**
Chris@0 1531 * @defgroup oo_conventions Objected-oriented programming conventions
Chris@0 1532 * @{
Chris@0 1533 * PSR-4, namespaces, class naming, and other conventions.
Chris@0 1534 *
Chris@0 1535 * A lot of the PHP code in Drupal is object oriented (OO), making use of
Chris@0 1536 * @link http://php.net/manual/language.oop5.php PHP classes, interfaces, and traits @endlink
Chris@0 1537 * (which are loosely referred to as "classes" in the rest of this topic). The
Chris@0 1538 * following conventions and standards apply to this version of Drupal:
Chris@0 1539 * - Each class must be in its own file.
Chris@0 1540 * - Classes must be namespaced. If a module defines a class, the namespace
Chris@0 1541 * must start with \Drupal\module_name. If it is defined by Drupal Core for
Chris@0 1542 * use across many modules, the namespace should be \Drupal\Core or
Chris@0 1543 * \Drupal\Component, with the exception of the global class \Drupal. See
Chris@0 1544 * https://www.drupal.org/node/1353118 for more about namespaces.
Chris@0 1545 * - In order for the PSR-4-based class auto-loader to find the class, it must
Chris@0 1546 * be located in a directory corresponding to the namespace. For
Chris@0 1547 * module-defined classes, if the namespace is \Drupal\module_name\foo\bar,
Chris@0 1548 * then the class goes under the main module directory in directory
Chris@0 1549 * src/foo/bar. For Drupal-wide classes, if the namespace is
Chris@0 1550 * \Drupal\Core\foo\bar, then it goes in directory
Chris@0 1551 * core/lib/Drupal/Core/foo/bar. See https://www.drupal.org/node/2156625 for
Chris@0 1552 * more information about PSR-4.
Chris@0 1553 * - Some classes have annotations added to their documentation headers. See
Chris@0 1554 * the @link annotation Annotation topic @endlink for more information.
Chris@0 1555 * - Standard plugin discovery requires particular namespaces and annotation
Chris@0 1556 * for most plugin classes. See the
Chris@0 1557 * @link plugin_api Plugin API topic @endlink for more information.
Chris@0 1558 * - There are project-wide coding standards for OO code, including naming:
Chris@0 1559 * https://www.drupal.org/node/608152
Chris@0 1560 * - Documentation standards for classes are covered on:
Chris@0 1561 * https://www.drupal.org/coding-standards/docs#classes
Chris@0 1562 * @}
Chris@0 1563 */
Chris@0 1564
Chris@0 1565 /**
Chris@0 1566 * @defgroup listing_page_class Page header for Classes page
Chris@0 1567 * @{
Chris@0 1568 * Introduction to classes
Chris@0 1569 *
Chris@0 1570 * A lot of the PHP code in Drupal is object oriented (OO), making use of
Chris@0 1571 * @link http://php.net/manual/language.oop5.php PHP classes, interfaces, and traits. @endlink
Chris@0 1572 * See the
Chris@0 1573 * @link oo_conventions Objected-oriented programming conventions @endlink
Chris@0 1574 * for more information.
Chris@0 1575 *
Chris@0 1576 * @see oo_conventions
Chris@0 1577 *
Chris@0 1578 * @}
Chris@0 1579 */
Chris@0 1580
Chris@0 1581 /**
Chris@0 1582 * @defgroup listing_page_namespace Page header for Namespaces page
Chris@0 1583 * @{
Chris@0 1584 * Introduction to namespaces
Chris@0 1585 *
Chris@0 1586 * PHP classes, interfaces, and traits in Drupal are
Chris@0 1587 * @link http://php.net/manual/en/language.namespaces.rationale.php namespaced. @endlink
Chris@0 1588 * See the
Chris@0 1589 * @link oo_conventions Objected-oriented programming conventions @endlink
Chris@0 1590 * for more information.
Chris@0 1591 *
Chris@0 1592 * @see oo_conventions
Chris@0 1593 *
Chris@0 1594 * @}
Chris@0 1595 */
Chris@0 1596
Chris@0 1597 /**
Chris@0 1598 * @defgroup best_practices Best practices for developers
Chris@0 1599 * @{
Chris@0 1600 * Overview of standards and best practices for developers
Chris@0 1601 *
Chris@0 1602 * Ideally, all code that is included in Drupal Core and contributed modules,
Chris@0 1603 * themes, and distributions will be secure, internationalized, maintainable,
Chris@0 1604 * and efficient. In order to facilitate this, the Drupal community has
Chris@0 1605 * developed a set of guidelines and standards for developers to follow. Most of
Chris@0 1606 * these standards can be found under
Chris@0 1607 * @link https://www.drupal.org/developing/best-practices Best practices on Drupal.org @endlink
Chris@0 1608 *
Chris@0 1609 * Standards and best practices that developers should be aware of include:
Chris@0 1610 * - Security: https://www.drupal.org/writing-secure-code and the
Chris@0 1611 * @link sanitization Sanitization functions topic @endlink
Chris@0 1612 * - Coding standards: https://www.drupal.org/coding-standards
Chris@0 1613 * and https://www.drupal.org/coding-standards/docs
Chris@0 1614 * - Accessibility: https://www.drupal.org/node/1637990 (modules) and
Chris@0 1615 * https://www.drupal.org/node/464472 (themes)
Chris@0 1616 * - Usability: https://www.drupal.org/ui-standards
Chris@0 1617 * - Internationalization: @link i18n Internationalization topic @endlink
Chris@0 1618 * - Automated testing: @link testing Automated tests topic @endlink
Chris@0 1619 * @}
Chris@0 1620 */
Chris@0 1621
Chris@0 1622 /**
Chris@0 1623 * @defgroup utility Utility classes and functions
Chris@0 1624 * @{
Chris@0 1625 * Overview of utility classes and functions for developers.
Chris@0 1626 *
Chris@0 1627 * Drupal provides developers with a variety of utility functions that make it
Chris@0 1628 * easier and more efficient to perform tasks that are either really common,
Chris@0 1629 * tedious, or difficult. Utility functions help to reduce code duplication and
Chris@0 1630 * should be used in place of one-off code whenever possible.
Chris@0 1631 *
Chris@0 1632 * @see common.inc
Chris@0 1633 * @see file
Chris@0 1634 * @see format
Chris@0 1635 * @see php_wrappers
Chris@0 1636 * @see sanitization
Chris@0 1637 * @see transliteration
Chris@0 1638 * @see validation
Chris@0 1639 * @}
Chris@0 1640 */
Chris@0 1641
Chris@0 1642 /**
Chris@0 1643 * @defgroup hooks Hooks
Chris@0 1644 * @{
Chris@0 1645 * Define functions that alter the behavior of Drupal core.
Chris@0 1646 *
Chris@0 1647 * One way for modules to alter the core behavior of Drupal (or another module)
Chris@0 1648 * is to use hooks. Hooks are specially-named functions that a module defines
Chris@0 1649 * (this is known as "implementing the hook"), which are discovered and called
Chris@0 1650 * at specific times to alter or add to the base behavior or data (this is
Chris@0 1651 * known as "invoking the hook"). Each hook has a name (example:
Chris@0 1652 * hook_batch_alter()), a defined set of parameters, and a defined return value.
Chris@0 1653 * Your modules can implement hooks that are defined by Drupal core or other
Chris@0 1654 * modules that they interact with. Your modules can also define their own
Chris@0 1655 * hooks, in order to let other modules interact with them.
Chris@0 1656 *
Chris@0 1657 * To implement a hook:
Chris@0 1658 * - Locate the documentation for the hook. Hooks are documented in *.api.php
Chris@0 1659 * files, by defining functions whose name starts with "hook_" (these
Chris@0 1660 * files and their functions are never loaded by Drupal -- they exist solely
Chris@0 1661 * for documentation). The function should have a documentation header, as
Chris@0 1662 * well as a sample function body. For example, in the core file
Chris@0 1663 * system.api.php, you can find hooks such as hook_batch_alter(). Also, if
Chris@0 1664 * you are viewing this documentation on an API reference site, the Core
Chris@0 1665 * hooks will be listed in this topic.
Chris@0 1666 * - Copy the function to your module's .module file.
Chris@0 1667 * - Change the name of the function, substituting your module's short name
Chris@0 1668 * (name of the module's directory, and .info.yml file without the extension)
Chris@0 1669 * for the "hook" part of the sample function name. For instance, to implement
Chris@0 1670 * hook_batch_alter(), you would rename it to my_module_batch_alter().
Chris@0 1671 * - Edit the documentation for the function (normally, your implementation
Chris@0 1672 * should just have one line saying "Implements hook_batch_alter().").
Chris@0 1673 * - Edit the body of the function, substituting in what you need your module
Chris@0 1674 * to do.
Chris@0 1675 *
Chris@0 1676 * To define a hook:
Chris@0 1677 * - Choose a unique name for your hook. It should start with "hook_", followed
Chris@0 1678 * by your module's short name.
Chris@0 1679 * - Provide documentation in a *.api.php file in your module's main
Chris@0 1680 * directory. See the "implementing" section above for details of what this
Chris@0 1681 * should contain (parameters, return value, and sample function body).
Chris@0 1682 * - Invoke the hook in your module's code.
Chris@0 1683 *
Chris@0 1684 * To invoke a hook, use methods on
Chris@0 1685 * \Drupal\Core\Extension\ModuleHandlerInterface such as alter(), invoke(),
Chris@0 1686 * and invokeAll(). You can obtain a module handler by calling
Chris@0 1687 * \Drupal::moduleHandler(), or getting the 'module_handler' service on an
Chris@0 1688 * injected container.
Chris@0 1689 *
Chris@0 1690 * @see extending
Chris@0 1691 * @see themeable
Chris@0 1692 * @see callbacks
Chris@0 1693 * @see \Drupal\Core\Extension\ModuleHandlerInterface
Chris@0 1694 * @see \Drupal::moduleHandler()
Chris@0 1695 *
Chris@0 1696 * @}
Chris@0 1697 */
Chris@0 1698
Chris@0 1699 /**
Chris@0 1700 * @defgroup callbacks Callbacks
Chris@0 1701 * @{
Chris@0 1702 * Callback function signatures.
Chris@0 1703 *
Chris@0 1704 * Drupal's API sometimes uses callback functions to allow you to define how
Chris@0 1705 * some type of processing happens. A callback is a function with a defined
Chris@0 1706 * signature, which you define in a module. Then you pass the function name as
Chris@0 1707 * a parameter to a Drupal API function or return it as part of a hook
Chris@0 1708 * implementation return value, and your function is called at an appropriate
Chris@0 1709 * time. For instance, when setting up batch processing you might need to
Chris@0 1710 * provide a callback function for each processing step and/or a callback for
Chris@0 1711 * when processing is finished; you would do that by defining these functions
Chris@0 1712 * and passing their names into the batch setup function.
Chris@0 1713 *
Chris@0 1714 * Callback function signatures, like hook definitions, are described by
Chris@0 1715 * creating and documenting dummy functions in a *.api.php file; normally, the
Chris@0 1716 * dummy callback function's name should start with "callback_", and you should
Chris@0 1717 * document the parameters and return value and provide a sample function body.
Chris@0 1718 * Then your API documentation can refer to this callback function in its
Chris@0 1719 * documentation. A user of your API can usually name their callback function
Chris@0 1720 * anything they want, although a standard name would be to replace "callback_"
Chris@0 1721 * with the module name.
Chris@0 1722 *
Chris@0 1723 * @see hooks
Chris@0 1724 * @see themeable
Chris@0 1725 *
Chris@0 1726 * @}
Chris@0 1727 */
Chris@0 1728
Chris@0 1729 /**
Chris@0 1730 * @defgroup form_api Form generation
Chris@0 1731 * @{
Chris@0 1732 * Describes how to generate and manipulate forms and process form submissions.
Chris@0 1733 *
Chris@0 1734 * Drupal provides a Form API in order to achieve consistency in its form
Chris@0 1735 * processing and presentation, while simplifying code and reducing the amount
Chris@0 1736 * of HTML that must be explicitly generated by a module.
Chris@0 1737 *
Chris@0 1738 * @section generating_forms Creating forms
Chris@0 1739 * Forms are defined as classes that implement the
Chris@0 1740 * \Drupal\Core\Form\FormInterface and are built using the
Chris@0 1741 * \Drupal\Core\Form\FormBuilder class. Drupal provides a couple of utility
Chris@0 1742 * classes that can be extended as a starting point for most basic forms, the
Chris@0 1743 * most commonly used of which is \Drupal\Core\Form\FormBase. FormBuilder
Chris@0 1744 * handles the low level processing of forms such as rendering the necessary
Chris@0 1745 * HTML, initial processing of incoming $_POST data, and delegating to your
Chris@0 1746 * implementation of FormInterface for validation and processing of submitted
Chris@0 1747 * data.
Chris@0 1748 *
Chris@0 1749 * Here is an example of a Form class:
Chris@0 1750 * @code
Chris@0 1751 * namespace Drupal\mymodule\Form;
Chris@0 1752 *
Chris@0 1753 * use Drupal\Core\Form\FormBase;
Chris@0 1754 * use Drupal\Core\Form\FormStateInterface;
Chris@0 1755 *
Chris@0 1756 * class ExampleForm extends FormBase {
Chris@0 1757 * public function getFormId() {
Chris@0 1758 * // Unique ID of the form.
Chris@0 1759 * return 'example_form';
Chris@0 1760 * }
Chris@0 1761 *
Chris@0 1762 * public function buildForm(array $form, FormStateInterface $form_state) {
Chris@0 1763 * // Create a $form API array.
Chris@0 1764 * $form['phone_number'] = array(
Chris@0 1765 * '#type' => 'tel',
Chris@0 1766 * '#title' => $this->t('Your phone number'),
Chris@0 1767 * );
Chris@0 1768 * $form['save'] = array(
Chris@0 1769 * '#type' => 'submit',
Chris@0 1770 * '#value' => $this->t('Save'),
Chris@0 1771 * );
Chris@0 1772 * return $form;
Chris@0 1773 * }
Chris@0 1774 *
Chris@0 1775 * public function validateForm(array &$form, FormStateInterface $form_state) {
Chris@0 1776 * // Validate submitted form data.
Chris@0 1777 * }
Chris@0 1778 *
Chris@0 1779 * public function submitForm(array &$form, FormStateInterface $form_state) {
Chris@0 1780 * // Handle submitted form data.
Chris@0 1781 * }
Chris@0 1782 * }
Chris@0 1783 * @endcode
Chris@0 1784 *
Chris@0 1785 * @section retrieving_forms Retrieving and displaying forms
Chris@0 1786 * \Drupal::formBuilder()->getForm() should be used to handle retrieving,
Chris@0 1787 * processing, and displaying a rendered HTML form. Given the ExampleForm
Chris@0 1788 * defined above,
Chris@0 1789 * \Drupal::formBuilder()->getForm('Drupal\mymodule\Form\ExampleForm') would
Chris@0 1790 * return the rendered HTML of the form defined by ExampleForm::buildForm(), or
Chris@0 1791 * call the validateForm() and submitForm(), methods depending on the current
Chris@0 1792 * processing state.
Chris@0 1793 *
Chris@0 1794 * The argument to \Drupal::formBuilder()->getForm() is the name of a class that
Chris@0 1795 * implements FormInterface. Any additional arguments passed to the getForm()
Chris@0 1796 * method will be passed along as additional arguments to the
Chris@0 1797 * ExampleForm::buildForm() method.
Chris@0 1798 *
Chris@0 1799 * For example:
Chris@0 1800 * @code
Chris@0 1801 * $extra = '612-123-4567';
Chris@0 1802 * $form = \Drupal::formBuilder()->getForm('Drupal\mymodule\Form\ExampleForm', $extra);
Chris@0 1803 * ...
Chris@0 1804 * public function buildForm(array $form, FormStateInterface $form_state, $extra = NULL)
Chris@0 1805 * $form['phone_number'] = array(
Chris@0 1806 * '#type' => 'tel',
Chris@0 1807 * '#title' => $this->t('Your phone number'),
Chris@0 1808 * '#value' => $extra,
Chris@0 1809 * );
Chris@0 1810 * return $form;
Chris@0 1811 * }
Chris@0 1812 * @endcode
Chris@0 1813 *
Chris@0 1814 * Alternatively, forms can be built directly via the routing system which will
Chris@0 1815 * take care of calling \Drupal::formBuilder()->getForm(). The following example
Chris@0 1816 * demonstrates the use of a routing.yml file to display a form at the given
Chris@0 1817 * route.
Chris@0 1818 *
Chris@0 1819 * @code
Chris@0 1820 * example.form:
Chris@0 1821 * path: '/example-form'
Chris@0 1822 * defaults:
Chris@0 1823 * _title: 'Example form'
Chris@0 1824 * _form: '\Drupal\mymodule\Form\ExampleForm'
Chris@0 1825 * @endcode
Chris@0 1826 *
Chris@0 1827 * The $form argument to form-related functions is a specialized render array
Chris@0 1828 * containing the elements and properties of the form. For more about render
Chris@0 1829 * arrays, see the @link theme_render Render API topic. @endlink For more
Chris@0 1830 * detailed explanations of the Form API workflow, see the
Chris@0 1831 * @link https://www.drupal.org/node/2117411 Form API documentation section. @endlink
Chris@0 1832 * In addition, there is a set of Form API tutorials in the
Chris@0 1833 * @link https://www.drupal.org/project/examples Examples for Developers project. @endlink
Chris@0 1834 *
Chris@0 1835 * In the form builder, validation, submission, and other form methods,
Chris@0 1836 * $form_state is the primary influence on the processing of the form and is
Chris@0 1837 * passed to most methods, so they can use it to communicate with the form
Chris@0 1838 * system and each other. $form_state is an object that implements
Chris@0 1839 * \Drupal\Core\Form\FormStateInterface.
Chris@0 1840 * @}
Chris@0 1841 */
Chris@0 1842
Chris@0 1843 /**
Chris@0 1844 * @defgroup queue Queue operations
Chris@0 1845 * @{
Chris@0 1846 * Queue items to allow later processing.
Chris@0 1847 *
Chris@0 1848 * The queue system allows placing items in a queue and processing them later.
Chris@0 1849 * The system tries to ensure that only one consumer can process an item.
Chris@0 1850 *
Chris@0 1851 * Before a queue can be used it needs to be created by
Chris@0 1852 * Drupal\Core\Queue\QueueInterface::createQueue().
Chris@0 1853 *
Chris@0 1854 * Items can be added to the queue by passing an arbitrary data object to
Chris@0 1855 * Drupal\Core\Queue\QueueInterface::createItem().
Chris@0 1856 *
Chris@0 1857 * To process an item, call Drupal\Core\Queue\QueueInterface::claimItem() and
Chris@0 1858 * specify how long you want to have a lease for working on that item.
Chris@0 1859 * When finished processing, the item needs to be deleted by calling
Chris@0 1860 * Drupal\Core\Queue\QueueInterface::deleteItem(). If the consumer dies, the
Chris@0 1861 * item will be made available again by the Drupal\Core\Queue\QueueInterface
Chris@0 1862 * implementation once the lease expires. Another consumer will then be able to
Chris@0 1863 * receive it when calling Drupal\Core\Queue\QueueInterface::claimItem().
Chris@0 1864 * Due to this, the processing code should be aware that an item might be handed
Chris@0 1865 * over for processing more than once.
Chris@0 1866 *
Chris@0 1867 * The $item object used by the Drupal\Core\Queue\QueueInterface can contain
Chris@0 1868 * arbitrary metadata depending on the implementation. Systems using the
Chris@0 1869 * interface should only rely on the data property which will contain the
Chris@0 1870 * information passed to Drupal\Core\Queue\QueueInterface::createItem().
Chris@0 1871 * The full queue item returned by Drupal\Core\Queue\QueueInterface::claimItem()
Chris@0 1872 * needs to be passed to Drupal\Core\Queue\QueueInterface::deleteItem() once
Chris@0 1873 * processing is completed.
Chris@0 1874 *
Chris@0 1875 * There are two kinds of queue backends available: reliable, which preserves
Chris@0 1876 * the order of messages and guarantees that every item will be executed at
Chris@0 1877 * least once. The non-reliable kind only does a best effort to preserve order
Chris@0 1878 * in messages and to execute them at least once but there is a small chance
Chris@0 1879 * that some items get lost. For example, some distributed back-ends like
Chris@0 1880 * Amazon SQS will be managing jobs for a large set of producers and consumers
Chris@0 1881 * where a strict FIFO ordering will likely not be preserved. Another example
Chris@0 1882 * would be an in-memory queue backend which might lose items if it crashes.
Chris@0 1883 * However, such a backend would be able to deal with significantly more writes
Chris@0 1884 * than a reliable queue and for many tasks this is more important. See
Chris@0 1885 * aggregator_cron() for an example of how to effectively use a non-reliable
Chris@0 1886 * queue. Another example is doing Twitter statistics -- the small possibility
Chris@0 1887 * of losing a few items is insignificant next to power of the queue being able
Chris@0 1888 * to keep up with writes. As described in the processing section, regardless
Chris@0 1889 * of the queue being reliable or not, the processing code should be aware that
Chris@0 1890 * an item might be handed over for processing more than once (because the
Chris@0 1891 * processing code might time out before it finishes).
Chris@0 1892 * @}
Chris@0 1893 */
Chris@0 1894
Chris@0 1895 /**
Chris@0 1896 * @defgroup annotation Annotations
Chris@0 1897 * @{
Chris@0 1898 * Annotations for class discovery and metadata description.
Chris@0 1899 *
Chris@0 1900 * The Drupal plugin system has a set of reusable components that developers
Chris@0 1901 * can use, override, and extend in their modules. Most of the plugins use
Chris@0 1902 * annotations, which let classes register themselves as plugins and describe
Chris@0 1903 * their metadata. (Annotations can also be used for other purposes, though
Chris@0 1904 * at the moment, Drupal only uses them for the plugin system.)
Chris@0 1905 *
Chris@0 1906 * To annotate a class as a plugin, add code similar to the following to the
Chris@0 1907 * end of the documentation block immediately preceding the class declaration:
Chris@0 1908 * @code
Chris@0 1909 * * @ContentEntityType(
Chris@0 1910 * * id = "comment",
Chris@0 1911 * * label = @Translation("Comment"),
Chris@0 1912 * * ...
Chris@0 1913 * * base_table = "comment"
Chris@0 1914 * * )
Chris@0 1915 * @endcode
Chris@0 1916 *
Chris@0 1917 * Note that you must use double quotes; single quotes will not work in
Chris@0 1918 * annotations.
Chris@0 1919 *
Chris@0 1920 * Some annotation types, which extend the "@ PluginID" annotation class, have
Chris@0 1921 * only a single 'id' key in their annotation. For these, it is possible to use
Chris@0 1922 * a shorthand annotation. For example:
Chris@0 1923 * @code
Chris@0 1924 * * @ViewsArea("entity")
Chris@0 1925 * @endcode
Chris@0 1926 * in place of
Chris@0 1927 * @code
Chris@0 1928 * * @ViewsArea(
Chris@0 1929 * * id = "entity"
Chris@0 1930 * *)
Chris@0 1931 * @endcode
Chris@0 1932 *
Chris@0 1933 * The available annotation classes are listed in this topic, and can be
Chris@0 1934 * identified when you are looking at the Drupal source code by having
Chris@0 1935 * "@ Annotation" in their documentation blocks (without the space after @). To
Chris@0 1936 * find examples of annotation for a particular annotation class, such as
Chris@0 1937 * EntityType, look for class files that have an @ annotation section using the
Chris@0 1938 * annotation class.
Chris@0 1939 *
Chris@0 1940 * @see plugin_translatable
Chris@0 1941 * @see plugin_context
Chris@0 1942 *
Chris@0 1943 * @}
Chris@0 1944 */
Chris@0 1945
Chris@0 1946 /**
Chris@0 1947 * @addtogroup hooks
Chris@0 1948 * @{
Chris@0 1949 */
Chris@0 1950
Chris@0 1951 /**
Chris@0 1952 * Perform periodic actions.
Chris@0 1953 *
Chris@0 1954 * Modules that require some commands to be executed periodically can
Chris@0 1955 * implement hook_cron(). The engine will then call the hook whenever a cron
Chris@0 1956 * run happens, as defined by the administrator. Typical tasks managed by
Chris@0 1957 * hook_cron() are database maintenance, backups, recalculation of settings
Chris@0 1958 * or parameters, automated mailing, and retrieving remote data.
Chris@0 1959 *
Chris@0 1960 * Short-running or non-resource-intensive tasks can be executed directly in
Chris@0 1961 * the hook_cron() implementation.
Chris@0 1962 *
Chris@0 1963 * Long-running tasks and tasks that could time out, such as retrieving remote
Chris@0 1964 * data, sending email, and intensive file tasks, should use the queue API
Chris@0 1965 * instead of executing the tasks directly. To do this, first define one or
Chris@0 1966 * more queues via a \Drupal\Core\Annotation\QueueWorker plugin. Then, add items
Chris@0 1967 * that need to be processed to the defined queues.
Chris@0 1968 */
Chris@0 1969 function hook_cron() {
Chris@0 1970 // Short-running operation example, not using a queue:
Chris@0 1971 // Delete all expired records since the last cron run.
Chris@0 1972 $expires = \Drupal::state()->get('mymodule.last_check', 0);
Chris@0 1973 \Drupal::database()->delete('mymodule_table')
Chris@0 1974 ->condition('expires', $expires, '>=')
Chris@0 1975 ->execute();
Chris@0 1976 \Drupal::state()->set('mymodule.last_check', REQUEST_TIME);
Chris@0 1977
Chris@0 1978 // Long-running operation example, leveraging a queue:
Chris@0 1979 // Queue news feeds for updates once their refresh interval has elapsed.
Chris@0 1980 $queue = \Drupal::queue('aggregator_feeds');
Chris@0 1981 $ids = \Drupal::entityManager()->getStorage('aggregator_feed')->getFeedIdsToRefresh();
Chris@0 1982 foreach (Feed::loadMultiple($ids) as $feed) {
Chris@0 1983 if ($queue->createItem($feed)) {
Chris@0 1984 // Add timestamp to avoid queueing item more than once.
Chris@0 1985 $feed->setQueuedTime(REQUEST_TIME);
Chris@0 1986 $feed->save();
Chris@0 1987 }
Chris@0 1988 }
Chris@0 1989 $ids = \Drupal::entityQuery('aggregator_feed')
Chris@0 1990 ->condition('queued', REQUEST_TIME - (3600 * 6), '<')
Chris@0 1991 ->execute();
Chris@0 1992 if ($ids) {
Chris@0 1993 $feeds = Feed::loadMultiple($ids);
Chris@0 1994 foreach ($feeds as $feed) {
Chris@0 1995 $feed->setQueuedTime(0);
Chris@0 1996 $feed->save();
Chris@0 1997 }
Chris@0 1998 }
Chris@0 1999 }
Chris@0 2000
Chris@0 2001 /**
Chris@0 2002 * Alter available data types for typed data wrappers.
Chris@0 2003 *
Chris@0 2004 * @param array $data_types
Chris@0 2005 * An array of data type information.
Chris@0 2006 *
Chris@0 2007 * @see hook_data_type_info()
Chris@0 2008 */
Chris@0 2009 function hook_data_type_info_alter(&$data_types) {
Chris@0 2010 $data_types['email']['class'] = '\Drupal\mymodule\Type\Email';
Chris@0 2011 }
Chris@0 2012
Chris@0 2013 /**
Chris@0 2014 * Alter cron queue information before cron runs.
Chris@0 2015 *
Chris@0 2016 * Called by \Drupal\Core\Cron to allow modules to alter cron queue settings
Chris@0 2017 * before any jobs are processesed.
Chris@0 2018 *
Chris@0 2019 * @param array $queues
Chris@0 2020 * An array of cron queue information.
Chris@0 2021 *
Chris@0 2022 * @see \Drupal\Core\QueueWorker\QueueWorkerInterface
Chris@0 2023 * @see \Drupal\Core\Annotation\QueueWorker
Chris@0 2024 * @see \Drupal\Core\Cron
Chris@0 2025 */
Chris@0 2026 function hook_queue_info_alter(&$queues) {
Chris@0 2027 // This site has many feeds so let's spend 90 seconds on each cron run
Chris@0 2028 // updating feeds instead of the default 60.
Chris@0 2029 $queues['aggregator_feeds']['cron']['time'] = 90;
Chris@0 2030 }
Chris@0 2031
Chris@0 2032 /**
Chris@0 2033 * Alter an email message created with MailManagerInterface->mail().
Chris@0 2034 *
Chris@0 2035 * hook_mail_alter() allows modification of email messages created and sent
Chris@0 2036 * with MailManagerInterface->mail(). Usage examples include adding and/or
Chris@0 2037 * changing message text, message fields, and message headers.
Chris@0 2038 *
Chris@0 2039 * Email messages sent using functions other than MailManagerInterface->mail()
Chris@0 2040 * will not invoke hook_mail_alter(). For example, a contributed module directly
Chris@0 2041 * calling the MailInterface->mail() or PHP mail() function will not invoke
Chris@0 2042 * this hook. All core modules use MailManagerInterface->mail() for messaging,
Chris@0 2043 * it is best practice but not mandatory in contributed modules.
Chris@0 2044 *
Chris@0 2045 * @param $message
Chris@0 2046 * An array containing the message data. Keys in this array include:
Chris@0 2047 * - 'id':
Chris@0 2048 * The MailManagerInterface->mail() id of the message. Look at module source
Chris@0 2049 * code or MailManagerInterface->mail() for possible id values.
Chris@0 2050 * - 'to':
Chris@0 2051 * The address or addresses the message will be sent to. The
Chris@0 2052 * formatting of this string must comply with RFC 2822.
Chris@0 2053 * - 'from':
Chris@0 2054 * The address the message will be marked as being from, which is
Chris@0 2055 * either a custom address or the site-wide default email address.
Chris@0 2056 * - 'subject':
Chris@0 2057 * Subject of the email to be sent. This must not contain any newline
Chris@0 2058 * characters, or the email may not be sent properly.
Chris@0 2059 * - 'body':
Chris@0 2060 * An array of strings or objects that implement
Chris@0 2061 * \Drupal\Component\Render\MarkupInterface containing the message text. The
Chris@0 2062 * message body is created by concatenating the individual array strings
Chris@0 2063 * into a single text string using "\n\n" as a separator.
Chris@0 2064 * - 'headers':
Chris@0 2065 * Associative array containing mail headers, such as From, Sender,
Chris@0 2066 * MIME-Version, Content-Type, etc.
Chris@0 2067 * - 'params':
Chris@0 2068 * An array of optional parameters supplied by the caller of
Chris@0 2069 * MailManagerInterface->mail() that is used to build the message before
Chris@0 2070 * hook_mail_alter() is invoked.
Chris@0 2071 * - 'language':
Chris@0 2072 * The language object used to build the message before hook_mail_alter()
Chris@0 2073 * is invoked.
Chris@0 2074 * - 'send':
Chris@0 2075 * Set to FALSE to abort sending this email message.
Chris@0 2076 *
Chris@0 2077 * @see \Drupal\Core\Mail\MailManagerInterface::mail()
Chris@0 2078 */
Chris@0 2079 function hook_mail_alter(&$message) {
Chris@0 2080 if ($message['id'] == 'modulename_messagekey') {
Chris@0 2081 if (!example_notifications_optin($message['to'], $message['id'])) {
Chris@0 2082 // If the recipient has opted to not receive such messages, cancel
Chris@0 2083 // sending.
Chris@0 2084 $message['send'] = FALSE;
Chris@0 2085 return;
Chris@0 2086 }
Chris@0 2087 $message['body'][] = "--\nMail sent out from " . \Drupal::config('system.site')->get('name');
Chris@0 2088 }
Chris@0 2089 }
Chris@0 2090
Chris@0 2091 /**
Chris@0 2092 * Prepares a message based on parameters;
Chris@0 2093 *
Chris@0 2094 * This hook is called from MailManagerInterface->mail(). Note that hook_mail(),
Chris@0 2095 * unlike hook_mail_alter(), is only called on the $module argument to
Chris@0 2096 * MailManagerInterface->mail(), not all modules.
Chris@0 2097 *
Chris@0 2098 * @param $key
Chris@0 2099 * An identifier of the mail.
Chris@0 2100 * @param $message
Chris@0 2101 * An array to be filled in. Elements in this array include:
Chris@0 2102 * - id: An ID to identify the mail sent. Look at module source code or
Chris@0 2103 * MailManagerInterface->mail() for possible id values.
Chris@0 2104 * - to: The address or addresses the message will be sent to. The
Chris@0 2105 * formatting of this string must comply with RFC 2822.
Chris@0 2106 * - subject: Subject of the email to be sent. This must not contain any
Chris@0 2107 * newline characters, or the mail may not be sent properly.
Chris@0 2108 * MailManagerInterface->mail() sets this to an empty
Chris@0 2109 * string when the hook is invoked.
Chris@0 2110 * - body: An array of lines containing the message to be sent. Drupal will
Chris@0 2111 * format the correct line endings for you. MailManagerInterface->mail()
Chris@0 2112 * sets this to an empty array when the hook is invoked. The array may
Chris@0 2113 * contain either strings or objects implementing
Chris@0 2114 * \Drupal\Component\Render\MarkupInterface.
Chris@0 2115 * - from: The address the message will be marked as being from, which is
Chris@0 2116 * set by MailManagerInterface->mail() to either a custom address or the
Chris@0 2117 * site-wide default email address when the hook is invoked.
Chris@0 2118 * - headers: Associative array containing mail headers, such as From,
Chris@0 2119 * Sender, MIME-Version, Content-Type, etc.
Chris@0 2120 * MailManagerInterface->mail() pre-fills several headers in this array.
Chris@0 2121 * @param $params
Chris@0 2122 * An array of parameters supplied by the caller of
Chris@0 2123 * MailManagerInterface->mail().
Chris@0 2124 *
Chris@0 2125 * @see \Drupal\Core\Mail\MailManagerInterface::mail()
Chris@0 2126 */
Chris@0 2127 function hook_mail($key, &$message, $params) {
Chris@0 2128 $account = $params['account'];
Chris@0 2129 $context = $params['context'];
Chris@0 2130 $variables = [
Chris@0 2131 '%site_name' => \Drupal::config('system.site')->get('name'),
Chris@0 2132 '%username' => $account->getDisplayName(),
Chris@0 2133 ];
Chris@0 2134 if ($context['hook'] == 'taxonomy') {
Chris@0 2135 $entity = $params['entity'];
Chris@0 2136 $vocabulary = Vocabulary::load($entity->id());
Chris@0 2137 $variables += [
Chris@0 2138 '%term_name' => $entity->name,
Chris@0 2139 '%term_description' => $entity->description,
Chris@0 2140 '%term_id' => $entity->id(),
Chris@0 2141 '%vocabulary_name' => $vocabulary->label(),
Chris@0 2142 '%vocabulary_description' => $vocabulary->getDescription(),
Chris@0 2143 '%vocabulary_id' => $vocabulary->id(),
Chris@0 2144 ];
Chris@0 2145 }
Chris@0 2146
Chris@0 2147 // Node-based variable translation is only available if we have a node.
Chris@0 2148 if (isset($params['node'])) {
Chris@0 2149 /** @var \Drupal\node\NodeInterface $node */
Chris@0 2150 $node = $params['node'];
Chris@0 2151 $variables += [
Chris@0 2152 '%uid' => $node->getOwnerId(),
Chris@0 2153 '%url' => $node->url('canonical', ['absolute' => TRUE]),
Chris@0 2154 '%node_type' => node_get_type_label($node),
Chris@0 2155 '%title' => $node->getTitle(),
Chris@0 2156 '%teaser' => $node->teaser,
Chris@0 2157 '%body' => $node->body,
Chris@0 2158 ];
Chris@0 2159 }
Chris@0 2160 $subject = strtr($context['subject'], $variables);
Chris@0 2161 $body = strtr($context['message'], $variables);
Chris@0 2162 $message['subject'] .= str_replace(["\r", "\n"], '', $subject);
Chris@0 2163 $message['body'][] = MailFormatHelper::htmlToText($body);
Chris@0 2164 }
Chris@0 2165
Chris@0 2166 /**
Chris@0 2167 * Alter the list of mail backend plugin definitions.
Chris@0 2168 *
Chris@0 2169 * @param array $info
Chris@0 2170 * The mail backend plugin definitions to be altered.
Chris@0 2171 *
Chris@0 2172 * @see \Drupal\Core\Annotation\Mail
Chris@0 2173 * @see \Drupal\Core\Mail\MailManager
Chris@0 2174 */
Chris@0 2175 function hook_mail_backend_info_alter(&$info) {
Chris@0 2176 unset($info['test_mail_collector']);
Chris@0 2177 }
Chris@0 2178
Chris@0 2179 /**
Chris@0 2180 * Alter the default country list.
Chris@0 2181 *
Chris@0 2182 * @param $countries
Chris@0 2183 * The associative array of countries keyed by two-letter country code.
Chris@0 2184 *
Chris@0 2185 * @see \Drupal\Core\Locale\CountryManager::getList()
Chris@0 2186 */
Chris@0 2187 function hook_countries_alter(&$countries) {
Chris@0 2188 // Elbonia is now independent, so add it to the country list.
Chris@0 2189 $countries['EB'] = 'Elbonia';
Chris@0 2190 }
Chris@0 2191
Chris@0 2192 /**
Chris@0 2193 * Alter display variant plugin definitions.
Chris@0 2194 *
Chris@0 2195 * @param array $definitions
Chris@0 2196 * The array of display variant definitions, keyed by plugin ID.
Chris@0 2197 *
Chris@0 2198 * @see \Drupal\Core\Display\VariantManager
Chris@0 2199 * @see \Drupal\Core\Display\Annotation\DisplayVariant
Chris@0 2200 */
Chris@0 2201 function hook_display_variant_plugin_alter(array &$definitions) {
Chris@0 2202 $definitions['full_page']['admin_label'] = t('Block layout');
Chris@0 2203 }
Chris@0 2204
Chris@0 2205 /**
Chris@0 2206 * Allow modules to alter layout plugin definitions.
Chris@0 2207 *
Chris@0 2208 * @param \Drupal\Core\Layout\LayoutDefinition[] $definitions
Chris@0 2209 * The array of layout definitions, keyed by plugin ID.
Chris@0 2210 */
Chris@0 2211 function hook_layout_alter(&$definitions) {
Chris@0 2212 // Remove a layout.
Chris@0 2213 unset($definitions['twocol']);
Chris@0 2214 }
Chris@0 2215
Chris@0 2216 /**
Chris@0 2217 * Flush all persistent and static caches.
Chris@0 2218 *
Chris@0 2219 * This hook asks your module to clear all of its static caches,
Chris@0 2220 * in order to ensure a clean environment for subsequently
Chris@0 2221 * invoked data rebuilds.
Chris@0 2222 *
Chris@0 2223 * Do NOT use this hook for rebuilding information. Only use it to flush custom
Chris@0 2224 * caches.
Chris@0 2225 *
Chris@0 2226 * Static caches using drupal_static() do not need to be reset manually.
Chris@0 2227 * However, all other static variables that do not use drupal_static() must be
Chris@0 2228 * manually reset.
Chris@0 2229 *
Chris@0 2230 * This hook is invoked by drupal_flush_all_caches(). It runs before module data
Chris@0 2231 * is updated and before hook_rebuild().
Chris@0 2232 *
Chris@0 2233 * @see drupal_flush_all_caches()
Chris@0 2234 * @see hook_rebuild()
Chris@0 2235 */
Chris@0 2236 function hook_cache_flush() {
Chris@0 2237 if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') {
Chris@0 2238 _update_cache_clear();
Chris@0 2239 }
Chris@0 2240 }
Chris@0 2241
Chris@0 2242 /**
Chris@0 2243 * Rebuild data based upon refreshed caches.
Chris@0 2244 *
Chris@0 2245 * This hook allows your module to rebuild its data based on the latest/current
Chris@0 2246 * module data. It runs after hook_cache_flush() and after all module data has
Chris@0 2247 * been updated.
Chris@0 2248 *
Chris@0 2249 * This hook is only invoked after the system has been completely cleared;
Chris@0 2250 * i.e., all previously cached data is known to be gone and every API in the
Chris@0 2251 * system is known to return current information, so your module can safely rely
Chris@0 2252 * on all available data to rebuild its own.
Chris@0 2253 *
Chris@0 2254 * @see hook_cache_flush()
Chris@0 2255 * @see drupal_flush_all_caches()
Chris@0 2256 */
Chris@0 2257 function hook_rebuild() {
Chris@0 2258 $themes = \Drupal::service('theme_handler')->listInfo();
Chris@0 2259 foreach ($themes as $theme) {
Chris@0 2260 _block_rehash($theme->getName());
Chris@0 2261 }
Chris@0 2262 }
Chris@0 2263
Chris@0 2264 /**
Chris@0 2265 * Alter the configuration synchronization steps.
Chris@0 2266 *
Chris@0 2267 * @param array $sync_steps
Chris@0 2268 * A one-dimensional array of \Drupal\Core\Config\ConfigImporter method names
Chris@0 2269 * or callables that are invoked to complete the import, in the order that
Chris@0 2270 * they will be processed. Each callable item defined in $sync_steps should
Chris@0 2271 * either be a global function or a public static method. The callable should
Chris@0 2272 * accept a $context array by reference. For example:
Chris@0 2273 * <code>
Chris@0 2274 * function _additional_configuration_step(&$context) {
Chris@0 2275 * // Do stuff.
Chris@0 2276 * // If finished set $context['finished'] = 1.
Chris@0 2277 * }
Chris@0 2278 * </code>
Chris@0 2279 * For more information on creating batches, see the
Chris@0 2280 * @link batch Batch operations @endlink documentation.
Chris@0 2281 *
Chris@0 2282 * @see callback_batch_operation()
Chris@0 2283 * @see \Drupal\Core\Config\ConfigImporter::initialize()
Chris@0 2284 */
Chris@0 2285 function hook_config_import_steps_alter(&$sync_steps, \Drupal\Core\Config\ConfigImporter $config_importer) {
Chris@0 2286 $deletes = $config_importer->getUnprocessedConfiguration('delete');
Chris@0 2287 if (isset($deletes['field.storage.node.body'])) {
Chris@0 2288 $sync_steps[] = '_additional_configuration_step';
Chris@0 2289 }
Chris@0 2290 }
Chris@0 2291
Chris@0 2292 /**
Chris@0 2293 * Alter config typed data definitions.
Chris@0 2294 *
Chris@0 2295 * For example you can alter the typed data types representing each
Chris@0 2296 * configuration schema type to change default labels or form element renderers
Chris@0 2297 * used for configuration translation.
Chris@0 2298 *
Chris@0 2299 * If implementations of this hook add or remove configuration schema a
Chris@0 2300 * ConfigSchemaAlterException will be thrown. Keep in mind that there are tools
Chris@0 2301 * that may use the configuration schema for static analysis of configuration
Chris@0 2302 * files, like the string extractor for the localization system. Such systems
Chris@0 2303 * won't work with dynamically defined configuration schemas.
Chris@0 2304 *
Chris@0 2305 * For adding new data types use configuration schema YAML files instead.
Chris@0 2306 *
Chris@0 2307 * @param $definitions
Chris@0 2308 * Associative array of configuration type definitions keyed by schema type
Chris@0 2309 * names. The elements are themselves array with information about the type.
Chris@0 2310 *
Chris@0 2311 * @see \Drupal\Core\Config\TypedConfigManager
Chris@0 2312 * @see \Drupal\Core\Config\Schema\ConfigSchemaAlterException
Chris@0 2313 */
Chris@0 2314 function hook_config_schema_info_alter(&$definitions) {
Chris@0 2315 // Enhance the text and date type definitions with classes to generate proper
Chris@0 2316 // form elements in ConfigTranslationFormBase. Other translatable types will
Chris@0 2317 // appear as a one line textfield.
Chris@0 2318 $definitions['text']['form_element_class'] = '\Drupal\config_translation\FormElement\Textarea';
Chris@0 2319 $definitions['date_format']['form_element_class'] = '\Drupal\config_translation\FormElement\DateFormat';
Chris@0 2320 }
Chris@0 2321
Chris@0 2322 /**
Chris@0 2323 * Alter validation constraint plugin definitions.
Chris@0 2324 *
Chris@0 2325 * @param array[] $definitions
Chris@0 2326 * The array of validation constraint definitions, keyed by plugin ID.
Chris@0 2327 *
Chris@0 2328 * @see \Drupal\Core\Validation\ConstraintManager
Chris@0 2329 * @see \Drupal\Core\Validation\Annotation\Constraint
Chris@0 2330 */
Chris@0 2331 function hook_validation_constraint_alter(array &$definitions) {
Chris@0 2332 $definitions['Null']['class'] = '\Drupal\mymodule\Validator\Constraints\MyClass';
Chris@0 2333 }
Chris@0 2334
Chris@0 2335 /**
Chris@0 2336 * @} End of "addtogroup hooks".
Chris@0 2337 */
Chris@0 2338
Chris@0 2339 /**
Chris@0 2340 * @defgroup ajax Ajax API
Chris@0 2341 * @{
Chris@0 2342 * Overview for Drupal's Ajax API.
Chris@0 2343 *
Chris@0 2344 * @section sec_overview Overview of Ajax
Chris@0 2345 * Ajax is the process of dynamically updating parts of a page's HTML based on
Chris@0 2346 * data from the server. When a specified event takes place, a PHP callback is
Chris@0 2347 * triggered, which performs server-side logic and may return updated markup or
Chris@0 2348 * JavaScript commands to run. After the return, the browser runs the JavaScript
Chris@0 2349 * or updates the markup on the fly, with no full page refresh necessary.
Chris@0 2350 *
Chris@0 2351 * Many different events can trigger Ajax responses, including:
Chris@0 2352 * - Clicking a button
Chris@0 2353 * - Pressing a key
Chris@0 2354 * - Moving the mouse
Chris@0 2355 *
Chris@0 2356 * @section sec_framework Ajax responses in forms
Chris@0 2357 * Forms that use the Drupal Form API (see the
Chris@0 2358 * @link form_api Form API topic @endlink for more information about forms) can
Chris@0 2359 * trigger AJAX responses. Here is an outline of the steps:
Chris@0 2360 * - Add property '#ajax' to a form element in your form array, to trigger an
Chris@0 2361 * Ajax response.
Chris@0 2362 * - Write an Ajax callback to process the input and respond.
Chris@0 2363 * See sections below for details on these two steps.
Chris@0 2364 *
Chris@0 2365 * @subsection sub_form Adding Ajax triggers to a form
Chris@0 2366 * As an example of adding Ajax triggers to a form, consider editing a date
Chris@0 2367 * format, where the user is provided with a sample of the generated date output
Chris@0 2368 * as they type. To accomplish this, typing in the text field should trigger an
Chris@0 2369 * Ajax response. This is done in the text field form array element
Chris@0 2370 * in \Drupal\config_translation\FormElement\DateFormat::getFormElement():
Chris@0 2371 * @code
Chris@0 2372 * '#ajax' => array(
Chris@0 2373 * 'callback' => 'Drupal\config_translation\FormElement\DateFormat::ajaxSample',
Chris@0 2374 * 'event' => 'keyup',
Chris@0 2375 * 'progress' => array(
Chris@0 2376 * 'type' => 'throbber',
Chris@0 2377 * 'message' => NULL,
Chris@0 2378 * ),
Chris@0 2379 * ),
Chris@0 2380 * @endcode
Chris@0 2381 *
Chris@0 2382 * As you can see from this example, the #ajax property for a form element is
Chris@0 2383 * an array. Here are the details of its elements, all of which are optional:
Chris@0 2384 * - callback: The callback to invoke to handle the server side of the
Chris@0 2385 * Ajax event. More information on callbacks is below in @ref sub_callback.
Chris@0 2386 * - wrapper: The HTML 'id' attribute of the area where the content returned by
Chris@0 2387 * the callback should be placed. Note that callbacks have a choice of
Chris@0 2388 * returning content or JavaScript commands; 'wrapper' is used for content
Chris@0 2389 * returns.
Chris@0 2390 * - method: The jQuery method for placing the new content (used with
Chris@0 2391 * 'wrapper'). Valid options are 'replaceWith' (default), 'append', 'prepend',
Chris@0 2392 * 'before', 'after', or 'html'. See
Chris@0 2393 * http://api.jquery.com/category/manipulation/ for more information on these
Chris@0 2394 * methods.
Chris@0 2395 * - effect: The jQuery effect to use when placing the new HTML (used with
Chris@0 2396 * 'wrapper'). Valid options are 'none' (default), 'slide', or 'fade'.
Chris@0 2397 * - speed: The effect speed to use (used with 'effect' and 'wrapper'). Valid
Chris@0 2398 * options are 'slow' (default), 'fast', or the number of milliseconds the
Chris@0 2399 * effect should run.
Chris@0 2400 * - event: The JavaScript event to respond to. This is selected automatically
Chris@0 2401 * for the type of form element; provide a value to override the default.
Chris@0 2402 * - prevent: A JavaScript event to prevent when the event is triggered. For
Chris@0 2403 * example, if you use event 'mousedown' on a button, you might want to
Chris@0 2404 * prevent 'click' events from also being triggered.
Chris@0 2405 * - progress: An array indicating how to show Ajax processing progress. Can
Chris@0 2406 * contain one or more of these elements:
Chris@0 2407 * - type: Type of indicator: 'throbber' (default) or 'bar'.
Chris@0 2408 * - message: Translated message to display.
Chris@0 2409 * - url: For a bar progress indicator, URL path for determining progress.
Chris@0 2410 * - interval: For a bar progress indicator, how often to update it.
Chris@0 2411 * - url: A \Drupal\Core\Url to which to submit the Ajax request. If omitted,
Chris@0 2412 * defaults to either the same URL as the form or link destination is for
Chris@0 2413 * someone with JavaScript disabled, or a slightly modified version (e.g.,
Chris@0 2414 * with a query parameter added, removed, or changed) of that URL if
Chris@0 2415 * necessary to support Drupal's content negotiation. It is recommended to
Chris@0 2416 * omit this key and use Drupal's content negotiation rather than using
Chris@0 2417 * substantially different URLs between Ajax and non-Ajax.
Chris@0 2418 *
Chris@0 2419 * @subsection sub_callback Setting up a callback to process Ajax
Chris@0 2420 * Once you have set up your form to trigger an Ajax response (see @ref sub_form
Chris@0 2421 * above), you need to write some PHP code to process the response. If you use
Chris@0 2422 * 'path' in your Ajax set-up, your route controller will be triggered with only
Chris@0 2423 * the information you provide in the URL. If you use 'callback', your callback
Chris@0 2424 * method is a function, which will receive the $form and $form_state from the
Chris@0 2425 * triggering form. You can use $form_state to get information about the
Chris@0 2426 * data the user has entered into the form. For instance, in the above example
Chris@0 2427 * for the date format preview,
Chris@0 2428 * \Drupal\config_translation\FormElement\DateFormat\ajaxSample() does this to
Chris@0 2429 * get the format string entered by the user:
Chris@0 2430 * @code
Chris@0 2431 * $format_value = \Drupal\Component\Utility\NestedArray::getValue(
Chris@0 2432 * $form_state->getValues(),
Chris@0 2433 * $form_state->getTriggeringElement()['#array_parents']);
Chris@0 2434 * @endcode
Chris@0 2435 *
Chris@0 2436 * Once you have processed the input, you have your choice of returning HTML
Chris@0 2437 * markup or a set of Ajax commands. If you choose to return HTML markup, you
Chris@0 2438 * can return it as a string or a renderable array, and it will be placed in
Chris@0 2439 * the defined 'wrapper' element (see documentation above in @ref sub_form).
Chris@0 2440 * In addition, any messages returned by drupal_get_messages(), themed as in
Chris@0 2441 * status-messages.html.twig, will be prepended.
Chris@0 2442 *
Chris@0 2443 * To return commands, you need to set up an object of class
Chris@0 2444 * \Drupal\Core\Ajax\AjaxResponse, and then use its addCommand() method to add
Chris@0 2445 * individual commands to it. In the date format preview example, the format
Chris@0 2446 * output is calculated, and then it is returned as replacement markup for a div
Chris@0 2447 * like this:
Chris@0 2448 * @code
Chris@0 2449 * $response = new AjaxResponse();
Chris@0 2450 * $response->addCommand(new ReplaceCommand(
Chris@0 2451 * '#edit-date-format-suffix',
Chris@0 2452 * '<small id="edit-date-format-suffix">' . $format . '</small>'));
Chris@0 2453 * return $response;
Chris@0 2454 * @endcode
Chris@0 2455 *
Chris@0 2456 * The individual commands that you can return implement interface
Chris@0 2457 * \Drupal\Core\Ajax\CommandInterface. Available commands provide the ability
Chris@0 2458 * to pop up alerts, manipulate text and markup in various ways, redirect
Chris@0 2459 * to a new URL, and the generic \Drupal\Core\Ajax\InvokeCommand, which
Chris@0 2460 * invokes an arbitrary jQuery command.
Chris@0 2461 *
Chris@0 2462 * As noted above, status messages are prepended automatically if you use the
Chris@0 2463 * 'wrapper' method and return HTML markup. This is not the case if you return
Chris@0 2464 * commands, but if you would like to show status messages, you can add
Chris@0 2465 * @code
Chris@0 2466 * array('#type' => 'status_messages')
Chris@0 2467 * @endcode
Chris@0 2468 * to a render array, use drupal_render() to render it, and add a command to
Chris@0 2469 * place the messages in an appropriate location.
Chris@0 2470 *
Chris@0 2471 * @section sec_other Other methods for triggering Ajax
Chris@0 2472 * Here are some additional methods you can use to trigger Ajax responses in
Chris@0 2473 * Drupal:
Chris@0 2474 * - Add class 'use-ajax' to a link. The link will be loaded using an Ajax
Chris@0 2475 * call. When using this method, the href of the link can contain '/nojs/' as
Chris@0 2476 * part of the path. When the Ajax JavaScript processes the page, it will
Chris@0 2477 * convert this to '/ajax/'. The server is then able to easily tell if this
Chris@0 2478 * request was made through an actual Ajax request or in a degraded state, and
Chris@0 2479 * respond appropriately.
Chris@0 2480 * - Add class 'use-ajax-submit' to a submit button in a form. The form will
Chris@0 2481 * then be submitted via Ajax to the path specified in the #action. Like the
Chris@0 2482 * ajax-submit class on links, this path will have '/nojs/' replaced with
Chris@0 2483 * '/ajax/' so that the submit handler can tell if the form was submitted in a
Chris@0 2484 * degraded state or not.
Chris@0 2485 * - Add property '#autocomplete_route_name' to a text field in a form. The
Chris@0 2486 * route controller for this route must return an array of options for
Chris@0 2487 * autocomplete, as a \Symfony\Component\HttpFoundation\JsonResponse object.
Chris@0 2488 * See the @link menu Routing topic @endlink for more information about
Chris@0 2489 * routing.
Chris@0 2490 */
Chris@0 2491
Chris@0 2492 /**
Chris@0 2493 * @} End of "defgroup ajax".
Chris@0 2494 */
Chris@0 2495
Chris@0 2496 /**
Chris@0 2497 * @defgroup service_tag Service Tags
Chris@0 2498 * @{
Chris@0 2499 * Service tags overview
Chris@0 2500 *
Chris@0 2501 * Some services have tags, which are defined in the service definition. Tags
Chris@0 2502 * are used to define a group of related services, or to specify some aspect of
Chris@0 2503 * how the service behaves. Typically, if you tag a service, your service class
Chris@0 2504 * must also implement a corresponding interface. Some common examples:
Chris@0 2505 * - access_check: Indicates a route access checking service; see the
Chris@0 2506 * @link menu Menu and routing system topic @endlink for more information.
Chris@0 2507 * - cache.bin: Indicates a cache bin service; see the
Chris@0 2508 * @link cache Cache topic @endlink for more information.
Chris@0 2509 * - event_subscriber: Indicates an event subscriber service. Event subscribers
Chris@0 2510 * can be used for dynamic routing and route altering; see the
Chris@0 2511 * @link menu Menu and routing system topic @endlink for more information.
Chris@0 2512 * They can also be used for other purposes; see
Chris@0 2513 * http://symfony.com/doc/current/cookbook/doctrine/event_listeners_subscribers.html
Chris@0 2514 * for more information.
Chris@0 2515 * - needs_destruction: Indicates that a destruct() method needs to be called
Chris@0 2516 * at the end of a request to finalize operations, if this service was
Chris@0 2517 * instantiated. Services should implement \Drupal\Core\DestructableInterface
Chris@0 2518 * in this case.
Chris@0 2519 * - context_provider: Indicates a block context provider, used for example
Chris@0 2520 * by block conditions. It has to implement
Chris@0 2521 * \Drupal\Core\Plugin\Context\ContextProviderInterface.
Chris@0 2522 * - http_client_middleware: Indicates that the service provides a guzzle
Chris@0 2523 * middleware, see
Chris@0 2524 * https://guzzle.readthedocs.org/en/latest/handlers-and-middleware.html for
Chris@0 2525 * more information.
Chris@0 2526 *
Chris@0 2527 * Creating a tag for a service does not do anything on its own, but tags
Chris@0 2528 * can be discovered or queried in a compiler pass when the container is built,
Chris@0 2529 * and a corresponding action can be taken. See
Chris@0 2530 * \Drupal\Core\Render\MainContent\MainContentRenderersPass for an example of
Chris@0 2531 * finding tagged services.
Chris@0 2532 *
Chris@0 2533 * See @link container Services and Dependency Injection Container @endlink for
Chris@0 2534 * information on services and the dependency injection container.
Chris@0 2535 *
Chris@0 2536 * @}
Chris@0 2537 */
Chris@0 2538
Chris@0 2539 /**
Chris@0 2540 * @defgroup events Events
Chris@0 2541 * @{
Chris@0 2542 * Overview of event dispatch and subscribing
Chris@0 2543 *
Chris@0 2544 * @section sec_intro Introduction and terminology
Chris@0 2545 * Events are part of the Symfony framework: they allow for different components
Chris@0 2546 * of the system to interact and communicate with each other. Each event has a
Chris@0 2547 * unique string name. One system component dispatches the event at an
Chris@0 2548 * appropriate time; many events are dispatched by Drupal core and the Symfony
Chris@0 2549 * framework in every request. Other system components can register as event
Chris@0 2550 * subscribers; when an event is dispatched, a method is called on each
Chris@0 2551 * registered subscriber, allowing each one to react. For more on the general
Chris@0 2552 * concept of events, see
Chris@0 2553 * http://symfony.com/doc/current/components/event_dispatcher/introduction.html
Chris@0 2554 *
Chris@0 2555 * @section sec_dispatch Dispatching events
Chris@0 2556 * To dispatch an event, call the
Chris@0 2557 * \Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch()
Chris@0 2558 * method on the 'event_dispatcher' service (see the
Chris@0 2559 * @link container Services topic @endlink for more information about how to
Chris@0 2560 * interact with services). The first argument is the unique event name, which
Chris@0 2561 * you should normally define as a constant in a separate static class (see
Chris@0 2562 * \Symfony\Component\HttpKernel\KernelEvents and
Chris@0 2563 * \Drupal\Core\Config\ConfigEvents for examples). The second argument is a
Chris@0 2564 * \Symfony\Component\EventDispatcher\Event object; normally you will need to
Chris@0 2565 * extend this class, so that your event class can provide data to the event
Chris@0 2566 * subscribers.
Chris@0 2567 *
Chris@0 2568 * @section sec_subscribe Registering event subscribers
Chris@0 2569 * Here are the steps to register an event subscriber:
Chris@0 2570 * - Define a service in your module, tagged with 'event_subscriber' (see the
Chris@0 2571 * @link container Services topic @endlink for instructions).
Chris@0 2572 * - Define a class for your subscriber service that implements
Chris@0 2573 * \Symfony\Component\EventDispatcher\EventSubscriberInterface
Chris@0 2574 * - In your class, the getSubscribedEvents method returns a list of the events
Chris@0 2575 * this class is subscribed to, and which methods on the class should be
Chris@0 2576 * called for each one. Example:
Chris@0 2577 * @code
Chris@0 2578 * public static function getSubscribedEvents() {
Chris@0 2579 * // Subscribe to kernel terminate with priority 100.
Chris@0 2580 * $events[KernelEvents::TERMINATE][] = array('onTerminate', 100);
Chris@0 2581 * // Subscribe to kernel request with default priority of 0.
Chris@0 2582 * $events[KernelEvents::REQUEST][] = array('onRequest');
Chris@0 2583 * return $events;
Chris@0 2584 * }
Chris@0 2585 * @endcode
Chris@0 2586 * - Write the methods that respond to the events; each one receives the
Chris@0 2587 * event object provided in the dispatch as its one argument. In the above
Chris@0 2588 * example, you would need to write onTerminate() and onRequest() methods.
Chris@0 2589 *
Chris@0 2590 * Note that in your getSubscribedEvents() method, you can optionally set the
Chris@0 2591 * priority of your event subscriber (see terminate example above). Event
Chris@0 2592 * subscribers with higher priority numbers get executed first; the default
Chris@0 2593 * priority is zero. If two event subscribers for the same event have the same
Chris@0 2594 * priority, the one defined in a module with a lower module weight will fire
Chris@0 2595 * first. Subscribers defined in the same services file are fired in
Chris@0 2596 * definition order. If order matters defining a priority is strongly advised
Chris@0 2597 * instead of relying on these two tie breaker rules as they might change in a
Chris@0 2598 * minor release.
Chris@0 2599 * @}
Chris@0 2600 */