graphql-php/src/Language/Source.php

87 lines
2.4 KiB
PHP
Raw Normal View History

2015-07-15 23:05:46 +06:00
<?php
2018-08-13 10:36:03 +02:00
declare(strict_types=1);
2015-07-15 23:05:46 +06:00
namespace GraphQL\Language;
use GraphQL\Utils\Utils;
2018-08-13 10:36:03 +02:00
use function is_string;
use function json_decode;
use function mb_strlen;
use function mb_substr;
use function preg_match_all;
use const PREG_OFFSET_CAPTURE;
2015-07-15 23:05:46 +06:00
class Source
{
2018-08-13 10:36:03 +02:00
/** @var string */
2015-07-15 23:05:46 +06:00
public $body;
2018-08-13 10:36:03 +02:00
/** @var int */
2015-07-15 23:05:46 +06:00
public $length;
2018-08-13 10:36:03 +02:00
/** @var string */
2015-07-15 23:05:46 +06:00
public $name;
2018-08-13 10:36:03 +02:00
/** @var SourceLocation */
public $locationOffset;
/**
2018-08-13 10:36:03 +02:00
*
*
* A representation of source input to GraphQL.
* `name` and `locationOffset` are optional. They are useful for clients who
* store GraphQL documents in source files; for example, if the GraphQL input
* starts at line 40 in a file named Foo.graphql, it might be useful for name to
* be "Foo.graphql" and location to be `{ line: 40, column: 0 }`.
* line and column in locationOffset are 1-indexed
*
2018-08-13 10:36:03 +02:00
* @param string $body
* @param string|null $name
*/
2018-08-13 10:36:03 +02:00
public function __construct($body, $name = null, ?SourceLocation $location = null)
2015-07-15 23:05:46 +06:00
{
Utils::invariant(
is_string($body),
'GraphQL query body is expected to be string, but got ' . Utils::getVariableType($body)
);
2018-08-13 10:36:03 +02:00
$this->body = $body;
$this->length = mb_strlen($body, 'UTF-8');
$this->name = $name ?: 'GraphQL request';
$this->locationOffset = $location ?: new SourceLocation(1, 1);
Utils::invariant(
$this->locationOffset->line > 0,
'line in locationOffset is 1-indexed and must be positive'
);
Utils::invariant(
$this->locationOffset->column > 0,
'column in locationOffset is 1-indexed and must be positive'
);
2015-07-15 23:05:46 +06:00
}
/**
2018-08-13 10:36:03 +02:00
* @param int $position
2015-07-15 23:05:46 +06:00
* @return SourceLocation
*/
public function getLocation($position)
{
2018-08-13 10:36:03 +02:00
$line = 1;
2015-07-15 23:05:46 +06:00
$column = $position + 1;
2018-08-13 10:36:03 +02:00
$utfChars = json_decode('"\u2028\u2029"');
$lineRegexp = '/\r\n|[\n\r' . $utfChars . ']/su';
$matches = [];
2015-07-15 23:05:46 +06:00
preg_match_all($lineRegexp, mb_substr($this->body, 0, $position, 'UTF-8'), $matches, PREG_OFFSET_CAPTURE);
foreach ($matches[0] as $index => $match) {
$line += 1;
2018-08-13 10:36:03 +02:00
2015-07-15 23:05:46 +06:00
$column = $position + 1 - ($match[1] + mb_strlen($match[0], 'UTF-8'));
}
return new SourceLocation($line, $column);
}
}