Skip to content
Snippets Groups Projects
Commit fdb23b9a authored by Klaus Purer's avatar Klaus Purer
Browse files

refactor(phpstan): Update PHPStan and other dev dependencies, cleanup todos (#3516305)

parent e0b97ba8
Branches
Tags
1 merge request!33refactor(phpstan): Update PHPStan and other dev dependencies
Pipeline #465418 passed
Showing
with 69 additions and 206 deletions
......@@ -20,6 +20,7 @@ variables:
OPT_IN_TEST_PREVIOUS_MINOR: 1
OPT_IN_TEST_NEXT_MINOR: 1
OPT_IN_TEST_MAX_PHP: 1
_PHPUNIT_CONCURRENT: 1
phpstan (custom):
extends: phpstan
......
......@@ -5,4 +5,4 @@ package: GraphQL
dependencies:
- graphql:graphql
- node:node
core_version_requirement: ^10.2 || ^11
core_version_requirement: ^10.4 || ^11
......@@ -7,6 +7,8 @@ namespace Drupal\graphql_composable\Plugin\GraphQL\Schema;
use Drupal\graphql\Plugin\GraphQL\Schema\ComposableSchema;
/**
* Example of a composable schema.
*
* @Schema(
* id = "composable",
* name = "Composable Example schema",
......
......@@ -11,6 +11,8 @@ use Drupal\graphql\Plugin\GraphQL\SchemaExtension\SdlSchemaExtensionPluginBase;
use Drupal\graphql_composable\GraphQL\Response\ArticleResponse;
/**
* Example schema plugin for extending the composable schema.
*
* @SchemaExtension(
* id = "composable_extension",
* name = "Composable Example extension",
......
......@@ -5,4 +5,4 @@ package: GraphQL
dependencies:
- graphql:graphql
- node:node
core_version_requirement: ^10.2 || ^11
core_version_requirement: ^10.4 || ^11
......@@ -15,6 +15,8 @@ use GraphQL\Error\UserError;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Example data producer that loads a list of articles.
*
* @DataProducer(
* id = "query_articles",
* name = @Translation("Load articles"),
......@@ -71,9 +73,7 @@ class QueryArticles extends DataProducerPluginBase implements ContainerFactoryPl
}
/**
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* Resolves the query by preparing an entity query for executing later.
*/
public function resolve(int $offset, int $limit, RefinableCacheableDependencyInterface $metadata): QueryConnection {
if ($limit > static::MAX_LIMIT) {
......
......@@ -11,6 +11,8 @@ use Drupal\graphql\Plugin\GraphQL\Schema\SdlSchemaPluginBase;
use Drupal\graphql_examples\Wrappers\QueryConnection;
/**
* Example schema plugin that maps article data.
*
* @Schema(
* id = "example",
* name = "Example schema"
......
......@@ -9,6 +9,8 @@ use Drupal\graphql\GraphQL\ResolverRegistryInterface;
use Drupal\graphql\Plugin\GraphQL\SchemaExtension\SdlSchemaExtensionPluginBase;
/**
* Example schema extension that adds to the mapping.
*
* @SchemaExtension(
* id = "example_extension",
* name = "Example extension",
......
......@@ -3,6 +3,6 @@ type: module
description: 'Base module for integrating GraphQL with Drupal.'
package: GraphQL
configure: entity.graphql_server.collection
core_version_requirement: ^10.3 || ^11
core_version_requirement: ^10.4 || ^11
dependencies:
- typed_data:typed_data
......@@ -34,41 +34,13 @@
<exclude-pattern>src/GraphQL/Buffers/BufferBase.php</exclude-pattern>
<exclude-pattern>src/GraphQL/Execution/FieldContext.php</exclude-pattern>
<exclude-pattern>src/GraphQL/Execution/ResolveContext.php</exclude-pattern>
<exclude-pattern>src/GraphQL/Utility/FileUpload.php</exclude-pattern>
<exclude-pattern>src/Plugin/GraphQL/DataProducer/Utility/Seek.php</exclude-pattern>
<exclude-pattern>src/SubRequestResponse.php</exclude-pattern>
<exclude-pattern>tests/src/Traits/QueryResultAssertionTrait.php</exclude-pattern>
<exclude-pattern>tests/src/Traits/MockingTrait.php</exclude-pattern>
</rule>
<rule ref="Drupal.Commenting.DocComment.MissingShort">
<exclude-pattern>src/Plugin/GraphQL/Schema/SdlSchemaPluginBase.php</exclude-pattern>
<exclude-pattern>src/Plugin/GraphQL/Schema/ComposableSchema.php</exclude-pattern>
<exclude-pattern>src/Plugin/DataProducerPluginManager.php</exclude-pattern>
<exclude-pattern>src/Plugin/PersistedQueryPluginInterface.php</exclude-pattern>
<exclude-pattern>src/Plugin/DataProducerPluginCachingInterface.php</exclude-pattern>
<exclude-pattern>src/Controller/RequestController.php</exclude-pattern>
<exclude-pattern>examples/graphql_example/src/Wrappers/QueryConnection.php</exclude-pattern>
<exclude-pattern>examples/graphql_example/src/Plugin/GraphQL/DataProducer/QueryArticles.php</exclude-pattern>
<exclude-pattern>examples/graphql_example/src/Plugin/GraphQL/Schema/ExampleSchema.php</exclude-pattern>
<exclude-pattern>examples/graphql_example/src/Plugin/GraphQL/SchemaExtension/ExampleSchemaExtension.php</exclude-pattern>
<exclude-pattern>examples/graphql_composable/src/Plugin/GraphQL/Schema/ComposableSchemaExample.php</exclude-pattern>
<exclude-pattern>examples/graphql_composable/src/Plugin/GraphQL/SchemaExtension/ComposableSchemaExampleExtension.php</exclude-pattern>
<exclude-pattern>tests/src/Traits/MockingTrait.php</exclude-pattern>
<exclude-pattern>tests/src/Traits/QueryResultAssertionTrait.php</exclude-pattern>
<exclude-pattern>tests/src/Traits/DataProducerExecutionTrait.php</exclude-pattern>
<exclude-pattern>tests/src/Kernel/ResolverBuilderTest.php</exclude-pattern>
<exclude-pattern>tests/src/Kernel/EntityBufferTest.php</exclude-pattern>
<exclude-pattern>tests/src/Kernel/DataProducer/MenuTest.php</exclude-pattern>
<exclude-pattern>tests/src/Kernel/DataProducer/EntityMultipleTest.php</exclude-pattern>
<exclude-pattern>tests/src/Kernel/DataProducer/EntityTest.php</exclude-pattern>
<exclude-pattern>tests/src/Kernel/EntityUuidBufferTest.php</exclude-pattern>
<exclude-pattern>tests/src/Kernel/Framework/PersistedQueriesTest.php</exclude-pattern>
<exclude-pattern>tests/src/Kernel/GraphQLTestBase.php</exclude-pattern>
<exclude-pattern>tests/modules/graphql_persisted_queries_test/src/Plugin/GraphQL/PersistedQuery/PersistedQueryPluginThree.php</exclude-pattern>
<exclude-pattern>tests/modules/graphql_persisted_queries_test/src/Plugin/GraphQL/PersistedQuery/PersistedQueryPluginOne.php</exclude-pattern>
<exclude-pattern>tests/modules/graphql_persisted_queries_test/src/Plugin/GraphQL/PersistedQuery/PersistedQueryPluginTwo.php</exclude-pattern>
</rule>
<rule ref="Drupal.Commenting.FunctionComment.MissingParamComment">
<exclude-pattern>src/PermissionProvider.php</exclude-pattern>
<exclude-pattern>src/Config/LanguageConfigOverride.php</exclude-pattern>
......
......@@ -148,13 +148,6 @@ class Server extends ConfigEntityBase implements ServerInterface {
*/
protected ?array $persisted_query_instances = NULL;
/**
* The sorted persisted query plugin instances available on this server.
*
* @var array|null
*/
protected ?array $sorted_persisted_query_instances = NULL;
/**
* {@inheritdoc}
*/
......@@ -302,9 +295,7 @@ class Server extends ConfigEntityBase implements ServerInterface {
return function (OperationParams $params, DocumentNode $document, $type) use ($schema, $config) {
$context = new ResolveContext($this, $params, $document, $type, $config);
$context->addCacheTags(['graphql_response']);
if ($this instanceof CacheableDependencyInterface) {
$context->addCacheableDependency($this);
}
$context->addCacheableDependency($this);
if ($schema instanceof CacheableDependencyInterface) {
$context->addCacheableDependency($schema);
......@@ -371,7 +362,6 @@ class Server extends ConfigEntityBase implements ServerInterface {
*/
public function removeAllPersistedQueryInstances(): void {
$this->persisted_query_instances = NULL;
$this->sorted_persisted_query_instances = NULL;
}
/**
......@@ -381,6 +371,7 @@ class Server extends ConfigEntityBase implements ServerInterface {
if (!is_null($this->persisted_query_instances)) {
return $this->persisted_query_instances;
}
$this->persisted_query_instances = [];
/** @var \Drupal\graphql\Plugin\PersistedQueryPluginManager $plugin_manager */
$plugin_manager = \Drupal::service('plugin.manager.graphql.persisted_query');
......@@ -392,24 +383,11 @@ class Server extends ConfigEntityBase implements ServerInterface {
$this->persisted_query_instances[$id] = $plugin_manager->createInstance($id, $configuration);
}
}
uasort($this->persisted_query_instances, function ($a, $b) {
return $a->getWeight() <= $b->getWeight() ? -1 : 1;
});
return $this->persisted_query_instances ?? [];
}
/**
* {@inheritDoc}
*/
public function getSortedPersistedQueryInstances(): array {
if (!is_null($this->sorted_persisted_query_instances)) {
return $this->sorted_persisted_query_instances;
}
$this->sorted_persisted_query_instances = $this->getPersistedQueryInstances();
if (!empty($this->sorted_persisted_query_instances)) {
uasort($this->sorted_persisted_query_instances, function ($a, $b) {
return $a->getWeight() <= $b->getWeight() ? -1 : 1;
});
}
return $this->sorted_persisted_query_instances;
return $this->persisted_query_instances;
}
/**
......@@ -420,7 +398,7 @@ class Server extends ConfigEntityBase implements ServerInterface {
*/
protected function getPersistedQueryLoader(): callable {
return function ($id, OperationParams $params) {
$sortedPersistedQueryInstances = $this->getSortedPersistedQueryInstances();
$sortedPersistedQueryInstances = $this->getPersistedQueryInstances();
if (!empty($sortedPersistedQueryInstances)) {
foreach ($sortedPersistedQueryInstances as $persistedQueryInstance) {
$query = $persistedQueryInstance->getQuery($id, $params);
......
......@@ -55,18 +55,11 @@ interface ServerInterface extends ConfigEntityInterface {
*/
public function removeAllPersistedQueryInstances(): void;
/**
* Returns the current persisted queries set.
*
* @return array<\Drupal\graphql\Plugin\PersistedQueryPluginInterface>
*/
public function getPersistedQueryInstances(): array;
/**
* Returns the current persisted queries set, sorted by the plugins weight.
*
* @return array<\Drupal\graphql\Plugin\PersistedQueryPluginInterface>
*/
public function getSortedPersistedQueryInstances(): array;
public function getPersistedQueryInstances(): array;
}
......@@ -13,7 +13,6 @@ use Drupal\Core\Utility\Error as ErrorUtil;
use Drupal\graphql\Event\OperationEvent;
use Drupal\graphql\GraphQL\Execution\ExecutionResult as CacheableExecutionResult;
use Drupal\graphql\GraphQL\Utility\DocumentSerializer;
use GraphQL\Error\ClientAware;
use GraphQL\Executor\ExecutionResult;
use GraphQL\Executor\ExecutorImplementation;
use GraphQL\Executor\Promise\Promise;
......@@ -200,7 +199,7 @@ class Executor implements ExecutorImplementation {
// Don't log errors intended for clients, only log those that
// a client would not be able to solve, they'd require work from
// a server developer.
if ($error instanceof ClientAware && $error->isClientSafe()) {
if ($error->isClientSafe()) {
continue;
}
......
<?php
declare(strict_types=1);
namespace Drupal\graphql\GraphQL\Resolver;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\TypedData\DataDefinitionInterface;
use Drupal\Core\TypedData\TypedDataTrait;
use Drupal\graphql\GraphQL\Execution\FieldContext;
use Drupal\graphql\GraphQL\Execution\ResolveContext;
use Drupal\typed_data\DataFetcherTrait;
use GraphQL\Type\Definition\ResolveInfo;
/**
* Resolves a property path.
*
* @todo Delete this resolver. This is a plugin already.
*/
class Path implements ResolverInterface {
use TypedDataTrait;
use DataFetcherTrait;
/**
* Name of the context.
*/
protected string|DataDefinitionInterface $type;
/**
* Source resolver.
*/
protected mixed $path;
/**
* Resolver.
*/
protected mixed $value;
/**
* Path constructor.
*/
public function __construct(string $type, mixed $path, ?ResolverInterface $value = NULL) {
$this->type = $type;
$this->path = $path;
$this->value = $value;
}
/**
* {@inheritdoc}
*/
public function resolve(mixed $value, array $args, ResolveContext $context, ResolveInfo $info, FieldContext $field): mixed {
$value = $this->value ?? new ParentValue();
$value = $value->resolve($value, $args, $context, $info, $field);
$metadata = new BubbleableMetadata();
$type = $this->type instanceof DataDefinitionInterface ? $this->type : DataDefinition::create($this->type);
$data = $this->getTypedDataManager()->create($type, $value);
$output = $this->getDataFetcher()->fetchDataByPropertyPath($data, $this->path, $metadata)->getValue();
$context->addCacheableDependency($metadata);
if ($output instanceof CacheableDependencyInterface) {
$context->addCacheableDependency($output);
}
return $output;
}
}
......@@ -22,7 +22,7 @@ class ResolverRegistry implements ResolverRegistryInterface {
*
* Contains a nested list of callables, keyed by type and field name.
*
* @var array<callable>
* @var array<string, array<string, \Drupal\graphql\GraphQL\Resolver\ResolverInterface>>
*/
protected array $fieldResolvers = [];
......@@ -109,12 +109,7 @@ class ResolverRegistry implements ResolverRegistryInterface {
}
/**
* Return all field resolvers in the registry.
*
* @return array<callable>
* A nested list of callables, keyed by type and field name.
*
* @todo This should be added to ResolverRegistryInterface in 5.0.0.
* {@inheritdoc}
*/
public function getAllFieldResolvers(): array {
return $this->fieldResolvers;
......@@ -136,24 +131,7 @@ class ResolverRegistry implements ResolverRegistryInterface {
}
/**
* Get a field resolver for the type or any of the interfaces it implements.
*
* This allows common functionality (such as for Edge's or Connections) to be
* implemented for an interface and re-used on any concrete type that extends
* it.
*
* This should be used instead of `getFieldResolver` unless you're certain you
* want the resolver only for the specific type.
*
* @param \GraphQL\Type\Definition\Type $type
* The type to find a resolver for.
* @param string $fieldName
* The name of the field to find a resolver for.
*
* @return \Drupal\graphql\GraphQL\Resolver\ResolverInterface|null
* The defined resolver for the field or NULL if none exists.
*
* @todo This should be added to ResolverRegistryInterface in 5.0.0.
* {@inheritdoc}
*/
public function getFieldResolverWithInheritance(Type $type, string $fieldName): ?ResolverInterface {
if ($resolver = $this->getFieldResolver($type->toString(), $fieldName)) {
......
......@@ -8,6 +8,7 @@ use Drupal\graphql\GraphQL\Execution\FieldContext;
use Drupal\graphql\GraphQL\Execution\ResolveContext;
use Drupal\graphql\GraphQL\Resolver\ResolverInterface;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\Type;
/**
* Defines a registry to resolve any field in the GraphQL schema tree.
......@@ -29,11 +30,39 @@ interface ResolverRegistryInterface {
*/
public function addFieldResolver(string $type, string $field, ResolverInterface $resolver): static;
/**
* Get a field resolver for the type or any of the interfaces it implements.
*
* This allows common functionality (such as for Edge's or Connections) to be
* implemented for an interface and re-used on any concrete type that extends
* it.
*
* This should be used instead of `getFieldResolver` unless you're certain you
* want the resolver only for the specific type.
*
* @param \GraphQL\Type\Definition\Type $type
* The type to find a resolver for.
* @param string $fieldName
* The name of the field to find a resolver for.
*
* @return \Drupal\graphql\GraphQL\Resolver\ResolverInterface|null
* The defined resolver for the field or NULL if none exists.
*/
public function getFieldResolverWithInheritance(Type $type, string $fieldName): ?ResolverInterface;
/**
* Return the field resolver for a given type and field name.
*/
public function getFieldResolver(string $type, string $field): ?ResolverInterface;
/**
* Return all field resolvers in the registry.
*
* @return array<string, array<string, \Drupal\graphql\GraphQL\Resolver\ResolverInterface>>
* A nested list of resolvers, keyed by type and field name.
*/
public function getAllFieldResolvers(): array;
/**
* Add a type resolver.
*
......
......@@ -13,6 +13,7 @@ use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\File\Event\FileUploadSanitizeNameEvent;
use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Image\ImageFactory;
use Drupal\Core\Lock\LockBackendInterface;
......@@ -235,10 +236,7 @@ class FileUpload {
$file_uri = "{$destination}/{$prepared_filename}";
$temp_file_path = $uploaded_file->getRealPath();
// Drupal 10.3 compatibility: use the deprecated constant for now.
// @phpstan-ignore-next-line as it is deprecated in D12.
$file_uri = $this->fileSystem->getDestinationFilename($file_uri, FileSystemInterface::EXISTS_RENAME);
$file_uri = $this->fileSystem->getDestinationFilename($file_uri, FileExists::Rename);
// Lock based on the prepared file URI.
$lock_id = $this->generateLockIdFromFileUri($file_uri);
......@@ -286,9 +284,7 @@ class FileUpload {
// FileSystemInterface::EXISTS_ERROR as the file location has already been
// determined above in FileSystem::getDestinationFilename().
try {
// Drupal 10.3 compatibility: use the deprecated constant for now.
// @phpstan-ignore-next-line as it is deprecated in D12.
$this->fileSystem->move($temp_file_path, $file_uri, FileSystemInterface::EXISTS_ERROR);
$this->fileSystem->move($temp_file_path, $file_uri, FileExists::Rename);
}
catch (FileException $e) {
$response->addViolation($this->t('Unknown error while uploading the file "@file".', [
......@@ -321,7 +317,7 @@ class FileUpload {
/**
* Validates uploaded files, saves them and returns a file upload response.
*
* @param array<\Symfony\Component\HttpFoundation\File\UploadedFile> $uploaded_files
* @param array<\Symfony\Component\HttpFoundation\File\UploadedFile|mixed> $uploaded_files
* The file entities to upload.
* @param array $settings
* File settings as specified in regular file field config. Contains keys:
......
......@@ -61,17 +61,6 @@ class Validator implements ValidatorInterface {
$plugin = $this->getSchemaPlugin($server);
$resolver_registry = $plugin->getResolverRegistry();
if (!method_exists($resolver_registry, "getFieldResolverWithInheritance")) {
$this->logger->warning(
"Could not get missing resolvers for @server_name as its registry class (@class) does not implement getFieldResolverWithInheritance.",
[
'@server_name' => $server->id(),
'@class' => get_class($resolver_registry),
]
);
return [];
}
try {
$schema = $plugin->getSchema($resolver_registry);
}
......@@ -127,17 +116,6 @@ class Validator implements ValidatorInterface {
return [];
}
if (!method_exists($resolver_registry, "getAllFieldResolvers")) {
$this->logger->warning(
"Could not get orphaned resolvers for @server_name as its registry class (@class) does not implement getAllFieldResolvers.",
[
'@server_name' => $server->id(),
'@class' => get_class($resolver_registry),
]
);
return [];
}
$orphaned_resolvers = [];
/**
* @var string $type_name
......
......@@ -129,6 +129,8 @@ abstract class EntityQueryBase extends DataProducerPluginBase implements Contain
}
// Ensure that desired access checking is performed on the query.
// Not sure why PHPStan complains about this?
// @phpstan-ignore-next-line
$query->accessCheck($access);
// Filter entities only of given bundles, if desired.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment