This commit is contained in:
cutemeli
2025-12-22 10:35:30 +00:00
parent 0bfc6c8425
commit 5ce7ca2c5d
38927 changed files with 0 additions and 4594700 deletions

View File

@@ -1,301 +0,0 @@
<?php
declare(strict_types=1);
$finder = PhpCsFixer\Finder::create()
->exclude('vendor')
->in(__DIR__);
return (new PhpCsFixer\Config())
->setParallelConfig(PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect())
->setRiskyAllowed(true)
->setFinder($finder)
->setCacheFile(sys_get_temp_dir() . '/php-cs-fixer' . preg_replace('~\W~', '-', __DIR__))
->setRules([
'align_multiline_comment' => true,
'array_indentation' => true,
'array_push' => true,
'array_syntax' => ['syntax' => 'short'],
'assign_null_coalescing_to_coalesce_equal' => true,
'attribute_empty_parentheses' => true,
'backtick_to_shell_exec' => true,
'binary_operator_spaces' => true,
'blank_line_after_namespace' => true,
'blank_line_after_opening_tag' => true,
'blank_line_before_statement' => true,
'blank_line_between_import_groups' => true,
'blank_lines_before_namespace' => true,
'braces' => false, // Deprecated
'braces_position' => true,
'cast_spaces' => true,
'class_attributes_separation' => ['elements' => ['method' => 'one', 'property' => 'one']], // const are often grouped with other related const
'class_definition' => true,
'class_keyword' => false, // Because risky, and sometimes we prefer to keep FQCN as is
'class_keyword_remove' => false, // Deprecated, and ::class keyword gives us better support in IDE
'class_reference_name_casing' => true,
'clean_namespace' => true,
'combine_consecutive_issets' => true,
'combine_consecutive_unsets' => true,
'combine_nested_dirname' => true,
'comment_to_phpdoc' => true,
'compact_nullable_type_declaration' => true,
'compact_nullable_typehint' => false, // Deprecated
'concat_space' => ['spacing' => 'one'],
'constant_case' => true,
'control_structure_braces' => true,
'control_structure_continuation_position' => true,
'curly_braces_position' => false, // Deprecated
'date_time_create_from_format_call' => false, // Because risky
'date_time_immutable' => true,
'declare_equal_normalize' => true,
'declare_parentheses' => true,
'declare_strict_types' => true,
'dir_constant' => true,
'doctrine_annotation_array_assignment' => true,
'doctrine_annotation_braces' => true,
'doctrine_annotation_indentation' => true,
'doctrine_annotation_spaces' => true,
'echo_tag_syntax' => true,
'elseif' => true,
'empty_loop_body' => true,
'empty_loop_condition' => true,
'encoding' => true,
'ereg_to_preg' => true,
'error_suppression' => true,
'escape_implicit_backslashes' => false, // Deprecated
'explicit_indirect_variable' => false, // I feel it makes the code actually harder to read
'explicit_string_variable' => false, // I feel it makes the code actually harder to read
'final_class' => false, // We need non-final classes
'final_internal_class' => true,
'final_public_method_for_abstract_class' => false, // We need non-final methods
'fopen_flag_order' => true,
'fopen_flags' => true,
'full_opening_tag' => true,
'fully_qualified_strict_types' => true,
'function_declaration' => true,
'function_to_constant' => true,
'function_typehint_space' => false, // Deprecated
'general_attribute_remove' => true,
'general_phpdoc_annotation_remove' => ['annotations' => ['author', 'category', 'copyright', 'package', 'throws']],
'general_phpdoc_tag_rename' => true,
'get_class_to_class_keyword' => true,
'global_namespace_import' => true,
'group_import' => false, // I feel it makes the code actually harder to read
'header_comment' => false, // We don't use common header in all our files
'heredoc_closing_marker' => ['closing_marker' => 'STRING'],
'heredoc_indentation' => true,
'heredoc_to_nowdoc' => false, // We often use variable in heredoc
'implode_call' => true,
'include' => true,
'increment_style' => true,
'indentation_type' => true,
'integer_literal_case' => true,
'is_null' => true,
'lambda_not_used_import' => true,
'line_ending' => true,
'linebreak_after_opening_tag' => true,
'list_syntax' => true,
'logical_operators' => true,
'long_to_shorthand_operator' => false, // Because risky
'lowercase_cast' => true,
'lowercase_keywords' => true,
'lowercase_static_reference' => true,
'magic_constant_casing' => true,
'magic_method_casing' => true,
'mb_str_functions' => true,
'method_argument_space' => true,
'method_chaining_indentation' => true,
'modernize_strpos' => true,
'modernize_types_casting' => true,
'multiline_comment_opening_closing' => true,
'multiline_promoted_properties' => true, // Experimental
'multiline_string_to_heredoc' => false, // We prefer to keep some freedom
'multiline_whitespace_before_semicolons' => true,
'native_constant_invocation' => false, // Micro optimization that look messy
'native_function_casing' => true,
'native_function_invocation' => false, // I suppose this would be best, but I am still unconvinced about the visual aspect of it
'native_function_type_declaration_casing' => false, // Deprecated
'native_type_declaration_casing' => true,
'new_expression_parentheses' => false, // Requires PHP 8.4
'new_with_braces' => false, // Deprecated
'new_with_parentheses' => true,
'no_alias_functions' => true,
'no_alias_language_construct_call' => true,
'no_alternative_syntax' => true,
'no_binary_string' => true,
'no_blank_lines_after_class_opening' => true,
'no_blank_lines_after_phpdoc' => true,
'no_blank_lines_before_namespace' => false, // Deprecated
'no_break_comment' => true,
'no_closing_tag' => true,
'no_empty_comment' => true,
'no_empty_phpdoc' => true,
'no_empty_statement' => true,
'no_extra_blank_lines' => true,
'no_homoglyph_names' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_mixed_echo_print' => true,
'no_multiline_whitespace_around_double_arrow' => true,
'no_multiple_statements_per_line' => true,
'no_null_property_initialization' => true,
'no_php4_constructor' => true,
'no_short_bool_cast' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_space_around_double_colon' => true,
'no_spaces_after_function_name' => true,
'no_spaces_around_offset' => true,
'no_spaces_inside_parenthesis' => false, // Deprecated
'no_superfluous_elseif' => true,
'no_superfluous_phpdoc_tags' => ['allow_mixed' => true],
'no_trailing_comma_in_list_call' => false, // Deprecated
'no_trailing_comma_in_singleline' => true,
'no_trailing_comma_in_singleline_array' => false, // Deprecated
'no_trailing_comma_in_singleline_function_call' => true, // Deprecated
'no_trailing_whitespace' => true,
'no_trailing_whitespace_in_comment' => true,
'no_trailing_whitespace_in_string' => false, // Too dangerous
'no_unneeded_control_parentheses' => true,
'no_unneeded_curly_braces' => false, // Deprecated
'no_unneeded_final_method' => true,
'no_unneeded_import_alias' => true,
'no_unreachable_default_argument_value' => true,
'no_unset_cast' => true,
'no_unset_on_property' => true,
'no_unused_imports' => true,
'no_useless_concat_operator' => true,
'no_useless_else' => true,
'no_useless_nullsafe_operator' => true,
'no_useless_return' => true,
'no_useless_sprintf' => true,
'no_whitespace_before_comma_in_array' => true,
'no_whitespace_in_blank_line' => true,
'non_printable_character' => true,
'normalize_index_brace' => true,
'not_operator_with_space' => false, // No we prefer to keep '!' without spaces
'not_operator_with_successor_space' => false, // idem
'nullable_type_declaration' => true,
'nullable_type_declaration_for_default_null_value' => true,
'numeric_literal_separator' => false, // Maybe later...
'object_operator_without_whitespace' => true,
'octal_notation' => true,
'operator_linebreak' => true,
'ordered_attributes' => false, // We prefer to keep some freedom
'ordered_class_elements' => false, // We prefer to keep some freedom
'ordered_imports' => true,
'ordered_interfaces' => true,
'ordered_traits' => true,
'ordered_types' => false, // We prefer to keep some freedom
'php_unit_assert_new_names' => true,
'php_unit_attributes' => false, // Requires PHPUnit 10
'php_unit_construct' => true,
'php_unit_data_provider_method_order' => true,
'php_unit_data_provider_name' => ['prefix' => 'provider', 'suffix' => ''],
'php_unit_data_provider_return_type' => true,
'php_unit_data_provider_static' => true,
'php_unit_dedicate_assert' => true,
'php_unit_dedicate_assert_internal_type' => true,
'php_unit_expectation' => true,
'php_unit_fqcn_annotation' => true,
'php_unit_internal_class' => false, // Because tests are excluded from package
'php_unit_method_casing' => true,
'php_unit_mock' => true,
'php_unit_mock_short_will_return' => true,
'php_unit_namespaced' => true,
'php_unit_no_expectation_annotation' => true,
'php_unit_set_up_tear_down_visibility' => true,
'php_unit_size_class' => false, // That seems extra work to maintain for little benefits
'php_unit_strict' => false, // We sometime actually need assertEquals
'php_unit_test_annotation' => true,
'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],
'php_unit_test_class_requires_covers' => false, // We don't care as much as we should about coverage
'phpdoc_add_missing_param_annotation' => true,
'phpdoc_align' => false, // Waste of time
'phpdoc_annotation_without_dot' => true,
'phpdoc_array_type' => false, // We prefer `T[]` instead of `array<T>`
'phpdoc_indent' => true,
'phpdoc_inline_tag_normalizer' => true,
'phpdoc_line_span' => true,
'phpdoc_list_type' => false, // Because we are not always sure what type it should actually be
'phpdoc_no_access' => true,
'phpdoc_no_empty_return' => true,
'phpdoc_order' => true,
'phpdoc_order_by_value' => true,
'phpdoc_param_order' => true,
'phpdoc_readonly_class_comment_to_keyword' => true,
'phpdoc_return_self_reference' => true,
'phpdoc_scalar' => true,
'phpdoc_separation' => true,
'phpdoc_single_line_var_spacing' => true,
'phpdoc_summary' => true,
'phpdoc_tag_casing' => true,
'phpdoc_tag_type' => true,
'phpdoc_to_comment' => true,
'phpdoc_to_param_type' => false, // Because experimental, but interesting for one shot use
'phpdoc_to_property_type' => false, // Because experimental, but interesting for one shot use
'phpdoc_to_return_type' => false, // Because experimental, but interesting for one shot use
'phpdoc_trim' => true,
'phpdoc_trim_consecutive_blank_line_separation' => true,
'phpdoc_types' => true,
'phpdoc_types_order' => true,
'phpdoc_var_annotation_correct_order' => true,
'phpdoc_var_without_name' => true,
'pow_to_exponentiation' => true,
'protected_to_private' => true,
'psr_autoloading' => true,
'random_api_migration' => true,
'regular_callable_call' => true,
'return_assignment' => false, // Sometimes useful for clarity or debug
'return_to_yield_from' => false, // That seems useless
'return_type_declaration' => true,
'self_accessor' => true,
'self_static_accessor' => true,
'semicolon_after_instruction' => false, // We prefer to keep .phtml files without semicolon
'set_type_to_cast' => true,
'short_scalar_cast' => true,
'simple_to_complex_string_variable' => false, // Would differ from TypeScript without obvious advantages
'simplified_if_return' => false, // Even if technically correct we prefer to be explicit
'simplified_null_return' => false, // Even if technically correct we prefer to be explicit
'single_blank_line_at_eof' => true,
'single_blank_line_before_namespace' => false, // Deprecated
'single_class_element_per_statement' => true,
'single_import_per_statement' => true,
'single_line_after_imports' => true,
'single_line_comment_spacing' => true,
'single_line_comment_style' => true,
'single_line_empty_body' => true,
'single_line_throw' => false, // I don't see any reason for having a special case for Exception
'single_quote' => true,
'single_space_after_construct' => false, // Deprecated
'single_space_around_construct' => true,
'single_trait_insert_per_statement' => true,
'space_after_semicolon' => true,
'spaces_inside_parentheses' => true,
'standardize_increment' => true,
'standardize_not_equals' => true,
'statement_indentation' => true,
'static_lambda' => false, // Risky if we can't guarantee nobody use `bindTo()`
'static_private_method' => false, // In PHP we'd rather avoid static as a rule of thumb
'strict_comparison' => true,
'strict_param' => true,
'string_implicit_backslashes' => true,
'string_length_to_empty' => true,
'string_line_ending' => true,
'switch_case_semicolon_to_colon' => true,
'switch_case_space' => true,
'switch_continue_to_break' => true,
'ternary_operator_spaces' => true,
'ternary_to_elvis_operator' => true,
'ternary_to_null_coalescing' => true,
'trailing_comma_in_multiline' => ['elements' => ['arguments', 'array_destructuring', 'arrays', 'match', 'parameters']],
'trim_array_spaces' => true,
'type_declaration_spaces' => true,
'types_spaces' => true,
'unary_operator_spaces' => true,
'use_arrow_functions' => true,
'visibility_required' => true,
'void_return' => true,
'whitespace_after_comma_in_array' => true,
'yield_from_array_to_yields' => true,
'yoda_style' => false, // Like Yoda we speak not
]);

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2018
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,96 +0,0 @@
# GraphQL Upload
[![Build Status](https://github.com/ecodev/graphql-upload/workflows/main/badge.svg)](https://github.com/ecodev/graphql-upload/actions)
[![Code Quality](https://scrutinizer-ci.com/g/Ecodev/graphql-upload/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/Ecodev/graphql-upload/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/Ecodev/graphql-upload/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/Ecodev/graphql-upload/?branch=master)
[![Total Downloads](https://poser.pugx.org/ecodev/graphql-upload/downloads.png)](https://packagist.org/packages/ecodev/graphql-upload)
[![Latest Stable Version](https://poser.pugx.org/ecodev/graphql-upload/v/stable.png)](https://packagist.org/packages/ecodev/graphql-upload)
[![License](https://poser.pugx.org/ecodev/graphql-upload/license.png)](https://packagist.org/packages/ecodev/graphql-upload)
[![Join the chat at https://gitter.im/Ecodev/graphql-upload](https://badges.gitter.im/Ecodev/graphql-upload.svg)](https://gitter.im/Ecodev/graphql-upload)
A [PSR-15](https://www.php-fig.org/psr/psr-15/) middleware to support file uploads in GraphQL. It implements
[the multipart request specification](https://github.com/jaydenseric/graphql-multipart-request-spec)
for [webonyx/graphql-php](https://github.com/webonyx/graphql-php).
## Quick start
Install the library via composer:
```sh
composer require ecodev/graphql-upload
```
### Configure as middleware
In Laminas Mezzio, it would typically be in `config/routes.php` something like:
```php
use Application\Action\GraphQLAction;
use Mezzio\Helper\BodyParams\BodyParamsMiddleware;
use GraphQL\Upload\UploadMiddleware;
$app->post('/graphql', [
BodyParamsMiddleware::class,
UploadMiddleware::class, // This is the magic
GraphQLAction::class,
], 'graphql');
```
#### Other frameworks
This lib is an implementation of PSR-15, so it can be used with any
framework supporting PSR-15. For specific configuration instructions, refer
to your framework documentation.
If your framework does not support PSR-15 middleware, you will probably
need some kind of bridge. Again, refer to your framework for specific instructions.
### Usage in schema
Then you can start using in your mutations like so:
```php
<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;
use GraphQL\Upload\UploadType;
use Psr\Http\Message\UploadedFileInterface;
// Build your Schema
$schema = new Schema([
'query' => new ObjectType([
'name' => 'Query',
'fields' => [],
]),
'mutation' => new ObjectType([
'name' => 'Mutation',
'fields' => [
'testUpload' => [
'type' => Type::string(),
'args' => [
'text' => Type::string(),
'file' => new UploadType(),
],
'resolve' => function ($root, array $args): string {
/** @var UploadedFileInterface $file */
$file = $args['file'];
// Do something with the file
$file->moveTo('some/folder/in/my/project');
return 'Uploaded file was ' . $file->getClientFilename() . ' (' . $file->getClientMediaType() . ') with description: ' . $args['text'];
},
],
],
]),
]);
```
## Limitations
- It only works with PSR-7 requests. If you were not using PSR-7 yet,
[laminas-diactoros](https://github.com/laminas/laminas-diactoros) is one of many
implementation that could be used to create PSR-7 requests.

View File

@@ -1,39 +0,0 @@
{
"name": "ecodev/graphql-upload",
"description": "A middleware to support file uploads in GraphQL",
"type": "library",
"keywords": ["api", "graphql", "upload", "multipart", "middleware"],
"scripts": {
"check": [
"php-cs-fixer fix --ansi --dry-run --diff",
"phpunit --color=always",
"phpstan analyse --ansi"
],
"fix": [
"php-cs-fixer fix --ansi"
]
},
"autoload": {
"psr-4": {
"GraphQL\\Upload\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"GraphQLTests\\Upload\\": "tests"
}
},
"require": {
"php": "^8.2",
"ext-json": "*",
"psr/http-server-middleware": "^1.0",
"webonyx/graphql-php": "^15.0",
"laminas/laminas-diactoros": "^3.6"
},
"license": "MIT",
"require-dev": {
"friendsofphp/php-cs-fixer": "@stable",
"phpstan/phpstan": "@stable",
"phpunit/phpunit": "@stable"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace GraphQL\Upload;
use Exception;
use GraphQL\Error\Error;
final class UploadError extends Error
{
public function __construct(int $uploadError)
{
parent::__construct('File upload: ' . $this->getMessageFromUploadError($uploadError));
}
private function getMessageFromUploadError(int $uploadError): string
{
return match ($uploadError) {
UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk',
UPLOAD_ERR_EXTENSION => 'A PHP extension stopped the upload',
UPLOAD_ERR_FORM_SIZE => 'The file exceeds the `MAX_FILE_SIZE` directive that was specified in the HTML form',
UPLOAD_ERR_INI_SIZE => 'The file exceeds the `upload_max_filesize` of ' . Utility::toMebibyte(Utility::getUploadMaxFilesize()),
UPLOAD_ERR_NO_FILE => 'No file was uploaded',
UPLOAD_ERR_NO_TMP_DIR => 'Missing a temporary folder',
UPLOAD_ERR_PARTIAL => 'The file was only partially uploaded',
default => throw new Exception('Unsupported UPLOAD_ERR_* constant value: ' . $uploadError),
};
}
}

View File

@@ -1,133 +0,0 @@
<?php
declare(strict_types=1);
namespace GraphQL\Upload;
use GraphQL\Error\InvariantViolation;
use GraphQL\Server\RequestError;
use GraphQL\Utils\Utils;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class UploadMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$contentType = $request->getHeader('content-type')[0] ?? '';
if (mb_stripos($contentType, 'multipart/form-data') !== false) {
$error = $this->postMaxSizeError($request);
if ($error) {
return $error;
}
$this->validateParsedBody($request);
$request = $this->parseUploadedFiles($request);
}
return $handler->handle($request);
}
/**
* Inject uploaded files defined in the 'map' key into the 'variables' key.
*/
private function parseUploadedFiles(ServerRequestInterface $request): ServerRequestInterface
{
/** @var string[] $bodyParams */
$bodyParams = $request->getParsedBody();
$map = $this->decodeArray($bodyParams, 'map');
$result = $this->decodeArray($bodyParams, 'operations');
$uploadedFiles = $request->getUploadedFiles();
foreach ($map as $fileKey => $locations) {
foreach ($locations as $location) {
$items = &$result;
foreach (explode('.', $location) as $key) {
if (!isset($items[$key]) || !is_array($items[$key])) {
$items[$key] = [];
}
$items = &$items[$key];
}
if (!array_key_exists($fileKey, $uploadedFiles)) {
throw new RequestError(
"GraphQL query declared an upload in `$location`, but no corresponding file were actually uploaded",
);
}
$items = $uploadedFiles[$fileKey];
}
}
return $request
->withHeader('content-type', 'application/json')
->withParsedBody($result);
}
/**
* Validates that the request meet our expectations.
*/
private function validateParsedBody(ServerRequestInterface $request): void
{
$bodyParams = $request->getParsedBody();
if (null === $bodyParams) {
throw new InvariantViolation(
'PSR-7 request is expected to provide parsed body for "multipart/form-data" requests but got null',
);
}
if (!is_array($bodyParams)) {
throw new RequestError(
'GraphQL Server expects JSON object or array, but got ' . Utils::printSafeJson($bodyParams),
);
}
if (empty($bodyParams)) {
throw new InvariantViolation(
'PSR-7 request is expected to provide parsed body for "multipart/form-data" requests but got empty array',
);
}
}
/**
* @param string[] $bodyParams
*
* @return string[][]
*/
private function decodeArray(array $bodyParams, string $key): array
{
if (!isset($bodyParams[$key])) {
throw new RequestError("The request must define a `$key`");
}
$value = json_decode($bodyParams[$key], true);
if (!is_array($value)) {
throw new RequestError("The `$key` key must be a JSON encoded array");
}
return $value;
}
private function postMaxSizeError(ServerRequestInterface $request): ?ResponseInterface
{
$contentLength = $request->getServerParams()['CONTENT_LENGTH'] ?? 0;
$postMaxSize = Utility::getPostMaxSize();
if ($contentLength && $contentLength > $postMaxSize) {
$contentLength = Utility::toMebibyte($contentLength);
$postMaxSize = Utility::toMebibyte($postMaxSize);
return new JsonResponse(
['message' => "The server `post_max_size` is configured to accept $postMaxSize, but received $contentLength"],
413,
);
}
return null;
}
}

View File

@@ -1,55 +0,0 @@
<?php
declare(strict_types=1);
namespace GraphQL\Upload;
use GraphQL\Error\Error;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\Node;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Utils\Utils;
use Psr\Http\Message\UploadedFileInterface;
use UnexpectedValueException;
final class UploadType extends ScalarType
{
public string $name = 'Upload';
public ?string $description
= 'The `Upload` special type represents a file to be uploaded in the same HTTP request as specified by
[graphql-multipart-request-spec](https://github.com/jaydenseric/graphql-multipart-request-spec).';
/**
* Serializes an internal value to include in a response.
*/
public function serialize(mixed $value): never
{
throw new InvariantViolation('`Upload` cannot be serialized');
}
/**
* Parses an externally provided value (query variable) to use as an input.
*/
public function parseValue(mixed $value): UploadedFileInterface
{
if (!$value instanceof UploadedFileInterface) {
throw new UnexpectedValueException('Could not get uploaded file, be sure to conform to GraphQL multipart request specification. Instead got: ' . Utils::printSafe($value));
}
$error = $value->getError();
if ($error !== UPLOAD_ERR_OK) {
throw new UploadError($error);
}
return $value;
}
/**
* Parses an externally provided literal value (hardcoded in GraphQL query) to use as an input.
*/
public function parseLiteral(Node $valueNode, ?array $variables = null): mixed
{
throw new Error('`Upload` cannot be hardcoded in query, be sure to conform to GraphQL multipart request specification. Instead got: ' . $valueNode->kind, $valueNode);
}
}

View File

@@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace GraphQL\Upload;
/**
* @internal
*/
final class Utility
{
public static function getPostMaxSize(): int
{
return self::fromIni('post_max_size');
}
public static function getUploadMaxFilesize(): int
{
return self::fromIni('upload_max_filesize');
}
private static function fromIni(string $key): int
{
return ini_parse_quantity(ini_get($key) ?: '0');
}
/**
* @param int|numeric-string $value
*/
public static function toMebibyte(string|int $value): string
{
return number_format($value / 1024 / 1024, 2, thousands_separator: "'") . ' MiB';
}
}