This commit is contained in:
Александр Рыбкин 2024-11-20 15:32:19 +03:00
commit f7159b7d57
10 changed files with 1005 additions and 0 deletions

366
GraphQL.php Normal file
View File

@ -0,0 +1,366 @@
<?php
namespace dominion\api;
use Yii;
use yii\console\Exception;
use linslin\yii2\curl;
class GraphQL
{
private $url;
private $authUrl;
private $refreshUrl;
private $login;
private $pass;
private $query = '';
private $variables = [];
private static $jwt;
private static $jwtKeyCache = 'jwt';
private static $jwtRefreshKeyCache = 'refresh-token';
function __construct($key = 'apiGraphQL')
{
$this->getConfig($key);
}
private function getConfig($key = 'apiGraphQL')
{
if(empty(Yii::$app->params[$key])){
throw new Exception('Отсутствует конфигурация для rest-сервиса');
}
if(!isset(Yii::$app->params[$key]['url'])){
throw Exception('Отсутствует конфигурация для "url"');
}
if(!isset(Yii::$app->params[$key]['authUrl'])){
throw new Exception('Отсутствует конфигурация для "authUrl"');
}
if(!isset(Yii::$app->params[$key]['refreshUrl'])){
throw new Exception('Отсутствует конфигурация для "refreshUrl"');
}
if(!isset(Yii::$app->params[$key]['login'])){
throw new Exception('Отсутствует конфигурация для "login"');
}
if(!isset(Yii::$app->params[$key]['pass'])){
throw new Exception('Отсутствует конфигурация для "pass"');
}
$this->url = Yii::$app->params[$key]['url'];
$this->authUrl = Yii::$app->params[$key]['authUrl'];
$this->refreshUrl = Yii::$app->params[$key]['refreshUrl'];
$this->login = Yii::$app->params[$key]['login'];
$this->pass = Yii::$app->params[$key]['pass'];
self::$jwtKeyCache = 'jwt'.$key;
self::$jwtRefreshKeyCache = 'refresh-token'.$key;
}
public function setQuery($str, $settings = '')
{
$this->query = "query {$settings} {" . $str . "}";
}
public function setMutation($str, $settings = '')
{
$this->query = "mutation {$settings} {" . $str . "}";
}
public function setVariables($array)
{
$this->variables = $array;
}
public function setMutationVariables($str, $array = [])
{
$arSettings = [];
$variables = [];
foreach ($array as $key =>$value)
{
$arSettings[] = "\${$key}: {$value['type']}";
$type = str_replace('!', '', trim($value['type']));
$variables[$key] = null;
if(mb_substr(trim($value['type']), -1) == '!' || $value['value'] !== null)
{
switch (mb_strtolower($type)){
case 'int':
$variables[$key] = (int)$value['value'];
break;
case 'boolean':
$variables[$key] = (bool)$value['value'];
break;
case 'string':
$variables[$key] = (string)$value['value'];
break;
case '[int]':
$variables[$key] = self::intValue($value['value']);
break;
case '[string]':
$variables[$key] = self::stringValue($value['value']);
break;
}
}
}
$settingsStr = 'settings(' . implode(', ', $arSettings) .')';
$this->setMutation($str, $settingsStr);
$this->setVariables($variables);
}
public function getValue($attribute = null)
{
try
{
$value = $this->sendRequest();
}
catch (\Exception $ex)
{
$value = $this->sendRequest();
}
$output = isset($value['data']) ? $value['data'] : [];
if(!empty($attribute))
{
$output = isset($output[$attribute]) ? $output[$attribute] : [];
}
return $output;
}
public function refreshToken()
{
try
{
if(($refreshToken = Yii::$app->cache->get(self::$jwtRefreshKeyCache)) !== false)
{
$curl = new curl\Curl();
$curl->setHeader('Content-Type', 'application/json; charset=UTF-8');
$curl->setHeader('cookie', $refreshToken);
$result = $curl->post($this->refreshUrl,false);
if(isset($result["token"]))
{
self::$jwt = $result["token"];
Yii::$app->cache->set(self::$jwtKeyCache, self::$jwt, self::getJwtExtDelta());
}
}
}
catch (Exception $e)
{
throw new Exception($e->getMessage() . "\n". "url:\n " . $this->refreshUrl);
}
}
public function login($update = false)
{
try
{
if($update || (self::$jwt = Yii::$app->cache->get(self::$jwtKeyCache)) == false)
{
$curl = new curl\Curl();
$curl->setHeader('Content-Type', 'application/json; charset=UTF-8');
$curl->setRequestBody(json_encode(['login' => $this->login, 'pass' => $this->pass]));
$result = $curl->post($this->authUrl,false);
if(isset($result["token"]))
{
self::$jwt = $result["token"];
Yii::$app->cache->set(self::$jwtKeyCache, self::$jwt, self::getJwtExtDelta());
preg_match_all('/^\s*([^;]*)/mi', $curl->responseHeaders["Set-Cookie"], $matches);
$cookies = array();
foreach($matches[1] as $item) {
parse_str($item, $cookie);
$cookies = array_merge($cookies, $cookie);
}
if(isset($cookies["refresh-token"]))
{
Yii::$app->cache->set(self::$jwtRefreshKeyCache, 'refresh-token='.$cookies["refresh-token"], 3600*24*100);
}
}
else
{
throw new Exception('Нет токена');
}
}
}
catch (Exception $e)
{
throw new Exception($e->getMessage() . "\n". "url:\n " . $this->authUrl);
}
return self::$jwt;
}
public static function getJwtParam($key, $default = false)
{
$output = $default;
self::$jwt = self::$jwt ? self::$jwt: Yii::$app->cache->get(self::$jwtKeyCache);
if(self::$jwt)
{
$params = explode('.', self::$jwt);
if(isset($params[1]))
{
$value = json_decode(base64_decode($params[1]), true);
$output = isset($value[$key]) ? $value[$key] : $output;
}
}
return $output;
}
public static function getJwtExtDelta()
{
$jwtExp = self::getJwtParam('exp');
return $jwtExp - time() - 30;
}
public function getJwt()
{
self::$jwt = self::$jwt ? self::$jwt: Yii::$app->cache->get(self::$jwtKeyCache);
if(self::$jwt)
{
if(self::getJwtExtDelta() <= 0)
{
self::$jwt = null;
}
}
if(!self::$jwt)
{
$this->refreshToken();
}
if(self::$jwt)
{
$role = self::getJwtParam('role', 'anon');
if($role == 'anon')
{
$this->login(true);
}
}
if(!self::$jwt)
{
$this->login();
}
return self::$jwt;
}
private function sendRequest()
{
$curl = new curl\Curl();
$curl->setHeader('Content-Type', 'application/json; charset=UTF-8');
$curl->setHeader('Authorization', 'Bearer ' . $this->getJwt());
$body = json_encode([
'query' => $this->query,
'variables' => $this->variables,
]);
if(isset(\Yii::$app->params['CURL_TIMEOUT']) && \Yii::$app->params['CURL_TIMEOUT'] > 0)
{
$curl->setOption(CURLOPT_TIMEOUT, \Yii::$app->params['CURL_TIMEOUT']);
}
$curl->setRequestBody($body);
$response = $curl->post($this->url,false);
if(isset($response['errors']))
{
throw new Exception('graphql error ' . json_encode($response) . "Тело:\n " . $body);
}
$errorMessage = ($curl->responseCode != 200) ? ("\n". print_r($response, true) . "Тело:\n " . $body) : '';
switch ($curl->responseCode) {
case 'timeout':
throw new Exception('Network timeout'.$errorMessage);
break;
case 200:
return $response;
break;
case 404:
throw new Exception('404. Page not found'.$errorMessage);
break;
case 403:
throw new Exception('403. Access deny'.$errorMessage);
break;
case 401:
throw new Exception('401. Autorization required'.$errorMessage);
break;
case 400:
throw new Exception('400. Bad request'.$errorMessage);
break;
case 500:
throw new Exception('500. Internal server error'.$errorMessage);
break;
case 503:
throw new Exception('503. Service unavailable'.$errorMessage);
break;
case 502:
throw new Exception('502. Bad gateway'.$errorMessage);
break;
}
}
public function setQueryPaginction($object, $select, $filter = [], $page = null, $perPage = null, $wrapper = 'data')
{
$page = $page === null ? (isset($_GET['page']) ? $_GET['page'] : 1) : $page;
$perPage = $perPage === null ? \Yii::$app->user->identity->countPage : $perPage;
$filterStr = empty($filter) ? '' : ('(' . implode(', ', $filter) . ')');
$this->setQuery(" {$object}(page:{$page}, perPage:{$perPage}) { {$wrapper} {$filterStr} { {$select} }, totalCount }");
}
public function setSortFilters($filter, $params, $default = 'id_desc', $field = 'sort')
{
$sort = $default;
if (isset($params[$field]))
{
$sort = (mb_substr($params[$field], 0, 1) == '-') ? (mb_substr($params[$field], 1).'_desc') : ( $params[$field].'_asc');
}
$filter[] = "sort: \"{$sort}\"";
return $filter;
}
public function setFilterModel($type, $filter, $model, $fields)
{
foreach ($fields as $key)
{
if(!empty($model->{$key}) || $model->{$key} === true || $model->{$key} === false || $model->{$key} === "0" || $model->{$key} === 0 )
{
switch ($type){
case "string":
$filter[] = "{$key}: \"{$model->$key}\"";
break;
case "number":
$value = (float)$model->$key;
$filter[] = "{$key}: {$value}";
break;
case "bool":
$value = $model->$key ? 'true' : 'false';
$filter[] = "{$key}: {$value}";
break;
}
}
}
return $filter;
}
public function setFilterString($filter, $model, $fields)
{
return $this->setFilterModel('string', $filter, $model, $fields);
}
public function setFilterNumber($filter, $model, $fields)
{
return $this->setFilterModel('number', $filter, $model, $fields);
}
public function setFilterBool($filter, $model, $fields)
{
return $this->setFilterModel('bool', $filter, $model, $fields);
}
public static function intValue($array)
{
$output = [];
foreach($array as $id)
{
$output[] = (int)$id;
}
return $output;
}
public static function stringValue($array)
{
$output = [];
foreach($array as $id)
{
$output[] = (string)$id;
}
return $output;
}
}

