Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • issue/project_browser-3278972
  • issue/project_browser-3240319
  • project/project_browser
  • issue/project_browser-3223747
  • issue/project_browser-3238996
  • issue/project_browser-3279510
  • issue/project_browser-3281209
  • issue/project_browser-3282592
  • issue/project_browser-3282691
  • issue/project_browser-3282681
  • issue/project_browser-3283861
  • issue/project_browser-3279918
  • issue/project_browser-3280627
  • issue/project_browser-3281216
  • issue/project_browser-3281692
  • issue/project_browser-3281891
  • issue/project_browser-3282201
  • issue/project_browser-3282707
  • issue/project_browser-3282732
  • issue/project_browser-3279927
  • issue/project_browser-3280190
  • issue/project_browser-3268626
  • issue/project_browser-3280706
  • issue/project_browser-3281388
  • issue/project_browser-3282777
  • issue/project_browser-3278333
  • issue/project_browser-3280167
  • issue/project_browser-3281252
  • issue/project_browser-3280006
  • issue/project_browser-3281686
  • issue/project_browser-3282698
  • issue/project_browser-3282688
  • issue/project_browser-3283826
  • issue/project_browser-3279676
  • issue/project_browser-3280176
  • issue/project_browser-3281327
  • issue/project_browser-3281624
  • issue/project_browser-3281217
  • issue/project_browser-3281187
  • issue/project_browser-3281200
  • issue/project_browser-3282591
  • issue/project_browser-3282648
  • issue/project_browser-3282705
  • issue/project_browser-3282589
  • issue/project_browser-3282692
  • issue/project_browser-3283683
  • issue/project_browser-3283825
  • issue/project_browser-3283875
  • issue/project_browser-3282709
  • issue/project_browser-3281418
  • issue/project_browser-3281620
  • issue/project_browser-3282499
  • issue/project_browser-3282778
  • issue/project_browser-3282683
  • issue/project_browser-3282700
  • issue/project_browser-3240318
  • issue/project_browser-3240128
  • issue/project_browser-3245770
  • issue/project_browser-3248299
  • issue/project_browser-3240321
  • issue/project_browser-3249483
  • issue/project_browser-3241358
  • issue/project_browser-3238572
  • issue/project_browser-3249958
  • issue/project_browser-3240320
  • issue/project_browser-3250132
  • issue/project_browser-3239477
  • issue/project_browser-3250356
  • issue/project_browser-3250413
  • issue/project_browser-3250454
  • issue/project_browser-3277551
  • issue/project_browser-3258248
  • issue/project_browser-3258247
  • issue/project_browser-3259324
  • issue/project_browser-3259657
  • issue/project_browser-3245948
  • issue/project_browser-3264474
  • issue/project_browser-3267656
  • issue/project_browser-3267658
  • issue/project_browser-3267661
  • issue/project_browser-3268636
  • issue/project_browser-3224709
  • issue/project_browser-3273634
  • issue/project_browser-3274010
  • issue/project_browser-3274277
  • issue/project_browser-3252674
  • issue/project_browser-3274701
  • issue/project_browser-3274520
  • issue/project_browser-3274906
  • issue/project_browser-3275413
  • issue/project_browser-3275536
  • issue/project_browser-3243019
  • issue/project_browser-3274577
  • issue/project_browser-3274335
  • issue/project_browser-3270210
  • issue/project_browser-3277052
  • issue/project_browser-3224896
  • issue/project_browser-3274897
  • issue/project_browser-3277253
  • issue/project_browser-3277260
  • issue/project_browser-3277264
  • issue/project_browser-3277764
  • issue/project_browser-3277808
  • issue/project_browser-3277811
  • issue/project_browser-3277832
  • issue/project_browser-3277224
  • issue/project_browser-3278352
  • issue/project_browser-3277255
  • issue/project_browser-3279663
  • issue/project_browser-3279983
  • issue/project_browser-3280721
  • issue/project_browser-3280765
  • issue/project_browser-3283771
  • issue/project_browser-3284094
  • issue/project_browser-3284233
  • issue/project_browser-3284092
  • issue/project_browser-3284312
  • issue/project_browser-3284321
  • issue/project_browser-3284315
  • issue/project_browser-3284333
  • issue/project_browser-3284325
  • issue/project_browser-3284327
  • issue/project_browser-3284463
  • issue/project_browser-3284330
  • issue/project_browser-3284347
  • issue/project_browser-3284332
  • issue/project_browser-3284631
  • issue/project_browser-3284945
  • issue/project_browser-3284880
  • issue/project_browser-3284341
  • issue/project_browser-3284309
  • issue/project_browser-3281218
  • issue/project_browser-3285889
  • issue/project_browser-3285874
  • issue/project_browser-3285880
  • issue/project_browser-3285878
  • issue/project_browser-3285870
  • issue/project_browser-3285443
  • issue/project_browser-3285879
  • issue/project_browser-3269587
  • issue/project_browser-3291995
  • issue/project_browser-3292019
  • issue/project_browser-3292395
  • issue/project_browser-3292562
  • issue/project_browser-3289165
  • issue/project_browser-3292996
  • issue/project_browser-3293014
  • issue/project_browser-3252678
  • issue/project_browser-3277214
  • issue/project_browser-3293691
  • issue/project_browser-3293694
  • issue/project_browser-3267678
  • issue/project_browser-3267685
  • issue/project_browser-3293909
  • issue/project_browser-3293937
  • issue/project_browser-3293898
  • issue/project_browser-3293905
  • issue/project_browser-3282163
  • issue/project_browser-3293899
  • issue/project_browser-3294763
  • issue/project_browser-3294754
  • issue/project_browser-3247332
  • issue/project_browser-3295320
  • issue/project_browser-3294608
  • issue/project_browser-3287419
  • issue/project_browser-3294576
  • issue/project_browser-3293424
  • issue/project_browser-3296264
  • issue/project_browser-3296324
  • issue/project_browser-3296494
  • issue/project_browser-3296250
  • issue/project_browser-3304245
  • issue/project_browser-3304569
  • issue/project_browser-3298525
  • issue/project_browser-3298575
  • issue/project_browser-3293929
  • issue/project_browser-3298755
  • issue/project_browser-3249550
  • issue/project_browser-3249553
  • issue/project_browser-3282842
  • issue/project_browser-3300093
  • issue/project_browser-3299285
  • issue/project_browser-3300447
  • issue/project_browser-3300262
  • issue/project_browser-3303920
  • issue/project_browser-3305515
  • issue/project_browser-3300735
  • issue/project_browser-3299029
  • issue/project_browser-3300520
  • issue/project_browser-3301498
  • issue/project_browser-3301577
  • issue/project_browser-3300397
  • issue/project_browser-3301989
  • issue/project_browser-3302094
  • issue/project_browser-3241731
  • issue/project_browser-3305551
  • issue/project_browser-3303328
  • issue/project_browser-3305983
  • issue/project_browser-3306162
  • issue/project_browser-3310703
  • issue/project_browser-3310725
  • issue/project_browser-3310876
  • issue/project_browser-3310884
  • issue/project_browser-3306717
  • issue/project_browser-3307512
  • issue/project_browser-3307674
  • issue/project_browser-3307917
  • issue/project_browser-3306714
  • issue/project_browser-3308068
  • issue/project_browser-3303496
  • issue/project_browser-3306722
  • issue/project_browser-3308522
  • issue/project_browser-3308525
  • issue/project_browser-3310864
  • issue/project_browser-3310877
  • issue/project_browser-3310898
  • issue/project_browser-3311370
  • issue/project_browser-3293977
  • issue/project_browser-3310893
  • issue/project_browser-3310874
  • issue/project_browser-3271591
  • issue/project_browser-3300090
  • issue/project_browser-3311763
  • issue/project_browser-3304183
  • issue/project_browser-3303522
  • issue/project_browser-3311980
  • issue/project_browser-3311992
  • issue/project_browser-3311978
  • issue/project_browser-3303520
  • issue/project_browser-3312289
  • issue/project_browser-3312537
  • issue/project_browser-3310882
  • issue/project_browser-3282338
  • issue/project_browser-3314210
  • issue/project_browser-3310896
  • issue/project_browser-3315866
  • issue/project_browser-3315853
  • issue/project_browser-3314520
  • issue/project_browser-3303373
  • issue/project_browser-3314728
  • issue/project_browser-3313292
  • issue/project_browser-3300350
  • issue/project_browser-3315867
  • issue/project_browser-3315860
  • issue/project_browser-3315854
  • issue/project_browser-3315858
  • issue/project_browser-3315859
  • issue/project_browser-3310906
  • issue/project_browser-3310903
  • issue/project_browser-3316454
  • issue/project_browser-3316740
  • issue/project_browser-3316744
  • issue/project_browser-3316820
  • issue/project_browser-3316852
  • issue/project_browser-3318442
  • issue/project_browser-3318732
  • issue/project_browser-3318789
  • issue/project_browser-3318905
  • issue/project_browser-3327323
  • issue/project_browser-3325409
  • issue/project_browser-3326049
  • issue/project_browser-3318794
  • issue/project_browser-3316357
  • issue/project_browser-3320295
  • issue/project_browser-3319785
  • issue/project_browser-3316998
  • issue/project_browser-3326245
  • issue/project_browser-3327400
  • issue/project_browser-3327684
  • issue/project_browser-3328136
  • issue/project_browser-3323354
  • issue/project_browser-3325630
  • issue/project_browser-3325658
  • issue/project_browser-3316162
  • issue/project_browser-3318750
  • issue/project_browser-3323531
  • issue/project_browser-3324905
  • issue/project_browser-3322594
  • issue/project_browser-3321703
  • issue/project_browser-3318791
  • issue/project_browser-3277506
  • issue/project_browser-3322164
  • issue/project_browser-3321698
  • issue/project_browser-3317264
  • issue/project_browser-3325657
  • issue/project_browser-3315862
  • issue/project_browser-3329644
  • issue/project_browser-3328124
  • issue/project_browser-3329861
  • issue/project_browser-3330071
  • issue/project_browser-3330102
  • issue/project_browser-3329889
  • issue/project_browser-3330128
  • issue/project_browser-3330129
  • issue/project_browser-3330122
  • issue/project_browser-3330124
  • issue/project_browser-3330887
  • issue/project_browser-3330123
  • issue/project_browser-3330116
  • issue/project_browser-3330130
  • issue/project_browser-3330133
  • issue/project_browser-3332968
  • issue/project_browser-3333456
  • issue/project_browser-3334585
  • issue/project_browser-3304184
  • issue/project_browser-3338357
  • issue/project_browser-3342535
  • issue/project_browser-3340133
  • issue/project_browser-3338356
  • issue/project_browser-3330235
  • issue/project_browser-3341230
  • issue/project_browser-3342128
  • issue/project_browser-3342218
  • issue/project_browser-3345607
  • issue/project_browser-3348249
  • issue/project_browser-3351987
  • issue/project_browser-3348781
  • issue/project_browser-3348872
  • issue/project_browser-3351137
  • issue/project_browser-3353355
  • issue/project_browser-3353483
  • issue/project_browser-3354450
  • issue/project_browser-3356614
  • issue/project_browser-3356685
  • issue/project_browser-3303190
  • issue/project_browser-3359678
  • issue/project_browser-3361123
  • issue/project_browser-3311503
  • issue/project_browser-3364776
  • issue/project_browser-3365345
  • issue/project_browser-3365350
  • issue/project_browser-3318726
  • issue/project_browser-3309273
  • issue/project_browser-3303381
  • issue/project_browser-3360062
  • issue/project_browser-3365404
  • issue/project_browser-3359980
  • issue/project_browser-3323860
  • issue/project_browser-3365180
  • issue/project_browser-3249549
  • issue/project_browser-3365678
  • issue/project_browser-3370284
  • issue/project_browser-3404483
  • issue/project_browser-3365435
  • issue/project_browser-3402908
  • issue/project_browser-3372796
  • issue/project_browser-3357036
  • issue/project_browser-3375619
  • issue/project_browser-3376206
  • issue/project_browser-3376201
  • issue/project_browser-3376202
  • issue/project_browser-3376203
  • issue/project_browser-3376208
  • issue/project_browser-3357003
  • issue/project_browser-3376291
  • issue/project_browser-3382457
  • issue/project_browser-3348761
  • issue/project_browser-3376160
  • issue/project_browser-3348960
  • issue/project_browser-3389246
  • issue/project_browser-3389250
  • issue/project_browser-3310908
  • issue/project_browser-3394166
  • issue/project_browser-3394570
  • issue/project_browser-3394904
  • issue/project_browser-3395472
  • issue/project_browser-3395480
  • issue/project_browser-3360033
  • issue/project_browser-3395478
  • issue/project_browser-3360063
  • issue/project_browser-3365392
  • issue/project_browser-3396245
  • issue/project_browser-3437724
  • issue/project_browser-3343805
  • issue/project_browser-3409134
  • issue/project_browser-3436249
  • issue/project_browser-3444662
  • issue/project_browser-3410505
  • issue/project_browser-3410797
  • issue/project_browser-3410947
  • issue/project_browser-3419177
  • issue/project_browser-3413564
  • issue/project_browser-3413763
  • issue/project_browser-3415079
  • issue/project_browser-3413567
  • issue/project_browser-3312354
  • issue/project_browser-3418454
  • issue/project_browser-3419925
  • issue/project_browser-3413498
  • issue/project_browser-3420501
  • issue/project_browser-3420552
  • issue/project_browser-3421211
  • issue/project_browser-3421699
  • issue/project_browser-3423695
  • issue/project_browser-3423697
  • issue/project_browser-3423915
  • issue/project_browser-3423429
  • issue/project_browser-3423442
  • issue/project_browser-3425989
  • issue/project_browser-3426658
  • issue/project_browser-3365103
  • issue/project_browser-3318817
  • issue/project_browser-3426767
  • issue/project_browser-3443929
  • issue/project_browser-3443930
  • issue/project_browser-3444658
  • issue/project_browser-3446591
  • issue/project_browser-3445765
  • issue/project_browser-3426094
  • issue/project_browser-3443943
  • issue/project_browser-3446092
  • issue/project_browser-3348954
  • issue/project_browser-3446604
  • issue/project_browser-3446414
  • issue/project_browser-3312056
  • issue/project_browser-3446109
  • issue/project_browser-3446257
  • issue/project_browser-3446416
  • issue/project_browser-3445811
  • issue/project_browser-3437721
  • issue/project_browser-3436529
  • issue/project_browser-3446322
  • issue/project_browser-3446528
  • issue/project_browser-3441425
  • issue/project_browser-3427491
  • issue/project_browser-3447377
  • issue/project_browser-3447420
  • issue/project_browser-3447764
  • issue/project_browser-3448808
  • issue/project_browser-3450499
  • issue/project_browser-3451142
  • issue/project_browser-3451659
  • issue/project_browser-3446161
  • issue/project_browser-3451863
  • issue/project_browser-3452431
  • issue/project_browser-3452504
  • issue/project_browser-3452541
  • issue/project_browser-3452737
  • issue/project_browser-3452787
  • issue/project_browser-3452784
  • issue/project_browser-3453039
  • issue/project_browser-3453101
  • issue/project_browser-3453437
  • issue/project_browser-3453766
  • issue/project_browser-3453775
  • issue/project_browser-3453794
  • issue/project_browser-3453808
  • issue/project_browser-3453997
  • issue/project_browser-3454248
  • issue/project_browser-3453738
  • issue/project_browser-3454294
  • issue/project_browser-3455152
  • issue/project_browser-3455284
  • issue/project_browser-3455215
  • issue/project_browser-3455220
  • issue/project_browser-3455477
  • issue/project_browser-3455485
  • issue/project_browser-3455210
  • issue/project_browser-3455715
  • issue/project_browser-3455917
  • issue/project_browser-3365434
  • issue/project_browser-3457003
  • issue/project_browser-3457054
  • issue/project_browser-3457376
  • issue/project_browser-3457682
  • issue/project_browser-3458287
  • issue/project_browser-3371084
  • issue/project_browser-3458765
  • issue/project_browser-3457972
  • issue/project_browser-3452435
  • issue/project_browser-3459662
  • issue/project_browser-3460033
  • issue/project_browser-3454873
  • issue/project_browser-3459288
  • issue/project_browser-3460938
  • issue/project_browser-3461670
  • issue/project_browser-3461518
  • issue/project_browser-3461892
  • issue/project_browser-3461879
  • issue/project_browser-3462173
  • issue/project_browser-3461340
  • issue/project_browser-3463833
  • issue/project_browser-3464077
  • issue/project_browser-3464450
  • issue/project_browser-3461037
  • issue/project_browser-3464794
  • issue/project_browser-3465046
  • issue/project_browser-3450629
  • issue/project_browser-3293907
  • issue/project_browser-3466307
  • issue/project_browser-3458908
  • issue/project_browser-3465232
  • issue/project_browser-3467911
  • issue/project_browser-3458844
  • issue/project_browser-3456978
  • issue/project_browser-3471232
  • issue/project_browser-3472206
  • issue/project_browser-3472230
  • issue/project_browser-3469490
  • issue/project_browser-3472231
  • issue/project_browser-3470540
  • issue/project_browser-3475056
  • issue/project_browser-3475852
  • issue/project_browser-3476400
  • issue/project_browser-3472334
  • issue/project_browser-3476717
  • issue/project_browser-3476812
  • issue/project_browser-3476887
  • issue/project_browser-3477288
  • issue/project_browser-3476818
  • issue/project_browser-3477314
  • issue/project_browser-3477343
  • issue/project_browser-3477232
  • issue/project_browser-3477231
  • issue/project_browser-3478295
  • issue/project_browser-3478832
  • issue/project_browser-3477335
  • issue/project_browser-3478994
  • issue/project_browser-3478437
  • issue/project_browser-3479219
  • issue/project_browser-3477238
  • issue/project_browser-3480064
  • issue/project_browser-3469552
  • issue/project_browser-3479907
  • issue/project_browser-3481084
  • issue/project_browser-3458840
  • issue/project_browser-3483725
  • issue/project_browser-3495318
  • issue/project_browser-3495328
  • issue/project_browser-3496059
  • issue/project_browser-3495317
  • issue/project_browser-3485108
  • issue/project_browser-3476807
  • issue/project_browser-3485386
  • issue/project_browser-3486091
  • issue/project_browser-3485747
  • issue/project_browser-3487842
  • issue/project_browser-3487834
  • issue/project_browser-3487868
  • issue/project_browser-3426179
  • issue/project_browser-3457378
  • issue/project_browser-3462307
  • issue/project_browser-3487835
  • issue/project_browser-3488078
  • issue/project_browser-3488141
  • issue/project_browser-3479924
  • issue/project_browser-3487960
  • issue/project_browser-3486291
  • issue/project_browser-3469860
  • issue/project_browser-3480098
  • issue/project_browser-3489028
  • issue/project_browser-3446603
  • issue/project_browser-3489573
  • issue/project_browser-3489665
  • issue/project_browser-3481652
  • issue/project_browser-3489810
  • issue/project_browser-3489827
  • issue/project_browser-3477950
  • issue/project_browser-3490176
  • issue/project_browser-3489972
  • issue/project_browser-3489126
  • issue/project_browser-3484474
  • issue/project_browser-3491232
  • issue/project_browser-3489422
  • issue/project_browser-3492153
  • issue/project_browser-3483412
  • issue/project_browser-3492108
  • issue/project_browser-3492209
  • issue/project_browser-3488156
  • issue/project_browser-3493332
  • issue/project_browser-3489729
  • issue/project_browser-3493778
  • issue/project_browser-3489054
  • issue/project_browser-3494672
  • issue/project_browser-3494858
  • issue/project_browser-3457966
  • issue/project_browser-3494506
  • issue/project_browser-3494655
  • issue/project_browser-3494978
  • issue/project_browser-3495112
  • issue/project_browser-3494818
  • issue/project_browser-3495168
  • issue/project_browser-3495211
  • issue/project_browser-3495330
  • issue/project_browser-3494819
  • issue/project_browser-3492262
  • issue/project_browser-3497778
  • issue/project_browser-3496236
  • issue/project_browser-3498040
  • issue/project_browser-3498231
  • issue/project_browser-3494512
  • issue/project_browser-3498267
  • issue/project_browser-3493916
  • issue/project_browser-3498560
  • issue/project_browser-3498835
  • issue/project_browser-3498901
  • issue/project_browser-3499390
  • issue/project_browser-3499406
  • issue/project_browser-3500024
  • issue/project_browser-3501036
  • issue/project_browser-3501194
  • issue/project_browser-3498564
  • issue/project_browser-3501590
  • issue/project_browser-3498562
  • issue/project_browser-3499411
  • issue/project_browser-3501766
  • issue/project_browser-3501455
  • issue/project_browser-3501453
  • issue/project_browser-3502161
  • issue/project_browser-3498570
  • issue/project_browser-3502465
  • issue/project_browser-3502399
  • issue/project_browser-3502612
  • issue/project_browser-3502645
  • issue/project_browser-3502666
  • issue/project_browser-3502643
  • issue/project_browser-3502604
  • issue/project_browser-3502850
  • issue/project_browser-3502918
  • issue/project_browser-3487845
  • issue/project_browser-3502935
  • issue/project_browser-3502986
  • issue/project_browser-3503148
  • issue/project_browser-3503140
  • issue/project_browser-3503197
  • issue/project_browser-3502854
  • issue/project_browser-3503137
  • issue/project_browser-3502603
  • issue/project_browser-3497909
  • issue/project_browser-3504656
  • issue/project_browser-3504781
  • issue/project_browser-3504960
  • issue/project_browser-3504997
  • issue/project_browser-3504665
  • issue/project_browser-3505152
  • issue/project_browser-3494824
  • issue/project_browser-3502734
  • issue/project_browser-3505188
  • issue/project_browser-3505249
  • issue/project_browser-3505285
  • issue/project_browser-3505450
  • issue/project_browser-3505607
  • issue/project_browser-3505608
  • issue/project_browser-3505592
  • issue/project_browser-3505700
  • issue/project_browser-3322601
  • issue/project_browser-3505837
  • issue/project_browser-3506252
  • issue/project_browser-3506178
  • issue/project_browser-3453724
  • issue/project_browser-3506517
  • issue/project_browser-3506511
  • issue/project_browser-3505159
  • issue/project_browser-3506547
  • issue/project_browser-3506557
  • issue/project_browser-3506377
  • issue/project_browser-3506454
  • issue/project_browser-3504655
  • issue/project_browser-3507468
  • issue/project_browser-3507536
  • issue/project_browser-3507922
  • issue/project_browser-3508090
  • issue/project_browser-3508182
  • issue/project_browser-3508334
  • issue/project_browser-3508547
  • issue/project_browser-3508350
  • issue/project_browser-3508631
  • issue/project_browser-3508786
  • issue/project_browser-3508956
  • issue/project_browser-3509170
  • issue/project_browser-3509222
  • issue/project_browser-3509184
  • issue/project_browser-3509242
  • issue/project_browser-3506513
  • issue/project_browser-3508906
  • issue/project_browser-3508971
  • issue/project_browser-3508969
  • issue/project_browser-3509375
  • issue/project_browser-3509380
  • issue/project_browser-3509449
  • issue/project_browser-3509499
  • issue/project_browser-3510420
  • issue/project_browser-3509730
  • issue/project_browser-3509217
  • issue/project_browser-3509733
  • issue/project_browser-3510642
  • issue/project_browser-3510506
  • issue/project_browser-3510796
  • issue/project_browser-3511079
  • issue/project_browser-3509162
  • issue/project_browser-3509674
  • issue/project_browser-3511104
  • issue/project_browser-3511069
  • issue/project_browser-3511080
  • issue/project_browser-3506565
  • issue/project_browser-3511246
  • issue/project_browser-3511417
  • issue/project_browser-3511994
  • issue/project_browser-3511927
  • issue/project_browser-3511942
  • issue/project_browser-3512609
  • issue/project_browser-3512610
  • issue/project_browser-3512781
  • issue/project_browser-3512785
  • issue/project_browser-3512856
  • issue/project_browser-3509738
  • issue/project_browser-3504664
