Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions app/GraphQL/Scalars/Url.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

namespace App\GraphQL\Scalars;

use GraphQL\Error\Error;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\Node;
use GraphQL\Language\AST\StringValueNode;
use GraphQL\Language\AST\ValueNode;
use GraphQL\Type\Definition\ScalarType;
use Illuminate\Support\Facades\Validator;

final class Url extends ScalarType
{
protected function validate(mixed $value): bool
{
return Validator::make([
'value' => $value,
], [
'value' => 'url',
])->passes();
}

/**
* Serializes an internal value to include in a response.
*
* @throws InvariantViolation
*/
public function serialize(mixed $value): string
{
if (!$this->validate($value)) {
throw new InvariantViolation("Could not serialize {$value} as URL.");
}

return $this->parseValue($value);
}

/**
* Parses an externally provided value (query variable) to use as an input.
*
* @throws InvariantViolation
*/
public function parseValue(mixed $value): string
{
if (!$this->validate($value)) {
throw new InvariantViolation("Could not parse {$value} as URL.");
}

return (string) $value;
}

/**
* Parses an externally provided literal value (hardcoded in GraphQL query) to use as an input.
*
* Should throw an exception with a client friendly message on invalid value nodes.
*
* @param ValueNode&Node $valueNode
* @param array<string, mixed>|null $variables
*
* @throws Error
*/
public function parseLiteral(Node $valueNode, ?array $variables = null): string
{
if (!($valueNode instanceof StringValueNode)) {
throw new Error("Query error: Can only parse Strings, got {$valueNode->kind}.", $valueNode);
}

return (string) $valueNode->value;
}
}
14 changes: 11 additions & 3 deletions graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ scalar NonNegativeSeconds @scalar(class: "App\\GraphQL\\Scalars\\NonNegativeSeco
"A non-negative integer number of milliseconds."
scalar NonNegativeIntegerMilliseconds @scalar(class: "App\\GraphQL\\Scalars\\NonNegativeIntegerMilliseconds")

scalar Url @scalar(class: "App\\GraphQL\\Scalars\\Url")


"Indicates what fields are available at the top level of a query operation."
type Query {
Expand Down Expand Up @@ -144,7 +146,10 @@ type Project {
description: String!

"Homepage for this project."
homeurl: String!
homeurl: Url @deprecated(reason: "Use 'homeUrl' instead.")

"Homepage for this project."
homeUrl: Url @rename(attribute: "homeurl")

"Visibility."
visibility: ProjectVisibility! @rename(attribute: "public") @filterable
Expand Down Expand Up @@ -201,13 +206,16 @@ enum ProjectVisibility {

input CreateProjectInput {
"Unique name."
name: String!
name: String! @rules(apply: ["App\\Rules\\ProjectVisibilityRule"])

"Description."
description: String!

"Project homepage"
homeurl: String!
homeurl: Url @deprecated(reason: "Use 'homeUrl' instead.") @rules(apply: ["prohibits:homeUrl"])

"Project homepage"
homeUrl: Url @rename(attribute: "homeurl") @rules(apply: ["prohibits:homeurl"])

"Visibility."
visibility: ProjectVisibility! @rename(attribute: "public") @rules(attribute: "public", apply: ["App\\Rules\\ProjectVisibilityRule"])
Expand Down
18 changes: 18 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,24 @@ parameters:
count: 2
path: app/GraphQL/Scalars/NonNegativeSeconds.php

-
rawMessage: Cannot cast mixed to string.
identifier: cast.string
count: 1
path: app/GraphQL/Scalars/Url.php

-
rawMessage: Casting to string something that's already string.
identifier: cast.useless
count: 1
path: app/GraphQL/Scalars/Url.php

-
rawMessage: 'Part $value (mixed) of encapsed string cannot be cast to string.'
identifier: encapsedStringPart.nonString
count: 2
path: app/GraphQL/Scalars/Url.php

-
rawMessage: Class App\Http\Controllers\AbstractBuildController has an uninitialized property $build. Give it default value or assign it in the constructor.
identifier: property.uninitialized
Expand Down
14 changes: 7 additions & 7 deletions tests/Feature/GraphQL/ProjectTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ public function testCreateProjectNoUser(): void
'input' => [
'name' => $name,
'description' => 'test',
'homeurl' => 'https://cdash.org',
'homeUrl' => 'https://cdash.org',
'visibility' => 'PUBLIC',
'authenticateSubmissions' => false,
],
Expand All @@ -377,7 +377,7 @@ public function testCreateProjectUnauthorizedUser(): void
'input' => [
'name' => $name,
'description' => 'test',
'homeurl' => 'https://cdash.org',
'homeUrl' => 'https://cdash.org',
'visibility' => 'PUBLIC',
'authenticateSubmissions' => false,
],
Expand Down Expand Up @@ -405,7 +405,7 @@ public function testCreateProjectUserCreateProjectNoUser(): void
'input' => [
'name' => $name,
'description' => 'test',
'homeurl' => 'https://cdash.org',
'homeUrl' => 'https://cdash.org',
'visibility' => 'PUBLIC',
'authenticateSubmissions' => false,
],
Expand Down Expand Up @@ -433,7 +433,7 @@ public function testCreateProjectUserCreateProject(): void
'input' => [
'name' => $name,
'description' => 'test',
'homeurl' => 'https://cdash.org',
'homeUrl' => 'https://cdash.org',
'visibility' => 'PUBLIC',
'authenticateSubmissions' => false,
],
Expand Down Expand Up @@ -467,7 +467,7 @@ public function testCreateProjectAdmin(): void
'input' => [
'name' => $name,
'description' => 'test',
'homeurl' => 'https://cdash.org',
'homeUrl' => 'https://cdash.org',
'visibility' => 'PUBLIC',
'authenticateSubmissions' => false,
],
Expand Down Expand Up @@ -952,7 +952,7 @@ public function testCreateProjectMaxVisibility(string $user, string $visibility,
'input' => [
'name' => $name,
'description' => 'test',
'homeurl' => 'https://cdash.org',
'homeUrl' => 'https://cdash.org',
'visibility' => $visibility,
'authenticateSubmissions' => false,
],
Expand Down Expand Up @@ -1023,7 +1023,7 @@ public function testRequireAuthenticatedSubmissions(
'input' => [
'name' => $name,
'description' => 'test',
'homeurl' => 'https://cdash.org',
'homeUrl' => 'https://cdash.org',
'visibility' => 'PUBLIC',
'authenticateSubmissions' => $use_authenticated_submits,
],
Expand Down