"Fossies" - the Fresh Open Source Software Archive

Member "drupal-8.9.10/core/lib/Drupal/Core/Extension/module.api.php" (26 Nov 2020, 47270 Bytes) of package /linux/www/drupal-8.9.10.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "module.api.php": 9.0.8_vs_9.1.0-rc1.

    1 <?php
    2 
    3 /**
    4  * @file
    5  * Hooks related to module and update systems.
    6  */
    7 
    8 use Drupal\Core\Database\Database;
    9 use Drupal\Core\Link;
   10 use Drupal\Core\Url;
   11 use Drupal\Core\Utility\UpdateException;
   12 
   13 /**
   14  * @defgroup update_api Update API
   15  * @{
   16  * Updating minor versions of modules
   17  *
   18  * When you update code in a module, you may need to update stored data so that
   19  * the stored data is compatible with the new code. If this update is between
   20  * two minor versions of your module within the same major version of Drupal,
   21  * you can use the Update API to update the data. This API is described in brief
   22  * here; for more details, see https://www.drupal.org/node/2535316. If you are
   23  * updating your module for a major version of Drupal (for instance, Drupal 7 to
   24  * Drupal 8), updates will not run and you will need to use the
   25  * @link migrate Migrate API @endlink instead.
   26  *
   27  * @section sec_when When to write update code
   28  * You need to provide code that performs an update to stored data whenever your
   29  * module makes a change to its data model. A data model change is any change
   30  * that makes stored data on an existing site incompatible with that site's
   31  * updated codebase. Examples:
   32  * - Configuration changes: adding/removing/renaming a config key, changing the
   33  *   expected data type or value structure, changing dependencies, schema
   34  *   changes, etc.
   35  * - Database schema changes: adding, changing, or removing a database table or
   36  *   field; moving stored data to different fields or tables; changing the
   37  *   format of stored data.
   38  * - Content entity or field changes: adding, changing, or removing a field
   39  *   definition, entity definition, or any of their properties.
   40  *
   41  * @section sec_how How to write update code
   42  * Update code for a module is put into an implementation of hook_update_N(),
   43  * which goes into file mymodule.install (if your module's machine name is
   44  * mymodule). See the documentation of hook_update_N() and
   45  * https://www.drupal.org/node/2535316 for details and examples.
   46  *
   47  * @section sec_test Testing update code
   48  * Update code should be tested both manually and by writing an automated test.
   49  * Automated tests for update code extend
   50  * \Drupal\system\Tests\Update\UpdatePathTestBase -- see that class for details,
   51  * and find classes that extend it for examples.
   52  *
   53  * @see migration
   54  * @}
   55  */
   56 
   57 /**
   58  * @addtogroup hooks
   59  * @{
   60  */
   61 
   62 /**
   63  * Defines one or more hooks that are exposed by a module.
   64  *
   65  * Normally hooks do not need to be explicitly defined. However, by declaring a
   66  * hook explicitly, a module may define a "group" for it. Modules that implement
   67  * a hook may then place their implementation in either $module.module or in
   68  * $module.$group.inc. If the hook is located in $module.$group.inc, then that
   69  * file will be automatically loaded when needed.
   70  * In general, hooks that are rarely invoked and/or are very large should be
   71  * placed in a separate include file, while hooks that are very short or very
   72  * frequently called should be left in the main module file so that they are
   73  * always available.
   74  *
   75  * See system_hook_info() for all hook groups defined by Drupal core.
   76  *
   77  * @return
   78  *   An associative array whose keys are hook names and whose values are an
   79  *   associative array containing:
   80  *   - group: A string defining the group to which the hook belongs. The module
   81  *     system will determine whether a file with the name $module.$group.inc
   82  *     exists, and automatically load it when required.
   83  */
   84 function hook_hook_info() {
   85   $hooks['token_info'] = [
   86     'group' => 'tokens',
   87   ];
   88   $hooks['tokens'] = [
   89     'group' => 'tokens',
   90   ];
   91   return $hooks;
   92 }
   93 
   94 /**
   95  * Alter the registry of modules implementing a hook.
   96  *
   97  * This hook is invoked during \Drupal::moduleHandler()->getImplementations().
   98  * A module may implement this hook in order to reorder the implementing
   99  * modules, which are otherwise ordered by the module's system weight.
  100  *
  101  * Note that hooks invoked using \Drupal::moduleHandler->alter() can have
  102  * multiple variations(such as hook_form_alter() and hook_form_FORM_ID_alter()).
  103  * \Drupal::moduleHandler->alter() will call all such variants defined by a
  104  * single module in turn. For the purposes of hook_module_implements_alter(),
  105  * these variants are treated as a single hook. Thus, to ensure that your
  106  * implementation of hook_form_FORM_ID_alter() is called at the right time,
  107  * you will have to change the order of hook_form_alter() implementation in
  108  * hook_module_implements_alter().
  109  *
  110  * @param $implementations
  111  *   An array keyed by the module's name. The value of each item corresponds
  112  *   to a $group, which is usually FALSE, unless the implementation is in a
  113  *   file named $module.$group.inc.
  114  * @param $hook
  115  *   The name of the module hook being implemented.
  116  */
  117 function hook_module_implements_alter(&$implementations, $hook) {
  118   if ($hook == 'form_alter') {
  119     // Move my_module_form_alter() to the end of the list.
  120     // \Drupal::moduleHandler()->getImplementations()
  121     // iterates through $implementations with a foreach loop which PHP iterates
  122     // in the order that the items were added, so to move an item to the end of
  123     // the array, we remove it and then add it.
  124     $group = $implementations['my_module'];
  125     unset($implementations['my_module']);
  126     $implementations['my_module'] = $group;
  127   }
  128 }
  129 
  130 /**
  131  * Alter the information parsed from module and theme .info.yml files.
  132  *
  133  * This hook is invoked in \Drupal\Core\Extension\ExtensionList::doList(). A
  134  * module may implement this hook in order to add to or alter the data generated
  135  * by reading the .info.yml file with \Drupal\Core\Extension\InfoParser.
  136  *
  137  * Using implementations of this hook to make modules required by setting the
  138  * $info['required'] key is discouraged. Doing so will slow down the module
  139  * installation and uninstallation process. Instead, use
  140  * \Drupal\Core\Extension\ModuleUninstallValidatorInterface.
  141  *
  142  * @param array $info
  143  *   The .info.yml file contents, passed by reference so that it can be altered.
  144  * @param \Drupal\Core\Extension\Extension $file
  145  *   Full information about the module or theme.
  146  * @param string $type
  147  *   Either 'module' or 'theme', depending on the type of .info.yml file that
  148  *   was passed.
  149  *
  150  * @see \Drupal\Core\Extension\ModuleUninstallValidatorInterface
  151  */
  152 function hook_system_info_alter(array &$info, \Drupal\Core\Extension\Extension $file, $type) {
  153   // Only fill this in if the .info.yml file does not define a 'datestamp'.
  154   if (empty($info['datestamp'])) {
  155     $info['datestamp'] = $file->getMTime();
  156   }
  157 }
  158 
  159 /**
  160  * Perform necessary actions before a module is installed.
  161  *
  162  * @param string $module
  163  *   The name of the module about to be installed.
  164  */
  165 function hook_module_preinstall($module) {
  166   mymodule_cache_clear();
  167 }
  168 
  169 /**
  170  * Perform necessary actions after modules are installed.
  171  *
  172  * This function differs from hook_install() in that it gives all other modules
  173  * a chance to perform actions when a module is installed, whereas
  174  * hook_install() is only called on the module actually being installed. See
  175  * \Drupal\Core\Extension\ModuleInstaller::install() for a detailed description of
  176  * the order in which install hooks are invoked.
  177  *
  178  * This hook should be implemented in a .module file, not in an .install file.
  179  *
  180  * @param $modules
  181  *   An array of the modules that were installed.
  182  * @param bool $is_syncing
  183  *   TRUE if the module is being installed as part of a configuration import. In
  184  *   these cases, your hook implementation needs to carefully consider what
  185  *   changes, if any, it should make. For example, it should not make any
  186  *   changes to configuration objects or entities.
  187  *
  188  * @see \Drupal\Core\Extension\ModuleInstaller::install()
  189  * @see hook_install()
  190  */
  191 function hook_modules_installed($modules, $is_syncing) {
  192   if (in_array('lousy_module', $modules)) {
  193     \Drupal::state()->set('mymodule.lousy_module_compatibility', TRUE);
  194   }
  195   if (!$is_syncing) {
  196     \Drupal::service('mymodule.service')->doSomething($modules);
  197   }
  198 }
  199 
  200 /**
  201  * Perform setup tasks when the module is installed.
  202  *
  203  * If the module implements hook_schema(), the database tables will
  204  * be created before this hook is fired.
  205  *
  206  * If the module provides a MODULE.routing.yml or alters routing information
  207  * these changes will not be available when this hook is fired. If up-to-date
  208  * router information is required, for example to use \Drupal\Core\Url, then
  209  * (preferably) use hook_modules_installed() or rebuild the router in the
  210  * hook_install() implementation.
  211  *
  212  * Implementations of this hook are by convention declared in the module's
  213  * .install file. The implementation can rely on the .module file being loaded.
  214  * The hook will only be called when a module is installed. The module's schema
  215  * version will be set to the module's greatest numbered update hook. Because of
  216  * this, any time a hook_update_N() is added to the module, this function needs
  217  * to be updated to reflect the current version of the database schema.
  218  *
  219  * See the @link https://www.drupal.org/node/146843 Schema API documentation
  220  * @endlink for details on hook_schema and how database tables are defined.
  221  *
  222  * Note that since this function is called from a full bootstrap, all functions
  223  * (including those in modules enabled by the current page request) are
  224  * available when this hook is called. Use cases could be displaying a user
  225  * message, or calling a module function necessary for initial setup, etc.
  226  *
  227  * Please be sure that anything added or modified in this function that can
  228  * be removed during uninstall should be removed with hook_uninstall().
  229  *
  230  * @param bool $is_syncing
  231  *   TRUE if the module is being installed as part of a configuration import. In
  232  *   these cases, your hook implementation needs to carefully consider what
  233  *   changes, if any, it should make. For example, it should not make any
  234  *   changes to configuration objects or entities.
  235  *
  236  * @see \Drupal\Core\Config\ConfigInstallerInterface::isSyncing
  237  * @see hook_schema()
  238  * @see \Drupal\Core\Extension\ModuleInstaller::install()
  239  * @see hook_uninstall()
  240  * @see hook_modules_installed()
  241  */
  242 function hook_install($is_syncing) {
  243   // Set general module variables.
  244   \Drupal::state()->set('mymodule.foo', 'bar');
  245 }
  246 
  247 /**
  248  * Perform necessary actions before a module is uninstalled.
  249  *
  250  * @param string $module
  251  *   The name of the module about to be uninstalled.
  252  */
  253 function hook_module_preuninstall($module) {
  254   mymodule_cache_clear();
  255 }
  256 
  257 /**
  258  * Perform necessary actions after modules are uninstalled.
  259  *
  260  * This function differs from hook_uninstall() in that it gives all other
  261  * modules a chance to perform actions when a module is uninstalled, whereas
  262  * hook_uninstall() is only called on the module actually being uninstalled.
  263  *
  264  * It is recommended that you implement this hook if your module stores
  265  * data that may have been set by other modules.
  266  *
  267  * @param $modules
  268  *   An array of the modules that were uninstalled.
  269  * @param bool $is_syncing
  270  *   TRUE if the module is being uninstalled as part of a configuration import.
  271  *   In these cases, your hook implementation needs to carefully consider what
  272  *   changes, if any, it should make. For example, it should not make any
  273  *   changes to configuration objects or entities.
  274  *
  275  * @see hook_uninstall()
  276  */
  277 function hook_modules_uninstalled($modules, $is_syncing) {
  278   if (in_array('lousy_module', $modules)) {
  279     \Drupal::state()->delete('mymodule.lousy_module_compatibility');
  280   }
  281   mymodule_cache_rebuild();
  282   if (!$is_syncing) {
  283     \Drupal::service('mymodule.service')->doSomething($modules);
  284   }
  285 }
  286 
  287 /**
  288  * Remove any information that the module sets.
  289  *
  290  * The information that the module should remove includes:
  291  * - state that the module has set using \Drupal::state()
  292  * - modifications to existing tables
  293  *
  294  * The module should not remove its entry from the module configuration.
  295  * Database tables defined by hook_schema() will be removed automatically.
  296  *
  297  * The uninstall hook must be implemented in the module's .install file. It
  298  * will fire when the module gets uninstalled but before the module's database
  299  * tables are removed, allowing your module to query its own tables during
  300  * this routine.
  301  *
  302  * @param bool $is_syncing
  303  *   TRUE if the module is being uninstalled as part of a configuration import.
  304  *   In these cases, your hook implementation needs to carefully consider what
  305  *   changes, if any, it should make. For example, it should not make any
  306  *   changes to configuration objects or entities.
  307  *
  308  * @see hook_install()
  309  * @see hook_schema()
  310  * @see hook_modules_uninstalled()
  311  */
  312 function hook_uninstall($is_syncing) {
  313   // Delete remaining general module variables.
  314   \Drupal::state()->delete('mymodule.foo');
  315 }
  316 
  317 /**
  318  * Return an array of tasks to be performed by an installation profile.
  319  *
  320  * Any tasks you define here will be run, in order, after the installer has
  321  * finished the site configuration step but before it has moved on to the
  322  * final import of languages and the end of the installation. This is invoked
  323  * by install_tasks(). You can have any number of custom tasks to perform
  324  * during this phase.
  325  *
  326  * Each task you define here corresponds to a callback function which you must
  327  * separately define and which is called when your task is run. This function
  328  * will receive the global installation state variable, $install_state, as
  329  * input, and has the opportunity to access or modify any of its settings. See
  330  * the install_state_defaults() function in the installer for the list of
  331  * $install_state settings used by Drupal core.
  332  *
  333  * At the end of your task function, you can indicate that you want the
  334  * installer to pause and display a page to the user by returning any themed
  335  * output that should be displayed on that page (but see below for tasks that
  336  * use the form API or batch API; the return values of these task functions are
  337  * handled differently). You should also use #title within the task
  338  * callback function to set a custom page title. For some tasks, however, you
  339  * may want to simply do some processing and pass control to the next task
  340  * without ending the page request; to indicate this, simply do not send back
  341  * a return value from your task function at all. This can be used, for
  342  * example, by installation profiles that need to configure certain site
  343  * settings in the database without obtaining any input from the user.
  344  *
  345  * The task function is treated specially if it defines a form or requires
  346  * batch processing; in that case, you should return either the form API
  347  * definition or batch API array, as appropriate. See below for more
  348  * information on the 'type' key that you must define in the task definition
  349  * to inform the installer that your task falls into one of those two
  350  * categories. It is important to use these APIs directly, since the installer
  351  * may be run non-interactively (for example, via a command line script), all
  352  * in one page request; in that case, the installer will automatically take
  353  * care of submitting forms and processing batches correctly for both types of
  354  * installations. You can inspect the $install_state['interactive'] boolean to
  355  * see whether or not the current installation is interactive, if you need
  356  * access to this information.
  357  *
  358  * Remember that a user installing Drupal interactively will be able to reload
  359  * an installation page multiple times, so you should use \Drupal::state() to
  360  * store any data that you may need later in the installation process. Any
  361  * temporary state must be removed using \Drupal::state()->delete() before
  362  * your last task has completed and control is handed back to the installer.
  363  *
  364  * @param array $install_state
  365  *   An array of information about the current installation state.
  366  *
  367  * @return array
  368  *   A keyed array of tasks the profile will perform during the final stage of
  369  *   the installation. Each key represents the name of a function (usually a
  370  *   function defined by this profile, although that is not strictly required)
  371  *   that is called when that task is run. The values are associative arrays
  372  *   containing the following key-value pairs (all of which are optional):
  373  *   - display_name: The human-readable name of the task. This will be
  374  *     displayed to the user while the installer is running, along with a list
  375  *     of other tasks that are being run. Leave this unset to prevent the task
  376  *     from appearing in the list.
  377  *   - display: This is a boolean which can be used to provide finer-grained
  378  *     control over whether or not the task will display. This is mostly useful
  379  *     for tasks that are intended to display only under certain conditions;
  380  *     for these tasks, you can set 'display_name' to the name that you want to
  381  *     display, but then use this boolean to hide the task only when certain
  382  *     conditions apply.
  383  *   - type: A string representing the type of task. This parameter has three
  384  *     possible values:
  385  *     - normal: (default) This indicates that the task will be treated as a
  386  *       regular callback function, which does its processing and optionally
  387  *       returns HTML output.
  388  *     - batch: This indicates that the task function will return a batch API
  389  *       definition suitable for batch_set() or an array of batch definitions
  390  *       suitable for consecutive batch_set() calls. The installer will then
  391  *       take care of automatically running the task via batch processing.
  392  *     - form: This indicates that the task function will return a standard
  393  *       form API definition (and separately define validation and submit
  394  *       handlers, as appropriate). The installer will then take care of
  395  *       automatically directing the user through the form submission process.
  396  *   - run: A constant representing the manner in which the task will be run.
  397  *     This parameter has three possible values:
  398  *     - INSTALL_TASK_RUN_IF_NOT_COMPLETED: (default) This indicates that the
  399  *       task will run once during the installation of the profile.
  400  *     - INSTALL_TASK_SKIP: This indicates that the task will not run during
  401  *       the current installation page request. It can be used to skip running
  402  *       an installation task when certain conditions are met, even though the
  403  *       task may still show on the list of installation tasks presented to the
  404  *       user.
  405  *     - INSTALL_TASK_RUN_IF_REACHED: This indicates that the task will run on
  406  *       each installation page request that reaches it. This is rarely
  407  *       necessary for an installation profile to use; it is primarily used by
  408  *       the Drupal installer for bootstrap-related tasks.
  409  *   - function: Normally this does not need to be set, but it can be used to
  410  *     force the installer to call a different function when the task is run
  411  *     (rather than the function whose name is given by the array key). This
  412  *     could be used, for example, to allow the same function to be called by
  413  *     two different tasks.
  414  *
  415  * @see install_state_defaults()
  416  * @see batch_set()
  417  * @see hook_install_tasks_alter()
  418  * @see install_tasks()
  419  */
  420 function hook_install_tasks(&$install_state) {
  421   // Here, we define a variable to allow tasks to indicate that a particular,
  422   // processor-intensive batch process needs to be triggered later on in the
  423   // installation.
  424   $myprofile_needs_batch_processing = \Drupal::state()->get('myprofile.needs_batch_processing', FALSE);
  425   $tasks = [
  426     // This is an example of a task that defines a form which the user who is
  427     // installing the site will be asked to fill out. To implement this task,
  428     // your profile would define a function named myprofile_data_import_form()
  429     // as a normal form API callback function, with associated validation and
  430     // submit handlers. In the submit handler, in addition to saving whatever
  431     // other data you have collected from the user, you might also call
  432     // \Drupal::state()->set('myprofile.needs_batch_processing', TRUE) if the
  433     // user has entered data which requires that batch processing will need to
  434     // occur later on.
  435     'myprofile_data_import_form' => [
  436       'display_name' => t('Data import options'),
  437       'type' => 'form',
  438     ],
  439     // Similarly, to implement this task, your profile would define a function
  440     // named myprofile_settings_form() with associated validation and submit
  441     // handlers. This form might be used to collect and save additional
  442     // information from the user that your profile needs. There are no extra
  443     // steps required for your profile to act as an "installation wizard"; you
  444     // can simply define as many tasks of type 'form' as you wish to execute,
  445     // and the forms will be presented to the user, one after another.
  446     'myprofile_settings_form' => [
  447       'display_name' => t('Additional options'),
  448       'type' => 'form',
  449     ],
  450     // This is an example of a task that performs batch operations. To
  451     // implement this task, your profile would define a function named
  452     // myprofile_batch_processing() which returns a batch API array definition
  453     // that the installer will use to execute your batch operations. Due to the
  454     // 'myprofile.needs_batch_processing' variable used here, this task will be
  455     // hidden and skipped unless your profile set it to TRUE in one of the
  456     // previous tasks.
  457     'myprofile_batch_processing' => [
  458       'display_name' => t('Import additional data'),
  459       'display' => $myprofile_needs_batch_processing,
  460       'type' => 'batch',
  461       'run' => $myprofile_needs_batch_processing ? INSTALL_TASK_RUN_IF_NOT_COMPLETED : INSTALL_TASK_SKIP,
  462     ],
  463     // This is an example of a task that will not be displayed in the list that
  464     // the user sees. To implement this task, your profile would define a
  465     // function named myprofile_final_site_setup(), in which additional,
  466     // automated site setup operations would be performed. Since this is the
  467     // last task defined by your profile, you should also use this function to
  468     // call \Drupal::state()->delete('myprofile.needs_batch_processing') and
  469     // clean up the state that was used above. If you want the user to pass
  470     // to the final Drupal installation tasks uninterrupted, return no output
  471     // from this function. Otherwise, return themed output that the user will
  472     // see (for example, a confirmation page explaining that your profile's
  473     // tasks are complete, with a link to reload the current page and therefore
  474     // pass on to the final Drupal installation tasks when the user is ready to
  475     // do so).
  476     'myprofile_final_site_setup' => [],
  477   ];
  478   return $tasks;
  479 }
  480 
  481 /**
  482  * Alter the full list of installation tasks.
  483  *
  484  * You can use this hook to change or replace any part of the Drupal
  485  * installation process that occurs after the installation profile is selected.
  486  *
  487  * This hook is invoked on the install profile in install_tasks().
  488  *
  489  * @param $tasks
  490  *   An array of all available installation tasks, including those provided by
  491  *   Drupal core. You can modify this array to change or replace individual
  492  *   steps within the installation process.
  493  * @param $install_state
  494  *   An array of information about the current installation state.
  495  *
  496  * @see hook_install_tasks()
  497  * @see install_tasks()
  498  */
  499 function hook_install_tasks_alter(&$tasks, $install_state) {
  500   // Replace the entire site configuration form provided by Drupal core
  501   // with a custom callback function defined by this installation profile.
  502   $tasks['install_configure_form']['function'] = 'myprofile_install_configure_form';
  503 }
  504 
  505 /**
  506  * Perform a single update between minor versions.
  507  *
  508  * Hook hook_update_N() can only be used to update between minor versions of a
  509  * module. To upgrade between major versions of Drupal (for example, between
  510  * Drupal 7 and 8), use the @link migrate Migrate API @endlink instead.
  511  *
  512  * @section sec_naming Naming and documenting your function
  513  * For each change in a module that requires one or more actions to be performed
  514  * when updating a site, add a new implementation of hook_update_N() to your
  515  * mymodule.install file (assuming mymodule is the machine name of your module).
  516  * Implementations of hook_update_N() are named (module name)_update_(number).
  517  * The numbers are normally composed of three parts:
  518  * - 1 or 2 digits for Drupal core compatibility (Drupal 8, 9, 10, etc.). This
  519  *   convention must be followed.
  520  * - 1 digit for your module's major release version; for example, for 8.x-1.*
  521  *   use 1, for 8.x-2.* use 2, for Core 8.0.x use 0, and for Core 8.1.x use 1.
  522  *   This convention is optional but suggested for clarity.
  523  * - 2 digits for sequential counting, starting with 01. Note that the x000
  524  *   number can never be used: the lowest update number that will be recognized
  525  *   and run for major version x is x001.
  526  * Examples:
  527  * - node_update_8001(): The first update for the Drupal 8.0.x version of the
  528  *   Drupal Core node module.
  529  * - mymodule_update_8101(): The first update for your custom or contributed
  530  *   module's 8.x-1.x versions.
  531  * - mymodule_update_8201(): The first update for the 8.x-2.x versions.
  532  *
  533  * Never renumber update functions. The numeric part of the hook implementation
  534  * function is stored in the database to keep track of which updates have run,
  535  * so it is important to maintain this information consistently.
  536  *
  537  * The documentation block preceding this function is stripped of newlines and
  538  * used as the description for the update on the pending updates task list,
  539  * which users will see when they run the update.php script.
  540  *
  541  * @section sec_notes Notes about the function body
  542  * Writing hook_update_N() functions is tricky. There are several reasons why
  543  * this is the case:
  544  * - You do not know when updates will be run: someone could be keeping up with
  545  *   every update and run them when the database and code are in the same state
  546  *   as when you wrote your update function, or they could have waited until a
  547  *   few more updates have come out, and run several at the same time.
  548  * - You do not know the state of other modules' updates either.
  549  * - Other modules can use hook_update_dependencies() to run updates between
  550  *   your module's updates, so you also cannot count on your functions running
  551  *   right after one another.
  552  * - You do not know what environment your update will run in (which modules
  553  *   are installed, whether certain hooks are implemented or not, whether
  554  *   services are overridden, etc.).
  555  *
  556  * Because of these reasons, you'll need to use care in writing your update
  557  * function. Some things to think about:
  558  * - Never assume that the database schema is the same when the update will run
  559  *   as it is when you wrote the update function. So, when updating a database
  560  *   table or field, put the schema information you want to update to directly
  561  *   into your function instead of calling your hook_schema() function to
  562  *   retrieve it (this is one case where the right thing to do is copy and paste
  563  *   the code).
  564  * - Never assume that the configuration schema is the same when the update will
  565  *   run as it is when you wrote the update function. So, when saving
  566  *   configuration, use the $has_trusted_data = TRUE parameter so that schema is
  567  *   ignored, and make sure that the configuration data you are saving matches
  568  *   the configuration schema at the time when you write the update function
  569  *   (later updates may change it again to match new schema changes).
  570  * - Never assume your field or entity type definitions are the same when the
  571  *   update will run as they are when you wrote the update function. Always
  572  *   retrieve the correct version via
  573  *   \Drupal::entityDefinitionUpdateManager()::getEntityType() or
  574  *   \Drupal::entityDefinitionUpdateManager()::getFieldStorageDefinition(). When
  575  *   adding a new definition always replicate it in the update function body as
  576  *   you would do with a schema definition.
  577  * - Never call \Drupal::entityDefinitionUpdateManager()::applyUpdates() in an
  578  *   update function, as it will apply updates for any module not only yours,
  579  *   which will lead to unpredictable results.
  580  * - Be careful about API functions and especially CRUD operations that you use
  581  *   in your update function. If they invoke hooks or use services, they may
  582  *   not behave as expected, and it may actually not be appropriate to use the
  583  *   normal API functions that invoke all the hooks, use the database schema,
  584  *   and/or use services in an update function -- you may need to switch to
  585  *   using a more direct method (database query, etc.).
  586  * - In particular, loading, saving, or performing any other CRUD operation on
  587  *   an entity is never safe to do (they always involve hooks and services).
  588  * - Never rebuild the router during an update function.
  589  *
  590  * The following actions are examples of things that are safe to do during
  591  * updates:
  592  * - Cache invalidation.
  593  * - Using \Drupal::configFactory()->getEditable() and \Drupal::config(), as
  594  *   long as you make sure that your update data matches the schema, and you
  595  *   use the $has_trusted_data argument in the save operation.
  596  * - Marking a container for rebuild.
  597  * - Using the API provided by \Drupal::entityDefinitionUpdateManager() to
  598  *   update the entity schema based on changes in entity type or field
  599  *   definitions provided by your module.
  600  *
  601  * See https://www.drupal.org/node/2535316 for more on writing update functions.
  602  *
  603  * @section sec_bulk Batch updates
  604  * If running your update all at once could possibly cause PHP to time out, use
  605  * the $sandbox parameter to indicate that the Batch API should be used for your
  606  * update. In this case, your update function acts as an implementation of
  607  * callback_batch_operation(), and $sandbox acts as the batch context
  608  * parameter. In your function, read the state information from the previous
  609  * run from $sandbox (or initialize), run a chunk of updates, save the state in
  610  * $sandbox, and set $sandbox['#finished'] to a value between 0 and 1 to
  611  * indicate the percent completed, or 1 if it is finished (you need to do this
  612  * explicitly in each pass).
  613  *
  614  * See the @link batch Batch operations topic @endlink for more information on
  615  * how to use the Batch API.
  616  *
  617  * @param array $sandbox
  618  *   Stores information for batch updates. See above for more information.
  619  *
  620  * @return string|null
  621  *   Optionally, update hooks may return a translated string that will be
  622  *   displayed to the user after the update has completed. If no message is
  623  *   returned, no message will be presented to the user.
  624  *
  625  * @throws \Drupal\Core\Utility\UpdateException|PDOException
  626  *   In case of error, update hooks should throw an instance of
  627  *   Drupal\Core\Utility\UpdateException with a meaningful message for the user.
  628  *   If a database query fails for whatever reason, it will throw a
  629  *   PDOException.
  630  *
  631  * @ingroup update_api
  632  *
  633  * @see batch
  634  * @see schemaapi
  635  * @see hook_update_last_removed()
  636  * @see update_get_update_list()
  637  * @see \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface
  638  * @see node_update_8001
  639  * @see system_update_8004
  640  * @see https://www.drupal.org/node/2535316
  641  */
  642 function hook_update_N(&$sandbox) {
  643   // For non-batch updates, the signature can simply be:
  644   // function hook_update_N() {
  645 
  646   // Example function body for adding a field to a database table, which does
  647   // not require a batch operation:
  648   $spec = [
  649     'type' => 'varchar',
  650     'description' => "New Col",
  651     'length' => 20,
  652     'not null' => FALSE,
  653   ];
  654   $schema = Database::getConnection()->schema();
  655   $schema->addField('mytable1', 'newcol', $spec);
  656 
  657   // Example of what to do if there is an error during your update.
  658   if ($some_error_condition_met) {
  659     throw new UpdateException('Something went wrong; here is what you should do.');
  660   }
  661 
  662   // Example function body for a batch update. In this example, the values in
  663   // a database field are updated.
  664   if (!isset($sandbox['progress'])) {
  665     // This must be the first run. Initialize the sandbox.
  666     $sandbox['progress'] = 0;
  667     $sandbox['current_pk'] = 0;
  668     $sandbox['max'] = Database::getConnection()->query('SELECT COUNT(myprimarykey) FROM {mytable1}')->fetchField();
  669   }
  670 
  671   // Update in chunks of 20.
  672   $records = Database::getConnection()->select('mytable1', 'm')
  673     ->fields('m', ['myprimarykey', 'otherfield'])
  674     ->condition('myprimarykey', $sandbox['current_pk'], '>')
  675     ->range(0, 20)
  676     ->orderBy('myprimarykey', 'ASC')
  677     ->execute();
  678   foreach ($records as $record) {
  679     // Here, you would make an update something related to this record. In this
  680     // example, some text is added to the other field.
  681     Database::getConnection()->update('mytable1')
  682       ->fields(['otherfield' => $record->otherfield . '-suffix'])
  683       ->condition('myprimarykey', $record->myprimarykey)
  684       ->execute();
  685 
  686     $sandbox['progress']++;
  687     $sandbox['current_pk'] = $record->myprimarykey;
  688   }
  689 
  690   $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
  691 
  692   // To display a message to the user when the update is completed, return it.
  693   // If you do not want to display a completion message, return nothing.
  694   return t('All foo bars were updated with the new suffix');
  695 }
  696 
  697 /**
  698  * Executes an update which is intended to update data, like entities.
  699  *
  700  * These implementations have to be placed in a MODULE.post_update.php file.
  701  *
  702  * These updates are executed after all hook_update_N() implementations. At this
  703  * stage Drupal is already fully repaired so you can use any API as you wish.
  704  *
  705  * NAME can be arbitrary machine names. In contrast to hook_update_N() the
  706  * alphanumeric naming of functions in the file is the only thing which ensures
  707  * the execution order of those functions. If update order is mandatory,
  708  * you should add numerical prefix to NAME or make it completely numerical.
  709  *
  710  * Drupal also ensures to not execute the same hook_post_update_NAME() function
  711  * twice.
  712  *
  713  * @section sec_bulk Batch updates
  714  * If running your update all at once could possibly cause PHP to time out, use
  715  * the $sandbox parameter to indicate that the Batch API should be used for your
  716  * update. In this case, your update function acts as an implementation of
  717  * callback_batch_operation(), and $sandbox acts as the batch context
  718  * parameter. In your function, read the state information from the previous
  719  * run from $sandbox (or initialize), run a chunk of updates, save the state in
  720  * $sandbox, and set $sandbox['#finished'] to a value between 0 and 1 to
  721  * indicate the percent completed, or 1 if it is finished (you need to do this
  722  * explicitly in each pass).
  723  *
  724  * See the @link batch Batch operations topic @endlink for more information on
  725  * how to use the Batch API.
  726  *
  727  * @param array $sandbox
  728  *   Stores information for batch updates. See above for more information.
  729  *
  730  * @return string|null
  731  *   Optionally, hook_post_update_NAME() hooks may return a translated string
  732  *   that will be displayed to the user after the update has completed. If no
  733  *   message is returned, no message will be presented to the user.
  734  *
  735  * @throws \Drupal\Core\Utility\UpdateException|PDOException
  736  *   In case of error, update hooks should throw an instance of
  737  *   \Drupal\Core\Utility\UpdateException with a meaningful message for the
  738  *   user. If a database query fails for whatever reason, it will throw a
  739  *   PDOException.
  740  *
  741  * @ingroup update_api
  742  *
  743  * @see hook_update_N()
  744  * @see hook_removed_post_updates()
  745  */
  746 function hook_post_update_NAME(&$sandbox) {
  747   // Example of updating some content.
  748   $node = \Drupal\node\Entity\Node::load(123);
  749   $node->setTitle('foo');
  750   $node->save();
  751 
  752   $result = t('Node %nid saved', ['%nid' => $node->id()]);
  753 
  754   // Example of disabling blocks with missing condition contexts. Note: The
  755   // block itself is in a state which is valid at that point.
  756   // @see block_update_8001()
  757   // @see block_post_update_disable_blocks_with_missing_contexts()
  758   $block_update_8001 = \Drupal::keyValue('update_backup')->get('block_update_8001', []);
  759 
  760   $block_ids = array_keys($block_update_8001);
  761   $block_storage = \Drupal::entityTypeManager()->getStorage('block');
  762   $blocks = $block_storage->loadMultiple($block_ids);
  763   /** @var $blocks \Drupal\block\BlockInterface[] */
  764   foreach ($blocks as $block) {
  765     // This block has had conditions removed due to an inability to resolve
  766     // contexts in block_update_8001() so disable it.
  767 
  768     // Disable currently enabled blocks.
  769     if ($block_update_8001[$block->id()]['status']) {
  770       $block->setStatus(FALSE);
  771       $block->save();
  772     }
  773   }
  774 
  775   return $result;
  776 }
  777 
  778 /**
  779  * Return an array of removed hook_post_update_NAME() function names.
  780  *
  781  * This should be used to indicate post-update functions that have existed in
  782  * some previous version of the module, but are no longer available.
  783  *
  784  * This implementation has to be placed in a MODULE.post_update.php file.
  785  *
  786  * @return string[]
  787  *   An array where the keys are removed post-update function names, and the
  788  *   values are the first stable version in which the update was removed.
  789  *
  790  * @ingroup update_api
  791  *
  792  * @see hook_post_update_NAME()
  793  */
  794 function hook_removed_post_updates() {
  795   return [
  796     'mymodule_post_update_foo' => '8.x-2.0',
  797     'mymodule_post_update_bar' => '8.x-3.0',
  798     'mymodule_post_update_baz' => '8.x-3.0',
  799   ];
  800 }
  801 
  802 /**
  803  * Return an array of information about module update dependencies.
  804  *
  805  * This can be used to indicate update functions from other modules that your
  806  * module's update functions depend on, or vice versa. It is used by the update
  807  * system to determine the appropriate order in which updates should be run, as
  808  * well as to search for missing dependencies.
  809  *
  810  * Implementations of this hook should be placed in a mymodule.install file in
  811  * the same directory as mymodule.module.
  812  *
  813  * @return
  814  *   A multidimensional array containing information about the module update
  815  *   dependencies. The first two levels of keys represent the module and update
  816  *   number (respectively) for which information is being returned, and the
  817  *   value is an array of information about that update's dependencies. Within
  818  *   this array, each key represents a module, and each value represents the
  819  *   number of an update function within that module. In the event that your
  820  *   update function depends on more than one update from a particular module,
  821  *   you should always list the highest numbered one here (since updates within
  822  *   a given module always run in numerical order).
  823  *
  824  * @ingroup update_api
  825  *
  826  * @see update_resolve_dependencies()
  827  * @see hook_update_N()
  828  */
  829 function hook_update_dependencies() {
  830   // Indicate that the mymodule_update_8001() function provided by this module
  831   // must run after the another_module_update_8003() function provided by the
  832   // 'another_module' module.
  833   $dependencies['mymodule'][8001] = [
  834     'another_module' => 8003,
  835   ];
  836   // Indicate that the mymodule_update_8002() function provided by this module
  837   // must run before the yet_another_module_update_8005() function provided by
  838   // the 'yet_another_module' module. (Note that declaring dependencies in this
  839   // direction should be done only in rare situations, since it can lead to the
  840   // following problem: If a site has already run the yet_another_module
  841   // module's database updates before it updates its codebase to pick up the
  842   // newest mymodule code, then the dependency declared here will be ignored.)
  843   $dependencies['yet_another_module'][8005] = [
  844     'mymodule' => 8002,
  845   ];
  846   return $dependencies;
  847 }
  848 
  849 /**
  850  * Return a number which is no longer available as hook_update_N().
  851  *
  852  * If you remove some update functions from your mymodule.install file, you
  853  * should notify Drupal of those missing functions. This way, Drupal can
  854  * ensure that no update is accidentally skipped.
  855  *
  856  * Implementations of this hook should be placed in a mymodule.install file in
  857  * the same directory as mymodule.module.
  858  *
  859  * @return
  860  *   An integer, corresponding to hook_update_N() which has been removed from
  861  *   mymodule.install.
  862  *
  863  * @ingroup update_api
  864  *
  865  * @see hook_update_N()
  866  */
  867 function hook_update_last_removed() {
  868   // We've removed the 8.x-1.x version of mymodule, including database updates.
  869   // The next update function is mymodule_update_8200().
  870   return 8103;
  871 }
  872 
  873 /**
  874  * Provide information on Updaters (classes that can update Drupal).
  875  *
  876  * Drupal\Core\Updater\Updater is a class that knows how to update various parts
  877  * of the Drupal file system, for example to update modules that have newer
  878  * releases, or to install a new theme.
  879  *
  880  * @return
  881  *   An associative array of information about the updater(s) being provided.
  882  *   This array is keyed by a unique identifier for each updater, and the
  883  *   values are subarrays that can contain the following keys:
  884  *   - class: The name of the PHP class which implements this updater.
  885  *   - name: Human-readable name of this updater.
  886  *   - weight: Controls what order the Updater classes are consulted to decide
  887  *     which one should handle a given task. When an update task is being run,
  888  *     the system will loop through all the Updater classes defined in this
  889  *     registry in weight order and let each class respond to the task and
  890  *     decide if each Updater wants to handle the task. In general, this
  891  *     doesn't matter, but if you need to override an existing Updater, make
  892  *     sure your Updater has a lighter weight so that it comes first.
  893  *
  894  * @ingroup update_api
  895  *
  896  * @see drupal_get_updaters()
  897  * @see hook_updater_info_alter()
  898  */
  899 function hook_updater_info() {
  900   return [
  901     'module' => [
  902       'class' => 'Drupal\Core\Updater\Module',
  903       'name' => t('Update modules'),
  904       'weight' => 0,
  905     ],
  906     'theme' => [
  907       'class' => 'Drupal\Core\Updater\Theme',
  908       'name' => t('Update themes'),
  909       'weight' => 0,
  910     ],
  911   ];
  912 }
  913 
  914 /**
  915  * Alter the Updater information array.
  916  *
  917  * An Updater is a class that knows how to update various parts of the Drupal
  918  * file system, for example to update modules that have newer releases, or to
  919  * install a new theme.
  920  *
  921  * @param array $updaters
  922  *   Associative array of updaters as defined through hook_updater_info().
  923  *   Alter this array directly.
  924  *
  925  * @ingroup update_api
  926  *
  927  * @see drupal_get_updaters()
  928  * @see hook_updater_info()
  929  */
  930 function hook_updater_info_alter(&$updaters) {
  931   // Adjust weight so that the theme Updater gets a chance to handle a given
  932   // update task before module updaters.
  933   $updaters['theme']['weight'] = -1;
  934 }
  935 
  936 /**
  937  * Check installation requirements and do status reporting.
  938  *
  939  * This hook has three closely related uses, determined by the $phase argument:
  940  * - Checking installation requirements ($phase == 'install').
  941  * - Checking update requirements ($phase == 'update').
  942  * - Status reporting ($phase == 'runtime').
  943  *
  944  * Note that this hook, like all others dealing with installation and updates,
  945  * must reside in a module_name.install file, or it will not properly abort
  946  * the installation of the module if a critical requirement is missing.
  947  *
  948  * During the 'install' phase, modules can for example assert that
  949  * library or server versions are available or sufficient.
  950  * Note that the installation of a module can happen during installation of
  951  * Drupal itself (by install.php) with an installation profile or later by hand.
  952  * As a consequence, install-time requirements must be checked without access
  953  * to the full Drupal API, because it is not available during install.php.
  954  * If a requirement has a severity of REQUIREMENT_ERROR, install.php will abort
  955  * or at least the module will not install.
  956  * Other severity levels have no effect on the installation.
  957  * Module dependencies do not belong to these installation requirements,
  958  * but should be defined in the module's .info.yml file.
  959  *
  960  * During installation (when $phase == 'install'), if you need to load a class
  961  * from your module, you'll need to include the class file directly.
  962  *
  963  * The 'runtime' phase is not limited to pure installation requirements
  964  * but can also be used for more general status information like maintenance
  965  * tasks and security issues.
  966  * The returned 'requirements' will be listed on the status report in the
  967  * administration section, with indication of the severity level.
  968  * Moreover, any requirement with a severity of REQUIREMENT_ERROR severity will
  969  * result in a notice on the administration configuration page.
  970  *
  971  * @param $phase
  972  *   The phase in which requirements are checked:
  973  *   - install: The module is being installed.
  974  *   - update: The module is enabled and update.php is run.
  975  *   - runtime: The runtime requirements are being checked and shown on the
  976  *     status report page.
  977  *
  978  * @return
  979  *   An associative array where the keys are arbitrary but must be unique (it
  980  *   is suggested to use the module short name as a prefix) and the values are
  981  *   themselves associative arrays with the following elements:
  982  *   - title: The name of the requirement.
  983  *   - value: The current value (e.g., version, time, level, etc). During
  984  *     install phase, this should only be used for version numbers, do not set
  985  *     it if not applicable.
  986  *   - description: The description of the requirement/status.
  987  *   - severity: The requirement's result/severity level, one of:
  988  *     - REQUIREMENT_INFO: For info only.
  989  *     - REQUIREMENT_OK: The requirement is satisfied.
  990  *     - REQUIREMENT_WARNING: The requirement failed with a warning.
  991  *     - REQUIREMENT_ERROR: The requirement failed with an error.
  992  */
  993 function hook_requirements($phase) {
  994   $requirements = [];
  995 
  996   // Report Drupal version
  997   if ($phase == 'runtime') {
  998     $requirements['drupal'] = [
  999       'title' => t('Drupal'),
 1000       'value' => \Drupal::VERSION,
 1001       'severity' => REQUIREMENT_INFO,
 1002     ];
 1003   }
 1004 
 1005   // Test PHP version
 1006   $requirements['php'] = [
 1007     'title' => t('PHP'),
 1008     'value' => ($phase == 'runtime') ? Link::fromTextAndUrl(phpversion(), Url::fromRoute('system.php'))->toString() : phpversion(),
 1009   ];
 1010   if (version_compare(phpversion(), DRUPAL_MINIMUM_PHP) < 0) {
 1011     $requirements['php']['description'] = t('Your PHP installation is too old. Drupal requires at least PHP %version.', ['%version' => DRUPAL_MINIMUM_PHP]);
 1012     $requirements['php']['severity'] = REQUIREMENT_ERROR;
 1013   }
 1014 
 1015   // Report cron status
 1016   if ($phase == 'runtime') {
 1017     $cron_last = \Drupal::state()->get('system.cron_last');
 1018 
 1019     if (is_numeric($cron_last)) {
 1020       $requirements['cron']['value'] = t('Last run @time ago', ['@time' => \Drupal::service('date.formatter')->formatTimeDiffSince($cron_last)]);
 1021     }
 1022     else {
 1023       $requirements['cron'] = [
 1024         'description' => t('Cron has not run. It appears cron jobs have not been setup on your system. Check the help pages for <a href=":url">configuring cron jobs</a>.', [':url' => 'https://www.drupal.org/cron']),
 1025         'severity' => REQUIREMENT_ERROR,
 1026         'value' => t('Never run'),
 1027       ];
 1028     }
 1029 
 1030     $requirements['cron']['description'] .= ' ' . t('You can <a href=":cron">run cron manually</a>.', [':cron' => Url::fromRoute('system.run_cron')->toString()]);
 1031 
 1032     $requirements['cron']['title'] = t('Cron maintenance tasks');
 1033   }
 1034 
 1035   return $requirements;
 1036 }
 1037 
 1038 /**
 1039  * @} End of "addtogroup hooks".
 1040  */