707 results
Show changes
Commits on Source (144)
Showing
with 1379 additions and 379 deletions
......@@ -10,3 +10,7 @@ tabwise
sophron
BOLDRED
NOCHANGES
CURLOPT
RETURNTRANSFER
varchar
techdebt
......@@ -39,6 +39,13 @@ include:
- '/includes/include.drupalci.variables.yml'
- '/includes/include.drupalci.workflows.yml'
stages:
- development
- build
- validate
- test
- publish
################
# Pipeline configuration variables
#
......@@ -49,6 +56,7 @@ include:
variables:
# For parallel running, needs more CPU resources.
KUBERNETES_CPU_REQUEST: 16
OPT_IN_TEST_PREVIOUS_MAJOR: '1'
OPT_IN_TEST_NEXT_MAJOR: '1'
# These two variables allow PHPUnit to run in a parallel job matrix.
_PHPUNIT_CONCURRENT: '1'
......@@ -59,6 +67,49 @@ variables:
OPT_IN_TEST_NEXT_MINOR: 1
OPT_IN_TEST_MAX_PHP: 1
# @todo Remove when https://www.drupal.org/project/gitlab_templates/issues/3452183 lands.
.is-push-rule: &is-push-rule
if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_ROOT_NAMESPACE == "project"
.manual-rule: &manual-rule
- when: manual
allow_failure: true
# @todo Remove when https://www.drupal.org/project/gitlab_templates/issues/3452183 lands.
.php-files-change-rule: &php-files-change-rule
- changes:
- "**/*.{php,module,inc,install,theme,profile}"
when: on_success
# @todo Remove when https://www.drupal.org/project/gitlab_templates/issues/3452183 lands.
.css-files-change-rule: &css-files-change-rule
- changes:
- "**/*.css"
when: on_success
# @todo Remove when https://www.drupal.org/project/gitlab_templates/issues/3452183 lands.
.module-metadata-files-change-rule: &module-metadata-files-change-rule
- changes:
- "**/*.yml"
when: on_success
# @todo Remove when https://www.drupal.org/project/gitlab_templates/issues/3452183 lands.
.module-config-files-change-rule: &module-config-files-change-rule
- changes:
# config schema and/or default config
- config
when: on_success
# @todo Remove when https://www.drupal.org/project/gitlab_templates/issues/3452183 lands.
composer-lint:
rules:
- *is-push-rule
- *php-files-change-rule
- changes:
- composer.json
when: on_success
- *manual-rule
################
# Require composer checks to pass.
################
......@@ -84,6 +135,50 @@ stylelint:
################
phpcs:
allow_failure: false
# @todo Remove when https://www.drupal.org/project/gitlab_templates/issues/3452183 lands.
rules:
- *is-push-rule
- *php-files-change-rule
# Also run whenever we catch up to the upstream PHPCS rules.
- changes:
- core.phpcs.xml.dist
when: on_success
- *manual-rule
phpcs-rules-match-drupal-11:
stage: development
script:
- |
# Download the file from the Drupal repository
curl -o drupal_core_phpcs.xml.dist https://git.drupalcode.org/project/drupal/-/raw/11.x/core/phpcs.xml.dist?ref_type=heads
# Check if the download was successful
if [ $? -ne 0 ]; then
echo "🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥"
echo "Error: Failed to download $DRUPAL_URL"
exit 1
fi
# Compare the downloaded file with the local file using a subshell to prevent premature exit
echo "Comparing downloaded file with local file..."
# With uses the braces the job just ends here for some reason.
{
diff drupal_core_phpcs.xml.dist core.phpcs.xml.dist
DIFF_EXIT_CODE=$?
} || true
if [ $DIFF_EXIT_CODE -ne 0 ]; then
echo "🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥"
echo "Error: core.phpcs.xml.dist not up to date with Drupal 11.x core/phpcs.xml.dist. Please create an issue to update this file."
else
echo "👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍"
echo "core.phpcs.xml.dist is up to date with Drupal 11.x core/phpcs.xml.dist"
fi
# Exit with the exit code of the diff command
exit $DIFF_EXIT_CODE
# Allow this to fail, to avoid disrupting XB's CI when upstream changes.
allow_failure: true
################
# Require phpstan checks to pass.
......@@ -177,3 +272,12 @@ phpunit:
phpunit (next major):
# Require us to be compatible with the next major version of core.
allow_failure: false
phpstan (previous major):
extends: phpstan
rules:
- !reference [ .opt-in-previous-major-rule ]
- !reference [ .skip-phpstan-rule ]
- !reference [ .phpstan-allow-failure-rule ]
needs:
- 'composer (previous major)'
......@@ -14,10 +14,11 @@
"require-dev": {
"colinodell/psr-testlogger": "^1.2",
"drupal/automatic_updates": "^3.1.3",
"kanopi/imagemagick-configuration": "@dev"
"drush/drush": "^12.5 || ^13"
},
"conflict": {
"drupal/automatic_updates": "<3.0"
"drupal/automatic_updates": "<3.0",
"drupal/gin": "<4.0.6"
},
"config": {
"optimize-autoloader": true,
......
enabled_sources:
- drupalorg_jsonapi
- recipes
allow_ui_install: false
allowed_projects: {}
max_selections: null
......@@ -22,3 +22,47 @@ project_browser.admin_settings:
label: 'Project identifier'
constraints:
NotBlank: []
max_selections:
type: integer
nullable: true
label: 'The maximum number of projects that can be chosen for installation at once. Internal use only.'
block.settings.project_browser_block:*:
type: block_settings
label: 'Project Browser block settings'
constraints:
FullyValidatable: ~
mapping:
paginate:
type: boolean
label: 'Enable pagination'
page_sizes:
type: string
label: 'Page sizes'
constraints:
# A comma-separated list of numbers with fuzzy spacing, e.g. `32, 64,88`.
Regex: '/^([0-9]+\s*,?\s*)+$/'
sort_options:
type: sequence
label: 'Sort options'
nullable: true
sequence:
type: string
label: 'Sort option ID'
constraints:
NotBlank: []
default_sort:
type: string
label: 'Default sort criterion'
nullable: true
constraints:
NotBlank: []
filters:
type: sequence
label: 'Enabled filters'
nullable: true
sequence:
type: string
label: 'Filter ID'
constraints:
NotBlank: []
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="drupal_core">
<arg name="extensions" value="engine,inc,install,module,php,profile,test,theme,yml"/>
<description>Default PHP CodeSniffer configuration for Drupal core.</description>
<!--Exclude folders used by common frontend tools. These folders match the file_scan_ignore_directories setting in default.settings.php-->
<exclude-pattern>*/bower_components/*</exclude-pattern>
<exclude-pattern>*/node_modules/*</exclude-pattern>
<!--Exclude third party code.-->
<exclude-pattern>./assets/vendor/*</exclude-pattern>
<!--Exclude the PHPStan baseline and temp dir from coding standards.-->
<exclude-pattern>./core/.phpstan-baseline.php</exclude-pattern>
<!-- Exclude third-party code maintained within core that does not follow our standards. -->
<!-- @todo This rule may be removed when https://www.drupal.org/node/1848264 is resolved. -->
<exclude-pattern>./core/lib/Drupal/Component/Diff/</exclude-pattern>
<exclude-pattern>./core/phpstan-tmp/*</exclude-pattern>
<exclude-pattern>./core/tests/Drupal/Tests/Component/Annotation/Doctrine/</exclude-pattern>
<!--Exclude test files that are intentionally empty, or intentionally violate coding standards.-->
<exclude-pattern>./modules/system/tests/fixtures/HtaccessTest</exclude-pattern>
<file>.</file>
<file>../composer</file>
<file>scripts/password-hash.sh</file>
<file>scripts/rebuild_token_calculator.sh</file>
<file>scripts/run-tests.sh</file>
<file>scripts/update-countries.sh</file>
<!-- Only include specific sniffs that pass. This ensures that, if new sniffs are added, HEAD does not fail.-->
<!-- Drupal sniffs -->
<rule ref="Drupal.Arrays.Array"/>
<rule ref="Drupal.Arrays.Array.LongLineDeclaration">
<include-pattern>core/lib/*</include-pattern>
<include-pattern>core/modules/*/tests/modules/*</include-pattern>
</rule>
<rule ref="Drupal.CSS.ClassDefinitionNameSpacing"/>
<rule ref="Drupal.CSS.ColourDefinition"/>
<rule ref="Drupal.Classes.ClassCreateInstance"/>
<rule ref="Drupal.Classes.ClassDeclaration"/>
<rule ref="Drupal.Classes.ClassFileName"/>
<rule ref="Drupal.Classes.FullyQualifiedNamespace"/>
<rule ref="Drupal.Classes.InterfaceName"/>
<rule ref="Drupal.Classes.PropertyDeclaration"/>
<rule ref="Drupal.Classes.UnusedUseStatement"/>
<rule ref="Drupal.Classes.UseGlobalClass"/>
<rule ref="Drupal.Classes.UseLeadingBackslash"/>
<rule ref="Drupal.Commenting.ClassComment"/>
<rule ref="Drupal.Commenting.ClassComment.Missing">
<include-pattern>*/Functional/*</include-pattern>
<include-pattern>*/tests/modules/*</include-pattern>
<include-pattern>./core/tests/Drupal/Tests/Core/*</include-pattern>
<include-pattern>./core/modules/*</include-pattern>
</rule>
<rule ref="Drupal.Commenting.DataTypeNamespace"/>
<rule ref="Drupal.Commenting.Deprecated"/>
<rule ref="Drupal.Commenting.DocComment">
<!-- Sniff for these errors: SpacingAfterTagGroup, WrongEnd, SpacingBetween,
ContentAfterOpen, SpacingBeforeShort, TagValueIndent, ShortStartSpace,
SpacingAfter, LongNotCapital, ShortFullStop, TagGroupSpacing, Empty,
TagsNotGrouped, ParamGroup -->
<exclude name="Drupal.Commenting.DocComment.LongFullStop"/>
<exclude name="Drupal.Commenting.DocComment.MissingShort"/>
</rule>
<rule ref="Drupal.Commenting.DocCommentAlignment"/>
<rule ref="Drupal.Commenting.DocCommentLongArraySyntax"/>
<rule ref="Drupal.Commenting.DocCommentStar"/>
<rule ref="Drupal.Commenting.FileComment"/>
<rule ref="Drupal.Commenting.FunctionComment"/>
<rule ref="Drupal.Commenting.FunctionComment.Missing">
<include-pattern>core/modules/*/Plugin/views/argument/*</include-pattern>
<include-pattern>core/modules/*/Plugin/views/filter/*</include-pattern>
<include-pattern>core/modules/*/Plugin/views/access/*</include-pattern>
<include-pattern>core/modules/*/Plugin/views/cache/*</include-pattern>
<include-pattern>core/modules/*/Plugin/views/query/*</include-pattern>
<include-pattern>core/modules/*/Plugin/views/sort/*</include-pattern>
<include-pattern>core/modules/*/Plugin/views/display/*</include-pattern>
<include-pattern>core/modules/*/Plugin/views/exposed_form/*</include-pattern>
<include-pattern>core/modules/*/Plugin/views/field/*</include-pattern>
<include-pattern>core/modules/*/Plugin/views/pager/*</include-pattern>
<include-pattern>core/modules/*/Plugin/views/style/*</include-pattern>
<include-pattern>*/Database/*</include-pattern>
<include-pattern>*/FunctionalJavascript/*</include-pattern>
<include-pattern>*/Kernel/*</include-pattern>
<include-pattern>*/Functional/*</include-pattern>
</rule>
<rule ref="Drupal.Commenting.FunctionComment.MissingParamType"/>
<rule ref="Drupal.Commenting.FunctionComment.MissingReturnComment">
<include-pattern>core/lib/Drupal/Core/*</include-pattern>
<include-pattern>core/lib/Drupal/Component/*</include-pattern>
<include-pattern>core/tests/*</include-pattern>
<include-pattern>core/*/tests/*</include-pattern>
</rule>
<rule ref="Drupal.Commenting.GenderNeutralComment"/>
<rule ref="Drupal.Commenting.HookComment"/>
<rule ref="Drupal.Commenting.InlineComment">
<!-- Sniff for: NoSpaceBefore, SpacingBefore, WrongStyle -->
<exclude name="Drupal.Commenting.InlineComment.InvalidEndChar"/>
<exclude name="Drupal.Commenting.InlineComment.SpacingAfter"/>
</rule>
<rule ref="Drupal.Commenting.InlineVariableComment"/>
<rule ref="Drupal.Commenting.PostStatementComment"/>
<rule ref="Drupal.Commenting.TodoComment" />
<rule ref="Drupal.Commenting.VariableComment"/>
<rule ref="Drupal.ControlStructures.ControlSignature"/>
<rule ref="Drupal.ControlStructures.ElseIf"/>
<rule ref="Drupal.ControlStructures.InlineControlStructure"/>
<rule ref="Drupal.Files.EndFileNewline"/>
<rule ref="Drupal.Files.FileEncoding"/>
<rule ref="Drupal.Files.TxtFileLineLength"/>
<rule ref="Drupal.Formatting.MultiLineAssignment"/>
<rule ref="Drupal.Formatting.MultipleStatementAlignment"/>
<rule ref="Drupal.Formatting.SpaceInlineIf"/>
<rule ref="Drupal.Formatting.SpaceUnaryOperator"/>
<rule ref="Drupal.Functions.DiscouragedFunctions"/>
<rule ref="Drupal.Functions.FunctionDeclaration"/>
<rule ref="Drupal.Functions.MultiLineFunctionDeclaration"/>
<rule ref="Drupal.InfoFiles.AutoAddedKeys"/>
<rule ref="Drupal.InfoFiles.ClassFiles"/>
<rule ref="Drupal.InfoFiles.DuplicateEntry"/>
<rule ref="Drupal.InfoFiles.Required"/>
<rule ref="Drupal.Methods.MethodDeclaration">
<!-- Silence method name underscore warning which is covered already in
Drupal.NamingConventions.ValidFunctionName.ScopeNotCamelCaps. -->
<exclude name="Drupal.Methods.MethodDeclaration.Underscore"/>
</rule>
<rule ref="Drupal.NamingConventions.ValidClassName"/>
<rule ref="Drupal.NamingConventions.ValidGlobal"/>
<rule ref="Drupal.NamingConventions.ValidVariableName"/>
<rule ref="Drupal.NamingConventions.ValidVariableName.LowerCamelName"/>
<rule ref="Drupal.Scope.MethodScope"/>
<rule ref="Drupal.Semantics.ConstantName.ConstantStart"/>
<rule ref="Drupal.Semantics.EmptyInstall"/>
<rule ref="Drupal.Semantics.FunctionAlias"/>
<rule ref="Drupal.Semantics.FunctionT"/>
<rule ref="Drupal.Semantics.FunctionTriggerError"/>
<rule ref="Drupal.Semantics.FunctionWatchdog"/>
<rule ref="Drupal.Semantics.InstallHooks"/>
<rule ref="Drupal.Semantics.LStringTranslatable"/>
<rule ref="Drupal.Semantics.PregSecurity"/>
<rule ref="Drupal.Semantics.RemoteAddress"/>
<rule ref="Drupal.Semantics.TInHookMenu"/>
<rule ref="Drupal.Semantics.TInHookSchema"/>
<rule ref="Drupal.Strings.UnnecessaryStringConcat"/>
<rule ref="Drupal.WhiteSpace.CloseBracketSpacing"/>
<rule ref="Drupal.WhiteSpace.Comma"/>
<rule ref="Drupal.WhiteSpace.EmptyLines"/>
<rule ref="Drupal.WhiteSpace.Namespace"/>
<rule ref="Drupal.WhiteSpace.ObjectOperatorIndent"/>
<rule ref="Drupal.WhiteSpace.ObjectOperatorSpacing"/>
<rule ref="Drupal.WhiteSpace.OpenBracketSpacing"/>
<rule ref="Drupal.WhiteSpace.OpenTagNewline"/>
<rule ref="Drupal.WhiteSpace.ScopeClosingBrace"/>
<rule ref="Drupal.WhiteSpace.ScopeIndent"/>
<!-- Drupal Practice sniffs -->
<rule ref="DrupalPractice.CodeAnalysis.VariableAnalysis">
<!-- Do not run this sniff on API files or transliteration data. -->
<exclude-pattern>*.api.php</exclude-pattern>
<exclude-pattern>core/lib/Drupal/Component/Transliteration/data/*.php</exclude-pattern>
<properties>
<property name="allowUnusedFunctionParameters" value="true"/>
</properties>
</rule>
<rule ref="DrupalPractice.CodeAnalysis.VariableAnalysis.UndefinedUnsetVariable">
<severity>0</severity>
</rule>
<rule ref="DrupalPractice.CodeAnalysis.VariableAnalysis.UndefinedVariable">
<!-- Setting severity to 0 to completely disable an error message in this sniff, without excluding the whole sniff -->
<!-- See https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options#changing-the-default-severity-levels -->
<severity>0</severity>
</rule>
<rule ref="DrupalPractice.Commenting.ExpectedException"/>
<rule ref="DrupalPractice.General.ExceptionT"/>
<rule ref="DrupalPractice.InfoFiles.NamespacedDependency"/>
<rule ref="DrupalPractice.Objects.GlobalFunction"/>
<!-- Generic sniffs -->
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
<rule ref="Generic.CodeAnalysis.EmptyPHPStatement"/>
<rule ref="Generic.Files.ByteOrderMark"/>
<rule ref="Generic.Files.LineEndings"/>
<rule ref="Generic.Formatting.DisallowMultipleStatements"/>
<rule ref="Generic.Formatting.SpaceAfterCast"/>
<rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
<rule ref="Generic.NamingConventions.ConstructorName"/>
<rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
<rule ref="Generic.PHP.DeprecatedFunctions"/>
<rule ref="Generic.PHP.DisallowShortOpenTag"/>
<rule ref="Generic.PHP.LowerCaseKeyword"/>
<rule ref="Generic.PHP.UpperCaseConstant"/>
<rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
<!-- Internal sniffs -->
<rule ref="Internal.NoCodeFound">
<!-- No PHP code in *.yml -->
<exclude-pattern>*.yml</exclude-pattern>
</rule>
<!-- MySource sniffs -->
<rule ref="MySource.Debug.DebugCode"/>
<!-- PEAR sniffs -->
<rule ref="PEAR.Files.IncludingFile"/>
<!-- Disable some error messages that we do not want. -->
<rule ref="PEAR.Files.IncludingFile.UseInclude">
<severity>0</severity>
</rule>
<rule ref="PEAR.Files.IncludingFile.UseIncludeOnce">
<severity>0</severity>
</rule>
<rule ref="PEAR.Files.IncludingFile.UseRequire">
<severity>0</severity>
</rule>
<rule ref="PEAR.Files.IncludingFile.UseRequireOnce">
<severity>0</severity>
</rule>
<rule ref="PEAR.Functions.FunctionCallSignature"/>
<!-- The sniffs inside PEAR.Functions.FunctionCallSignature silenced below are
also silenced in Drupal CS' ruleset.xml. The code below is a 1-on-1 copy
from that file. -->
<rule ref="PEAR.Functions.FunctionCallSignature.CloseBracketLine">
<severity>0</severity>
</rule>
<rule ref="PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket">
<severity>0</severity>
</rule>
<rule ref="PEAR.Functions.FunctionCallSignature.EmptyLine">
<severity>0</severity>
</rule>
<!-- Disable some error messages that we do not want. -->
<rule ref="PEAR.Functions.FunctionCallSignature.Indent">
<severity>0</severity>
</rule>
<rule ref="PEAR.Functions.FunctionCallSignature.OpeningIndent">
<severity>0</severity>
</rule>
<!-- Disable some error messages that we already cover. -->
<rule ref="PEAR.Functions.FunctionCallSignature.SpaceAfterOpenBracket">
<severity>0</severity>
</rule>
<rule ref="PEAR.Functions.FunctionCallSignature.SpaceBeforeCloseBracket">
<severity>0</severity>
</rule>
<rule ref="PEAR.Functions.ValidDefaultValue"/>
<!-- PSR-2 sniffs -->
<rule ref="PSR2.Classes.PropertyDeclaration">
<!-- Silence method name underscore warning which is covered already in
Drupal.Classes.PropertyDeclaration. -->
<exclude name="PSR2.Classes.PropertyDeclaration.Underscore"/>
</rule>
<rule ref="PSR2.Namespaces.NamespaceDeclaration"/>
<rule ref="PSR2.Namespaces.UseDeclaration"/>
<!-- SlevomatCodingStandard sniffs -->
<rule ref="SlevomatCodingStandard.Classes.BackedEnumTypeSpacing"/>
<rule ref="SlevomatCodingStandard.Commenting.ForbiddenAnnotations">
<properties>
<property name="forbiddenAnnotations" type="array">
<element value="@inheritDoc"/>
<element value="@inheritdoc"/>
<element value="@returns"/>
</property>
</properties>
</rule>
<rule ref="SlevomatCodingStandard.Commenting.ForbiddenComments">
<properties>
<property name="forbiddenCommentPatterns" type="array">
<element value="/@inheritDoc/"/>
</property>
</properties>
</rule>
<rule ref="SlevomatCodingStandard.ControlStructures.RequireNullCoalesceOperator"/>
<rule ref="SlevomatCodingStandard.ControlStructures.RequireShortTernaryOperator"/>
<rule ref="SlevomatCodingStandard.Exceptions.RequireNonCapturingCatch" />
<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
<properties>
<property name="spacesCountAroundEqualsSign" value="0" />
</properties>
<include-pattern>*/tests/*</include-pattern>
<exclude-pattern>*/fixtures/*</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue"/>
<!-- Squiz sniffs -->
<rule ref="Squiz.Arrays.ArrayBracketSpacing"/>
<rule ref="Squiz.Arrays.ArrayDeclaration">
<exclude name="Squiz.Arrays.ArrayDeclaration.KeySpecified"/>
<exclude name="Squiz.Arrays.ArrayDeclaration.NoKeySpecified"/>
</rule>
<!-- Disable some error messages that we do not want. -->
<rule ref="Squiz.Arrays.ArrayDeclaration.CloseBraceNotAligned">
<severity>0</severity>
</rule>
<rule ref="Squiz.Arrays.ArrayDeclaration.DoubleArrowNotAligned">
<severity>0</severity>
</rule>
<rule ref="Squiz.Arrays.ArrayDeclaration.FirstValueNoNewline">
<severity>0</severity>
</rule>
<rule ref="Squiz.Arrays.ArrayDeclaration.KeyNotAligned">
<severity>0</severity>
</rule>
<rule ref="Squiz.Arrays.ArrayDeclaration.MultiLineNotAllowed">
<severity>0</severity>
</rule>
<rule ref="Squiz.Arrays.ArrayDeclaration.NoComma">
<severity>0</severity>
</rule>
<rule ref="Squiz.Arrays.ArrayDeclaration.NoCommaAfterLast">
<severity>0</severity>
</rule>
<rule ref="Squiz.Arrays.ArrayDeclaration.NotLowerCase">
<severity>0</severity>
</rule>
<rule ref="Squiz.Arrays.ArrayDeclaration.SingleLineNotAllowed">
<severity>0</severity>
</rule>
<rule ref="Squiz.Arrays.ArrayDeclaration.ValueNoNewline">
<severity>0</severity>
</rule>
<rule ref="Squiz.Arrays.ArrayDeclaration.ValueNotAligned">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.ForEachLoopDeclaration"/>
<!-- Disable some error messages that we already cover. -->
<rule ref="Squiz.ControlStructures.ForEachLoopDeclaration.AsNotLower">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.ForEachLoopDeclaration.SpaceAfterOpen">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.ForEachLoopDeclaration.SpaceBeforeClose">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.ForLoopDeclaration"/>
<!-- Disable some error messages that we already cover. -->
<rule ref="Squiz.ControlStructures.ForLoopDeclaration.SpacingAfterOpen">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.ForLoopDeclaration.SpacingBeforeClose">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.SwitchDeclaration"/>
<!-- Disable some error messages that we do not want. -->
<rule ref="Squiz.ControlStructures.SwitchDeclaration.BreakIndent">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.SwitchDeclaration.CaseIndent">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.SwitchDeclaration.CloseBraceAlign">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.SwitchDeclaration.DefaultIndent">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.SwitchDeclaration.DefaultNoBreak">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.SwitchDeclaration.EmptyCase">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.SwitchDeclaration.EmptyDefault">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.SwitchDeclaration.MissingDefault">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.SwitchDeclaration.SpacingAfterCase">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.SwitchDeclaration.SpacingAfterDefaultBreak">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.SwitchDeclaration.SpacingBeforeBreak">
<severity>0</severity>
</rule>
<rule ref="Squiz.Functions.FunctionDeclarationArgumentSpacing">
<properties>
<property name="equalsSpacing" value="1"/>
</properties>
</rule>
<rule ref="Squiz.Functions.FunctionDeclarationArgumentSpacing.NoSpaceBeforeArg">
<severity>0</severity>
</rule>
<rule ref="Squiz.PHP.LowercasePHPFunctions"/>
<rule ref="Squiz.PHP.NonExecutableCode"/>
<rule ref="Squiz.Strings.ConcatenationSpacing">
<properties>
<property name="spacing" value="1"/>
<property name="ignoreNewlines" value="true"/>
</properties>
</rule>
<rule ref="Squiz.WhiteSpace.FunctionSpacing">
<properties>
<property name="spacing" value="1"/>
</properties>
</rule>
<rule ref="Squiz.WhiteSpace.LanguageConstructSpacing"/>
<rule ref="Squiz.WhiteSpace.OperatorSpacing">
<properties>
<property name="ignoreNewlines" value="true"/>
</properties>
</rule>
<rule ref="Squiz.WhiteSpace.ScopeKeywordSpacing"/>
<rule ref="Squiz.WhiteSpace.SemicolonSpacing"/>
<rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/>
<!-- Zend sniffs -->
<rule ref="Zend.Files.ClosingTag"/>
</ruleset>
/* cspell:ignore xxxs */
#project-browser .search__form-container,
#project-browser .pb-layout,
#project-browser .pb-module-page {
margin-block-start: 0;
padding: var(--gin-spacing-s);
border: 1px solid var(--gin-border-color-layer);
border-radius: var(--gin-border-l);
background: var(--gin-bg-layer);
box-shadow: var(--gin-shadow-l1);
}
@media (min-width: 48em) {
#project-browser .search__form-container,
#project-browser .pb-layout,
#project-browser .pb-module-page {
padding: var(--gin-spacing-l);
}
}
.gin--dark-mode #project-browser .search__form-container,
.gin--dark-mode #project-browser .pb-layout,
.gin--dark-mode #project-browser .pb-module-page {
box-shadow: 0 6px 16px var(--gin-border-color-layer);
}
.gin--high-contrast-mode #project-browser .search__form-container,
.gin--high-contrast-mode #project-browser .pb-layout,
.gin--high-contrast-mode #project-browser .pb-module-page {
box-shadow: none;
}
#project-browser .search__form-container {
margin-block-start: var(--gin-spacing-l);
}
#project-browser .search__search-bar {
border: none;
background: none;
}
#project-browser .search__search-bar .search__search_term {
padding: var(--gin-spacing-m);
border: 1px solid var(--gin-border-color-form-element);
}
#project-browser .search__search-icon {
width: 16px;
height: 16px;
inset-inline-end: 20px;
inset-block-end: 20px;
}
#project-browser .search__search-clear {
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
margin-right: 10px;
padding: 0;
border-radius: 50%;
background: var(--gin-status-bg);
inset-block-start: 17px;
inset-inline-end: 16px;
}
#project-browser .search__search-clear img {
width: 12px;
height: 12px;
}
.gin--dark-mode #project-browser .search__search-clear img {
filter: brightness(0) invert(1);
}
#project-browser .search__search-clear + .search__search-icon {
display: none;
}
#project-browser .search__form-item {
margin-block-start: 0;
margin-block-end: var(--gin-spacing-s);
}
#project-browser .search__results-count {
display: flex;
flex-wrap: wrap;
gap: var(--gin-spacing-xs);
}
#project-browser .search__form-filters-container {
padding: var(--gin-spacing-m);
border: 1px solid var(--gin-border-color);
border-radius: var(--gin-border-m);
background: none;
}
#project-browser .search__form-filters {
align-items: baseline;
}
#project-browser .search__form-filters .form-item {
padding-block-start: 0;
margin-block: 0 var(--gin-spacing-s);
}
#project-browser .search__grid-container,
#project-browser .search__dropdown.dropdown-filters {
border: none;
background-color: transparent;
}
#project-browser .search__grid-container {
grid-gap: 0;
padding: 0;
}
#project-browser .search__filters {
margin-block-start: 0;
padding: 0;
background: none;
}
#project-browser .search__filter-wrapper {
gap: var(--gin-spacing-s);
margin-block-start: var(--gin-spacing-s);
}
@media (min-width: 48em) {
#project-browser .search__filter-wrapper {
margin-block-start: 0;
}
}
#project-browser .search__filter__toggle-container {
margin-inline-end: 0;
}
#project-browser .search__filter-button {
color: var(--gin-color-primary);
font-size: var(--gin-font-size-xs);
}
#project-browser .search__filter__toggle.form-element,
#project-browser .search__sort-select.form-element {
margin-block-start: 0;
margin-inline-start: 0;
transition: var(--gin-transition);
text-decoration: none;
color: var(--gin-color-text);
border: 1px solid var(--gin-border-color-form-element);
border-radius: var(--gin-border-m);
background-color: var(--gin-bg-input);
}
#project-browser .search__checkbox-label {
font-size: var(--gin-font-size-s);
}
#project-browser
.search__filter__toggle.form-element
.search__filter__toggle-img {
padding: 0;
}
.gin--dark-mode
#project-browser
.search__filter__toggle.form-element
.search__filter__toggle-img {
filter: invert(1);
}
#project-browser .search__sort {
display: flex;
align-items: center;
gap: var(--gin-spacing-xs);
}
#project-browser .search__sort label {
flex-shrink: 0;
}
#project-browser .pb-display {
gap: var(--gin-spacing-xxxs);
margin-block-end: 0;
margin-inline-end: 0;
padding: var(--gin-spacing-xxs);
border: 1px solid var(--gin-border-color);
border-radius: var(--gin-spacing-xl);
background: var(--gin-bg-layer);
}
#project-browser .pb-display__button {
padding: var(--gin-spacing-xs) var(--gin-spacing-s);
color: var(--gin-color-text);
border-radius: var(--gin-border-xl);
background: var(--gin-bg-layer);
box-shadow: none;
font-size: var(--gin-font-size-s);
}
#project-browser .pb-display__button:hover {
z-index: 2;
color: var(--gin-color-primary);
background: var(--gin-color-primary-light);
}
#project-browser .pb-display__button:active,
#project-browser .pb-display__button:focus,
#project-browser .pb-display__button--selected {
z-index: 2;
color: var(--gin-color-button-text);
background: var(--gin-color-primary);
}
#project-browser .pb-display__button:active img,
#project-browser .pb-display__button:focus img,
#project-browser .pb-display__button--selected img {
filter: invert(1);
}
.gin--dark-mode #project-browser .pb-display__button:active img,
.gin--dark-mode #project-browser .pb-display__button:focus img,
.gin--dark-mode #project-browser .pb-display__button--selected img {
filter: none;
}
#project-browser .pb-display__button:focus {
box-shadow:
0 0 0 1px var(--gin-color-focus-border),
0 0 0 4px var(--gin-color-focus);
}
.gin--dark-mode #project-browser .pb-display__button-icon {
filter: invert(1);
}
#project-browser .pb-layout__header {
align-items: baseline;
margin-block: var(--gin-spacing-l) var(--gin-spacing-s);
border-block-end: none;
}
#project-browser .filter-group__title-wrapper,
#project-browser .pb-filter__heading {
margin-block-end: 0;
color: var(--gin-color-title);
font-size: var(--gin-font-size-s);
font-weight: var(--gin-font-weight-bold);
}
#project-browser .pb-filter__heading {
display: inline-flex;
}
@media (min-width: 61em) {
#project-browser .pb-filter__heading {
margin-block-end: var(--gin-spacing-s);
}
}
#project-browser .pb-filter__summary {
padding: var(--gin-spacing-s);
border-radius: var(--gin-border-m);
background: var(--gin-bg-layer2);
}
#project-browser .pb-filter__checkbox-label {
padding-block-start: 0;
font-size: var(--gin-font-size-s);
}
#project-browser .filter-applied {
min-height: 2rem;
margin: 0;
color: var(--gin-color-primary-active);
background: var(--gin-color-primary-light);
font-size: var(--gin-font-size-xs);
font-weight: var(--gin-font-weight-semibold);
padding-block: 0;
padding-inline: var(--gin-spacing-s) var(--gin-spacing-xs);
}
.gin--dark-mode #project-browser .filter-applied img {
filter: invert(1);
}
.pb-project.pb-project--grid,
.pb-project.pb-project--list {
border: 1px solid var(--gin-border-color-layer2);
border-radius: var(--gin-border-m);
background: transparent;
box-shadow: none;
}
.gin--dark-mode .pb-project.pb-project--grid,
.gin--dark-mode .pb-project.pb-project--list {
background: var(--gin-bg-layer2);
}
.pb-project.pb-project--grid .pb-project__logo,
.pb-project.pb-project--list .pb-project__logo {
line-height: 0;
}
.pb-project.pb-project--grid .pb-project__logo-image,
.pb-project.pb-project--list .pb-project__logo-image {
width: 64px;
}
.pb-project.pb-project--grid .pb-project__title,
.pb-project.pb-project--list .pb-project__title {
margin-block-end: var(--gin-spacing-xxs);
font-size: var(--gin-font-size-l);
font-weight: var(--gin-font-weight-bold);
}
.pb-project.pb-project--grid .pb-project__title .pb-project__link,
.pb-project.pb-project--list .pb-project__title .pb-project__link {
text-decoration: none;
color: var(--gin-color-primary);
}
.pb-project.pb-project--grid .pb-project__body,
.pb-project.pb-project--list .pb-project__body {
font-size: var(--gin-font-size-s);
}
.pb-project.pb-project--grid .project__action_button,
.pb-project.pb-project--list .project__action_button {
border-radius: var(--gin-border-s);
font-size: var(--gin-font-size-xxs);
padding-block: calc(var(--gin-spacing-xxs) + 2px);
padding-inline: var(--gin-spacing-s);
}
.pb-project--list {
grid-template-columns: 64px 1fr;
}
.pb-project__image--list {
padding-inline-start: 0;
}
.pb-project__project-usage-container {
gap: var(--gin-spacing-xxxs);
}
.pb-project__status-icon img {
width: 24px;
}
.pb-search-results {
margin: 0;
margin-block-start: var(--gin-spacing-xs);
font-size: var(--gin-font-size-h3);
font-weight: var(--gin-font-weight-bold);
}
.pb-actions .project_status-indicator {
display: inline-flex;
border-radius: var(--gin-border-xl);
font-size: var(--gin-font-size-s);
font-weight: var(--gin-font-weight-bold);
gap: var(--gin-spacing-xs);
padding-block: var(--gin-spacing-xxs);
padding-inline: var(--gin-spacing-xs) var(--gin-spacing-s);
}
.pb-actions__icon {
color: var(--gin-status-success-text);
}
.gin--dark-mode .pb-icon--usage {
filter: invert(1);
}
.pb-icon--module-details {
width: auto;
margin-inline: 0;
}
.gin--dark-mode .pb-icon--status.pb-module-page__module-details-icon,
.gin--dark-mode .pb-project__status-icon img {
mix-blend-mode: plus-lighter;
}
.gin--dark-mode .project-browser-popup .command-box,
.gin--dark-mode .project-browser-popup input {
background: var(--gin-bg-layer2);
}
.search__form .filter-applied,
.pb-project-categories__item,
.pb-module-page__categories-list-item {
margin-inline-end: 0.25em;
border-radius: 2rem;
font-size: var(--gin-font-size-xs);
font-weight: var(--gin-font-weight-semibold);
}
.pb-project-categories__item,
.pb-module-page__categories-list-item {
padding: var(--gin-spacing-xxxs) var(--gin-spacing-xs);
}
.pb-module-page {
display: flex;
flex-wrap: wrap;
gap: var(--gin-spacing-xl);
margin-block-start: var(--gin-spacing-s) !important;
}
@media (min-width: 61em) {
.pb-module-page {
flex-wrap: nowrap;
}
}
.pb-module-page__sidebar,
.pb-module-page__main {
flex-basis: 100%;
padding: var(--gin-spacing-s);
}
@media (min-width: 61em) {
.pb-module-page__sidebar,
.pb-module-page__main {
padding: 0;
}
}
.pb-module-page__main {
overflow: auto;
max-width: 100%;
}
@media (min-width: 61em) {
.pb-module-page__sidebar {
flex-basis: 320px;
}
}
.pb-module-page hr {
margin-block: var(--gin-spacing-s);
}
.pb-module-page__project-logo {
max-width: 96px;
margin-block-end: var(--gin-spacing-xs);
}
.pb-module-page__title {
color: var(--gin-color-title);
font-size: var(--gin-font-size-h1);
font-weight: var(--gin-font-weight-bold);
margin-block: 0;
}
.pb-module-page__author {
margin-block-start: 0;
margin-block-end: var(--gin-spacing-m);
color: var(--gin-color-text-light);
}
.pb-module-page__details-title {
position: absolute !important;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
width: 1px;
height: 1px;
word-wrap: normal;
}
.pb-module-page__module-details {
grid-template-columns: 2rem 2fr;
align-items: start;
}
.pb-module-page__module-details-info {
margin: 0;
margin-block-end: var(--gin-spacing-s);
font-size: var(--gin-font-size-s);
}
.pb-module-page__categories-list {
display: flex;
flex-wrap: wrap;
height: auto;
margin-block-end: var(--gin-spacing-m);
gap: var(--gin-spacing-xs);
}
.pb-module-page__categories-label {
margin-block-end: var(--gin-spacing-xs);
}
.pb-module-page__actions {
margin: var(--gin-spacing-s) 0;
}
.pb-module-page__categories-list-item {
margin: 0;
}
/* Prevent the dropbutton from being misaligned within the row of icons. For some
* reason, this is caused by Gin exacerbating the `inline-flex` display of
* dropbuttons that is defined by core. */
.pb-actions .dropbutton-wrapper {
display: inherit;
/* Move the dropbutton slightly away from the "installed" badge. */
margin-block-start: 4px;
}
.gin--dark-mode .pb-filter__multi-dropdown__items--visible {
background-color: var(--gin-bg-layer);
}
.gin--dark-mode .pb-filter__multi-dropdown__items--visible div:hover {
background-color: var(--gin-bg-layer2);
}
.gin--dark-mode .project_status-indicator__label {
color: var(--gin-status-success-text);
}
[data-gin-accent="blue"] .pb-layout__main .views-bulk-actions {
background: rgba(var(--gin-color-sticky-rgb), 0.9);
}
.gin--dark-mode [data-gin-accent="blue"] .pb-layout__main .views-bulk-actions {
background: rgba(27, 27, 29, 0.8);
}
[data-gin-accent="blue"] .views-bulk-actions__item {
color: var(--gin-color-text-light);
}
.gin--dark-mode button.project_status-indicator.project_status-indicator {
margin-bottom: 5px;
margin-left: 5px;
background: none;
font-size: 16px;
font-weight: 700;
}
......@@ -67,7 +67,8 @@
.pb-filter__multi-dropdown__items--visible {
position: absolute;
z-index: 100;
/* This needs to be underneath the loading overlay. */
z-index: 90;
top: 47px;
right: 0;
display: block;
......@@ -272,7 +273,7 @@
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 0;
padding: 0.5rem 0;
}
.pb-search-results {
......@@ -373,7 +374,7 @@
.pb-projects-list,
.pb-projects-grid {
--grid-layout-gap: 1.5rem;
--grid-item--min-width: 400px;
--grid-item--min-width: 350px;
--gap-count: calc(var(--grid-column-count) - 1);
--total-gap-width: calc(var(--gap-count) * var(--grid-layout-gap));
--grid-item--max-width: calc(
......@@ -414,16 +415,17 @@
.pb-actions {
margin-inline-start: auto;
}
.pb-detail-modal__sidebar .pb-actions {
display: grid;
max-width: fit-content;
margin: auto;
}
.pb-actions .loading__ajax-progress {
display: inline-block;
line-height: 0.75;
}
.pb-actions__icon {
color: #228572;
}
/* <Project/Categories> */
.pb-project-categories__list {
display: inline-block;
......@@ -527,7 +529,7 @@
gap: var(--grid-layout-gap);
border: 1px solid rgba(212, 212, 218, 0.8);
border-radius: 2px;
box-shadow: 0 4px 10px rgb(0, 0, 0 / 0.1);
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.pb-project__title {
......@@ -545,6 +547,7 @@
border: none;
background: transparent;
font-weight: bold;
line-height: 1.75rem;
}
.pb-project__link:hover {
......@@ -715,8 +718,12 @@
/* <Project/ProjectStatusIndicator> */
.project_status-indicator {
text-decoration: none;
font-weight: bold;
display: flex;
align-items: center;
padding: 0.25rem 0.5rem;
cursor: not-allowed;
border: none;
background: none;
}
/* <Search/FilterApplied> */
......@@ -795,7 +802,7 @@
/* <Search/Search> */
.search__form-container {
margin: -1px 0 2rem;
margin: -1px 0 0.5rem;
padding: 1.5rem;
border: 1px solid #dedfe4;
border-radius: 1px;
......@@ -803,6 +810,10 @@
box-shadow: 0 2px 0.25rem rgba(0, 0, 0, 0.1);
}
.search__form-container .form-item {
margin-block: 0;
}
@media screen and (min-width: 600px) {
.search__form-filters {
display: grid;
......@@ -841,7 +852,7 @@
}
.search__bar-container.form-item {
margin-block-end: 1.5rem;
margin-block-end: 0.5rem;
}
.search__search-bar .search__search_term {
......@@ -914,7 +925,7 @@
border: 3px solid #f3f4f9;
}
.search__form-filters-container {
.search__form-container {
padding: 1rem 1.5rem;
background-color: #f3f4f9;
}
......@@ -1002,7 +1013,6 @@
/* <Search/SearchSort> */
.search__sort {
z-index: 2;
margin-block-end: 1.5rem;
}
.search__sort label[for] {
......@@ -1037,3 +1047,86 @@
border: 1px solid;
}
}
.pb-layout__main .pb-install_bulk_actions {
margin-top: 1rem;
border-radius: 0.5rem;
}
.pb-layout__main .pb-install_bulk_actions[data-drupal-sticky-vbo="true"] {
animation: none;
}
.pb-install_bulk_actions .install_button {
padding: 5px;
color: var(--color-white);
background-color: var(--color-blue-400);
}
.pb-install_bulk_actions .install_button:hover {
background-color: var(--color-blue-500);
}
.pb-install_bulk_actions button.install_button_common {
height: 34px;
margin-left: 20px;
font-size: 0.79rem;
margin-block: 0;
}
.select_button {
padding: calc(0.5rem - 1px) calc(1rem - 1px);
cursor: pointer;
color: var(--color-blue-600);
border: 2px solid var(--color-blue-600);
border-radius: 2px;
background-color: #fff;
font-size: 0.79rem;
font-weight: bold;
}
.select_button:hover {
color: var(--color-blue-650);
border: 2px solid var(--color-blue-650);
}
.select_button:active {
color: var(--color-blue-700);
border: 2px solid var(--color-blue-700);
}
.project_status-indicator__label {
margin-left: 5px;
color: var(--color-gray-800);
font-size: 16px;
font-weight: 700;
}
.pb-project__status-icon-span {
display: flex;
}
.pb-install_bulk_actions button.clear_button {
margin-block: 0;
margin-inline: 0;
height: 34px;
margin-left: 10px;
padding: 5px;
font-size: 0.79rem;
}
[data-project-browser-instance-id] {
position: relative;
}
[data-project-browser-instance-id] .pb-projects__loading-overlay {
position: absolute;
/* No element of the Project Browser UI should have a higher z-index than this. */
z-index: 100;
top: 0;
left: 0;
display: flex;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.6);
}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 13"><path d="M2 6.571L5.6 10 14 2" fill="none" stroke="#42a877" stroke-width="3"/></svg>
<svg fill="#55565B" height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6.464 13.676c-.194.194-.513.194-.707 0l-4.96-4.955c-.194-.193-.194-.513 0-.707l1.405-1.407c.194-.195.512-.195.707 0l2.849 2.848c.194.193.513.193.707 0l6.629-6.626c.195-.194.514-.194.707 0l1.404 1.404c.193.194.193.513 0 .707z"/></svg>
name: Project Browser Devel
type: module
description: Provides a Project Browser source plugin that generates random data.
core_version_requirement: ^10 || ^11
dependencies:
- project_browser:project_browser
<?php
/**
* @file
* Install and uninstall functions for the project_browser_devel module.
*/
use Drupal\project_browser\Plugin\ProjectBrowserSourceManager;
/**
* Implements hook_install().
*/
function project_browser_devel_install() {
// Set the new random data generator as plugin and keep the current one.
$configFactory = \Drupal::configFactory();
$current_source_plugin = $configFactory->getEditable('project_browser.admin_settings')
->get('enabled_sources');
$current_source_plugin[] = 'random_data';
$configFactory->getEditable('project_browser.admin_settings')
->set('enabled_sources', $current_source_plugin)
->save(TRUE);
// Invalidate the cache to reflect the configuration changes.
\Drupal::service(ProjectBrowserSourceManager::class)->clearCachedDefinitions();
}
/**
* Implements hook_uninstall().
*/
function project_browser_devel_uninstall() {
// Set the previous plugin.
$admin_settings = \Drupal::configFactory()->getEditable('project_browser.admin_settings');
$enabled_sources = $admin_settings->get('enabled_sources');
if (($key = array_search('random_data', $enabled_sources)) !== FALSE) {
unset($enabled_sources[$key]);
$admin_settings
->set('enabled_sources', array_values($enabled_sources) ?: ['drupalorg_jsonapi'])
->save(TRUE);
}
}
<?php
namespace Drupal\project_browser_devel\Plugin\ProjectBrowserSource;
use Drupal\Component\Utility\Random;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\project_browser\Plugin\ProjectBrowserSourceBase;
use Drupal\project_browser\ProjectBrowser\Filter\BooleanFilter;
use Drupal\project_browser\ProjectBrowser\Filter\MultipleChoiceFilter;
use Drupal\project_browser\ProjectBrowser\Project;
use Drupal\project_browser\ProjectBrowser\ProjectsResultsPage;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Random data plugin. Used mostly for testing.
*
* To enable this source use the following drush command.
* phpcs:ignore
* drush config:set project_browser.admin_settings enabled_source random_data
*
* @ProjectBrowserSource(
* id = "random_data",
* label = @Translation("Random data"),
* description = @Translation("Gets random project and filters information"),
* )
*/
class RandomDataPlugin extends ProjectBrowserSourceBase {
/**
* Utility to create random data.
*
* @var \Drupal\Component\Utility\Random
*/
protected $randomGenerator;
/**
* ProjectBrowser cache bin.
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected $cacheBin;
/**
* Constructs a MockDrupalDotOrg object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_bin
* The cache bin.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, CacheBackendInterface $cache_bin) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->randomGenerator = new Random();
$this->cacheBin = $cache_bin;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('cache.project_browser'),
);
}
/**
* Generate random IDs and labels.
*
* @param int $array_length
* Length of the array to generate.
*
* @return array
* Array of random IDs and names.
*/
protected function getRandomIdsAndNames($array_length = 4): array {
$data = [];
for ($i = 0; $i < $array_length; $i++) {
$data[] = [
'id' => uniqid(),
'name' => ucwords($this->randomGenerator->word(rand(6, 10))),
];
}
return $data;
}
/**
* Returns a random date.
*
* @return int
* Random timestamp.
*/
protected function getRandomDate() {
return rand(strtotime('2 years ago'), strtotime('today'));
}
/**
* {@inheritdoc}
*/
public function getCategories(): array {
$stored_categories = $this->cacheBin->get('RandomData:categories');
if ($stored_categories) {
$categories = $stored_categories->data;
}
else {
$categories = $this->getRandomIdsAndNames(20);
$this->cacheBin->set('RandomData:categories', $categories);
}
return $categories;
}
/**
* {@inheritdoc}
*/
public function getFilterDefinitions(): array {
$filters = [];
$categories = $this->getCategories();
$choices = array_combine(
array_column($categories, 'id'),
array_column($categories, 'name'),
);
$filters['categories'] = new MultipleChoiceFilter($choices, [], $this->t('Categories'), NULL);
$filters['securityCoverage'] = new BooleanFilter(
TRUE,
$this->t('Show projects covered by a security policy'),
$this->t('Show all'),
$this->t('Security advisory coverage'),
NULL,
);
$filters['maintenanceStatus'] = new BooleanFilter(
TRUE,
$this->t('Show actively maintained projects'),
$this->t('Show all'),
$this->t('Maintenance status'),
NULL,
);
$filters['developmentStatus'] = new BooleanFilter(
TRUE,
$this->t('Show projects under active development'),
$this->t('Show all'),
$this->t('Development status'),
NULL,
);
return $filters;
}
/**
* {@inheritdoc}
*/
public function getProjects(array $query = []) : ProjectsResultsPage {
$projects = $this->getProjectData();
// Filter by project machine name.
if (!empty($query['machine_name'])) {
$projects = array_filter($projects, fn(Project $project) => $project->machineName === $query['machine_name']);
}
// Filter by categories.
if (!empty($query['categories'])) {
$projects = array_filter($projects, fn(Project $project) => array_intersect(array_column($project->categories, 'id'), explode(',', $query['categories'])));
}
// Filter by search text.
if (!empty($query['search'])) {
$projects = array_filter($projects, fn(Project $project) => stripos($project->title, $query['search']) !== FALSE);
}
return $this->createResultsPage($projects);
}
/**
* Gets the project data from cache if available, or builds it if not.
*/
private function getProjectData(): array {
$stored_projects = $this->cacheBin->get('RandomData:projects');
if ($stored_projects) {
return $stored_projects->data;
}
$projects = [];
$number_of_projects = rand(16, 36);
$categories = $this->getCategories();
$broken_image = 'https://image.not/found' . uniqid() . '.jpg';
$good_image = 'https://picsum.photos/600/400';
for ($i = 0; $i < $number_of_projects; $i++) {
$machine_name = strtolower($this->randomGenerator->word(10));
$project_images = [];
if ($i !== 0) {
$project_images[] = [
'file' => [
'uri' => str_replace(4, 5, $good_image),
'resource' => 'image',
],
'alt' => $machine_name . ' something',
];
$project_images[] = [
'file' => [
'uri' => str_replace(4, 6, $good_image),
'resource' => 'image',
],
'alt' => $machine_name . ' another thing',
];
}
$projects[] = new Project(
logo: [
'file' => [
'uri' => ($i % 3) ? $good_image : $broken_image,
'resource' => 'image',
],
'alt' => $machine_name . ' logo',
],
isCompatible: (bool) ($i / 4),
isMaintained: (bool) rand(0, 1),
isCovered: (bool) rand(0, 1),
projectUsageTotal: rand(0, 100000),
machineName: $machine_name,
body: [
'summary' => $this->randomGenerator->paragraphs(1),
'value' => $this->randomGenerator->paragraphs(5),
],
title: ucwords($machine_name),
author: [
'name' => $this->randomGenerator->word(10),
],
packageName: 'random/' . $machine_name,
categories: [$categories[array_rand($categories)]],
images: $project_images,
id: $machine_name,
);
}
$this->cacheBin->set('RandomData:projects', $projects);
return $projects;
}
}
......@@ -10,7 +10,7 @@
/**
* Implements hook_install().
*/
function project_browser_source_example_install() {
function project_browser_source_example_install(): void {
$configFactory = \Drupal::configFactory();
$current_source_plugin = $configFactory->getEditable('project_browser.admin_settings')
->get('enabled_sources');
......@@ -23,7 +23,7 @@ function project_browser_source_example_install() {
/**
* Implements hook_uninstall().
*/
function project_browser_source_example_uninstall() {
function project_browser_source_example_uninstall(): void {
$admin_settings = \Drupal::configFactory()->getEditable('project_browser.admin_settings');
$enabled_sources = $admin_settings->get('enabled_sources');
if (($key = array_search('project_browser_source_example', $enabled_sources)) !== FALSE) {
......
......@@ -2,8 +2,12 @@
namespace Drupal\project_browser_source_example\Plugin\ProjectBrowserSource;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\project_browser\Attribute\ProjectBrowserSource;
use Drupal\project_browser\Plugin\ProjectBrowserSourceBase;
use Drupal\project_browser\ProjectBrowser\Filter\MultipleChoiceFilter;
use Drupal\project_browser\ProjectBrowser\Filter\TextFilter;
use Drupal\project_browser\ProjectBrowser\Project;
use Drupal\project_browser\ProjectBrowser\ProjectsResultsPage;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -11,14 +15,13 @@ use Symfony\Component\HttpFoundation\RequestStack;
/**
* Project Browser Source Plugin example code.
*
* @ProjectBrowserSource(
* id = "project_browser_source_example",
* label = @Translation("Example source"),
* description = @Translation("Example source plugin for Project Browser."),
* )
*/
class ProjectBrowserSourceExample extends ProjectBrowserSourceBase {
#[ProjectBrowserSource(
id: 'project_browser_source_example',
label: new TranslatableMarkup('Example source'),
description: new TranslatableMarkup('Example source plugin for Project Browser.'),
)]
final class ProjectBrowserSourceExample extends ProjectBrowserSourceBase {
/**
* Constructor for example plugin.
......@@ -31,15 +34,12 @@ class ProjectBrowserSourceExample extends ProjectBrowserSourceBase {
* The plugin implementation definition.
* @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
* The request from the browser.
* @param \Drupal\Core\Extension\ModuleExtensionList $moduleExtensionList
* The module extension list.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
protected readonly RequestStack $requestStack,
protected ModuleExtensionList $moduleExtensionList,
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
......@@ -47,13 +47,12 @@ class ProjectBrowserSourceExample extends ProjectBrowserSourceBase {
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get(RequestStack::class),
$container->get(ModuleExtensionList::class),
);
}
......@@ -84,8 +83,7 @@ class ProjectBrowserSourceExample extends ProjectBrowserSourceBase {
'label' => 'Project 1',
'short_description' => 'Quick summary to show in the cards.',
'long_description' => 'Extended project information to show in the detail page',
'author' => 'Jane Doe',
'logo' => $request->getSchemeAndHttpHost() . '/core/misc/logo/drupal-logo.svg',
'logo' => $request?->getSchemeAndHttpHost() . '/core/misc/logo/drupal-logo.svg',
'created_at' => strtotime('1 year ago'),
'updated_at' => strtotime('1 month ago'),
'categories' => ['cat_1:Category 1'],
......@@ -108,20 +106,7 @@ class ProjectBrowserSourceExample extends ProjectBrowserSourceBase {
// fully populated.
$projects = [];
foreach ($projects_from_source as $project_from_source) {
// Empty array if no author information is provided.
$author = [
'name' => $project_from_source['author'],
];
// Empty array if there is no logo.
$logo = [
'file' => [
// Url of the logo in "https" format.
'uri' => $project_from_source['logo'],
'resource' => 'image',
],
'alt' => 'Project 1 logo',
];
$logo = Url::fromUri($project_from_source['logo']);
// Empty array if there are no categories.
$categories = [];
......@@ -140,20 +125,19 @@ class ProjectBrowserSourceExample extends ProjectBrowserSourceBase {
isCompatible: TRUE,
isMaintained: TRUE,
isCovered: TRUE,
projectUsageTotal: 0,
machineName: $project_from_source['unique_name'],
body: [
'summary' => $project_from_source['short_description'],
'value' => $project_from_source['long_description'],
],
title: $project_from_source['label'],
author: $author,
packageName: $project_from_source['composer_namespace'],
categories: $categories,
// Images: Array of images using the same structure as $logo, above.
// Images: Array of images, each of which is an array with two elements:
// `file`, which is a \Drupal\Core\Url object pointing to the image,
// and `alt`, which is the alt text.
images: [],
);
$pb_path = $this->moduleExtensionList->getPath('project_browser');
$projects[] = new Project(
logo: $logo,
// Maybe the source won't have all fields, but we still need to
......@@ -161,17 +145,17 @@ class ProjectBrowserSourceExample extends ProjectBrowserSourceBase {
isCompatible: TRUE,
isMaintained: TRUE,
isCovered: TRUE,
projectUsageTotal: 0,
machineName: $project_from_source['unique_name'] . '2',
body: [
'summary' => $project_from_source['short_description'] . ' (different commands)',
'value' => $project_from_source['long_description'] . ' (different commands)',
],
title: 'A project with different commands',
author: $author,
packageName: $project_from_source['composer_namespace'],
categories: $categories,
// Images: Array of images using the same structure as $logo, above.
// Images: Array of images, each of which is an array with two elements:
// `file`, which is a \Drupal\Core\Url object pointing to the image,
// and `alt`, which is the alt text.
images: [],
);
}
......@@ -184,21 +168,18 @@ class ProjectBrowserSourceExample extends ProjectBrowserSourceBase {
/**
* {@inheritdoc}
*/
public function getCategories(): array {
// Step 1: The list of categories that the modules can have. The array
// must have the "id" and "name" properties defined. If your source data
// does not use categories then return an empty array. These can be
// hardcoded, come from REST or GraphQL endpoints, etc.
return [
[
'id' => 'cat_1',
'name' => 'Category 1',
],
[
'id' => 'cat_2',
'name' => 'Category 2',
],
public function getFilterDefinitions(): array {
$filters = [
'search' => new TextFilter('', $this->t('Search')),
];
$categories = [
'cat_1' => 'Category 1',
'cat_2' => 'Category 2',
];
$filters['categories'] = new MultipleChoiceFilter($categories, [], $this->t('Categories'));
return $filters;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="project_browser">
<!-- Drupal (core) uses stylelint: https://www.drupal.org/list-changes/drupal/published?keywords_description=stylelint-->
<exclude-pattern>*.css</exclude-pattern>
<!-- Drupal (core) uses eslint: https://www.drupal.org/list-changes/drupal/published?keywords_description=eslint-->
<exclude-pattern>*.js</exclude-pattern>
<!-- Use the Drupal core coding standard -->
<rule ref="./core.phpcs.xml.dist"></rule>
</ruleset>
parameters:
ignoreErrors:
-
message: "#^Call to function method_exists\\(\\) with 'Drupal\\\\\\\\Core\\\\\\\\Recipe\\\\\\\\Recipe' and 'getExtra' will always evaluate to true\\.$#"
identifier: function.alreadyNarrowedType
count: 1
path: src/Activator/RecipeActivator.php
-
message: "#^Call to function method_exists\\(\\) with 'Drupal\\\\\\\\Core\\\\\\\\Recipe\\\\\\\\Recipe' and 'getExtra' will always evaluate to true\\.$#"
identifier: function.alreadyNarrowedType
count: 1
path: tests/src/Kernel/RecipeActivatorTest.php
parameters:
ignoreErrors:
-
message: "#^Call to function method_exists\\(\\) with 'Drupal\\\\\\\\Core\\\\\\\\Recipe\\\\\\\\Recipe' and 'getExtra' will always evaluate to false\\.$#"
identifier: function.impossibleType
count: 1
path: src/Activator/RecipeActivator.php
-
message: "#^Call to function method_exists\\(\\) with 'Drupal\\\\\\\\Core\\\\\\\\Recipe\\\\\\\\Recipe' and 'getExtra' will always evaluate to false\\.$#"
identifier: function.impossibleType
count: 1
path: tests/src/Kernel/RecipeActivatorTest.php
-
message: "#^Call to an undefined method Drupal\\\\Core\\\\Recipe\\\\Recipe\\:\\:getExtra\\(\\)\\.$#"
identifier: method.notFound
count: 1
path: src/Activator/RecipeActivator.php
<?php
/**
* @file
* Allows for specific PHPStan ignores for different versions of Drupal core.
*/
declare(strict_types = 1);
use Composer\InstalledVersions;
use Composer\Semver\VersionParser;
use Drupal\Core\Recipe\Recipe;
$includes = [];
if (method_exists(Recipe::class, 'getExtra')) {
if (InstalledVersions::satisfies(new VersionParser(), 'phpstan/phpstan', '^2')) {
$includes[] = 'phpstan-baseline-getExtras.neon';
}
}
else {
$includes[] = 'phpstan-baseline-no-getExtras.neon';
}
$config = [];
$config['includes'] = $includes;
return $config;
includes:
- phpstan-drupal-core-bc-layer.neon.php
parameters:
level: 1
level: 8
universalObjectCratesClasses:
- Drupal\Core\Extension\Extension
reportUnmatchedIgnoredErrors: true
excludePaths:
- phpstan-drupal-core-bc-layer.neon.php
# The scripts directory does not contain runtime code.
- scripts
# The node_modules contains some PHP to ignore.
- sveltejs
# The recipe form contains a couple of errors that cannot be ignored.
# @todo Remove this exclusion when support for Drupal 10 is dropped in https://www.drupal.org/i/3494848.
- src/Form/RecipeForm.php
# Every ignore should be documented.
ignoreErrors:
# Ignore errors when using `array` as a return type.
-
# @see https://www.drupal.org/docs/develop/development-tools/phpstan/handling-unsafe-usage-of-new-static#s-ignoring-the-issue
identifier: new.static
identifier: missingType.iterableValue
reportUnmatched: false
# @todo: Remove the following rules when support is dropped for Drupal 10.2, which does not have recipes.
### Core testing suite
# Caused by missing return type on \Drupal\FunctionalJavascriptTests\WebDriverTestBase::assertSession().
-
message: "#^Access to constant COMPOSER_PROJECT_TYPE on an unknown class Drupal\\\\Core\\\\Recipe\\\\Recipe\\.$#"
message: "#^Call to an undefined method Drupal\\\\Tests\\\\WebAssert\\:\\:assert[a-zA-Z]+\\(\\)\\.$#"
identifier: method.notFound
paths:
- src/Plugin/ProjectBrowserSource/Recipes.php
- src/RecipeActivator.php
- tests/src/Kernel/RecipesSourceTest.php
- tests/src/FunctionalJavascript
reportUnmatched: false
# Caused by missing return type on \Drupal\FunctionalJavascriptTests\WebDriverTestBase::assertSession().
-
message: "#^Call to static method [a-zA-Z]+\\(\\) on an unknown class Drupal\\\\Core\\\\Recipe\\\\Recipe[a-zA-Z]*\\.$#"
path: src/RecipeActivator.php
message: "#^Call to an undefined method Drupal\\\\Tests\\\\WebAssert\\:\\:wait[a-zA-Z]+\\(\\)\\.$#"
identifier: method.notFound
paths:
- tests/src/FunctionalJavascript
reportUnmatched: false
# Caused by \Drupal\KernelTests\KernelTestBase::$container having the wrong type.
-
message: "#^Class Drupal\\\\Core\\\\Recipe\\\\RecipeAppliedEvent not found\\.$#"
path: src/RecipeActivator.php
message: "#^Property Drupal\\\\KernelTests\\\\KernelTestBase\\:\\:\\$container \\(Drupal\\\\Core\\\\DependencyInjection\\\\ContainerBuilder\\) does not accept Drupal\\\\Component\\\\DependencyInjection\\\\ContainerInterface\\.$#"
identifier: assign.propertyType
paths:
- tests/src/Kernel/DatabaseTablesTest.php
reportUnmatched: false
# Caused by \Drupal\Tests\user\Traits\UserCreationTrait::createUser() returning FALSE instead of throwing an exception.
-
message: "#^Parameter \\$event of method Drupal\\\\project_browser\\\\RecipeActivator\\:\\:onApply\\(\\) has invalid type Drupal\\\\Core\\\\Recipe\\\\RecipeAppliedEvent\\.$#"
path: src/RecipeActivator.php
message: "#^Parameter \\#1 \\$account of method Drupal\\\\Tests\\\\BrowserTestBase\\:\\:drupalLogin\\(\\) expects Drupal\\\\Core\\\\Session\\\\AccountInterface, Drupal\\\\user\\\\Entity\\\\User\\|false given\\.$#"
identifier: argument.type
paths:
- tests/src/Functional
- tests/src/FunctionalJavascript
reportUnmatched: false
### Package Manager
# @todo Remove after resolving https://www.drupal.org/i/3501836.
# Caused by using self instead of static as a return type in \Drupal\fixture_manipulator\FixtureManipulator.
-
message: "#^Method Drupal\\\\fixture_manipulator\\\\FixtureManipulator\\:\\:commitChanges\\(\\) invoked with 0 parameters, 1 required\\.$#"
identifier: arguments.count
paths:
- tests/src/Kernel/InstallerTest.php
- tests/src/Kernel/CoreNotUpdatedValidatorTest.php
- tests/src/Kernel/PackageNotInstalledValidatorTest.php
reportUnmatched: false
# Caused by missing return type on \Drupal\Tests\package_manager\Traits\FixtureManipulatorTrait::getStageFixtureManipulator().
-
message: "#^Call to static method createFromDirectory\\(\\) on an unknown class Drupal\\\\Core\\\\Recipe\\\\Recipe\\.$#"
path: tests/src/Kernel/RecipeActivatorTest.php
message: "#^Call to an undefined method object\\:\\:setCorePackageVersion\\(\\)\\.$#"
identifier: method.notFound
paths:
- tests/src/Kernel/CoreNotUpdatedValidatorTest.php
reportUnmatched: false
# Caused by missing @throws on \Drupal\package_manager\StageBase::apply().
-
message: "#^Call to static method processRecipe\\(\\) on an unknown class Drupal\\\\Core\\\\Recipe\\\\RecipeRunner\\.$#"
path: tests/src/Kernel/RecipeActivatorTest.php
message: "#^Dead catch \\- Drupal\\\\package_manager\\\\Exception\\\\StageEventException is never thrown in the try block\\.$#"
identifier: catch.neverThrown
paths:
- tests/src/Kernel/CoreNotUpdatedValidatorTest.php
reportUnmatched: false