2015-08-17 17:00:26 -07:00
< ? php
/**
* @ file
* Documentation landing page and topics , plus core library hooks .
*/
/**
* @ mainpage
* Welcome to the Drupal API Documentation !
*
* This site is an API reference for Drupal , generated from comments embedded
* in the source code . More in - depth documentation can be found at
* https :// www . drupal . org / developing / api .
*
* Here are some topics to help you get started developing with Drupal .
*
* @ section essentials Essential background concepts
*
* - @ link oo_conventions Object - oriented conventions used in Drupal @ endlink
* - @ link extending Extending and altering Drupal @ endlink
* - @ link best_practices Security and best practices @ endlink
* - @ link info_types Types of information in Drupal @ endlink
*
* @ section interface User interface
*
2015-10-08 11:40:12 -07:00
* - @ link menu Menu entries , local tasks , and other links @ endlink
* - @ link routing Routing API and page controllers @ endlink
2015-08-17 17:00:26 -07:00
* - @ link form_api Forms @ endlink
* - @ link block_api Blocks @ endlink
* - @ link ajax Ajax @ endlink
*
* @ section store_retrieve Storing and retrieving data
*
* - @ link entity_api Entities @ endlink
* - @ link field Fields @ endlink
* - @ link config_api Configuration API @ endlink
* - @ link state_api State API @ endlink
* - @ link views_overview Views @ endlink
* - @ link database Database abstraction layer @ endlink
*
* @ section other_essentials Other essential APIs
*
* - @ link plugin_api Plugins @ endlink
* - @ link container Services and the Dependency Injection Container @ endlink
* - @ link events Events @ endlink
* - @ link i18n Internationalization @ endlink
* - @ link cache Caching @ endlink
* - @ link utility Utility classes and functions @ endlink
* - @ link user_api User accounts , permissions , and roles @ endlink
* - @ link theme_render Render API @ endlink
* - @ link themeable Theme system @ endlink
2015-09-04 13:20:09 -07:00
* - @ link update_api Update API @ endlink
2015-08-17 17:00:26 -07:00
* - @ link migration Migration @ endlink
*
* @ section additional Additional topics
*
* - @ link batch Batch API @ endlink
* - @ link queue Queue API @ endlink
* - @ link typed_data Typed Data @ endlink
* - @ link testing Automated tests @ endlink
2015-08-27 12:03:05 -07:00
* - @ link php_assert PHP Runtime Assert Statements @ endlink
2015-08-17 17:00:26 -07:00
* - @ link third_party Integrating third - party applications @ endlink
*
* @ section more_info Further information
*
* - @ link https :// api . drupal . org / api / drupal / groups / 8 All topics @ endlink
* - @ link https :// www . drupal . org / project / examples Examples project ( sample modules ) @ endlink
* - @ link https :// www . drupal . org / list - changes API change notices @ endlink
* - @ link https :// www . drupal . org / developing / api / 8 Drupal 8 API longer references @ endlink
*/
/**
* @ defgroup third_party REST and Application Integration
* @ {
* Integrating third - party applications using REST and related operations .
*
* @ section sec_overview Overview of web services
* Web services make it possible for applications and web sites to read and
* update information from other web sites . There are several standard
* techniques for providing web services , including :
2016-04-20 09:56:34 -07:00
* - SOAP : http :// wikipedia . org / wiki / SOAP
* - XML - RPC : http :// wikipedia . org / wiki / XML - RPC
* - REST : http :// wikipedia . org / wiki / Representational_state_transfer
2015-08-17 17:00:26 -07:00
* Drupal sites can both provide web services and integrate third - party web
* services .
*
* @ section sec_rest_overview Overview of REST
* The REST technique uses basic HTTP requests to obtain and update data , where
* each web service defines a specific API ( HTTP GET and / or POST parameters and
* returned response ) for its HTTP requests . REST requests are separated into
* several types , known as methods , including :
* - GET : Requests to obtain data .
2015-10-08 11:40:12 -07:00
* - POST : Requests to update or create data .
* - PUT : Requests to update or create data ( limited support , currently unused
* by entity resources ) .
2015-08-17 17:00:26 -07:00
* - PATCH : Requests to update a subset of data , such as one field .
* - DELETE : Requests to delete data .
2015-10-08 11:40:12 -07:00
* The Drupal Core REST module provides support for GET , POST , PATCH , and DELETE
2015-08-17 17:00:26 -07:00
* quests on entities , GET requests on the database log from the Database
* Logging module , and a plugin framework for providing REST support for other
* data and other methods .
*
* REST requests can be authenticated . The Drupal Core Basic Auth module
* provides authentication using the HTTP Basic protocol ; the contributed module
* OAuth ( https :// www . drupal . org / project / oauth ) implements the OAuth
* authentication protocol . You can also use cookie - based authentication , which
* would require users to be logged into the Drupal site while using the
* application on the third - party site that is using the REST service .
*
* @ section sec_rest Enabling REST for entities and the log
* Here are the steps to take to use the REST operations provided by Drupal
* Core :
* - Enable the REST module , plus Basic Auth ( or another authentication method )
* and HAL .
* - Node entity support is configured by default . If you would like to support
* other types of entities , you can copy
2015-10-08 11:40:12 -07:00
* core / modules / rest / config / install / rest . settings . yml to your sync
2015-08-17 17:00:26 -07:00
* configuration directory , appropriately modified for other entity types ,
* and import it . Support for GET on the log from the Database Logging module
* can also be enabled in this way ; in this case , the 'entity:node' line
* in the configuration would be replaced by the appropriate plugin ID ,
* 'dblog' .
* - Set up permissions to allow the desired REST operations for a role , and set
* up one or more user accounts to perform the operations .
* - To perform a REST operation , send a request to either the canonical URL
* for an entity ( such as node / 12345 for a node ), or if the entity does not
* have a canonical URL , a URL like entity / ( type ) / ( ID ) . The URL for a log
* entry is dblog / ( ID ) . The request must have the following properties :
* - The request method must be set to the REST method you are using ( POST ,
* GET , PATCH , etc . ) .
* - The content type for the data you send , or the accept type for the
* data you are receiving , must be set to 'application/hal+json' .
* - If you are sending data , it must be JSON - encoded .
* - You ' ll also need to make sure the authentication information is sent
* with the request , unless you have allowed access to anonymous users .
*
* For more detailed information on setting up REST , see
* https :// www . drupal . org / documentation / modules / rest .
*
* @ section sec_plugins Defining new REST plugins
* The REST framework in the REST module has support built in for entities , but
* it is also an extensible plugin - based system . REST plugins implement
* interface \Drupal\rest\Plugin\ResourceInterface , and generally extend base
* class \Drupal\rest\Plugin\ResourceBase . They are annotated with
* \Drupal\rest\Annotation\RestResource annotation , and must be in plugin
* namespace subdirectory Plugin\rest\resource . For more information on how to
* create plugins , see the @ link plugin_api Plugin API topic . @ endlink
*
* If you create a new REST plugin , you will also need to enable it by
* providing default configuration or configuration import , as outlined in
* @ ref sec_rest above .
*
* @ section sec_integrate Integrating data from other sites into Drupal
* If you want to integrate data from other web sites into Drupal , here are
* some notes :
* - There are contributed modules available for integrating many third - party
* sites into Drupal . Search on https :// www . drupal . org / project / project_module
* - If there is not an existing module , you will need to find documentation on
* the specific web services API for the site you are trying to integrate .
* - There are several classes and functions that are useful for interacting
* with web services :
* - You should make requests using the 'http_client' service , which
* implements \GuzzleHttp\ClientInterface . See the
* @ link container Services topic @ endlink for more information on
* services . If you cannot use dependency injection to retrieve this
* service , the \Drupal :: httpClient () method is available . A good example
* of how to use this service can be found in
* \Drupal\aggregator\Plugin\aggregator\fetcher\DefaultFetcher
* - \Drupal\Component\Serialization\Json ( JSON encoding and decoding ) .
* - PHP has functions and classes for parsing XML ; see
* http :// php . net / manual / refs . xml . php
* @ }
*/
/**
* @ defgroup state_api State API
* @ {
* Information about the State API .
*
* The State API is one of several methods in Drupal for storing information .
* See the @ link info_types Information types topic @ endlink for an
* overview of the different types of information .
*
* The basic entry point into the State API is \Drupal :: state (), which returns
* an object of class \Drupal\Core\State\StateInterface . This class has
* methods for storing and retrieving state information ; each piece of state
* information is associated with a string - valued key . Example :
* @ code
* // Get the state class.
* $state = \Drupal :: state ();
* // Find out when cron was last run; the key is 'system.cron_last'.
* $time = $state -> get ( 'system.cron_last' );
* // Set the cron run time to the current request time.
* $state -> set ( 'system.cron_last' , REQUEST_TIME );
* @ endcode
*
* For more on the State API , see https :// www . drupal . org / developing / api / 8 / state
* @ }
*/
/**
* @ defgroup config_api Configuration API
* @ {
* Information about the Configuration API .
*
* The Configuration API is one of several methods in Drupal for storing
* information . See the @ link info_types Information types topic @ endlink for
* an overview of the different types of information . The sections below have
* more information about the configuration API ; see
* https :// www . drupal . org / developing / api / 8 / configuration for more details .
*
* @ section sec_storage Configuration storage
* In Drupal , there is a concept of the " active " configuration , which is the
* configuration that is currently in use for a site . The storage used for the
* active configuration is configurable : it could be in the database , in files
* in a particular directory , or in other storage backends ; the default storage
* is in the database . Module developers must use the configuration API to
* access the active configuration , rather than being concerned about the
* details of where and how it is stored .
*
* Configuration is divided into individual objects , each of which has a
* unique name or key . Some modules will have only one configuration object ,
* typically called 'mymodule.settings' ; some modules will have many . Within
* a configuration object , configuration settings have data types ( integer ,
* string , Boolean , etc . ) and settings can also exist in a nested hierarchy ,
* known as a " mapping " .
*
* Configuration can also be overridden on a global , per - language , or
* per - module basis . See https :// www . drupal . org / node / 1928898 for more
* information .
*
* @ section sec_yaml Configuration YAML files
* Whether or not configuration files are being used for the active
* configuration storage on a particular site , configuration files are always
* used for :
2015-09-04 13:20:09 -07:00
* - Defining the default configuration for an extension ( module , theme , or
2015-12-02 11:38:43 -08:00
* profile ), which is imported to the active storage when the extension is
2015-09-04 13:20:09 -07:00
* enabled . These configuration items are located in the config / install
* sub - directory of the extension . Note that changes to this configuration
* after a module or theme is already enabled have no effect ; to make a
* configuration change after a module or theme is enabled , you would need to
* uninstall / reinstall or use a hook_update_N () function .
* - Defining optional configuration for a module or theme . Optional
* configuration items are located in the config / optional sub - directory of the
* extension . These configuration items have dependencies that are not
* explicit dependencies of the extension , so they are only installed if all
* dependencies are met . For example , in the scenario that module A defines a
* dependency which requires module B , but module A is installed first and
* module B some time later , then module A ' s config / optional directory will be
* scanned at that time for newly met dependencies , and the configuration will
* be installed then . If module B is never installed , the configuration item
* will not be installed either .
2015-08-17 17:00:26 -07:00
* - Exporting and importing configuration .
*
* The file storage format for configuration information in Drupal is
2016-04-20 09:56:34 -07:00
* @ link http :// wikipedia . org / wiki / YAML YAML files . @ endlink Configuration is
2015-08-17 17:00:26 -07:00
* divided into files , each containing one configuration object . The file name
* for a configuration object is equal to the unique name of the configuration ,
* with a '.yml' extension . The default configuration files for each module are
* placed in the config / install directory under the top - level module directory ,
* so look there in most Core modules for examples .
*
* @ section sec_schema Configuration schema and translation
* Each configuration file has a specific structure , which is expressed as a
* YAML - based configuration schema . The configuration schema details the
* structure of the configuration , its data types , and which of its values need
* to be translatable . Each module needs to define its configuration schema in
* files in the config / schema directory under the top - level module directory , so
* look there in most Core modules for examples .
*
* Configuration can be internationalized ; see the
* @ link i18n Internationalization topic @ endlink for more information . Data
* types label , text , and date_format in configuration schema are translatable ;
* string is non - translatable text ( the 'translatable' property on a schema
* data type definition indicates that it is translatable ) .
*
* @ section sec_simple Simple configuration
* The simple configuration API should be used for information that will always
* have exactly one copy or version . For instance , if your module has a
* setting that is either on or off , then this is only defined once , and it
* would be a Boolean - valued simple configuration setting .
*
* The first task in using the simple configuration API is to define the
* configuration file structure , file name , and schema of your settings ( see
2016-04-07 11:19:57 -07:00
* @ ref sec_yaml above ) . Once you have done that , you can retrieve the active
* configuration object that corresponds to configuration file mymodule . foo . yml
* with a call to :
2015-08-17 17:00:26 -07:00
* @ code
* $config = \Drupal :: config ( 'mymodule.foo' );
* @ endcode
*
* This will be an object of class \Drupal\Core\Config\Config , which has methods
2016-04-07 11:19:57 -07:00
* for getting configuration information . For instance , if your YAML file
* structure looks like this :
2015-08-17 17:00:26 -07:00
* @ code
* enabled : '0'
* bar :
* baz : 'string1'
* boo : 34
* @ endcode
* you can make calls such as :
* @ code
* // Get a single value.
* $enabled = $config -> get ( 'enabled' );
* // Get an associative array.
* $bar = $config -> get ( 'bar' );
* // Get one element of the array.
* $bar_baz = $config -> get ( 'bar.baz' );
2016-04-07 11:19:57 -07:00
* @ endcode
*
* The Config object that was obtained and used in the previous examples does
* not allow you to change configuration . If you want to change configuration ,
* you will instead need to get the Config object by making a call to
* getEditable () on the config factory :
* @ code
* $config = \Drupal :: service ( 'config.factory' ) -> getEditable ( 'mymodule.foo' );
* @ endcode
*
* Individual configuration values can be changed or added using the set ()
* method and saved using the save () method :
* @ code
* // Set a scalar value.
* $config -> set ( 'enabled' , 1 );
* // Save the configuration.
2015-08-17 17:00:26 -07:00
* $config -> save ();
* @ endcode
*
2016-04-07 11:19:57 -07:00
* Configuration values can also be unset using the clear () method , which is
* also chainable :
* @ code
* $config -> clear ( 'bar.boo' ) -> save ();
* $config_data = $config -> get ( 'bar' );
* @ endcode
* In this example $config_data would return an array with one key - 'baz' -
* because 'boo' was unset .
*
2015-08-17 17:00:26 -07:00
* @ section sec_entity Configuration entities
* In contrast to the simple configuration settings described in the previous
* section , if your module allows users to create zero or more items ( where
* " items " are things like content type definitions , view definitions , and the
* like ), then you need to define a configuration entity type to store your
* configuration . Creating an entity type , loading entities , and querying them
* are outlined in the @ link entity_api Entity API topic . @ endlink Here are a
* few additional steps and notes specific to configuration entities :
* - For examples , look for classes that implement
* \Drupal\Core\Config\Entity\ConfigEntityInterface -- one good example is
* the \Drupal\user\Entity\Role entity type .
* - In the entity type annotation , you will need to define a 'config_prefix'
* string . When Drupal stores a configuration item , it will be given a name
* composed of your module name , your chosen config prefix , and the ID of
* the individual item , separated by '.' . For example , in the Role entity ,
* the config prefix is 'role' , so one configuration item might be named
* user . role . anonymous , with configuration file user . role . anonymous . yml .
* - You will need to define the schema for your configuration in your
* modulename . schema . yml file , with an entry for 'modulename.config_prefix.*' .
* For example , for the Role entity , the file user . schema . yml has an entry
* user . role .* ; see @ ref sec_yaml above for more information .
2015-09-04 13:20:09 -07:00
* - Your module can provide default / optional configuration entities in YAML
* files ; see @ ref sec_yaml above for more information .
2015-08-17 17:00:26 -07:00
* - Some configuration entities have dependencies on other configuration
* entities , and module developers need to consider this so that configuration
* can be imported , uninstalled , and synchronized in the right order . For
* example , a field display configuration entity would need to depend on
* field configuration , which depends on field and bundle configuration .
* Configuration entity classes expose dependencies by overriding the
* \Drupal\Core\Config\Entity\ConfigEntityInterface :: calculateDependencies ()
* method .
2016-01-06 16:31:26 -08:00
* - On routes for paths starting with '/admin' or otherwise designated as
2015-08-17 17:00:26 -07:00
* administration paths ( such as node editing when it is set as an admin
* operation ), if they have configuration entity placeholders , configuration
* entities are normally loaded in their original language , without
* translations or other overrides . This is usually desirable , because most
* admin paths are for editing configuration , and you need that to be in the
* source language and to lack possibly dynamic overrides . If for some reason
* you need to have your configuration entity loaded in the currently - selected
* language on an admin path ( for instance , if you go to
* example . com / es / admin / your_path and you need the entity to be in Spanish ),
* then you can add a 'with_config_overrides' parameter option to your route .
* The same applies if you need to load the entity with overrides ( or
* translated ) on an admin path like '/node/add/article' ( when configured to
* be an admin path ) . Here ' s an example using the configurable_language config
* entity :
* @ code
* mymodule . myroute :
* path : '/admin/mypath/{configurable_language}'
* defaults :
* _controller : '\Drupal\mymodule\MyController::myMethod'
* options :
* parameters :
* configurable_language :
* type : entity : configurable_language
* with_config_overrides : TRUE
* @ endcode
* With the route defined this way , the $configurable_language parameter to
* your controller method will come in translated to the current language .
* Without the parameter options section , it would be in the original
* language , untranslated .
*
* @ see i18n
*
* @ }
*/
/**
* @ defgroup cache Cache API
* @ {
* Information about the Drupal Cache API
*
* @ section basics Basics
*
* Note : If not specified , all of the methods mentioned here belong to
* \Drupal\Core\Cache\CacheBackendInterface .
*
* The Cache API is used to store data that takes a long time to compute .
* Caching can either be permanent or valid only for a certain timespan , and
* the cache can contain any type of data .
*
* To use the Cache API :
* - Request a cache object through \Drupal :: cache () or by injecting a cache
* service .
* - Define a Cache ID ( cid ) value for your data . A cid is a string , which must
* contain enough information to uniquely identify the data . For example , if
* your data contains translated strings , then your cid value must include the
* interface text language selected for page .
* - Call the get () method to attempt a cache read , to see if the cache already
* contains your data .
* - If your data is not already in the cache , compute it and add it to the
* cache using the set () method . The third argument of set () can be used to
* control the lifetime of your cache item .
*
* Example :
* @ code
* $cid = 'mymodule_example:' . \Drupal :: languageManager () -> getCurrentLanguage () -> getId ();
*
* $data = NULL ;
* if ( $cache = \Drupal :: cache () -> get ( $cid )) {
* $data = $cache -> data ;
* }
* else {
* $data = my_module_complicated_calculation ();
* \Drupal :: cache () -> set ( $cid , $data );
* }
* @ endcode
*
* Note the use of $data and $cache -> data in the above example . Calls to
* \Drupal :: cache () -> get () return a record that contains the information stored
* by \Drupal :: cache () -> set () in the data property as well as additional meta
* information about the cached data . In order to make use of the cached data
* you can access it via $cache -> data .
*
* @ section bins Cache bins
*
* Cache storage is separated into " bins " , each containing various cache items .
* Each bin can be configured separately ; see @ ref configuration .
*
* When you request a cache object , you can specify the bin name in your call to
* \Drupal :: cache () . Alternatively , you can request a bin by getting service
* " cache.nameofbin " from the container . The default bin is called " default " , with
* service name " cache.default " , it is used to store common and frequently used
* caches .
*
* Other common cache bins are the following :
2016-08-03 13:22:33 -07:00
* - bootstrap : Data needed from the beginning to the end of most requests ,
* that has a very strict limit on variations and is invalidated rarely .
2015-08-17 17:00:26 -07:00
* - render : Contains cached HTML strings like cached pages and blocks , can
* grow to large size .
* - data : Contains data that can vary by path or similar context .
* - discovery : Contains cached discovery data for things such as plugins ,
* views_data , or YAML discovered data such as library info .
*
* A module can define a cache bin by defining a service in its
* modulename . services . yml file as follows ( substituting the desired name for
* " nameofbin " ) :
* @ code
* cache . nameofbin :
* class : Drupal\Core\Cache\CacheBackendInterface
* tags :
* - { name : cache . bin }
* factory : cache_factory : get
* arguments : [ nameofbin ]
* @ endcode
* See the @ link container Services topic @ endlink for more on defining
* services .
*
* @ section delete Deletion
*
* There are two ways to remove an item from the cache :
* - Deletion ( using delete (), deleteMultiple () or deleteAll ()) permanently
* removes the item from the cache .
* - Invalidation ( using invalidate (), invalidateMultiple () or invalidateAll ())
* is a " soft " delete that only marks items as " invalid " , meaning " not fresh "
* or " not fresh enough " . Invalid items are not usually returned from the
* cache , so in most ways they behave as if they have been deleted . However ,
* it is possible to retrieve invalid items , if they have not yet been
* permanently removed by the garbage collector , by passing TRUE as the second
* argument for get ( $cid , $allow_invalid ) .
*
* Use deletion if a cache item is no longer useful ; for instance , if the item
* contains references to data that has been deleted . Use invalidation if the
* cached item may still be useful to some callers until it has been updated
* with fresh data . The fact that it was fresh a short while ago may often be
* sufficient .
*
* Invalidation is particularly useful to protect against stampedes . Rather than
* having multiple concurrent requests updating the same cache item when it
* expires or is deleted , there can be one request updating the cache , while the
* other requests can proceed using the stale value . As soon as the cache item
* has been updated , all future requests will use the updated value .
*
* @ section tags Cache Tags
*
* The fourth argument of the set () method can be used to specify cache tags ,
* which are used to identify which data is included in each cache item . A cache
* item can have multiple cache tags ( an array of cache tags ), and each cache
* tag is a string . The convention is to generate cache tags of the form
* [ prefix ] : [ suffix ] . Usually , you ' ll want to associate the cache tags of
* entities , or entity listings . You won ' t have to manually construct cache tags
* for them — just get their cache tags via
* \Drupal\Core\Cache\CacheableDependencyInterface :: getCacheTags () and
* \Drupal\Core\Entity\EntityTypeInterface :: getListCacheTags () .
* Data that has been tagged can be invalidated as a group : no matter the Cache
* ID ( cid ) of the cache item , no matter in which cache bin a cache item lives ;
* as long as it is tagged with a certain cache tag , it will be invalidated .
*
* Because of that , cache tags are a solution to the cache invalidation problem :
* - For caching to be effective , each cache item must only be invalidated when
* absolutely necessary . ( i . e . maximizing the cache hit ratio . )
* - For caching to be correct , each cache item that depends on a certain thing
* must be invalidated whenever that certain thing is modified .
*
* A typical scenario : a user has modified a node that appears in two views ,
* three blocks and on twelve pages . Without cache tags , we couldn ' t possibly
* know which cache items to invalidate , so we ' d have to invalidate everything :
* we had to sacrifice effectiveness to achieve correctness . With cache tags , we
* can have both .
*
* Example :
* @ code
* // A cache item with nodes, users, and some custom module data.
* $tags = array (
* 'my_custom_tag' ,
* 'node:1' ,
* 'node:3' ,
* 'user:7' ,
* );
* \Drupal :: cache () -> set ( $cid , $data , CacheBackendInterface :: CACHE_PERMANENT , $tags );
*
* // Invalidate all cache items with certain tags.
* \Drupal\Core\Cache\Cache :: invalidateTags ( array ( 'user:1' ));
* @ endcode
*
* Drupal is a content management system , so naturally you want changes to your
* content to be reflected everywhere , immediately . That ' s why we made sure that
* every entity type in Drupal 8 automatically has support for cache tags : when
* you save an entity , you can be sure that the cache items that have the
* corresponding cache tags will be invalidated .
* This also is the case when you define your own entity types : you ' ll get the
* exact same cache tag invalidation as any of the built - in entity types , with
* the ability to override any of the default behavior if needed .
* See \Drupal\Core\Cache\CacheableDepenencyInterface :: getCacheTags (),
* \Drupal\Core\Entity\EntityTypeInterface :: getListCacheTags (),
* \Drupal\Core\Entity\Entity :: invalidateTagsOnSave () and
* \Drupal\Core\Entity\Entity :: invalidateTagsOnDelete () .
*
* @ section context Cache contexts
*
* Some computed data depends on contextual data , such as the user roles of the
* logged - in user who is viewing a page , the language the page is being rendered
* in , the theme being used , etc . When caching the output of such a calculation ,
* you must cache each variation separately , along with information about which
* variation of the contextual data was used in the calculatation . The next time
* the computed data is needed , if the context matches that for an existing
* cached data set , the cached data can be reused ; if no context matches , a new
* data set can be calculated and cached for later use .
*
* Cache contexts are services tagged with 'cache.context' , whose classes
* implement \Drupal\Core\Cache\Context\CacheContextInterface . See
* https :// www . drupal . org / developing / api / 8 / cache / contexts for more information
* on cache contexts , including a list of the contexts that exist in Drupal
* core , and information on how to define your own contexts . See the
* @ link container Services and the Dependency Injection Container @ endlink
* topic for more information about services .
*
* Typically , the cache context is specified as part of the #cache property
* of a render array ; see the Caching section of the
* @ link theme_render Render API overview topic @ endlink for details .
*
* @ section configuration Configuration
*
* By default cached data is stored in the database . This can be configured
* though so that all cached data , or that of an individual cache bin , uses a
2016-01-06 16:31:26 -08:00
* different cache backend , such as APCu or Memcache , for storage .
2015-08-17 17:00:26 -07:00
*
* In a settings . php file , you can override the service used for a particular
* cache bin . For example , if your service implementation of
* \Drupal\Core\Cache\CacheBackendInterface was called cache . custom , the
* following line would make Drupal use it for the 'cache_render' bin :
* @ code
* $settings [ 'cache' ][ 'bins' ][ 'render' ] = 'cache.custom' ;
* @ endcode
*
* Additionally , you can register your cache implementation to be used by
* default for all cache bins with :
* @ code
* $settings [ 'cache' ][ 'default' ] = 'cache.custom' ;
* @ endcode
*
2015-09-04 13:20:09 -07:00
* Finally , you can chain multiple cache backends together , see
* \Drupal\Core\Cache\ChainedFastBackend and \Drupal\Core\Cache\BackendChain .
*
2015-08-17 17:00:26 -07:00
* @ see https :// www . drupal . org / node / 1884796
* @ }
*/
/**
* @ defgroup user_api User accounts , permissions , and roles
* @ {
* API for user accounts , access checking , roles , and permissions .
*
* @ section sec_overview Overview and terminology
* Drupal ' s permission system is based on the concepts of accounts , roles ,
* and permissions .
*
* Users ( site visitors ) have accounts , which include a user name , an email
* address , a password ( or some other means of authentication ), and possibly
* other fields ( if defined on the site ) . Anonymous users have an implicit
* account that does not have a real user name or any account information .
*
* Each user account is assigned one or more roles . The anonymous user account
* automatically has the anonymous user role ; real user accounts
* automatically have the authenticated user role , plus any roles defined on
* the site that they have been assigned .
*
* Each role , including the special anonymous and authenticated user roles , is
* granted one or more named permissions , which allow them to perform certain
* tasks or view certain content on the site . It is possible to designate a
* role to be the " administrator " role ; if this is set up , this role is
* automatically granted all available permissions whenever a module is
* enabled that defines permissions .
*
* All code in Drupal that allows users to perform tasks or view content must
* check that the current user has the correct permission before allowing the
* action . In the standard case , access checking consists of answering the
* question " Does the current user have permission 'foo'? " , and allowing or
* denying access based on the answer . Note that access checking should nearly
* always be done at the permission level , not by checking for a particular role
* or user ID , so that site administrators can set up user accounts and roles
* appropriately for their particular sites .
*
* @ section sec_define Defining permissions
* Modules define permissions via a $module . permissions . yml file . See
* \Drupal\user\PermissionHandler for documentation of permissions . yml files .
*
* @ section sec_access Access permission checking
* Depending on the situation , there are several methods for ensuring that
* access checks are done properly in Drupal :
* - Routes : When you register a route , include a 'requirements' section that
* either gives the machine name of the permission that is needed to visit the
* URL of the route , or tells Drupal to use an access check method or service
* to check access . See the @ link menu Routing topic @ endlink for more
* information .
* - Entities : Access for various entity operations is designated either with
* simple permissions or access control handler classes in the entity
* annotation . See the @ link entity_api Entity API topic @ endlink for more
* information .
* - Other code : There is a 'current_user' service , which can be injected into
* classes to provide access to the current user account ( see the
* @ link container Services and Dependency Injection topic @ endlink for more
* information on dependency injection ) . In code that cannot use dependency
* injection , you can access this service and retrieve the current user
* account object by calling \Drupal :: currentUser () . Once you have a user
* object for the current user ( implementing \Drupal\user\UserInterface ), you
* can call inherited method
* \Drupal\Core\Session\AccountInterface :: hasPermission () to check
* permissions , or pass this object into other functions / methods .
* - Forms : Each element of a form array can have a Boolean '#access' property ,
* which determines whether that element is visible and / or usable . This is a
* common need in forms , so the current user service ( described above ) is
* injected into the form base class as method
* \Drupal\Core\Form\FormBase :: currentUser () .
*
* @ section sec_entities User and role objects
* User objects in Drupal are entity items , implementing
* \Drupal\user\UserInterface . Role objects in Drupal are also entity items ,
* implementing \Drupal\user\RoleInterface . See the
* @ link entity_api Entity API topic @ endlink for more information about
* entities in general ( including how to load , create , modify , and query them ) .
*
* Roles often need to be manipulated in automated test code , such as to add
* permissions to them . Here ' s an example :
* @ code
* $role = \Drupal\user\Entity\Role :: load ( 'authenticated' );
* $role -> grantPermission ( 'access comments' );
* $role -> save ();
* @ endcode
*
* Other important interfaces :
* - \Drupal\Core\Session\AccountInterface : The part of UserInterface that
* deals with access checking . In writing code that checks access , your
* method parameters should use this interface , not UserInterface .
* - \Drupal\Core\Session\AccountProxyInterface : The interface for the
* current_user service ( described above ) .
* @ }
*/
/**
* @ defgroup container Services and Dependency Injection Container
* @ {
* Overview of the Dependency Injection Container and Services .
*
* @ section sec_overview Overview of container , injection , and services
* The Services and Dependency Injection Container concepts have been adopted by
* Drupal from the @ link http :// symfony . com / Symfony framework . @ endlink A
* " service " ( such as accessing the database , sending email , or translating user
* interface text ) is defined ( given a name and an interface or at least a
* class that defines the methods that may be called ), and a default class is
2016-01-06 16:31:26 -08:00
* designated to provide the service . These two steps must be done together , and
2015-08-17 17:00:26 -07:00
* can be done by Drupal Core or a module . Other modules can then define
* alternative classes to provide the same services , overriding the default
* classes . Classes and functions that need to use the service should always
* instantiate the class via the dependency injection container ( also known
* simply as the " container " ), rather than instantiating a particular service
* provider class directly , so that they get the correct class ( default or
* overridden ) .
*
* See https :// www . drupal . org / node / 2133171 for more detailed information on
* services and the dependency injection container .
*
* @ section sec_discover Discovering existing services
* Drupal core defines many core services in the core . services . yml file ( in the
* top - level core directory ) . Some Drupal Core modules and contributed modules
* also define services in modulename . services . yml files . API reference sites
* ( such as https :// api . drupal . org ) generate lists of all existing services from
2016-04-07 11:19:57 -07:00
* these files . Look for the Services link in the API Navigation block .
* Alternatively you can look through the individual files manually .
2015-08-17 17:00:26 -07:00
*
* A typical service definition in a *. services . yml file looks like this :
* @ code
* path . alias_manager :
* class : Drupal\Core\Path\AliasManager
* arguments : [ '@path.crud' , '@path.alias_whitelist' , '@language_manager' ]
* @ endcode
* Some services use other services as factories ; a typical service definition
* is :
* @ code
* cache . entity :
* class : Drupal\Core\Cache\CacheBackendInterface
* tags :
* - { name : cache . bin }
* factory : cache_factory : get
* arguments : [ entity ]
* @ endcode
*
* The first line of a service definition gives the unique machine name of the
* service . This is often prefixed by the module name if provided by a module ;
* however , by convention some service names are prefixed by a group name
* instead , such as cache .* for cache bins and plugin . manager .* for plugin
* managers .
*
* The class line either gives the default class that provides the service , or
* if the service uses a factory class , the interface for the service . If the
* class depends on other services , the arguments line lists the machine
* names of the dependencies ( preceded by '@' ); objects for each of these
* services are instantiated from the container and passed to the class
* constructor when the service class is instantiated . Other arguments can also
* be passed in ; see the section at https :// www . drupal . org / node / 2133171 for more
* detailed information .
*
* Services using factories can be defined as shown in the above example , if the
* factory is itself a service . The factory can also be a class ; details of how
* to use service factories can be found in the section at
* https :// www . drupal . org / node / 2133171.
*
* @ section sec_container Accessing a service through the container
* As noted above , if you need to use a service in your code , you should always
* instantiate the service class via a call to the container , using the machine
* name of the service , so that the default class can be overridden . There are
* several ways to make sure this happens :
* - For service - providing classes , see other sections of this documentation
* describing how to pass services as arguments to the constructor .
* - Plugin classes , controllers , and similar classes have create () or
* createInstance () methods that are used to create an instance of the class .
* These methods come from different interfaces , and have different
* arguments , but they all include an argument $container of type
* \Symfony\Component\DependencyInjection\ContainerInterface .
* If you are defining one of these classes , in the create () or
* createInstance () method , call $container -> get ( 'myservice.name' ) to
* instantiate a service . The results of these calls are generally passed to
* the class constructor and saved as member variables in the class .
* - For functions and class methods that do not have access to either of
* the above methods of dependency injection , you can use service location to
* access services , via a call to the global \Drupal class . This class has
* special methods for accessing commonly - used services , or you can call a
* generic method to access any service . Examples :
* @ code
* // Retrieve the entity.manager service object (special method exists).
* $manager = \Drupal :: entityManager ();
* // Retrieve the service object for machine name 'foo.bar'.
* $foobar = \Drupal :: service ( 'foo.bar' );
* @ endcode
*
* As a note , you should always use dependency injection ( via service arguments
* or create () / createInstance () methods ) if possible to instantiate services ,
* rather than service location ( via the \Drupal class ), because :
* - Dependency injection facilitates writing unit tests , since the container
* argument can be mocked and the create () method can be bypassed by using
* the class constructor . If you use the \Drupal class , unit tests are much
* harder to write and your code has more dependencies .
* - Having the service interfaces on the class constructor and member variables
* is useful for IDE auto - complete and self - documentation .
*
* @ section sec_define Defining a service
* If your module needs to define a new service , here are the steps :
* - Choose a unique machine name for your service . Typically , this should
* start with your module name . Example : mymodule . myservice .
* - Create a PHP interface to define what your service does .
* - Create a default class implementing your interface that provides your
* service . If your class needs to use existing services ( such as database
* access ), be sure to make these services arguments to your class
* constructor , and save them in member variables . Also , if the needed
* services are provided by other modules and not Drupal Core , you ' ll want
* these modules to be dependencies of your module .
* - Add an entry to a modulename . services . yml file for the service . See
* @ ref sec_discover above , or existing *. services . yml files in Core , for the
* syntax ; it will start with your machine name , refer to your default class ,
* and list the services that need to be passed into your constructor .
*
* Services can also be defined dynamically , as in the
* \Drupal\Core\CoreServiceProvider class , but this is less common for modules .
*
* @ section sec_tags Service tags
* Some services have tags , which are defined in the service definition . See
* @ link service_tag Service Tags @ endlink for usage .
*
* @ section sec_injection Overriding the default service class
* Modules can override the default classes used for services . Here are the
* steps :
* - Define a class in the top - level namespace for your module
* ( Drupal\my_module ), whose name is the camel - case version of your module ' s
* machine name followed by " ServiceProvider " ( for example , if your module
* machine name is my_module , the class must be named
* MyModuleServiceProvider ) .
* - The class needs to implement
* \Drupal\Core\DependencyInjection\ServiceModifierInterface , which is
* typically done by extending
* \Drupal\Core\DependencyInjection\ServiceProviderBase .
* - The class needs to contain one method : alter () . This method does the
* actual work of telling Drupal to use your class instead of the default .
* Here ' s an example :
* @ code
* public function alter ( ContainerBuilder $container ) {
* // Override the language_manager class with a new class.
* $definition = $container -> getDefinition ( 'language_manager' );
* $definition -> setClass ( 'Drupal\my_module\MyLanguageManager' );
* }
* @ endcode
* Note that $container here is an instance of
* \Drupal\Core\DependencyInjection\ContainerBuilder .
*
* @ see https :// www . drupal . org / node / 2133171
* @ see core . services . yml
* @ see \Drupal
* @ see \Symfony\Component\DependencyInjection\ContainerInterface
* @ see plugin_api
* @ see menu
* @ }
*/
2016-01-06 16:31:26 -08:00
/**
* @ defgroup listing_page_service Page header for Services page
* @ {
* Introduction to services
*
* A " service " ( such as accessing the database , sending email , or translating
* user interface text ) can be defined by a module or Drupal core . Defining a
* service means giving it a name and designating a default class to provide the
* service ; ideally , there should also be an interface that defines the methods
* that may be called . Services are collected into the Dependency Injection
* Container , and can be overridden to use different classes or different
* instantiation by modules . See the
* @ link container Services and Dependency Injection Container topic @ endlink
* for details .
*
* Some services have tags , which are defined in the service definition . Tags
* are used to define a group of related services , or to specify some aspect of
* how the service behaves . See the
* @ link service_tag Service Tags topic @ endlink for more information .
*
* @ see container
* @ see service_tag
*
* @ }
*/
2015-08-17 17:00:26 -07:00
/**
* @ defgroup typed_data Typed Data API
* @ {
* API for describing data based on a set of available data types .
*
2015-09-04 13:20:09 -07:00
* PHP has data types , such as int , string , float , array , etc . , and it is an
* object - oriented language that lets you define classes and interfaces .
* However , in some cases , it is useful to be able to define an abstract
* type ( as in an interface , free of implementation details ), that still has
* properties ( which an interface cannot ) as well as meta - data . The Typed Data
* API provides this abstraction .
*
* @ section sec_overview Overview
* Each data type in the Typed Data API is a plugin class ( annotation class
* example : \Drupal\Core\TypedData\Annotation\DataType ); these plugins are
* managed by the typed_data_manager service ( by default
* \Drupal\Core\TypedData\TypedDataManager ) . Each data object encapsulates a
* single piece of data , provides access to the metadata , and provides
* validation capability . Also , the typed data plugins have a shorthand
* for easily accessing data values , described in @ ref sec_tree .
*
* The metadata of a data object is defined by an object based on a class called
* the definition class ( see \Drupal\Core\TypedData\DataDefinitionInterface ) .
* The class used can vary by data type and can be specified in the data type ' s
* plugin definition , while the default is set in the $definition_class property
* of the annotation class . The default class is
* \Drupal\Core\TypedData\DataDefinition . For data types provided by a plugin
* deriver , the plugin deriver can set the definition_class property too .
* The metadata object provides information about the data , such as the data
* type , whether it is translatable , the names of its properties ( for complex
* types ), and who can access it .
2015-08-17 17:00:26 -07:00
*
* See https :// www . drupal . org / node / 1794140 for more information about the Typed
* Data API .
*
2015-09-04 13:20:09 -07:00
* @ section sec_varieties Varieties of typed data
* There are three kinds of typed data : primitive , complex , and list .
*
* @ subsection sub_primitive Primitive data types
* Primitive data types wrap PHP data types and also serve as building blocks
* for complex and list typed data . Each primitive data type has an interface
* that extends \Drupal\Core\TypedData\PrimitiveInterface , with getValue ()
* and setValue () methods for accessing the data value , and a default plugin
* implementation . Here ' s a list :
* - \Drupal\Core\TypedData\Type\IntegerInterface : Plugin ID integer ,
* corresponds to PHP type int .
* - \Drupal\Core\TypedData\Type\StringInterface : Plugin ID string ,
* corresponds to PHP type string .
* - \Drupal\Core\TypedData\Type\FloatInterface : Plugin ID float ,
* corresponds to PHP type float .
* - \Drupal\Core\TypedData\Type\BooleanInterface : Plugin ID bool ,
* corresponds to PHP type bool .
* - \Drupal\Core\TypedData\Type\BinaryInterface : Plugin ID binary ,
* corresponds to a PHP file resource .
* - \Drupal\Core\TypedData\Type\UriInterface : Plugin ID uri .
*
* @ subsection sec_complex Complex data
* Complex data types , with interface
* \Drupal\Core\TypedData\ComplexDataInterface , represent data with named
* properties ; the properties can be accessed with get () and set () methods .
* The value of each property is itself a typed data object , which can be
* primitive , complex , or list data .
*
* The base type for most complex data is the
* \Drupal\Core\TypedData\Plugin\DataType\Map class , which represents an
* associative array . Map provides its own definition class in the annotation ,
* \Drupal\Core\TypedData\MapDataDefinition , and most complex data classes
* extend this class . The getValue () and setValue () methods on the Map class
* enforce the data definition and its property structure .
*
* The Drupal Field API uses complex typed data for its field items , with
* definition class \Drupal\Core\Field\TypedData\FieldItemDataDefinition .
*
* @ section sec_list Lists
* List data types , with interface \Drupal\Core\TypedData\ListInterface ,
* represent data that is an ordered list of typed data , all of the same type .
* More precisely , the plugins in the list must have the same base plugin ID ;
* however , some types ( for example field items and entities ) are provided by
* plugin derivatives and the sub IDs can be different .
*
* @ section sec_tree Tree handling
* Typed data allows you to use shorthand to get data values nested in the
* implicit tree structure of the data . For example , to get the value from
* an entity field item , the Entity Field API allows you to call :
* @ code
* $value = $entity -> fieldName -> propertyName ;
* @ endcode
* This is really shorthand for :
* @ code
* $field_item_list = $entity -> get ( 'fieldName' );
* $field_item = $field_item_list -> get ( 0 );
* $property = $field_item -> get ( 'propertyName' );
* $value = $property -> getValue ();
* @ endcode
* Some notes :
* - $property , $field_item , and $field_item_list are all typed data objects ,
* while $value is a raw PHP value .
* - You can call $property -> getParent () to get $field_item ,
* $field_item -> getParent () to get $field_item_list , or
* $field_item_list -> getParent () to get $typed_entity ( $entity wrapped in a
* typed data object ) . $typed_entity -> getParent () is NULL .
* - For all of these -> getRoot () returns $typed_entity .
* - The langcode property is on $field_item_list , but you can access it
* on $property as well , so that all items will report the same langcode .
* - When the value of $property is changed by calling $property -> setValue (),
* $property -> onChange () will fire , which in turn calls the parent object ' s
* onChange () method and so on . This allows parent objects to react upon
* changes of contained properties or list items .
*
* @ section sec_defining Defining data types
2015-08-17 17:00:26 -07:00
* To define a new data type :
* - Create a class that implements one of the Typed Data interfaces .
* Typically , you will want to extend one of the classes listed in the
2015-09-04 13:20:09 -07:00
* sections above as a starting point .
2015-08-17 17:00:26 -07:00
* - Make your class into a DataType plugin . To do that , put it in namespace
* \Drupal\yourmodule\Plugin\DataType ( where " yourmodule " is your module ' s
* short name ), and add annotation of type
* \Drupal\Core\TypedData\Annotation\DataType to the documentation header .
* See the @ link plugin_api Plugin API topic @ endlink and the
* @ link annotation Annotations topic @ endlink for more information .
*
2015-09-04 13:20:09 -07:00
* @ section sec_using Using data types
2015-08-17 17:00:26 -07:00
* The data types of the Typed Data API can be used in several ways , once they
* have been defined :
* - In the Field API , data types can be used as the class in the property
* definition of the field . See the @ link field Field API topic @ endlink for
* more information .
* - In configuration schema files , you can use the unique ID ( 'id' annotation )
* from any DataType plugin class as the 'type' value for an entry . See the
* @ link config_api Confuration API topic @ endlink for more information .
2015-09-04 13:20:09 -07:00
* - If you need to create a typed data object in code , first get the
* typed_data_manager service from the container or by calling
* \Drupal :: typedDataManager () . Then pass the plugin ID to
* $manager :: createDataDefinition () to create an appropriate data definition
* object . Then pass the data definition object and the value of the data to
* $manager :: create () to create a typed data object .
*
* @ see plugin_api
* @ see container
2015-08-17 17:00:26 -07:00
* @ }
*/
/**
* @ defgroup testing Automated tests
* @ {
* Overview of PHPUnit tests and Simpletest tests .
*
* The Drupal project has embraced a philosophy of using automated tests ,
* consisting of both unit tests ( which test the functionality of classes at a
* low level ) and functional tests ( which test the functionality of Drupal
* systems at a higher level , usually involving web output ) . The goal is to
* have test coverage for all or most of the components and features , and to
* run the automated tests before any code is changed or added , to make sure
* it doesn ' t break any existing functionality ( regression testing ) .
*
* In order to implement this philosophy , developers need to do the following :
* - When making a patch to fix a bug , make sure that the bug fix patch includes
* a test that fails without the code change and passes with the code change .
* This helps reviewers understand what the bug is , demonstrates that the code
* actually fixes the bug , and ensures the bug will not reappear due to later
* code changes .
* - When making a patch to implement a new feature , include new unit and / or
* functional tests in the patch . This serves to both demonstrate that the
* code actually works , and ensure that later changes do not break the new
* functionality .
*
* @ section write_unit Writing PHPUnit tests for classes
* PHPUnit tests for classes are written using the industry - standard PHPUnit
* framework . Use a PHPUnit test to test functionality of a class if the Drupal
* environment ( database , settings , etc . ) and web browser are not needed for the
* test , or if the Drupal environment can be replaced by a " mock " object . To
* write a PHPUnit test :
* - Define a class that extends \Drupal\Tests\UnitTestCase .
* - The class name needs to end in the word Test .
* - The namespace must be a subspace / subdirectory of \Drupal\yourmodule\Tests ,
* where yourmodule is your module ' s machine name .
2016-03-02 12:40:24 -08:00
* - The test class file must be named and placed under the
* yourmodule / tests / src / Unit directory , according to the PSR - 4 standard .
2015-08-17 17:00:26 -07:00
* - Your test class needs a phpDoc comment block with a description and
* a @ group annotation , which gives information about the test .
* - Methods in your test class whose names start with 'test' are the actual
* test cases . Each one should test a logical subset of the functionality .
* For more details , see :
* - https :// www . drupal . org / phpunit for full documentation on how to write
* PHPUnit tests for Drupal .
* - http :// phpunit . de for general information on the PHPUnit framework .
* - @ link oo_conventions Object - oriented programming topic @ endlink for more
* on PSR - 4 , namespaces , and where to place classes .
*
* @ section write_functional Writing functional tests
* Functional tests are written using a Drupal - specific framework that is , for
* historical reasons , known as " Simpletest " . Use a Simpletest test to test the
* functionality of sub - system of Drupal , if the functionality depends on the
* Drupal database and settings , or to test the web output of Drupal . To
* write a Simpletest test :
* - For functional tests of the web output of Drupal , define a class that
* extends \Drupal\simpletest\WebTestBase , which contains an internal web
* browser and defines many helpful test assertion methods that you can use
* in your tests . You can specify modules to be enabled by defining a
* $modules member variable -- keep in mind that by default , WebTestBase uses
* a " testing " install profile , with a minimal set of modules enabled .
* - For functional tests that do not test web output , define a class that
2016-03-02 12:40:24 -08:00
* extends \Drupal\KernelTests\KernelTestBase . This class is much faster
2015-08-17 17:00:26 -07:00
* than WebTestBase , because instead of making a full install of Drupal , it
* uses an in - memory pseudo - installation ( similar to what the installer and
* update scripts use ) . To use this test class , you will need to create the
* database tables you need and install needed modules manually .
* - The namespace must be a subspace / subdirectory of \Drupal\yourmodule\Tests ,
* where yourmodule is your module ' s machine name .
* - The test class file must be named and placed under the yourmodule / src / Tests
* directory , according to the PSR - 4 standard .
* - Your test class needs a phpDoc comment block with a description and
* a @ group annotation , which gives information about the test .
* - You may also override the default setUp () method , which can set be used to
* set up content types and similar procedures .
* - In some cases , you may need to write a test module to support your test ;
* put such modules under the yourmodule / tests / modules directory .
* - Methods in your test class whose names start with 'test' , and which have
* no arguments , are the actual test cases . Each one should test a logical
* subset of the functionality , and each one runs in a new , isolated test
* environment , so it can only rely on the setUp () method , not what has
* been set up by other test methods .
* For more details , see :
* - https :// www . drupal . org / simpletest for full documentation on how to write
* functional tests for Drupal .
* - @ link oo_conventions Object - oriented programming topic @ endlink for more
* on PSR - 4 , namespaces , and where to place classes .
*
* @ section running Running tests
* You can run both Simpletest and PHPUnit tests by enabling the core Testing
* module ( core / modules / simpletest ) . Once that module is enabled , tests can be
* run using the core / scripts / run - tests . sh script , using
* @ link https :// www . drupal . org / project / drush Drush @ endlink , or from the
* Testing module user interface .
*
* PHPUnit tests can also be run from the command line , using the PHPUnit
* framework . See https :// www . drupal . org / node / 2116263 for more information .
* @ }
*/
2015-08-27 12:03:05 -07:00
/**
* @ defgroup php_assert PHP Runtime Assert Statements
* @ {
* Use of the assert () statement in Drupal .
*
* Unit tests also use the term " assertion " to refer to test conditions , so to
* avoid confusion the term " runtime assertion " will be used for the assert ()
* statement throughout the documentation .
*
* A runtime assertion is a statement that is expected to always be true at
* the point in the code it appears at . They are tested using PHP ' s internal
2016-04-20 09:56:34 -07:00
* @ link http :// php . net / assert assert () @ endlink statement . If an
2015-08-27 12:03:05 -07:00
* assertion is ever FALSE it indicates an error in the code or in module or
* theme configuration files . User - provided configuration files should be
* verified with standard control structures at all times , not just checked in
* development environments with assert () statements on .
*
2015-09-04 13:20:09 -07:00
* When runtime assertions fail in PHP 7 an \AssertionError is thrown .
2015-08-27 12:03:05 -07:00
* Drupal uses an assertion callback to do the same in PHP 5. x so that unit
* tests involving runtime assertions will work uniformly across both versions .
*
* The Drupal project primarily uses runtime assertions to enforce the
* expectations of the API by failing when incorrect calls are made by code
* under development . While PHP type hinting does this for objects and arrays ,
* runtime assertions do this for scalars ( strings , integers , floats , etc . ) and
* complex data structures such as cache and render arrays . They ensure that
* methods ' return values are the documented datatypes . They also verify that
* objects have been properly configured and set up by the service container .
* Runtime assertions are checked throughout development . They supplement unit
* tests by checking scenarios that do not have unit tests written for them ,
* and by testing the API calls made by all the code in the system .
*
* When using assert () keep the following in mind :
* - Runtime assertions are disabled by default in production and enabled in
* development , so they can ' t be used as control structures . Use exceptions
* for errors that can occur in production no matter how unlikely they are .
* - Assert () functions in a buggy manner prior to PHP 7. If you do not use a
* string for the first argument of the statement but instead use a function
* call or expression then that code will be evaluated even when runtime
* assertions are turned off . To avoid this you must use a string as the
* first argument , and assert will pass this string to the eval () statement .
* - Since runtime assertion strings are parsed by eval () use caution when
* using them to work with data that may be unsanitized .
*
* See https :// www . drupal . org / node / 2492225 for more information on runtime
* assertions .
* @ }
*/
2015-08-17 17:00:26 -07:00
/**
* @ defgroup info_types Information types
* @ {
* Types of information in Drupal .
*
* Drupal has several distinct types of information , each with its own methods
* for storage and retrieval :
* - Content : Information meant to be displayed on your site : articles , basic
* pages , images , files , custom blocks , etc . Content is stored and accessed
* using @ link entity_api Entities @ endlink .
* - Session : Information about individual users ' interactions with the site ,
* such as whether they are logged in . This is really " state " information , but
* it is not stored the same way so it ' s a separate type here . Session
* information is available from the Request object . The session implements
* \Symfony\Component\HttpFoundation\Session\SessionInterface .
* - State : Information of a temporary nature , generally machine - generated and
* not human - edited , about the current state of your site . Examples : the time
* when Cron was last run , whether node access permissions need rebuilding ,
* etc . See @ link state_api the State API topic @ endlink for more information .
* - Configuration : Information about your site that is generally ( or at least
* can be ) human - edited , but is not Content , and is meant to be relatively
* permanent . Examples : the name of your site , the content types and views
* you have defined , etc . See
* @ link config_api the Configuration API topic @ endlink for more information .
*
* @ see cache
* @ see i18n
* @ }
*/
/**
* @ defgroup extending Extending and altering Drupal
* @ {
* Overview of extensions and alteration methods for Drupal .
*
* @ section sec_types Types of extensions
* Drupal ' s core behavior can be extended and altered via these three basic
* types of extensions :
* - Themes : Themes alter the appearance of Drupal sites . They can include
* template files , which alter the HTML markup and other raw output of the
* site ; CSS files , which alter the styling applied to the HTML ; and
* JavaScript , Flash , images , and other files . For more information , see the
* @ link theme_render Theme system and render API topic @ endlink and
* https :// www . drupal . org / theme - guide / 8
* - Modules : Modules add to or alter the behavior and functionality of Drupal ,
* by using one or more of the methods listed below . For more information
* about creating modules , see https :// www . drupal . org / developing / modules / 8
* - Installation profiles : Installation profiles can be used to
* create distributions , which are complete specific - purpose packages of
* Drupal including additional modules , themes , and data . For more
* information , see https :// www . drupal . org / developing / distributions .
*
* @ section sec_alter Alteration methods for modules
* Here is a list of the ways that modules can alter or extend Drupal ' s core
* behavior , or the behavior of other modules :
* - Hooks : Specially - named functions that a module defines , which are
* discovered and called at specific times , usually to alter behavior or data .
* See the @ link hooks Hooks topic @ endlink for more information .
* - Plugins : Classes that a module defines , which are discovered and
* instantiated at specific times to add functionality . See the
* @ link plugin_api Plugin API topic @ endlink for more information .
* - Entities : Special plugins that define entity types for storing new types
* of content or configuration in Drupal . See the
* @ link entity_api Entity API topic @ endlink for more information .
* - Services : Classes that perform basic operations within Drupal , such as
* accessing the database and sending email . See the
* @ link container Dependency Injection Container and Services topic @ endlink
* for more information .
* - Routing : Providing or altering " routes " , which are URLs that Drupal
* responds to , or altering routing behavior with event listener classes .
* See the @ link menu Routing and menu topic @ endlink for more information .
* - Events : Modules can register as event subscribers ; when an event is
* dispatched , a method is called on each registered subscriber , allowing each
* one to react . See the @ link events Events topic @ endlink for more
* information .
*
* @ section sec_sample *. info . yml files
* Extensions must each be located in a directory whose name matches the short
* name ( or machine name ) of the extension , and this directory must contain a
* file named machine_name . info . yml ( where machine_name is the machine name of
* the extension ) . See \Drupal\Core\Extension\InfoParserInterface :: parse () for
* documentation of the format of . info . yml files .
* @ }
*/
/**
* @ defgroup plugin_api Plugin API
* @ {
* Using the Plugin API
*
* @ section sec_overview Overview and terminology
*
* The basic idea of plugins is to allow a particular module or subsystem of
* Drupal to provide functionality in an extensible , object - oriented way . The
* controlling module or subsystem defines the basic framework ( interface ) for
* the functionality , and other modules can create plugins ( implementing the
* interface ) with particular behaviors . The controlling module instantiates
* existing plugins as needed , and calls methods to invoke their functionality .
* Examples of functionality in Drupal Core that use plugins include : the block
* system ( block types are plugins ), the entity / field system ( entity types ,
* field types , field formatters , and field widgets are plugins ), the image
* manipulation system ( image effects and image toolkits are plugins ), and the
* search system ( search page types are plugins ) .
*
* Plugins are grouped into plugin types , each generally defined by an
* interface . Each plugin type is managed by a plugin manager service , which
* uses a plugin discovery method to discover provided plugins of that type and
* instantiate them using a plugin factory .
*
* Some plugin types make use of the following concepts or components :
* - Plugin derivatives : Allows a single plugin class to present itself as
* multiple plugins . Example : the Menu module provides a block for each
* defined menu via a block plugin derivative .
* - Plugin mapping : Allows a plugin class to map a configuration string to an
* instance , and have the plugin automatically instantiated without writing
* additional code .
* - Plugin collections : Provide a way to lazily instantiate a set of plugin
* instances from a single plugin definition .
*
* There are several things a module developer may need to do with plugins :
* - Define a completely new plugin type : see @ ref sec_define below .
* - Create a plugin of an existing plugin type : see @ ref sec_create below .
* - Perform tasks that involve plugins : see @ ref sec_use below .
*
* See https :// www . drupal . org / developing / api / 8 / plugins for more detailed
* documentation on the plugin system . There are also topics for a few
* of the many existing types of plugins :
* - @ link block_api Block API @ endlink
* - @ link entity_api Entity API @ endlink
* - @ link field Various types of field - related plugins @ endlink
* - @ link views_plugins Views plugins @ endlink ( has links to topics covering
* various specific types of Views plugins ) .
* - @ link search Search page plugins @ endlink
*
* @ section sec_define Defining a new plugin type
* To define a new plugin type :
* - Define an interface for the plugin . This describes the common set of
* behavior , and the methods you will call on each plugin class that is
* instantiated . Usually this interface will extend one or more of the
* following interfaces :
* - \Drupal\Component\Plugin\PluginInspectionInterface
* - \Drupal\Component\Plugin\ConfigurablePluginInterface
* - \Drupal\Component\Plugin\ContextAwarePluginInterface
* - \Drupal\Core\Plugin\PluginFormInterface
* - \Drupal\Core\Executable\ExecutableInterface
* - ( optional ) Create a base class that provides a partial implementation of
* the interface , for the convenience of developers wishing to create plugins
* of your type . The base class usually extends
* \Drupal\Core\Plugin\PluginBase , or one of the base classes that extends
* this class .
* - Choose a method for plugin discovery , and define classes as necessary .
* See @ ref sub_discovery below .
* - Create a plugin manager / factory class and service , which will discover and
* instantiate plugins . See @ ref sub_manager below .
* - Use the plugin manager to instantiate plugins . Call methods on your plugin
* interface to perform the tasks of your plugin type .
* - ( optional ) If appropriate , define a plugin collection . See @ ref
* sub_collection below for more information .
*
* @ subsection sub_discovery Plugin discovery
* Plugin discovery is the process your plugin manager uses to discover the
* individual plugins of your type that have been defined by your module and
* other modules . Plugin discovery methods are classes that implement
* \Drupal\Component\Plugin\Discovery\DiscoveryInterface . Most plugin types use
* one of the following discovery mechanisms :
* - Annotation : Plugin classes are annotated and placed in a defined namespace
* subdirectory . Most Drupal Core plugins use this method of discovery .
* - Hook : Plugin modules need to implement a hook to tell the manager about
* their plugins .
* - YAML : Plugins are listed in YAML files . Drupal Core uses this method for
* discovering local tasks and local actions . This is mainly useful if all
* plugins use the same class , so it is kind of like a global derivative .
* - Static : Plugin classes are registered within the plugin manager class
* itself . Static discovery is only useful if modules cannot define new
* plugins of this type ( if the list of available plugins is static ) .
*
* It is also possible to define your own custom discovery mechanism or mix
* methods together . And there are many more details , such as annotation
* decorators , that apply to some of the discovery methods . See
* https :// www . drupal . org / developing / api / 8 / plugins for more details .
*
* The remainder of this documentation will assume Annotation - based discovery ,
* since this is the most common method .
*
* @ subsection sub_manager Defining a plugin manager class and service
* To define an annotation - based plugin manager :
* - Choose a namespace subdirectory for your plugin . For example , search page
* plugins go in directory Plugin / Search under the module namespace .
* - Define an annotation class for your plugin type . This class should extend
* \Drupal\Component\Annotation\Plugin , and for most plugin types , it should
* contain member variables corresponding to the annotations plugins will
* need to provide . All plugins have at least $id : a unique string
* identifier .
* - Define an alter hook for altering the discovered plugin definitions . You
* should document the hook in a *. api . php file .
* - Define a plugin manager class . This class should implement
* \Drupal\Component\Plugin\PluginManagerInterface ; most plugin managers do
* this by extending \Drupal\Core\Plugin\DefaultPluginManager . If you do
* extend the default plugin manager , the only method you will probably need
* to define is the class constructor , which will need to call the parent
* constructor to provide information about the annotation class and plugin
* namespace for discovery , set up the alter hook , and possibly set up
* caching . See classes that extend DefaultPluginManager for examples .
* - Define a service for your plugin manager . See the
* @ link container Services topic for more information . @ endlink Your service
* definition should look something like this , referencing your manager
* class and the parent ( default ) plugin manager service to inherit
* constructor arguments :
* @ code
* plugin . manager . mymodule :
* class : Drupal\mymodule\MyPluginManager
* parent : default_plugin_manager
* @ endcode
* - If your plugin is configurable , you will also need to define the
* configuration schema and possibly a configuration entity type . See the
* @ link config_api Configuration API topic @ endlink for more information .
*
* @ subsection sub_collection Defining a plugin collection
* Some configurable plugin types allow administrators to create zero or more
* instances of each plugin , each with its own configuration . For example ,
* a single block plugin can be configured several times , to display in
* different regions of a theme , with different visibility settings , a
* different title , or other plugin - specific settings . To make this possible ,
* a plugin type can make use of what ' s known as a plugin collection .
*
* A plugin collection is a class that extends
* \Drupal\Component\Plugin\LazyPluginCollection or one of its subclasses ; there
* are several examples in Drupal Core . If your plugin type uses a plugin
* collection , it will usually also have a configuration entity , and the entity
* class should implement
* \Drupal\Core\Entity\EntityWithPluginCollectionInterface . Again , there are
* several examples in Drupal Core ; see also the @ link config_api Configuration
* API topic @ endlink for more information about configuration entities .
*
* @ section sec_create Creating a plugin of an existing type
* Assuming the plugin type uses annotation - based discovery , in order to create
* a plugin of an existing type , you will be creating a class . This class must :
* - Implement the plugin interface , so that it has the required methods
* defined . Usually , you ' ll want to extend the plugin base class , if one has
* been provided .
* - Have the right annotation in its documentation header . See the
* @ link annotation Annotation topic @ endlink for more information about
* annotation .
* - Be in the right plugin namespace , in order to be discovered .
* Often , the easiest way to make sure this happens is to find an existing
* example of a working plugin class of the desired type , and copy it into your
* module as a starting point .
*
* You can also create a plugin derivative , which allows your plugin class
* to present itself to the user interface as multiple plugins . To do this ,
* in addition to the plugin class , you ' ll need to create a separate plugin
* derivative class implementing
* \Drupal\Component\Plugin\Derivative\DerivativeInterface . The classes
* \Drupal\system\Plugin\Block\SystemMenuBlock ( plugin class ) and
* \Drupal\system\Plugin\Derivative\SystemMenuBlock ( derivative class ) are a
* good example to look at .
*
* @ section sec_use Performing tasks involving plugins
* Here are the steps to follow to perform a task that involves plugins :
* - Locate the machine name of the plugin manager service , and instantiate the
* service . See the @ link container Services topic @ endlink for more
* information on how to do this .
* - On the plugin manager class , use methods like getDefinition (),
* getDefinitions (), or other methods specific to particular plugin managers
* to retrieve information about either specific plugins or the entire list of
* defined plugins .
* - Call the createInstance () method on the plugin manager to instantiate
* individual plugin objects .
* - Call methods on the plugin objects to perform the desired tasks .
*
* @ see annotation
* @ }
*/
/**
* @ defgroup oo_conventions Objected - oriented programming conventions
* @ {
* PSR - 4 , namespaces , class naming , and other conventions .
*
* A lot of the PHP code in Drupal is object oriented ( OO ), making use of
* @ link http :// php . net / manual / language . oop5 . php PHP classes , interfaces , and traits @ endlink
* ( which are loosely referred to as " classes " in the rest of this topic ) . The
* following conventions and standards apply to this version of Drupal :
* - Each class must be in its own file .
* - Classes must be namespaced . If a module defines a class , the namespace
* must start with \Drupal\module_name . If it is defined by Drupal Core for
* use across many modules , the namespace should be \Drupal\Core or
* \Drupal\Component , with the exception of the global class \Drupal . See
* https :// www . drupal . org / node / 1353118 for more about namespaces .
* - In order for the PSR - 4 - based class auto - loader to find the class , it must
* be located in a directory corresponding to the namespace . For
* module - defined classes , if the namespace is \Drupal\module_name\foo\bar ,
* then the class goes under the main module directory in directory
* src / foo / bar . For Drupal - wide classes , if the namespace is
* \Drupal\Core\foo\bar , then it goes in directory
* core / lib / Drupal / Core / foo / bar . See https :// www . drupal . org / node / 2156625 for
* more information about PSR - 4.
* - Some classes have annotations added to their documentation headers . See
* the @ link annotation Annotation topic @ endlink for more information .
* - Standard plugin discovery requires particular namespaces and annotation
* for most plugin classes . See the
* @ link plugin_api Plugin API topic @ endlink for more information .
* - There are project - wide coding standards for OO code , including naming :
* https :// www . drupal . org / node / 608152
* - Documentation standards for classes are covered on :
* https :// www . drupal . org / coding - standards / docs #classes
* @ }
*/
2016-01-06 16:31:26 -08:00
/**
* @ defgroup listing_page_class Page header for Classes page
* @ {
* Introduction to classes
*
* A lot of the PHP code in Drupal is object oriented ( OO ), making use of
* @ link http :// php . net / manual / language . oop5 . php PHP classes , interfaces , and traits . @ endlink
* See the
* @ link oo_conventions Objected - oriented programming conventions @ endlink
* for more information .
*
* @ see oo_conventions
*
* @ }
*/
/**
* @ defgroup listing_page_namespace Page header for Namespaces page
* @ {
* Introduction to namespaces
*
* PHP classes , interfaces , and traits in Drupal are
* @ link http :// php . net / manual / en / language . namespaces . rationale . php namespaced . @ endlink
* See the
* @ link oo_conventions Objected - oriented programming conventions @ endlink
* for more information .
*
* @ see oo_conventions
*
* @ }
*/
2015-08-17 17:00:26 -07:00
/**
* @ defgroup best_practices Best practices for developers
* @ {
* Overview of standards and best practices for developers
*
* Ideally , all code that is included in Drupal Core and contributed modules ,
* themes , and distributions will be secure , internationalized , maintainable ,
* and efficient . In order to facilitate this , the Drupal community has
* developed a set of guidelines and standards for developers to follow . Most of
* these standards can be found under
* @ link https :// www . drupal . org / developing / best - practices Best practices on Drupal . org @ endlink
*
* Standards and best practices that developers should be aware of include :
* - Security : https :// www . drupal . org / writing - secure - code and the
* @ link sanitization Sanitization functions topic @ endlink
* - Coding standards : https :// www . drupal . org / coding - standards
* and https :// www . drupal . org / coding - standards / docs
* - Accessibility : https :// www . drupal . org / node / 1637990 ( modules ) and
* https :// www . drupal . org / node / 464472 ( themes )
* - Usability : https :// www . drupal . org / ui - standards
* - Internationalization : @ link i18n Internationalization topic @ endlink
* - Automated testing : @ link testing Automated tests topic @ endlink
* @ }
*/
/**
* @ defgroup utility Utility classes and functions
* @ {
* Overview of utility classes and functions for developers .
*
* Drupal provides developers with a variety of utility functions that make it
* easier and more efficient to perform tasks that are either really common ,
* tedious , or difficult . Utility functions help to reduce code duplication and
* should be used in place of one - off code whenever possible .
*
* @ see common . inc
* @ see file
* @ see format
* @ see php_wrappers
* @ see sanitization
* @ see transliteration
* @ see validation
* @ }
*/
/**
* @ defgroup hooks Hooks
* @ {
* Define functions that alter the behavior of Drupal core .
*
* One way for modules to alter the core behavior of Drupal ( or another module )
* is to use hooks . Hooks are specially - named functions that a module defines
* ( this is known as " implementing the hook " ), which are discovered and called
* at specific times to alter or add to the base behavior or data ( this is
* known as " invoking the hook " ) . Each hook has a name ( example :
* hook_batch_alter ()), a defined set of parameters , and a defined return value .
* Your modules can implement hooks that are defined by Drupal core or other
* modules that they interact with . Your modules can also define their own
* hooks , in order to let other modules interact with them .
*
* To implement a hook :
* - Locate the documentation for the hook . Hooks are documented in *. api . php
* files , by defining functions whose name starts with " hook_ " ( these
* files and their functions are never loaded by Drupal -- they exist solely
* for documentation ) . The function should have a documentation header , as
* well as a sample function body . For example , in the core file
* system . api . php , you can find hooks such as hook_batch_alter () . Also , if
* you are viewing this documentation on an API reference site , the Core
* hooks will be listed in this topic .
* - Copy the function to your module ' s . module file .
* - Change the name of the function , substituting your module ' s short name
* ( name of the module ' s directory , and . info . yml file without the extension )
* for the " hook " part of the sample function name . For instance , to implement
* hook_batch_alter (), you would rename it to my_module_batch_alter () .
* - Edit the documentation for the function ( normally , your implementation
* should just have one line saying " Implements hook_batch_alter(). " ) .
* - Edit the body of the function , substituting in what you need your module
* to do .
*
* To define a hook :
* - Choose a unique name for your hook . It should start with " hook_ " , followed
* by your module ' s short name .
* - Provide documentation in a *. api . php file in your module ' s main
* directory . See the " implementing " section above for details of what this
* should contain ( parameters , return value , and sample function body ) .
* - Invoke the hook in your module ' s code .
*
* To invoke a hook , use methods on
* \Drupal\Core\Extension\ModuleHandlerInterface such as alter (), invoke (),
* and invokeAll () . You can obtain a module handler by calling
* \Drupal :: moduleHandler (), or getting the 'module_handler' service on an
* injected container .
*
* @ see extending
* @ see themeable
* @ see callbacks
* @ see \Drupal\Core\Extension\ModuleHandlerInterface
* @ see \Drupal :: moduleHandler ()
*
* @ }
*/
/**
* @ defgroup callbacks Callbacks
* @ {
* Callback function signatures .
*
* Drupal ' s API sometimes uses callback functions to allow you to define how
* some type of processing happens . A callback is a function with a defined
* signature , which you define in a module . Then you pass the function name as
* a parameter to a Drupal API function or return it as part of a hook
* implementation return value , and your function is called at an appropriate
* time . For instance , when setting up batch processing you might need to
* provide a callback function for each processing step and / or a callback for
* when processing is finished ; you would do that by defining these functions
* and passing their names into the batch setup function .
*
* Callback function signatures , like hook definitions , are described by
* creating and documenting dummy functions in a *. api . php file ; normally , the
* dummy callback function ' s name should start with " callback_ " , and you should
* document the parameters and return value and provide a sample function body .
* Then your API documentation can refer to this callback function in its
* documentation . A user of your API can usually name their callback function
* anything they want , although a standard name would be to replace " callback_ "
* with the module name .
*
* @ see hooks
* @ see themeable
*
* @ }
*/
/**
* @ defgroup form_api Form generation
* @ {
* Describes how to generate and manipulate forms and process form submissions .
*
* Drupal provides a Form API in order to achieve consistency in its form
* processing and presentation , while simplifying code and reducing the amount
* of HTML that must be explicitly generated by a module .
*
* @ section generating_forms Creating forms
* Forms are defined as classes that implement the
* \Drupal\Core\Form\FormInterface and are built using the
* \Drupal\Core\Form\FormBuilder class . Drupal provides a couple of utility
* classes that can be extended as a starting point for most basic forms , the
* most commonly used of which is \Drupal\Core\Form\FormBase . FormBuilder
* handles the low level processing of forms such as rendering the necessary
* HTML , initial processing of incoming $_POST data , and delegating to your
* implementation of FormInterface for validation and processing of submitted
* data .
*
* Here is an example of a Form class :
* @ code
* namespace Drupal\mymodule\Form ;
*
* use Drupal\Core\Form\FormBase ;
* use Drupal\Core\Form\FormStateInterface ;
*
* class ExampleForm extends FormBase {
* public function getFormId () {
* // Unique ID of the form.
* return 'example_form' ;
* }
*
* public function buildForm ( array $form , FormStateInterface $form_state ) {
* // Create a $form API array.
* $form [ 'phone_number' ] = array (
* '#type' => 'tel' ,
2016-10-06 15:16:20 -07:00
* '#title' => $this -> t ( 'Your phone number' ),
* );
* $form [ 'save' ] = array (
* '#type' => 'submit' ,
* '#value' => $this -> t ( 'Save' ),
2015-08-17 17:00:26 -07:00
* );
* return $form ;
* }
*
* public function validateForm ( array & $form , FormStateInterface $form_state ) {
* // Validate submitted form data.
* }
*
* public function submitForm ( array & $form , FormStateInterface $form_state ) {
* // Handle submitted form data.
* }
* }
* @ endcode
*
* @ section retrieving_forms Retrieving and displaying forms
* \Drupal :: formBuilder () -> getForm () should be used to handle retrieving ,
* processing , and displaying a rendered HTML form . Given the ExampleForm
* defined above ,
* \Drupal :: formBuilder () -> getForm ( 'Drupal\mymodule\Form\ExampleForm' ) would
* return the rendered HTML of the form defined by ExampleForm :: buildForm (), or
* call the validateForm () and submitForm (), methods depending on the current
* processing state .
*
* The argument to \Drupal :: formBuilder () -> getForm () is the name of a class that
* implements FormBuilderInterface . Any additional arguments passed to the
* getForm () method will be passed along as additional arguments to the
* ExampleForm :: buildForm () method .
*
* For example :
* @ code
* $extra = '612-123-4567' ;
* $form = \Drupal :: formBuilder () -> getForm ( 'Drupal\mymodule\Form\ExampleForm' , $extra );
* ...
* public function buildForm ( array $form , FormStateInterface $form_state , $extra = NULL )
* $form [ 'phone_number' ] = array (
* '#type' => 'tel' ,
* '#title' => $this -> t ( 'Your phone number' ),
* '#value' => $extra ,
* );
* return $form ;
* }
* @ endcode
*
* Alternatively , forms can be built directly via the routing system which will
* take care of calling \Drupal :: formBuilder () -> getForm () . The following example
* demonstrates the use of a routing . yml file to display a form at the given
* route .
*
* @ code
* example . form :
* path : '/example-form'
* defaults :
* _title : 'Example form'
* _form : '\Drupal\mymodule\Form\ExampleForm'
* @ endcode
*
2016-01-06 16:31:26 -08:00
* The $form argument to form - related functions is a specialized render array
* containing the elements and properties of the form . For more about render
* arrays , see the @ link theme_render Render API topic . @ endlink For more
* detailed explanations of the Form API workflow , see the
2015-08-17 17:00:26 -07:00
* @ link https :// www . drupal . org / node / 2117411 Form API documentation section . @ endlink
2016-01-06 16:31:26 -08:00
* In addition , there is a set of Form API tutorials in the
* @ link https :// www . drupal . org / project / examples Examples for Developers project . @ endlink
2015-08-17 17:00:26 -07:00
*
* In the form builder , validation , submission , and other form methods ,
* $form_state is the primary influence on the processing of the form and is
* passed to most methods , so they can use it to communicate with the form
* system and each other . $form_state is an object that implements
* \Drupal\Core\Form\FormStateInterface .
* @ }
*/
/**
* @ defgroup queue Queue operations
* @ {
* Queue items to allow later processing .
*
* The queue system allows placing items in a queue and processing them later .
* The system tries to ensure that only one consumer can process an item .
*
* Before a queue can be used it needs to be created by
* Drupal\Core\Queue\QueueInterface :: createQueue () .
*
* Items can be added to the queue by passing an arbitrary data object to
* Drupal\Core\Queue\QueueInterface :: createItem () .
*
* To process an item , call Drupal\Core\Queue\QueueInterface :: claimItem () and
* specify how long you want to have a lease for working on that item .
* When finished processing , the item needs to be deleted by calling
* Drupal\Core\Queue\QueueInterface :: deleteItem () . If the consumer dies , the
* item will be made available again by the Drupal\Core\Queue\QueueInterface
* implementation once the lease expires . Another consumer will then be able to
* receive it when calling Drupal\Core\Queue\QueueInterface :: claimItem () .
* Due to this , the processing code should be aware that an item might be handed
* over for processing more than once .
*
* The $item object used by the Drupal\Core\Queue\QueueInterface can contain
* arbitrary metadata depending on the implementation . Systems using the
* interface should only rely on the data property which will contain the
* information passed to Drupal\Core\Queue\QueueInterface :: createItem () .
* The full queue item returned by Drupal\Core\Queue\QueueInterface :: claimItem ()
* needs to be passed to Drupal\Core\Queue\QueueInterface :: deleteItem () once
* processing is completed .
*
* There are two kinds of queue backends available : reliable , which preserves
* the order of messages and guarantees that every item will be executed at
* least once . The non - reliable kind only does a best effort to preserve order
* in messages and to execute them at least once but there is a small chance
* that some items get lost . For example , some distributed back - ends like
* Amazon SQS will be managing jobs for a large set of producers and consumers
* where a strict FIFO ordering will likely not be preserved . Another example
* would be an in - memory queue backend which might lose items if it crashes .
* However , such a backend would be able to deal with significantly more writes
* than a reliable queue and for many tasks this is more important . See
* aggregator_cron () for an example of how to effectively use a non - reliable
* queue . Another example is doing Twitter statistics -- the small possibility
* of losing a few items is insignificant next to power of the queue being able
* to keep up with writes . As described in the processing section , regardless
* of the queue being reliable or not , the processing code should be aware that
* an item might be handed over for processing more than once ( because the
* processing code might time out before it finishes ) .
* @ }
*/
/**
* @ defgroup annotation Annotations
* @ {
* Annotations for class discovery and metadata description .
*
* The Drupal plugin system has a set of reusable components that developers
* can use , override , and extend in their modules . Most of the plugins use
* annotations , which let classes register themselves as plugins and describe
* their metadata . ( Annotations can also be used for other purposes , though
* at the moment , Drupal only uses them for the plugin system . )
*
* To annotate a class as a plugin , add code similar to the following to the
* end of the documentation block immediately preceding the class declaration :
* @ code
* * @ ContentEntityType (
* * id = " comment " ,
* * label = @ Translation ( " Comment " ),
* * ...
* * base_table = " comment "
* * )
* @ endcode
*
* Note that you must use double quotes ; single quotes will not work in
* annotations .
*
* Some annotation types , which extend the " @ PluginID " annotation class , have
* only a single 'id' key in their annotation . For these , it is possible to use
* a shorthand annotation . For example :
* @ code
* * @ ViewsArea ( " entity " )
* @ endcode
* in place of
* @ code
* * @ ViewsArea (
* * id = " entity "
* * )
* @ endcode
*
* The available annotation classes are listed in this topic , and can be
* identified when you are looking at the Drupal source code by having
* " @ Annotation " in their documentation blocks ( without the space after @ ) . To
* find examples of annotation for a particular annotation class , such as
* EntityType , look for class files that have an @ annotation section using the
* annotation class .
*
* @ see plugin_translatable
* @ see plugin_context
*
* @ }
*/
/**
* @ addtogroup hooks
* @ {
*/
/**
* Perform periodic actions .
*
* Modules that require some commands to be executed periodically can
* implement hook_cron () . The engine will then call the hook whenever a cron
* run happens , as defined by the administrator . Typical tasks managed by
* hook_cron () are database maintenance , backups , recalculation of settings
* or parameters , automated mailing , and retrieving remote data .
*
* Short - running or non - resource - intensive tasks can be executed directly in
* the hook_cron () implementation .
*
* Long - running tasks and tasks that could time out , such as retrieving remote
* data , sending email , and intensive file tasks , should use the queue API
* instead of executing the tasks directly . To do this , first define one or
* more queues via a \Drupal\Core\Annotation\QueueWorker plugin . Then , add items
* that need to be processed to the defined queues .
*/
function hook_cron () {
// Short-running operation example, not using a queue:
// Delete all expired records since the last cron run.
2016-09-07 13:26:21 -07:00
$expires = \Drupal :: state () -> get ( 'mymodule.last_check' , 0 );
\Drupal :: database () -> delete ( 'mymodule_table' )
2015-08-17 17:00:26 -07:00
-> condition ( 'expires' , $expires , '>=' )
-> execute ();
2016-09-07 13:26:21 -07:00
\Drupal :: state () -> set ( 'mymodule.last_check' , REQUEST_TIME );
2015-08-17 17:00:26 -07:00
// Long-running operation example, leveraging a queue:
2016-09-07 13:26:21 -07:00
// Queue news feeds for updates once their refresh interval has elapsed.
2015-08-17 17:00:26 -07:00
$queue = \Drupal :: queue ( 'aggregator_feeds' );
2016-09-07 13:26:21 -07:00
$ids = \Drupal :: entityManager () -> getStorage ( 'aggregator_feed' ) -> getFeedIdsToRefresh ();
foreach ( Feed :: loadMultiple ( $ids ) as $feed ) {
if ( $queue -> createItem ( $feed )) {
// Add timestamp to avoid queueing item more than once.
$feed -> setQueuedTime ( REQUEST_TIME );
$feed -> save ();
}
}
$ids = \Drupal :: entityQuery ( 'aggregator_feed' )
-> condition ( 'queued' , REQUEST_TIME - ( 3600 * 6 ), '<' )
-> execute ();
if ( $ids ) {
$feeds = Feed :: loadMultiple ( $ids );
foreach ( $feeds as $feed ) {
$feed -> setQueuedTime ( 0 );
$feed -> save ();
}
2015-08-17 17:00:26 -07:00
}
}
/**
* Alter available data types for typed data wrappers .
*
* @ param array $data_types
* An array of data type information .
*
* @ see hook_data_type_info ()
*/
function hook_data_type_info_alter ( & $data_types ) {
$data_types [ 'email' ][ 'class' ] = '\Drupal\mymodule\Type\Email' ;
}
/**
* Alter cron queue information before cron runs .
*
* Called by \Drupal\Core\Cron to allow modules to alter cron queue settings
* before any jobs are processesed .
*
* @ param array $queues
* An array of cron queue information .
*
* @ see \Drupal\Core\QueueWorker\QueueWorkerInterface
* @ see \Drupal\Core\Annotation\QueueWorker
* @ see \Drupal\Core\Cron
*/
function hook_queue_info_alter ( & $queues ) {
// This site has many feeds so let's spend 90 seconds on each cron run
// updating feeds instead of the default 60.
$queues [ 'aggregator_feeds' ][ 'cron' ][ 'time' ] = 90 ;
}
/**
* Alter an email message created with MailManagerInterface -> mail () .
*
* hook_mail_alter () allows modification of email messages created and sent
* with MailManagerInterface -> mail () . Usage examples include adding and / or
* changing message text , message fields , and message headers .
*
* Email messages sent using functions other than MailManagerInterface -> mail ()
* will not invoke hook_mail_alter () . For example , a contributed module directly
* calling the MailInterface -> mail () or PHP mail () function will not invoke
* this hook . All core modules use MailManagerInterface -> mail () for messaging ,
* it is best practice but not mandatory in contributed modules .
*
* @ param $message
* An array containing the message data . Keys in this array include :
2016-04-20 09:56:34 -07:00
* - 'id' :
2015-08-17 17:00:26 -07:00
* The MailManagerInterface -> mail () id of the message . Look at module source
* code or MailManagerInterface -> mail () for possible id values .
2016-04-20 09:56:34 -07:00
* - 'to' :
2015-08-17 17:00:26 -07:00
* The address or addresses the message will be sent to . The
* formatting of this string must comply with RFC 2822.
2016-04-20 09:56:34 -07:00
* - 'from' :
2015-08-17 17:00:26 -07:00
* The address the message will be marked as being from , which is
* either a custom address or the site - wide default email address .
2016-04-20 09:56:34 -07:00
* - 'subject' :
2015-08-17 17:00:26 -07:00
* Subject of the email to be sent . This must not contain any newline
* characters , or the email may not be sent properly .
2016-04-20 09:56:34 -07:00
* - 'body' :
* An array of strings or objects that implement
* \Drupal\Component\Render\MarkupInterface containing the message text . The
* message body is created by concatenating the individual array strings
* into a single text string using " \n \n " as a separator .
* - 'headers' :
2015-08-17 17:00:26 -07:00
* Associative array containing mail headers , such as From , Sender ,
* MIME - Version , Content - Type , etc .
2016-04-20 09:56:34 -07:00
* - 'params' :
2015-08-17 17:00:26 -07:00
* An array of optional parameters supplied by the caller of
* MailManagerInterface -> mail () that is used to build the message before
* hook_mail_alter () is invoked .
2016-04-20 09:56:34 -07:00
* - 'language' :
2015-08-17 17:00:26 -07:00
* The language object used to build the message before hook_mail_alter ()
* is invoked .
2016-04-20 09:56:34 -07:00
* - 'send' :
2015-08-17 17:00:26 -07:00
* Set to FALSE to abort sending this email message .
*
* @ see \Drupal\Core\Mail\MailManagerInterface :: mail ()
*/
function hook_mail_alter ( & $message ) {
if ( $message [ 'id' ] == 'modulename_messagekey' ) {
if ( ! example_notifications_optin ( $message [ 'to' ], $message [ 'id' ])) {
// If the recipient has opted to not receive such messages, cancel
// sending.
$message [ 'send' ] = FALSE ;
return ;
}
$message [ 'body' ][] = " -- \n Mail sent out from " . \Drupal :: config ( 'system.site' ) -> get ( 'name' );
}
}
/**
* Prepares a message based on parameters ;
*
* This hook is called from MailManagerInterface -> mail () . Note that hook_mail (),
* unlike hook_mail_alter (), is only called on the $module argument to
* MailManagerInterface -> mail (), not all modules .
*
* @ param $key
* An identifier of the mail .
* @ param $message
* An array to be filled in . Elements in this array include :
* - id : An ID to identify the mail sent . Look at module source code or
* MailManagerInterface -> mail () for possible id values .
* - to : The address or addresses the message will be sent to . The
* formatting of this string must comply with RFC 2822.
* - subject : Subject of the email to be sent . This must not contain any
* newline characters , or the mail may not be sent properly .
* MailManagerInterface -> mail () sets this to an empty
* string when the hook is invoked .
* - body : An array of lines containing the message to be sent . Drupal will
* format the correct line endings for you . MailManagerInterface -> mail ()
2016-04-20 09:56:34 -07:00
* sets this to an empty array when the hook is invoked . The array may
* contain either strings or objects implementing
* \Drupal\Component\Render\MarkupInterface .
2015-08-17 17:00:26 -07:00
* - from : The address the message will be marked as being from , which is
* set by MailManagerInterface -> mail () to either a custom address or the
* site - wide default email address when the hook is invoked .
* - headers : Associative array containing mail headers , such as From ,
* Sender , MIME - Version , Content - Type , etc .
* MailManagerInterface -> mail () pre - fills several headers in this array .
* @ param $params
* An array of parameters supplied by the caller of
* MailManagerInterface -> mail () .
*
2016-09-07 13:26:21 -07:00
* @ see \Drupal\Core\Mail\MailManagerInterface :: mail ()
2015-08-17 17:00:26 -07:00
*/
function hook_mail ( $key , & $message , $params ) {
$account = $params [ 'account' ];
$context = $params [ 'context' ];
$variables = array (
'%site_name' => \Drupal :: config ( 'system.site' ) -> get ( 'name' ),
2015-10-08 11:40:12 -07:00
'%username' => $account -> getDisplayName (),
2015-08-17 17:00:26 -07:00
);
if ( $context [ 'hook' ] == 'taxonomy' ) {
$entity = $params [ 'entity' ];
$vocabulary = Vocabulary :: load ( $entity -> id ());
$variables += array (
'%term_name' => $entity -> name ,
'%term_description' => $entity -> description ,
'%term_id' => $entity -> id (),
'%vocabulary_name' => $vocabulary -> label (),
'%vocabulary_description' => $vocabulary -> getDescription (),
'%vocabulary_id' => $vocabulary -> id (),
);
}
// Node-based variable translation is only available if we have a node.
if ( isset ( $params [ 'node' ])) {
/** @var \Drupal\node\NodeInterface $node */
$node = $params [ 'node' ];
$variables += array (
'%uid' => $node -> getOwnerId (),
'%url' => $node -> url ( 'canonical' , array ( 'absolute' => TRUE )),
'%node_type' => node_get_type_label ( $node ),
'%title' => $node -> getTitle (),
'%teaser' => $node -> teaser ,
'%body' => $node -> body ,
);
}
$subject = strtr ( $context [ 'subject' ], $variables );
$body = strtr ( $context [ 'message' ], $variables );
$message [ 'subject' ] .= str_replace ( array ( " \r " , " \n " ), '' , $subject );
$message [ 'body' ][] = MailFormatHelper :: htmlToText ( $body );
}
/**
* Alter the list of mail backend plugin definitions .
*
* @ param array $info
* The mail backend plugin definitions to be altered .
*
* @ see \Drupal\Core\Annotation\Mail
* @ see \Drupal\Core\Mail\MailManager
*/
function hook_mail_backend_info_alter ( & $info ) {
unset ( $info [ 'test_mail_collector' ]);
}
/**
* Alter the default country list .
*
* @ param $countries
* The associative array of countries keyed by two - letter country code .
*
2016-06-02 15:56:09 -07:00
* @ see \Drupal\Core\Locale\CountryManager :: getList ()
2015-08-17 17:00:26 -07:00
*/
function hook_countries_alter ( & $countries ) {
// Elbonia is now independent, so add it to the country list.
$countries [ 'EB' ] = 'Elbonia' ;
}
/**
* Alter display variant plugin definitions .
*
* @ param array $definitions
* The array of display variant definitions , keyed by plugin ID .
*
* @ see \Drupal\Core\Display\VariantManager
* @ see \Drupal\Core\Display\Annotation\DisplayVariant
*/
function hook_display_variant_plugin_alter ( array & $definitions ) {
$definitions [ 'full_page' ][ 'admin_label' ] = t ( 'Block layout' );
}
/**
* Flush all persistent and static caches .
*
* This hook asks your module to clear all of its static caches ,
* in order to ensure a clean environment for subsequently
* invoked data rebuilds .
*
* Do NOT use this hook for rebuilding information . Only use it to flush custom
* caches .
*
* Static caches using drupal_static () do not need to be reset manually .
* However , all other static variables that do not use drupal_static () must be
* manually reset .
*
* This hook is invoked by drupal_flush_all_caches () . It runs before module data
* is updated and before hook_rebuild () .
*
* @ see drupal_flush_all_caches ()
* @ see hook_rebuild ()
*/
function hook_cache_flush () {
if ( defined ( 'MAINTENANCE_MODE' ) && MAINTENANCE_MODE == 'update' ) {
_update_cache_clear ();
}
}
/**
* Rebuild data based upon refreshed caches .
*
* This hook allows your module to rebuild its data based on the latest / current
* module data . It runs after hook_cache_flush () and after all module data has
* been updated .
*
* This hook is only invoked after the system has been completely cleared ;
* i . e . , all previously cached data is known to be gone and every API in the
* system is known to return current information , so your module can safely rely
* on all available data to rebuild its own .
*
* @ see hook_cache_flush ()
* @ see drupal_flush_all_caches ()
*/
function hook_rebuild () {
$themes = \Drupal :: service ( 'theme_handler' ) -> listInfo ();
foreach ( $themes as $theme ) {
_block_rehash ( $theme -> getName ());
}
}
/**
* Alter the configuration synchronization steps .
*
* @ param array $sync_steps
* A one - dimensional array of \Drupal\Core\Config\ConfigImporter method names
* or callables that are invoked to complete the import , in the order that
* they will be processed . Each callable item defined in $sync_steps should
* either be a global function or a public static method . The callable should
* accept a $context array by reference . For example :
* < code >
* function _additional_configuration_step ( & $context ) {
* // Do stuff.
* // If finished set $context['finished'] = 1.
* }
* </ code >
* For more information on creating batches , see the
* @ link batch Batch operations @ endlink documentation .
*
* @ see callback_batch_operation ()
* @ see \Drupal\Core\Config\ConfigImporter :: initialize ()
*/
function hook_config_import_steps_alter ( & $sync_steps , \Drupal\Core\Config\ConfigImporter $config_importer ) {
$deletes = $config_importer -> getUnprocessedConfiguration ( 'delete' );
if ( isset ( $deletes [ 'field.storage.node.body' ])) {
$sync_steps [] = '_additional_configuration_step' ;
}
}
/**
* Alter config typed data definitions .
*
* For example you can alter the typed data types representing each
* configuration schema type to change default labels or form element renderers
* used for configuration translation .
*
* If implementations of this hook add or remove configuration schema a
* ConfigSchemaAlterException will be thrown . Keep in mind that there are tools
* that may use the configuration schema for static analysis of configuration
* files , like the string extractor for the localization system . Such systems
* won ' t work with dynamically defined configuration schemas .
*
* For adding new data types use configuration schema YAML files instead .
*
* @ param $definitions
* Associative array of configuration type definitions keyed by schema type
* names . The elements are themselves array with information about the type .
*
* @ see \Drupal\Core\Config\TypedConfigManager
* @ see \Drupal\Core\Config\Schema\ConfigSchemaAlterException
*/
function hook_config_schema_info_alter ( & $definitions ) {
// Enhance the text and date type definitions with classes to generate proper
// form elements in ConfigTranslationFormBase. Other translatable types will
// appear as a one line textfield.
$definitions [ 'text' ][ 'form_element_class' ] = '\Drupal\config_translation\FormElement\Textarea' ;
$definitions [ 'date_format' ][ 'form_element_class' ] = '\Drupal\config_translation\FormElement\DateFormat' ;
}
/**
* Alter validation constraint plugin definitions .
*
* @ param array [] $definitions
* The array of validation constraint definitions , keyed by plugin ID .
*
* @ see \Drupal\Core\Validation\ConstraintManager
* @ see \Drupal\Core\Validation\Annotation\Constraint
*/
function hook_validation_constraint_alter ( array & $definitions ) {
$definitions [ 'Null' ][ 'class' ] = '\Drupal\mymodule\Validator\Constraints\MyClass' ;
}
/**
* @ } End of " addtogroup hooks " .
*/
/**
* @ defgroup ajax Ajax API
* @ {
* Overview for Drupal ' s Ajax API .
*
* @ section sec_overview Overview of Ajax
* Ajax is the process of dynamically updating parts of a page ' s HTML based on
* data from the server . When a specified event takes place , a PHP callback is
* triggered , which performs server - side logic and may return updated markup or
* JavaScript commands to run . After the return , the browser runs the JavaScript
* or updates the markup on the fly , with no full page refresh necessary .
*
* Many different events can trigger Ajax responses , including :
* - Clicking a button
* - Pressing a key
* - Moving the mouse
*
* @ section sec_framework Ajax responses in forms
* Forms that use the Drupal Form API ( see the
* @ link form_api Form API topic @ endlink for more information about forms ) can
* trigger AJAX responses . Here is an outline of the steps :
* - Add property '#ajax' to a form element in your form array , to trigger an
* Ajax response .
* - Write an Ajax callback to process the input and respond .
* See sections below for details on these two steps .
*
* @ subsection sub_form Adding Ajax triggers to a form
* As an example of adding Ajax triggers to a form , consider editing a date
* format , where the user is provided with a sample of the generated date output
* as they type . To accomplish this , typing in the text field should trigger an
* Ajax response . This is done in the text field form array element
* in \Drupal\config_translation\FormElement\DateFormat :: getFormElement () :
* @ code
* '#ajax' => array (
* 'callback' => 'Drupal\config_translation\FormElement\DateFormat::ajaxSample' ,
* 'event' => 'keyup' ,
* 'progress' => array (
* 'type' => 'throbber' ,
* 'message' => NULL ,
* ),
* ),
* @ endcode
*
* As you can see from this example , the #ajax property for a form element is
* an array . Here are the details of its elements , all of which are optional :
* - callback : The callback to invoke to handle the server side of the
* Ajax event . More information on callbacks is below in @ ref sub_callback .
* - wrapper : The HTML 'id' attribute of the area where the content returned by
* the callback should be placed . Note that callbacks have a choice of
* returning content or JavaScript commands ; 'wrapper' is used for content
* returns .
* - method : The jQuery method for placing the new content ( used with
* 'wrapper' ) . Valid options are 'replaceWith' ( default ), 'append' , 'prepend' ,
* 'before' , 'after' , or 'html' . See
* http :// api . jquery . com / category / manipulation / for more information on these
* methods .
* - effect : The jQuery effect to use when placing the new HTML ( used with
* 'wrapper' ) . Valid options are 'none' ( default ), 'slide' , or 'fade' .
* - speed : The effect speed to use ( used with 'effect' and 'wrapper' ) . Valid
* options are 'slow' ( default ), 'fast' , or the number of milliseconds the
* effect should run .
* - event : The JavaScript event to respond to . This is selected automatically
* for the type of form element ; provide a value to override the default .
* - prevent : A JavaScript event to prevent when the event is triggered . For
* example , if you use event 'mousedown' on a button , you might want to
* prevent 'click' events from also being triggered .
* - progress : An array indicating how to show Ajax processing progress . Can
* contain one or more of these elements :
* - type : Type of indicator : 'throbber' ( default ) or 'bar' .
* - message : Translated message to display .
* - url : For a bar progress indicator , URL path for determining progress .
* - interval : For a bar progress indicator , how often to update it .
2015-08-27 12:03:05 -07:00
* - url : A \Drupal\Core\Url to which to submit the Ajax request . If omitted ,
* defaults to either the same URL as the form or link destination is for
* someone with JavaScript disabled , or a slightly modified version ( e . g . ,
* with a query parameter added , removed , or changed ) of that URL if
* necessary to support Drupal ' s content negotiation . It is recommended to
* omit this key and use Drupal ' s content negotiation rather than using
* substantially different URLs between Ajax and non - Ajax .
2015-08-17 17:00:26 -07:00
*
* @ subsection sub_callback Setting up a callback to process Ajax
* Once you have set up your form to trigger an Ajax response ( see @ ref sub_form
* above ), you need to write some PHP code to process the response . If you use
* 'path' in your Ajax set - up , your route controller will be triggered with only
* the information you provide in the URL . If you use 'callback' , your callback
* method is a function , which will receive the $form and $form_state from the
* triggering form . You can use $form_state to get information about the
* data the user has entered into the form . For instance , in the above example
* for the date format preview ,
* \Drupal\config_translation\FormElement\DateFormat\ajaxSample () does this to
* get the format string entered by the user :
* @ code
* $format_value = \Drupal\Component\Utility\NestedArray :: getValue (
* $form_state -> getValues (),
* $form_state -> getTriggeringElement ()[ '#array_parents' ]);
* @ endcode
*
* Once you have processed the input , you have your choice of returning HTML
* markup or a set of Ajax commands . If you choose to return HTML markup , you
* can return it as a string or a renderable array , and it will be placed in
* the defined 'wrapper' element ( see documentation above in @ ref sub_form ) .
* In addition , any messages returned by drupal_get_messages (), themed as in
* status - messages . html . twig , will be prepended .
*
* To return commands , you need to set up an object of class
* \Drupal\Core\Ajax\AjaxResponse , and then use its addCommand () method to add
* individual commands to it . In the date format preview example , the format
* output is calculated , and then it is returned as replacement markup for a div
* like this :
* @ code
* $response = new AjaxResponse ();
* $response -> addCommand ( new ReplaceCommand (
* '#edit-date-format-suffix' ,
* '<small id="edit-date-format-suffix">' . $format . '</small>' ));
* return $response ;
* @ endcode
*
* The individual commands that you can return implement interface
* \Drupal\Core\Ajax\CommandInterface . Available commands provide the ability
* to pop up alerts , manipulate text and markup in various ways , redirect
* to a new URL , and the generic \Drupal\Core\Ajax\InvokeCommand , which
* invokes an arbitrary jQuery command .
*
* As noted above , status messages are prepended automatically if you use the
* 'wrapper' method and return HTML markup . This is not the case if you return
* commands , but if you would like to show status messages , you can add
* @ code
* array ( '#type' => 'status_messages' )
* @ endcode
* to a render array , use drupal_render () to render it , and add a command to
* place the messages in an appropriate location .
*
* @ section sec_other Other methods for triggering Ajax
* Here are some additional methods you can use to trigger Ajax responses in
* Drupal :
* - Add class ' use - ajax ' to a link . The link will be loaded using an Ajax
* call . When using this method , the href of the link can contain '/nojs/' as
* part of the path . When the Ajax JavaScript processes the page , it will
* convert this to '/ajax/' . The server is then able to easily tell if this
* request was made through an actual Ajax request or in a degraded state , and
* respond appropriately .
* - Add class ' use - ajax - submit ' to a submit button in a form . The form will
* then be submitted via Ajax to the path specified in the #action. Like the
* ajax - submit class on links , this path will have '/nojs/' replaced with
* '/ajax/' so that the submit handler can tell if the form was submitted in a
* degraded state or not .
* - Add property '#autocomplete_route_name' to a text field in a form . The
* route controller for this route must return an array of options for
* autocomplete , as a \Symfony\Component\HttpFoundation\JsonResponse object .
* See the @ link menu Routing topic @ endlink for more information about
* routing .
*/
/**
* @ } End of " defgroup ajax " .
*/
/**
* @ defgroup service_tag Service Tags
* @ {
* Service tags overview
*
* Some services have tags , which are defined in the service definition . Tags
* are used to define a group of related services , or to specify some aspect of
* how the service behaves . Typically , if you tag a service , your service class
* must also implement a corresponding interface . Some common examples :
* - access_check : Indicates a route access checking service ; see the
* @ link menu Menu and routing system topic @ endlink for more information .
* - cache . bin : Indicates a cache bin service ; see the
* @ link cache Cache topic @ endlink for more information .
* - event_subscriber : Indicates an event subscriber service . Event subscribers
* can be used for dynamic routing and route altering ; see the
* @ link menu Menu and routing system topic @ endlink for more information .
* They can also be used for other purposes ; see
* http :// symfony . com / doc / current / cookbook / doctrine / event_listeners_subscribers . html
* for more information .
* - needs_destruction : Indicates that a destruct () method needs to be called
* at the end of a request to finalize operations , if this service was
* instantiated . Services should implement \Drupal\Core\DestructableInterface
* in this case .
2015-08-27 12:03:05 -07:00
* - context_provider : Indicates a block context provider , used for example
* by block conditions . It has to implement
* \Drupal\Core\Plugin\Context\ContextProviderInterface .
* - http_client_middleware : Indicates that the service provides a guzzle
* middleware , see
* https :// guzzle . readthedocs . org / en / latest / handlers - and - middleware . html for
* more information .
2015-08-17 17:00:26 -07:00
*
* Creating a tag for a service does not do anything on its own , but tags
* can be discovered or queried in a compiler pass when the container is built ,
* and a corresponding action can be taken . See
* \Drupal\Core\Render\MainContent\MainContentRenderersPass for an example of
* finding tagged services .
*
* See @ link container Services and Dependency Injection Container @ endlink for
* information on services and the dependency injection container .
*
* @ }
*/
/**
* @ defgroup events Events
* @ {
* Overview of event dispatch and subscribing
*
* @ section sec_intro Introduction and terminology
* Events are part of the Symfony framework : they allow for different components
* of the system to interact and communicate with each other . Each event has a
* unique string name . One system component dispatches the event at an
* appropriate time ; many events are dispatched by Drupal core and the Symfony
* framework in every request . Other system components can register as event
* subscribers ; when an event is dispatched , a method is called on each
* registered subscriber , allowing each one to react . For more on the general
* concept of events , see
* http :// symfony . com / doc / current / components / event_dispatcher / introduction . html
*
* @ section sec_dispatch Dispatching events
* To dispatch an event , call the
* \Symfony\Component\EventDispatcher\EventDispatchInterface :: dispatch () method
* on the 'event_dispatcher' service ( see the
* @ link container Services topic @ endlink for more information about how to
* interact with services ) . The first argument is the unique event name , which
* you should normally define as a constant in a separate static class ( see
* \Symfony\Component\HttpKernel\KernelEvents and
* \Drupal\Core\Config\ConfigEvents for examples ) . The second argument is a
* \Symfony\Component\EventDispatcher\Event object ; normally you will need to
* extend this class , so that your event class can provide data to the event
* subscribers .
*
* @ section sec_subscribe Registering event subscribers
* Here are the steps to register an event subscriber :
* - Define a service in your module , tagged with 'event_subscriber' ( see the
* @ link container Services topic @ endlink for instructions ) .
* - Define a class for your subscriber service that implements
* \Symfony\Component\EventDispatcher\EventSubscriberInterface
* - In your class , the getSubscribedEvents method returns a list of the events
* this class is subscribed to , and which methods on the class should be
* called for each one . Example :
* @ code
* public function getSubscribedEvents () {
* // Subscribe to kernel terminate with priority 100.
* $events [ KernelEvents :: TERMINATE ][] = array ( 'onTerminate' , 100 );
* // Subscribe to kernel request with default priority of 0.
* $events [ KernelEvents :: REQUEST ][] = array ( 'onRequest' );
* return $events ;
* }
* @ endcode
* - Write the methods that respond to the events ; each one receives the
* event object provided in the dispatch as its one argument . In the above
* example , you would need to write onTerminate () and onRequest () methods .
*
* Note that in your getSubscribedEvents () method , you can optionally set the
* priority of your event subscriber ( see terminate example above ) . Event
* subscribers with higher priority numbers get executed first ; the default
* priority is zero . If two event subscribers for the same event have the same
* priority , the one defined in a module with a lower module weight will fire
* first . Subscribers defined in the same services file are fired in
* definition order . If order matters defining a priority is strongly advised
* instead of relying on these two tie breaker rules as they might change in a
* minor release .
* @ }
*/