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