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