144
GraphQLPagination.php Normal file
View File

@ -0,0 +1,144 @@
<?php
namespace dominion\api;
use GraphQL\Type\Definition\Type;
class GraphQLPagination
{
public $parentRoot;
public $page = 1;
public $perPage = 25;
public $offset = 0;
public $totalCount = 0;
public $pageCount = 0;
public $currentPage = 0;
public $sort = '';
public $data = [];
public $addArgs = [];
public static $arPrefix = [
'<' => 'lt',
'>' => 'gt',
'<=' => 'lte',
'>=' => 'gte',
'!=' => 'neq',
'IN' => 'in',
'NOT IN' => 'nin',
// 'LIKE' => 'like',
];
public function setMeta($totalCount, $perPage)
{
$this->totalCount = $totalCount - $this->offset;
$this->perPage = $perPage;
$this->currentPage = $this->page;
$this->pageCount = ceil($this->totalCount/ $this->perPage);
}
public function setMetaByQuery($query)
{
$this->setMeta($query->count(), $this->perPage);
}
public function andWhere($query, $params, $fields, $prefix = '')
{
$prefix = empty($prefix) ? '' : ($prefix . '.');
foreach($fields as $item)
{
if(isset($params[$item]))
{
$query->andWhere([$prefix . $item => is_bool($params[$item]) ? (int)$params[$item] : $params[$item]]);
}
foreach (self::$arPrefix as $key => $pref)
{
$newKey = "{$pref}_{$item}";
if(isset($params[$newKey]))
{
$query->andWhere([$key, $prefix . $item, $params[$newKey]]);
}
}
}
return $query;
}
public function andWhereLike($query, $params, $fields, $prefix = '')
{
$prefix = empty($prefix) ? '' : ($prefix . '.');
foreach($fields as $item)
{
if(isset($params[$item]))
{
$query->andWhere(['like', $prefix . $item, $params[$item]]);
}
}
return $query;
}
public function orderBy($query, $params, $fields, $sortParam = 'sort', $prefix = '')
{
$prefix = empty($prefix) ? '' : ($prefix . '.');
$sort = isset($params[$sortParam]) ? $params[$sortParam] : (isset($params['in_'.$sortParam]) ? $params['in_'.$sortParam] : []);
if(!empty($sort))
{
$sort = is_array($sort) ? $sort : (array)$sort;
$orderBy = [];
foreach($sort as $item)
{
$value = explode('_', $item);
if(count($value) == 2 && in_array($value[0], $fields) && in_array($value[1], ['asc', 'desc']))
{
$orderBy[$prefix . $value[0]] = $value[1] == 'asc' ? SORT_ASC : SORT_DESC;
}
elseif($item == 'rand')
{
$orderBy['RAND()'] = SORT_ASC;
}
}
if(!empty($orderBy))
{
$query->orderBy($orderBy);
}
}
return $query;
}
public function getItemsByPage($query)
{
$offset = $this->perPage * ($this->page -1);
$offset += $this->offset;
return $query->limit($this->perPage)->offset($offset)->all();
}
public static function argumentModify($args = [])
{
foreach ($args as $key=> $value)
{
if(isset($value['type']) && /*in_array($value['type'], [Type::int()]) &&*/ isset($value['modify']) && $value['modify'])
{
$arPrefix = isset($value['modifyOption']) ? (array)$value['modifyOption'] : self::$arPrefix;
if(str_replace($arPrefix, '', $key) == $key)
{
foreach ($arPrefix as $prefix)
{
$newKey = "{$prefix}_{$key}";
if (!isset($args[$newKey]))
{
$args[$newKey] = $value;
if(in_array($prefix, ['in', 'nin']))
{
$args[$newKey]['type'] = Type::listOf($args[$newKey]['type']);
}
}
}
}
}
}
return $args;
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace dominion\api;
use Yii;
class GraphQLResultSaveHalper
{
public static function setResultValue($model, $value)
{
$model->id = isset($value["id"]) ? $value["id"] : 0;
if(isset($value["errors"]))
{
foreach ($value["errors"] as $errors)
{
foreach ($errors['messages'] as $message)
{
$model->addError($errors['code'], $message);
}
}
}
return isset($value['status']) && $value['status'] == 'success';
}
}

View File

@ -0,0 +1,74 @@
<?php
namespace dominion\api;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use dominion\api\GraphQLPagination;
class GraphQLSchemaPagination extends ObjectType
{
public $isPagination = false;
public function getCustomFields()
{
return [
'totalCount' => [
'type' => Type::int(),
'description' => 'Количество элементов',
],
'pageCount' => [
'type' => Type::int(),
'description' => 'Количество страниц',
],
'currentPage' => [
'type' => Type::int(),
'description' => 'Текущая страница',
],
'perPage' => [
'type' => Type::int(),
'description' => 'Элементов на странице',
],
];
}
public function getCustomResolve($root, $args)
{
$model = new GraphQLPagination;
$model->parentRoot = $root;
$model->page = isset($args['page']) && $args['page'] > 1 ? $args['page'] : 1;
$model->perPage = isset($args['perPage']) && $args['perPage'] > 0 ? $args['perPage'] : 50;
$model->offset = isset($args['offset']) && $args['offset'] > 0 ? $args['offset'] : 0;
$model->addArgs = isset($args['addArgs']) ? (array)$args['addArgs'] : [];
return $model;//['totalCount' =>0, 'pageCount' => 0, 'currentPage' => 0, 'perPage'=> 0, 'data' => []];
}
public function getCustomArgs()
{
return [
'page' => [
'type' => Type::int(),
'description' => 'Номер страницы (по умолчанию 1)',
],
'perPage' => [
'type' => Type::int(),
'description' => 'Количество элементов на странице (по умолчанию 50)',
],
'offset' => [
'type' => Type::int(),
'description' => 'Смещение от начала выборки',
],
];
}
public function resultArguments($args)
{
$output = [];
foreach ($args as $key => $value)
{
$output[$key] = json_decode($value, true);
}
return $output;
}
}

274
Swagger.php Normal file
View File

@ -0,0 +1,274 @@
<?php
namespace dominion\api;
use Yii;
use yii\console\Exception;
use linslin\yii2\curl;
class Swagger
{
private $url;
private $method;
private $perPage;
private $perPageParam;
private $pageParam;
private $params;
private $content;
private $currentPage = 1;
private $lastPage = false;
public $isRaw = false;
function __construct($apiName, $function, $params = [], $urlParams = [], $version = false, $raw = false)
{
$arConfig = $this->getConfig($apiName, $function, $urlParams, $version);
$this->url = $arConfig['url'];
$this->method = $arConfig['method'];
$this->perPage = $arConfig['perPage'];
$this->perPageParam = $arConfig['perPageParam'];
$this->pageParam = $arConfig['pageParam'];
$this->content = $arConfig['content'];
$this->params = $params;
$this->isRaw = $raw;
}
private function getConfig($apiName, $function, $urlParams = [], $version = false)
{
$configParams = isset(Yii::$app->params[$apiName]) ? Yii::$app->params[$apiName] : [];
if(empty($configParams)) {
throw new Exception('Отсутствует конфигурация для rest-сервиса');
}
if(!isset($configParams['defaultVersion']) or (empty($configParams['defaultVersion']))) {
throw new Exception('Отсутствует дефолтная версия для rest-сервиса');
}
if(!isset($configParams['defaultPerPage']) or (empty($configParams['defaultPerPage']))) {
throw new Exception('Отсутствует дефолтная конфигурация постраничной навигации rest-сервиса');
}
if(!isset($configParams['protocol']) or empty($configParams['protocol'])) {
throw new Exception('Протокол rest-сервиса не указан.');
}
if(($configParams['protocol'] !== 'http://') and ($configParams['protocol'] !== 'https://')) {
throw new Exception('Протокол rest-сервиса указан неверно.');
}
if(!isset($configParams['perPageParam']) or empty($configParams['perPageParam'])) {
throw new Exception('Отсутствует параметр постраничной навигации perPageParam.');
}
if(!isset($configParams['pageParam']) or empty($configParams['pageParam'])) {
throw new Exception('Отсутствует парамер постраничной навигации pageParam.');
}
if(!isset($configParams['baseUrl']) or empty($configParams['baseUrl'])) {
throw new Exception('Отсутствует доменное имя для rest-сервиса.');
}
if(empty($version)) {
$version = $configParams['defaultVersion'];
}
if(empty($configParams['version'][$version])) {
throw new Exception('Выбранная версия rest-сервиса отсутствует');
}
if(!isset($configParams['version'][$version]['functions'][$function])) {
throw new Exception('Функция '.$function.' отсутствует в api версии '.$version);
}
$url = '';
if(is_string($configParams['version'][$version]['functions'][$function]))
{
$url = $configParams['version'][$version]['functions'][$function];
}
elseif(isset($configParams['version'][$version]['functions'][$function]['url']))
{
$url = $configParams['version'][$version]['functions'][$function]['url'];
}
if(!isset($url) or empty($url)) {
throw new Exception('Для функции '.$function.' отсутствует url');
}
if(isset($configParams['version'][$version]['functions'][$function]['content']))
{
$content = $configParams['version'][$version]['functions'][$function]['content'];
}
else
{
$content = $configParams['version'][$version]['content'];
}
if(!isset($content) or empty($content)) {
throw new Exception('Для функции '.$function.' отсутствует ключ массива в котором содержится ответ');
}
if(!isset($configParams['version'][$version]['functions'][$function]['perPage']) or empty($configParams['version'][$version]['functions'][$function]['perPage'])) {
$perPage = $configParams['defaultPerPage'];
} else {
$perPage = $configParams['version'][$version]['functions'][$function]['perPage'];
}
if(!isset($configParams['version'][$version]['functions'][$function]['method']) or
empty($configParams['version'][$version]['functions'][$function]['method']))
{
$method = isset($configParams['version'][$version]['method']) ? $configParams['version'][$version]['method'] : 'GET';
}
else
{
$method = $configParams['version'][$version]['functions'][$function]['method'];
}
if(!empty($urlParams)) {
$url = vsprintf($url, $urlParams);
}
return [
'url' => $configParams['protocol']
.$configParams['baseUrl']
.$configParams['version'][$version]['url']
.$url,
'method' => $method,
'perPage' => $perPage,
'perPageParam' => $configParams['perPageParam'],
'pageParam' => $configParams['pageParam'],
'content' => $content,
];
}
public function resetCounter()
{
$this->currentPage = 1;
$this->lastPage = false;
}
public function getNextPage()
{
if($this->lastPage) return false;
$result = [];
$response = $this->sendRequest($this->currentPage);
if(isset($response[$this->content]))
{
foreach ($response[$this->content] as $value)
{
$result[] = $value;
}
}
if(
!isset($response['_meta']['pageCount']) or
empty($response['_meta']['pageCount']) or
$response['_meta']['pageCount'] === $this->currentPage
) {
$this->lastPage = true;
} else {
$this->currentPage++;
}
return $result;
}
public function getOne()
{
$result = $this->getNextPage();
return isset($result[0]) ? $result[0] : false;
}
public function doBatchRequest()
{
$result = [];
$page = 1;
while(true) {
$response = $this->sendRequest($page);
if (isset($response[$this->content]) and is_array($response[$this->content]) and !empty($response[$this->content]) ) {
foreach ($response[$this->content] as $value) {
$result[] = $value;
}
} else {
return $result;
}
if(
!isset($response['_meta']['pageCount']) or
empty($response['_meta']['pageCount']) or
$response['_meta']['pageCount'] === $page
) {
break;
}
unset($response);
$page++;
}
return $result;
}
public function getBody()
{
return $this->isRaw ? json_encode($this->params) : json_encode(['filter' => $this->params]) ;
}
private function sendRequest($page = 1)
{
$curl = new curl\Curl();
$curl->setHeader('Content-Type', 'application/json; charset=UTF-8');
$params = [$this->perPageParam => $this->perPage, $this->pageParam => $page];
if (!empty($this->sort))
{
$params['sort'] = $this->sort;
}
if($this->method === 'POST')
{
$curl->setGetParams($params);
if(!empty($this->params))
{
$curl->setRequestBody($this->getBody());
}
$response = $curl->post($this->url,false);
}
elseif($this->method === 'GET') {
$curl->setGetParams(array_merge($params, ['filter' => $this->params]));
$response = $curl->get($this->url,false);
} else {
throw new Exception('Метод '.$this->method.' не поддерживается');
}
switch ($curl->responseCode) {
case 'timeout':
throw new Exception('Network timeout');
break;
case 200:
return $response;
break;
case 404:
throw new Exception('404. Page not found '. $this->url . ' ' . $this->getBody());
break;
case 403:
throw new Exception('403. Access deny '. $this->url . ' ' . $this->getBody());
break;
case 401:
throw new Exception('401. Autorization required '. $this->url . ' ' . $this->getBody());
break;
case 400:
throw new Exception('400. Bad request '. $this->url . ' ' . $this->getBody());
break;
case 500:
throw new Exception('500. Internal server error '. $this->url . ' ' . $this->getBody());
break;
case 503:
throw new Exception('503. Service unavailable '. $this->url . ' ' . $this->getBody());
break;
case 502:
throw new Exception('502. Bad gateway '. $this->url . ' ' . $this->getBody());
break;
}
}
public function setSort($str)
{
$this->sort = $str;
}
}

21
composer.json Normal file
View File

@ -0,0 +1,21 @@
{
"name": "dominion/api",
"description": "Функционал для работы с api",
"type": "yii2-extension",
"keywords": ["yii2","extension"],
"license": "MIT",
"authors": [
{
"name": "Rybkin Sasha",
"email": "ribkin@dominion.ru"
}
],
"require": {
"yiisoft/yii2": "~2.0.0"
},
"autoload": {
"psr-4": {
"dominion\\api\\": ""
}
}
}

19
schema/ApiTypes.php Normal file
View File

@ -0,0 +1,19 @@
<?php
namespace dominion\api\schema;
trait ApiTypes
{
private static $resultSave;
private static $resultSaveError;
public static function resultSave()
{
return self::$resultSave ?: (self::$resultSave = new ResultSaveType());
}
public static function resultSaveError()
{
return self::$resultSaveError ?: (self::$resultSaveError = new ResultSaveErrorType());
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace dominion\api\schema;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
class ResultSaveErrorType extends ObjectType
{
public function __construct()
{
$config = [
'fields' => function() {
return [
'code' => [
'type' => Type::string(),
'description' => 'поле',
],
'messages' => [
'type' => Type::listOf(Type::string()),
'description' => 'текст ошибки',
],
];
}
];
parent::__construct($config);
}
}

45
schema/ResultSaveType.php Normal file
View File

@ -0,0 +1,45 @@
<?php
namespace dominion\api\schema;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
class ResultSaveType extends ObjectType
{
public function __construct()
{
$config = [
'fields' => function() {
return [
'id' => [
'type' => Type::int(),
'description' => 'Id',
],
'status' => [
'type' => Type::string(),
'description' => 'status',
'resolve' => function($root, $args) {
return empty($root->errors) ? 'success' : 'error';
}
],
'errors' => [
'type' => Type::listOf(Types::resultSaveError()),
'description' => 'ошибки',
'resolve' => function($root, $args) {
$output = [];
foreach ($root->errors as $key => $value)
{
$output[] = ['code' => $key, 'messages'=> $value];
}
return $output;
}
],
];
}
];
parent::__construct($config);
}
}

8
schema/Types.php Normal file
View File

@ -0,0 +1,8 @@
<?php
namespace dominion\api\schema;
class Types
{
use ApiTypes;
}