Skip to content

Commit b677475

Browse files
authored
feat(drupal): Implement Drupal 11 readiness. (#1407)
1 parent e0dacc2 commit b677475

26 files changed

+129
-119
lines changed

.github/workflows/testing.yml

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,24 @@ on:
77
jobs:
88
drupal:
99
name: Drupal ${{ matrix.drupal-core }} (PHP ${{ matrix.php-versions }})
10-
runs-on: ubuntu-latest
10+
# We cannot use ubuntu-latest right now as it still points to 22.04 and we need a newer database driver.
11+
runs-on: ubuntu-24.04
1112
env:
1213
extensions: mbstring, xml, pdo_sqlite, gd, opcache
1314
strategy:
1415
fail-fast: false
1516
matrix:
16-
php-versions: ['8.1', '8.2']
17+
php-versions: ['8.1', '8.2', '8.3']
1718
drupal-core: ['10.3.x']
1819
phpstan: ['0']
1920
include:
20-
# Extra run to test older supported Drupal 10.1.x.
21-
- php-versions: '8.1'
22-
drupal-core: '10.1.x'
23-
phpstan: '0'
2421
# Extra run to test older supported Drupal 10.2.x.
2522
- php-versions: '8.1'
2623
drupal-core: '10.2.x'
2724
phpstan: '0'
2825
# We only need to run PHPStan once on the latest PHP version.
2926
- php-versions: '8.3'
30-
drupal-core: '10.3.x'
27+
drupal-core: '11.0.x'
3128
phpstan: '1'
3229
steps:
3330
- name: Checkout Drupal core
@@ -86,12 +83,13 @@ jobs:
8683
composer --no-interaction run-script drupal-phpunit-upgrade
8784
composer config --no-plugins allow-plugins.phpstan/extension-installer true
8885
86+
# Revisit - check for latest release of dependent modules.
8987
- name: Install GraphQL dependencies
9088
run: |
9189
composer --no-interaction --no-progress require \
9290
webonyx/graphql-php:^14.8 \
93-
drupal/typed_data:^1.0 \
94-
drupal/redirect:^1.0
91+
drupal/typed_data:^2.0 \
92+
drupal/redirect:dev-1.x
9593
9694
- name: Run PHPUnit
9795
run: |
@@ -109,8 +107,8 @@ jobs:
109107
mglaman/phpstan-drupal:^1.1.2 \
110108
phpstan/phpstan-deprecation-rules:^1.0.0 \
111109
jangregor/phpstan-prophecy:^1.0.0 \
112-
phpstan/phpstan-phpunit:^1.0.0 \
113-
phpstan/extension-installer:^1.0
110+
phpstan/phpstan-phpunit:^1.4 \
111+
phpstan/extension-installer:^1.4
114112
composer --no-interaction --no-progress --with-all-dependencies upgrade drupal/coder:8.3.24
115113
116114
- name: Run PHPStan

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"homepage": "http://drupal.org/project/graphql",
66
"license": "GPL-2.0+",
77
"require": {
8-
"php": ">=7.3",
8+
"drupal/typed_data": "^1.0 || ^2.0",
9+
"php": ">=8.1",
910
"webonyx/graphql-php": "^14.8.0"
1011
},
1112
"minimum-stability": "dev"

examples/graphql_composable/graphql_composable.info.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ package: GraphQL
55
dependencies:
66
- graphql:graphql
77
- node:node
8-
core_version_requirement: ^10.1
8+
core_version_requirement: ^10.2 || ^11

examples/graphql_example/graphql_examples.info.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ package: GraphQL
55
dependencies:
66
- graphql:graphql
77
- node:node
8-
core_version_requirement: ^10.1
8+
core_version_requirement: ^10.2 || ^11

graphql.info.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ type: module
33
description: 'Base module for integrating GraphQL with Drupal.'
44
package: GraphQL
55
configure: graphql.config_page
6-
core_version_requirement: ^10.1
6+
core_version_requirement: ^10.2 || ^11
77
dependencies:
88
- typed_data:typed_data

graphql.services.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ services:
184184
- '@renderer'
185185
- '@event_dispatcher'
186186
- '@image.factory'
187+
- '@file.validator'
187188

188189
plugin.manager.graphql.persisted_query:
189190
class: Drupal\graphql\Plugin\PersistedQueryPluginManager

src/EventSubscriber/ApqSubscriber.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public function onBeforeOperation(OperationEvent $event): void {
6565
/**
6666
* {@inheritdoc}
6767
*/
68-
public static function getSubscribedEvents() {
68+
public static function getSubscribedEvents(): array {
6969
return [
7070
OperationEvent::GRAPHQL_OPERATION_BEFORE => 'onBeforeOperation',
7171
];

src/EventSubscriber/OperationSubscriber.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public function onAfterOperation(OperationEvent $event): void {
7373
/**
7474
* {@inheritdoc}
7575
*/
76-
public static function getSubscribedEvents() {
76+
public static function getSubscribedEvents(): array {
7777
return [
7878
OperationEvent::GRAPHQL_OPERATION_BEFORE => 'onBeforeOperation',
7979
OperationEvent::GRAPHQL_OPERATION_AFTER => 'onAfterOperation',

src/EventSubscriber/SubrequestSubscriber.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public function onKernelRequestFinished(FinishRequestEvent $event): void {
6767
/**
6868
* {@inheritdoc}
6969
*/
70-
public static function getSubscribedEvents() {
70+
public static function getSubscribedEvents(): array {
7171
return [
7272
KernelEvents::REQUEST => 'onKernelRequest',
7373
KernelEvents::FINISH_REQUEST => 'onKernelRequestFinished',

src/GraphQL/Utility/FileUpload.php

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
use Drupal\Core\Render\RenderContext;
1818
use Drupal\Core\Render\RendererInterface;
1919
use Drupal\Core\Session\AccountProxyInterface;
20+
use Drupal\Core\StringTranslation\ByteSizeMarkup;
2021
use Drupal\Core\StringTranslation\StringTranslationTrait;
2122
use Drupal\Core\Utility\Token;
2223
use Drupal\file\FileInterface;
24+
use Drupal\file\Validation\FileValidatorInterface;
2325
use Drupal\graphql\GraphQL\Response\FileUploadResponse;
2426
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
2527
use Symfony\Component\HttpFoundation\File\UploadedFile;
@@ -111,6 +113,13 @@ class FileUpload {
111113
*/
112114
protected $imageFactory;
113115

116+
/**
117+
* The file validator service.
118+
*
119+
* @var \Drupal\file\Validation\FileValidatorInterface
120+
*/
121+
protected FileValidatorInterface $fileValidator;
122+
114123
/**
115124
* Constructor.
116125
*/
@@ -126,6 +135,7 @@ public function __construct(
126135
RendererInterface $renderer,
127136
EventDispatcherInterface $eventDispatcher,
128137
ImageFactory $image_factory,
138+
FileValidatorInterface $file_validator,
129139
) {
130140
/** @var \Drupal\file\FileStorageInterface $file_storage */
131141
$file_storage = $entityTypeManager->getStorage('file');
@@ -140,6 +150,7 @@ public function __construct(
140150
$this->renderer = $renderer;
141151
$this->eventDispatcher = $eventDispatcher;
142152
$this->imageFactory = $image_factory;
153+
$this->fileValidator = $file_validator;
143154
}
144155

145156
/**
@@ -193,10 +204,7 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
193204
switch ($uploaded_file->getError()) {
194205
case UPLOAD_ERR_INI_SIZE:
195206
case UPLOAD_ERR_FORM_SIZE:
196-
// @todo Drupal 10.1 compatibility, needs to be converted to
197-
// ByteSizeMarkup later.
198-
// @phpstan-ignore-next-line
199-
$maxUploadSize = format_size($this->getMaxUploadSize($settings));
207+
$maxUploadSize = ByteSizeMarkup::create($this->getMaxUploadSize($settings));
200208
$response->addViolation($this->t('The file @file could not be saved because it exceeds @maxsize, the maximum allowed size for uploads.', [
201209
'@file' => $uploaded_file->getClientOriginalName(),
202210
'@maxsize' => $maxUploadSize,
@@ -248,8 +256,8 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
248256

249257
$temp_file_path = $uploaded_file->getRealPath();
250258

251-
// Drupal 10.2 compatibility: use the deprecated constant for now.
252-
// @phpstan-ignore-next-line
259+
// Drupal 10.3 compatibility: use the deprecated constant for now.
260+
// @phpstan-ignore-next-line as it is deprecated in D12.
253261
$file_uri = $this->fileSystem->getDestinationFilename($file_uri, FileSystemInterface::EXISTS_RENAME);
254262

255263
// Lock based on the prepared file URI.
@@ -272,11 +280,17 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
272280
// before it is saved.
273281
$file->setSize(@filesize($temp_file_path));
274282

275-
// Validate against file_validate() first with the temporary path.
276-
// @todo Drupal 10.1 compatibility, needs to be converted to file validate
277-
// service later.
278-
// @phpstan-ignore-next-line
279-
$errors = file_validate($file, $validators);
283+
// Validate against fileValidator first with the temporary path.
284+
/** @var \Symfony\Component\Validator\ConstraintViolationListInterface $file_validate_errors */
285+
$file_validate_errors = $this->fileValidator->validate($file, $validators);
286+
$errors = [];
287+
if (count($file_validate_errors) > 0) {
288+
foreach ($file_validate_errors as $violation) {
289+
$errors[] = $violation->getMessage();
290+
}
291+
}
292+
293+
// Validate Image resolution.
280294
$maxResolution = $settings['max_resolution'] ?? 0;
281295
$minResolution = $settings['min_resolution'] ?? 0;
282296
if (!empty($maxResolution) || !empty($minResolution)) {
@@ -287,14 +301,13 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
287301
$response->addViolations($errors);
288302
return $response;
289303
}
290-
291304
$file->setFileUri($file_uri);
292305
// Move the file to the correct location after validation. Use
293306
// FileSystemInterface::EXISTS_ERROR as the file location has already been
294307
// determined above in FileSystem::getDestinationFilename().
295308
try {
296-
// Drupal 10.2 compatibility: use the deprecated constant for now.
297-
// @phpstan-ignore-next-line
309+
// Drupal 10.3 compatibility: use the deprecated constant for now.
310+
// @phpstan-ignore-next-line as it is deprecated in D12.
298311
$this->fileSystem->move($temp_file_path, $file_uri, FileSystemInterface::EXISTS_ERROR);
299312
}
300313
catch (FileException $e) {
@@ -315,7 +328,6 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
315328
}
316329

317330
$file->save();
318-
319331
$response->setFileEntity($file);
320332
return $response;
321333
}
@@ -487,12 +499,12 @@ protected function validateFileImageResolution(FileInterface $file, $maximum_dim
487499
protected function prepareFilename(string $filename, array &$validators): string {
488500
// Don't rename if 'allow_insecure_uploads' evaluates to TRUE.
489501
if (!$this->systemFileConfig->get('allow_insecure_uploads')) {
490-
if (!empty($validators['file_validate_extensions'][0])) {
491-
// If there is a file_validate_extensions validator and a list of
492-
// valid extensions, munge the filename to protect against possible
493-
// malicious extension hiding within an unknown file type. For example,
494-
// "filename.html.foo".
495-
$event = new FileUploadSanitizeNameEvent($filename, $validators['file_validate_extensions'][0]);
502+
if (!empty($validators['FileExtension']['extensions'])) {
503+
// If there is a fileValidator service to validate FileExtension and
504+
// a list of valid extensions, munge the filename to protect against
505+
// possible malicious extension hiding within an unknown file type.
506+
// For example, "filename.html.foo".
507+
$event = new FileUploadSanitizeNameEvent($filename, $validators['FileExtension']['extensions']);
496508
$this->eventDispatcher->dispatch($event);
497509
$filename = $event->getFilename();
498510
}
@@ -502,33 +514,30 @@ protected function prepareFilename(string $filename, array &$validators): string
502514
// and filename._php.txt, respectively).
503515
if (preg_match(FileSystemInterface::INSECURE_EXTENSION_REGEX, $filename)) {
504516
// If the file will be rejected anyway due to a disallowed extension, it
505-
// should not be renamed; rather, we'll let file_validate_extensions()
506-
// reject it below.
517+
// should not be renamed; rather, we'll let fileValidator service
518+
// to validate FileExtension reject it below.
507519
$passes_validation = FALSE;
508-
if (!empty($validators['file_validate_extensions'][0])) {
520+
if (!empty($validators['FileExtension']['extensions'])) {
509521
/** @var \Drupal\file\FileInterface $file */
510522
$file = $this->fileStorage->create([]);
511523
$file->setFilename($filename);
512-
// @todo Drupal 10.1 compatibility, needs to be converted to file
513-
// validator service later.
514-
// @phpstan-ignore-next-line
515-
$passes_validation = empty(file_validate_extensions($file, $validators['file_validate_extensions'][0]));
524+
$passes_validation = count($this->fileValidator->validate($file, $validators['FileExtension']['extensions']));
516525
}
517-
if (empty($validators['file_validate_extensions'][0]) || $passes_validation) {
526+
if (empty($validators['FileExtension']['extensions']) || ($passes_validation > 0)) {
518527
if ((substr($filename, -4) != '.txt')) {
519528
// The destination filename will also later be used to create the
520529
// URI.
521530
$filename .= '.txt';
522531
}
523532

524-
$event = new FileUploadSanitizeNameEvent($filename, $validators['file_validate_extensions'][0] ?? '');
533+
$event = new FileUploadSanitizeNameEvent($filename, $validators['FileExtension']['extensions'] ?? '');
525534
$this->eventDispatcher->dispatch($event);
526535
$filename = $event->getFilename();
527536

528537
// The .txt extension may not be in the allowed list of extensions. We
529538
// have to add it here or else the file upload will fail.
530-
if (!empty($validators['file_validate_extensions'][0])) {
531-
$validators['file_validate_extensions'][0] .= ' txt';
539+
if (!empty($validators['FileExtension']['extensions'])) {
540+
$validators['FileExtension']['extensions'] .= ' txt';
532541
}
533542
}
534543
}
@@ -579,7 +588,7 @@ protected function getUploadLocation(array $settings): string {
579588
protected function getUploadValidators(array $settings): array {
580589
$validators = [
581590
// Add in our check of the file name length.
582-
'file_validate_name_length' => [],
591+
'FileNameLength' => [],
583592
];
584593

585594
// Cap the upload size according to the PHP limit.
@@ -589,11 +598,11 @@ protected function getUploadValidators(array $settings): array {
589598
}
590599

591600
// There is always a file size limit due to the PHP server limit.
592-
$validators['file_validate_size'] = [$max_filesize];
601+
$validators['FileSizeLimit'] = ['fileLimit' => $max_filesize];
593602

594603
// Add the extension check if necessary.
595604
if (!empty($settings['file_extensions'])) {
596-
$validators['file_validate_extensions'] = [$settings['file_extensions']];
605+
$validators['FileExtension'] = ['extensions' => $settings['file_extensions']];
597606
}
598607

599608
return $validators;

src/Plugin/GraphQL/DataProducer/Entity/Fields/Image/ImageDerivative.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,12 @@ public function resolve(FileInterface $entity = NULL, $style, RefinableCacheable
9797
$access = $entity->access('view', NULL, TRUE);
9898
$metadata->addCacheableDependency($access);
9999
if ($access->isAllowed() && $image_style = ImageStyle::load($style)) {
100-
100+
// @phpstan-ignore-next-line
101101
$width = $entity->width;
102+
// @phpstan-ignore-next-line
102103
$height = $entity->height;
103104

104-
// @phpstan-ignore-next-line
105-
if (empty($width) || empty($height)) {
105+
if ($width == NULL || $height == NULL) {
106106
/** @var \Drupal\Core\Image\ImageInterface $image */
107107
$image = \Drupal::service('image.factory')->get($entity->getFileUri());
108108
if ($image->isValid()) {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
type: module
22
name: GraphQL File Validate Test
3-
description: Tests hook_file_validate() on uploads.
3+
description: Tests file validate on uploads.
44
package: Testing
55
hidden: TRUE

tests/modules/graphql_file_validate/graphql_file_validate.module

Lines changed: 0 additions & 17 deletions
This file was deleted.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
services:
2+
graphql_file_validate_test_subscriber:
3+
class: Drupal\graphql_file_validate\EventSubscriber\GraphqlFileValidationTestSubscriber
4+
tags:
5+
- { name: event_subscriber }

0 commit comments

Comments
 (0)