Initial Commit
This commit is contained in:
commit
052cbe3038
69
Plugin.php
Normal file
69
Plugin.php
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?php namespace GermanAirlinesVa\Graphql;
|
||||||
|
|
||||||
|
use System\Classes\PluginBase;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Config;
|
||||||
|
use Illuminate\Foundation\AliasLoader;
|
||||||
|
use GermanAirlinesVa\Graphql\Classes\GraphqlServiceProvider;
|
||||||
|
|
||||||
|
class Plugin extends PluginBase
|
||||||
|
{
|
||||||
|
public function registerComponents()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function registerSettings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
App::make('October\Rain\Support\ClassLoader')->addDirectories('graphql');
|
||||||
|
$this->bootPackages();
|
||||||
|
App::register(GraphqlServiceProvider::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bootPackages()
|
||||||
|
{
|
||||||
|
// Get the namespace of the current plugin to use in accessing the Config of the plugin
|
||||||
|
$pluginNamespace = str_replace('\\', '.', strtolower(__NAMESPACE__));
|
||||||
|
|
||||||
|
// Instantiate the AliasLoader for any aliases that will be loaded
|
||||||
|
$aliasLoader = AliasLoader::getInstance();
|
||||||
|
|
||||||
|
// Get the packages to boot
|
||||||
|
$packages = Config::get($pluginNamespace . '::packages');
|
||||||
|
|
||||||
|
// Boot each package
|
||||||
|
foreach ($packages as $name => $options)
|
||||||
|
{
|
||||||
|
// Setup the configuration for the package, pulling from this plugin's config
|
||||||
|
if (!empty($options['config']) && !empty($options['config_namespace']))
|
||||||
|
{
|
||||||
|
Config::set($options['config_namespace'], $options['config']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register any Service Providers for the package
|
||||||
|
if (!empty($options['providers']))
|
||||||
|
{
|
||||||
|
foreach ($options['providers'] as $provider)
|
||||||
|
{
|
||||||
|
App::register($provider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register any Aliases for the package
|
||||||
|
if (!empty($options['aliases']))
|
||||||
|
{
|
||||||
|
foreach ($options['aliases'] as $alias => $path)
|
||||||
|
{
|
||||||
|
$aliasLoader->alias($alias, $path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $packages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
24
classes/CreatesContext.php
Normal file
24
classes/CreatesContext.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace GermanAirlinesVa\Graphql\Classes;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Nuwave\Lighthouse\Support\Contracts\CreatesContext as LighthouseCreatesContext;
|
||||||
|
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||||
|
|
||||||
|
|
||||||
|
class CreatesContext implements LighthouseCreatesContext
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate GraphQL context.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @return GraphQLContext
|
||||||
|
*/
|
||||||
|
public function generate(Request $request): GraphQLContext
|
||||||
|
{
|
||||||
|
return new SchemaContext($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
46
classes/Graph.php
Normal file
46
classes/Graph.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace GermanAirlinesVa\Graphql\Classes;
|
||||||
|
|
||||||
|
use Lang;
|
||||||
|
use Cms\Classes\Page;
|
||||||
|
|
||||||
|
|
||||||
|
class Graph extends Page
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string The container name associated with the model.
|
||||||
|
*/
|
||||||
|
protected $dirName = 'graphs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array The attributes that are mass assignable.
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'title',
|
||||||
|
'description',
|
||||||
|
'markup',
|
||||||
|
'settings',
|
||||||
|
'code'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array The rules to be applied to the data.
|
||||||
|
*/
|
||||||
|
public $rules = [
|
||||||
|
'title' => 'required'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function getCodeClassParent() : string {
|
||||||
|
return GraphCode::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function runComponents()
|
||||||
|
{
|
||||||
|
foreach ($this->components as $component) {
|
||||||
|
$component->onRun();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
55
classes/GraphCode.php
Normal file
55
classes/GraphCode.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php namespace GermanAirlinesVa\Graphql\Classes;
|
||||||
|
|
||||||
|
use Cms\Classes\CodeBase;
|
||||||
|
use October\Rain\Extension\Extendable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent class for PHP classes created for graph PHP resolver section.
|
||||||
|
*/
|
||||||
|
class GraphCode extends CodeBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public $graph;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the object instance.
|
||||||
|
* @param \GermanAirlinesVa\Graphql\Classes\Graph $graph Specifies the Headstart graph.
|
||||||
|
* @param null
|
||||||
|
* @param \GermanAirlinesVa\Graphql\Classes\GraphController $controller Specifies the Graph controller.
|
||||||
|
*/
|
||||||
|
public function __construct($graph, $layout, $controller)
|
||||||
|
{
|
||||||
|
$this->graph = $graph;
|
||||||
|
$this->controller = $controller;
|
||||||
|
|
||||||
|
Extendable::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __get($name)
|
||||||
|
{
|
||||||
|
if (isset($this->graph->components[$name]) || isset($this->layout->components[$name])) {
|
||||||
|
return $this[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($value = $this->graph->{$name}) !== null) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists($name, $this->controller->vars)) {
|
||||||
|
return $this[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __set($name, $value)
|
||||||
|
{
|
||||||
|
return $this->graph->{$name} = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __isset($name)
|
||||||
|
{
|
||||||
|
return isset($this->graph->{$name});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
118
classes/GraphController.php
Normal file
118
classes/GraphController.php
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace GermanAirlinesVa\Graphql\Classes;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Config;
|
||||||
|
use Cms\Classes\Controller;
|
||||||
|
use Cms\Classes\CmsException;
|
||||||
|
use Cms\Classes\ComponentManager;
|
||||||
|
|
||||||
|
|
||||||
|
class GraphController// extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $graph;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var self Cache of self
|
||||||
|
*/
|
||||||
|
protected static $instance;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the controller.
|
||||||
|
*/
|
||||||
|
public function __construct($graph, $args)
|
||||||
|
{
|
||||||
|
$this->graph = $graph;
|
||||||
|
$this->router = new GraphRouter($args);
|
||||||
|
|
||||||
|
self::$instance = $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an existing instance of the controller.
|
||||||
|
* If the controller doesn't exists, returns null.
|
||||||
|
* @return mixed Returns the controller object or null.
|
||||||
|
*/
|
||||||
|
public static function getController()
|
||||||
|
{
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function component($alias) {
|
||||||
|
if (isset($this->graph->components[$alias])) {
|
||||||
|
return $this->graph->components[$alias];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->graph->settings['components'] as $component => $properties) {
|
||||||
|
list($name, $component_alias) = strpos($component, ' ')
|
||||||
|
? explode(' ', $component)
|
||||||
|
: [$component, $component];
|
||||||
|
|
||||||
|
if ($component_alias == $alias) {
|
||||||
|
// make component
|
||||||
|
$manager = ComponentManager::instance();
|
||||||
|
|
||||||
|
if (!$componentObj = $manager->makeComponent($name, null, $properties)) {
|
||||||
|
throw new CmsException(Lang::get('cms::lang.component.not_found', ['name' => $name]));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setComponentPropertiesFromParams($componentObj, $this->router->getParameters());
|
||||||
|
$componentObj->init();
|
||||||
|
|
||||||
|
$componentObj->alias = $alias;
|
||||||
|
$this->graph->components[$alias] = $componentObj;
|
||||||
|
|
||||||
|
return $componentObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets component property values from partial parameters.
|
||||||
|
* The property values should be defined as {{ param }}.
|
||||||
|
* @param ComponentBase $component The component object.
|
||||||
|
* @param array $parameters Specifies the partial parameters.
|
||||||
|
*/
|
||||||
|
protected function setComponentPropertiesFromParams($component, $parameters = [])
|
||||||
|
{
|
||||||
|
$properties = $component->getProperties();
|
||||||
|
$routerParameters = $this->router->getParameters();
|
||||||
|
|
||||||
|
foreach ($properties as $propertyName => $propertyValue) {
|
||||||
|
if (is_array($propertyValue)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$matches = [];
|
||||||
|
if (preg_match('/^\{\{([^\}]+)\}\}$/', $propertyValue, $matches)) {
|
||||||
|
$paramName = trim($matches[1]);
|
||||||
|
|
||||||
|
if (substr($paramName, 0, 1) == ':') {
|
||||||
|
$routeParamName = substr($paramName, 1);
|
||||||
|
$newPropertyValue = $routerParameters[$routeParamName] ?? null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$newPropertyValue = $parameters[$paramName] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$component->setProperty($propertyName, $newPropertyValue);
|
||||||
|
$component->setExternalPropertyName($propertyName, $paramName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a routing parameter.
|
||||||
|
* @param string $name Routing parameter name.
|
||||||
|
* @param string $default Default to use if none is found.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function param($name, $default = null)
|
||||||
|
{
|
||||||
|
return $this->router->getParameter($name, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
44
classes/GraphRouter.php
Normal file
44
classes/GraphRouter.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace GermanAirlinesVa\Graphql\Classes;
|
||||||
|
|
||||||
|
use File;
|
||||||
|
use Cms\Classes\Router;
|
||||||
|
|
||||||
|
class GraphRouter //extends Router
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array A list of parameters names and values extracted from the URL pattern and URL string.
|
||||||
|
*/
|
||||||
|
protected $parameters = [];
|
||||||
|
|
||||||
|
public function __construct($parameters)
|
||||||
|
{
|
||||||
|
$this->parameters = $parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current routing parameters.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getParameters()
|
||||||
|
{
|
||||||
|
return $this->parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a routing parameter.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getParameter($name, $default = null)
|
||||||
|
{
|
||||||
|
if (isset($this->parameters[$name]) && !empty($this->parameters[$name])) {
|
||||||
|
return $this->parameters[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
22
classes/GraphqlServiceProvider.php
Normal file
22
classes/GraphqlServiceProvider.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php namespace GermanAirlinesVa\Graphql\Classes;
|
||||||
|
|
||||||
|
use Nuwave\Lighthouse\Schema\Source\SchemaSourceProvider;
|
||||||
|
use Nuwave\Lighthouse\Support\Contracts\CreatesContext;
|
||||||
|
use Nuwave\Lighthouse\Support\Contracts\ProvidesResolver;
|
||||||
|
use GermanAirlinesVa\Graphql\Classes\ResolverProvider as GraphqlProvidesResolver;
|
||||||
|
use GermanAirlinesVa\Graphql\Classes\SchemaSourceProvider as GraphqlSchemaSourceProvider;
|
||||||
|
use GermanAirlinesVa\Graphql\Classes\CreatesContext as GraphqlCreatesContext;
|
||||||
|
|
||||||
|
use October\Rain\Support\ServiceProvider;
|
||||||
|
|
||||||
|
|
||||||
|
class GraphqlServiceProvider extends ServiceProvider {
|
||||||
|
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
$this->app->bind(ProvidesResolver::class, GraphqlProvidesResolver::class);
|
||||||
|
$this->app->singleton(CreatesContext::class, GraphqlCreatesContext::class);
|
||||||
|
$this->app->singleton(SchemaSourceProvider::class, GraphqlSchemaSourceProvider::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
39
classes/ResolverProvider.php
Normal file
39
classes/ResolverProvider.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php namespace GermanAirlinesVa\Graphql\Classes;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Nuwave\Lighthouse\Schema\Values\FieldValue;
|
||||||
|
use GraphQL\Type\Definition\ResolveInfo;
|
||||||
|
use Cms\Classes\CodeParser;
|
||||||
|
use Nuwave\Lighthouse\Schema\ResolverProvider as LighthouseResolverProvider;
|
||||||
|
|
||||||
|
|
||||||
|
class ResolverProvider extends LighthouseResolverProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a field resolver in case no resolver directive is defined for a field.
|
||||||
|
*
|
||||||
|
* @param \Nuwave\Lighthouse\Schema\Values\FieldValue $fieldValue
|
||||||
|
* @return \Closure
|
||||||
|
*/
|
||||||
|
public function provideResolver(FieldValue $fieldValue): Closure
|
||||||
|
{
|
||||||
|
return function ($root, array $args, $context, ResolveInfo $resolveInfo) use ($fieldValue) {
|
||||||
|
$fieldName = $fieldValue->getFieldName();
|
||||||
|
// use local graph resolver in code section if existent
|
||||||
|
if ($graphObj = $context->source->findGraph($fieldName)) {
|
||||||
|
/* @var $graphObj \GermanAirlinesVa\Graphql\Classes\Graph */
|
||||||
|
$parser = new CodeParser($graphObj);
|
||||||
|
$codeObj = $parser->source($graphObj, null, new GraphController($graphObj, $args));
|
||||||
|
$resolveMethod = 'resolve' . studly_case($fieldName);
|
||||||
|
|
||||||
|
if (method_exists($codeObj, $resolveMethod)) {
|
||||||
|
return $codeObj->$resolveMethod($root, $args, $context, $resolveInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// default resolver
|
||||||
|
return parent::provideResolver($fieldValue)($root, $args, $context, $resolveInfo);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
44
classes/Schema.php
Normal file
44
classes/Schema.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace GermanAirlinesVa\Graphql\Classes;
|
||||||
|
|
||||||
|
use Cms\Classes\Theme;
|
||||||
|
|
||||||
|
class Schema extends Theme
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the absolute theme path.
|
||||||
|
* @param string $dirName Optional theme directory. Defaults to $this->getDirName()
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPath(?string $dirName = null): string
|
||||||
|
{
|
||||||
|
if (!$dirName) {
|
||||||
|
$dirName = $this->getDirName();
|
||||||
|
}
|
||||||
|
return base_path() . '/' . $dirName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of graphs in the template.
|
||||||
|
* @param boolean $skipCache Indicates if the pages should be reloaded from the disk bypassing the cache.
|
||||||
|
* @return array Returns an array of Nocio\Headstart\Classes\Graph objects.
|
||||||
|
*/
|
||||||
|
public function listGraphs($skipCache = false)
|
||||||
|
{
|
||||||
|
return Graph::listInTheme($this, $skipCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the active theme code.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* If the theme doesn't exist, returns null.
|
||||||
|
*/
|
||||||
|
public static function getActiveThemeCode(): ?string
|
||||||
|
{
|
||||||
|
return 'graphql';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
30
classes/SchemaContext.php
Normal file
30
classes/SchemaContext.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace GermanAirlinesVa\Graphql\Classes;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Nuwave\Lighthouse\Schema\Context;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Nuwave\Lighthouse\Schema\Source\SchemaSourceProvider;
|
||||||
|
|
||||||
|
|
||||||
|
class SchemaContext extends Context
|
||||||
|
{
|
||||||
|
|
||||||
|
public $source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new context.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param $source
|
||||||
|
*/
|
||||||
|
public function __construct(Request $request)
|
||||||
|
{
|
||||||
|
parent::__construct($request);
|
||||||
|
|
||||||
|
$this->source = App::make(SchemaSourceProvider::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
221
classes/SchemaSourceProvider.php
Normal file
221
classes/SchemaSourceProvider.php
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace GermanAirlinesVa\Graphql\Classes;
|
||||||
|
|
||||||
|
use Cache;
|
||||||
|
use Nuwave\Lighthouse\Schema\Source\SchemaSourceProvider as LighthouseSchemaSourceProvider;
|
||||||
|
use GraphQL\Language\Parser;
|
||||||
|
use GraphQL\Error\Error;
|
||||||
|
use Cms\Classes\ComponentManager;
|
||||||
|
use Cms\Classes\ComponentPartial;
|
||||||
|
|
||||||
|
class SchemaSourceProvider implements LighthouseSchemaSourceProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $fieldGraphMapCacheKey = 'graphql-schema-field-graph-map';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Schema
|
||||||
|
*/
|
||||||
|
public $template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $rootSchemaPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
* Collects graphs and their parsed schema
|
||||||
|
*/
|
||||||
|
protected $graphMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
* Maps field names to graphs
|
||||||
|
*/
|
||||||
|
protected $fieldGraphMap;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SchemaSource constructor.
|
||||||
|
*
|
||||||
|
* @param string|null $template
|
||||||
|
*/
|
||||||
|
public function __construct($template = null)
|
||||||
|
{
|
||||||
|
$this->template = Schema::load(is_string($template) ? $template : 'graphql');
|
||||||
|
$this->rootSchemaPath = $this->template->getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set schema root path.
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
*
|
||||||
|
* @return SchemaSourceProvider
|
||||||
|
*/
|
||||||
|
public function setRootPath(string $path): self
|
||||||
|
{
|
||||||
|
$this->rootSchemaPath = $path;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stitch together schema documents and return the result as a string.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSchemaString(): string
|
||||||
|
{
|
||||||
|
// root types
|
||||||
|
$schema = '
|
||||||
|
type Query {
|
||||||
|
graphql: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mutation {
|
||||||
|
graphql: Boolean
|
||||||
|
}
|
||||||
|
';
|
||||||
|
// schema
|
||||||
|
$schema .= collect($this->getGraphMap())->implode('schema', '');
|
||||||
|
return $schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findGraph($fieldName, $findOrFail=false) {
|
||||||
|
if (!isset($this->getFieldGraphMap()[$fieldName])) {
|
||||||
|
if ($findOrFail) {
|
||||||
|
throw new Error("Could not find graph of field '{$fieldName}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = $this->getFieldGraphMap()[$fieldName];
|
||||||
|
|
||||||
|
if (isset($this->graphMap[$name])) {
|
||||||
|
// if available, use already instantiated graph objects in memory
|
||||||
|
return $this->graphMap[$name]['graph'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Graph::loadCached($this->template, $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFieldGraphMap() {
|
||||||
|
if (! is_null($this->fieldGraphMap)) {
|
||||||
|
return $this->fieldGraphMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore from cache
|
||||||
|
|
||||||
|
$cacheable = true;
|
||||||
|
|
||||||
|
if ($cacheable) {
|
||||||
|
$map = Cache::get($this->fieldGraphMapCacheKey, false);
|
||||||
|
if (
|
||||||
|
$map &&
|
||||||
|
($map = @unserialize(@base64_decode($map))) &&
|
||||||
|
is_array($map)
|
||||||
|
) {
|
||||||
|
$this->fieldGraphMap = $map;
|
||||||
|
return $this->fieldGraphMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rebuild mapping
|
||||||
|
|
||||||
|
$this->fieldGraphMap = [];
|
||||||
|
|
||||||
|
foreach ($this->getGraphMap() as $key => $element) {
|
||||||
|
if (empty(trim($element['schema']))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the AST to collect fields mapping
|
||||||
|
$ast = Parser::parse($element['schema'], ['noLocation' => true]);
|
||||||
|
$fields = collect($ast->definitions)
|
||||||
|
->filter(function ($node) {
|
||||||
|
// we only consider the root types since their fields are unique
|
||||||
|
return $node->name->value == 'Query' || $node->name->value == 'Mutation';
|
||||||
|
})
|
||||||
|
->flatMap(function ($node) {
|
||||||
|
// collect field names
|
||||||
|
return collect($node->fields)->map(function($field) {
|
||||||
|
return $field->name->value;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// map as [$field_name => $graph_filename]
|
||||||
|
$this->fieldGraphMap = array_merge($this->fieldGraphMap, array_fill_keys($fields->toArray(), $key));
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache mapping
|
||||||
|
|
||||||
|
if ($cacheable) {
|
||||||
|
Cache::put(
|
||||||
|
$this->fieldGraphMapCacheKey,
|
||||||
|
base64_encode(serialize($this->fieldGraphMap)),
|
||||||
|
10
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->fieldGraphMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGraphMap() {
|
||||||
|
if (!is_null($this->graphMap)) {
|
||||||
|
return $this->graphMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->graphMap = [];
|
||||||
|
$component_re = '/{%\s*component\s+["|\'](.*)["|\']\s*%}/m';
|
||||||
|
$component_str = [$this, 'getComponentSchemaString'];
|
||||||
|
foreach ($this->template->listGraphs() as $graph) {
|
||||||
|
/* @var $graph \GermanAirlinesVa\Graphql\Classes\Graph */
|
||||||
|
$markup = $graph->markup;
|
||||||
|
|
||||||
|
$schema = preg_replace_callback($component_re, function(array $matches) use ($graph, $component_str) {
|
||||||
|
$matched_alias = $matches[1];
|
||||||
|
foreach ($graph->settings['components'] as $component => $properties) {
|
||||||
|
// find component by alias
|
||||||
|
list($name, $alias) = strpos($component, ' ')
|
||||||
|
? explode(' ', $component)
|
||||||
|
: [$component, $component];
|
||||||
|
if ($alias == $matched_alias) {
|
||||||
|
// resolve component schema
|
||||||
|
return $component_str($name, $alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if not found, remove
|
||||||
|
return '';
|
||||||
|
}, $markup);
|
||||||
|
|
||||||
|
$this->graphMap[$graph->getFileName()] = [
|
||||||
|
'graph' => $graph,
|
||||||
|
'schema' => $schema
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->graphMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getComponentSchemaString($componentName, $alias) {
|
||||||
|
$manager = ComponentManager::instance();
|
||||||
|
$componentObj = $manager->makeComponent($componentName);
|
||||||
|
if ($partial = ComponentPartial::load($componentObj, 'schema.graphqls')) {
|
||||||
|
$content = $partial->getContent();
|
||||||
|
$content = str_replace('__SELF__', $alias, $content);
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
} else {
|
||||||
|
return "# {$componentName} does not provide a default schema definition";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clearCache() {
|
||||||
|
Cache::forget($this->fieldGraphMapCacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
8
composer.json
Normal file
8
composer.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "germanairlinesva/graphql",
|
||||||
|
"type": "october-plugin",
|
||||||
|
"description": "None",
|
||||||
|
"require": {
|
||||||
|
"composer/installers": "~1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
251
config/config.php
Normal file
251
config/config.php
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Cms\Classes\Theme;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'packages' => [
|
||||||
|
'nuwave/lighthouse' => [
|
||||||
|
'config_namespace' => 'lighthouse',
|
||||||
|
'providers' => [
|
||||||
|
'Nuwave\Lighthouse\LighthouseServiceProvider'
|
||||||
|
],
|
||||||
|
'aliases' => [
|
||||||
|
],
|
||||||
|
'config' => [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Route Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Controls the HTTP route that your GraphQL server responds to.
|
||||||
|
| You may set `route` => false, to disable the default route
|
||||||
|
| registration and take full control.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'route' => [
|
||||||
|
/*
|
||||||
|
* The URI the endpoint responds to, e.g. mydomain.com/graphql.
|
||||||
|
*/
|
||||||
|
'uri' => 'graphql',
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lighthouse creates a named route for convenient URL generation and redirects.
|
||||||
|
*/
|
||||||
|
'name' => 'graphql',
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Beware that middleware defined here runs before the GraphQL execution phase,
|
||||||
|
* so you have to take extra care to return spec-compliant error responses.
|
||||||
|
* To apply middleware on a field level, use the @middleware directive.
|
||||||
|
*/
|
||||||
|
'middleware' => [\Nuwave\Lighthouse\Support\Http\Middleware\AcceptJson::class]
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Schema Declaration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This is a path that points to where your GraphQL schema is located
|
||||||
|
| relative to the app path. You should define your entire GraphQL
|
||||||
|
| schema in this file (additional files may be imported).
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'schema' => [
|
||||||
|
'register' => '',
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Schema Cache
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| A large part of schema generation consists of parsing and AST manipulation.
|
||||||
|
| This operation is very expensive, so it is highly recommended to enable
|
||||||
|
| caching of the final schema to optimize performance of large schemas.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'cache' => [
|
||||||
|
'enable' => false,
|
||||||
|
'key' => env('GRAPHQL_CACHE_KEY', 'graphql-schema'),
|
||||||
|
'ttl' => env('GRAPHQL_CACHE_TTL', null),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Namespaces
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| These are the default namespaces where Lighthouse looks for classes
|
||||||
|
| that extend functionality of the schema. You may pass either a string
|
||||||
|
| or an array, they are tried in order and the first match is used.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'namespaces' => [
|
||||||
|
'models' => 'Graphql\\Models',
|
||||||
|
'queries' => 'Graphql\\Queries',
|
||||||
|
'mutations' => 'Graphql\\Mutations',
|
||||||
|
'subscriptions' => 'Graphql\\Subscriptions',
|
||||||
|
'interfaces' => 'Graphql\\Interfaces',
|
||||||
|
'unions' => 'Graphql\\Unions',
|
||||||
|
'scalars' => 'Graphql\\Scalars',
|
||||||
|
'directives' => ['GermanAirlinesVa\\Graphql\\GraphQL\\Directives', 'Graphql\\Directives'],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Security
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Control how Lighthouse handles security related query validation.
|
||||||
|
| This configures the options from http://webonyx.github.io/graphql-php/security/
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'security' => [
|
||||||
|
'max_query_complexity' => \GraphQL\Validator\Rules\QueryComplexity::DISABLED,
|
||||||
|
'max_query_depth' => \GraphQL\Validator\Rules\QueryDepth::DISABLED,
|
||||||
|
'disable_introspection' => \GraphQL\Validator\Rules\DisableIntrospection::DISABLED,
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Pagination
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Limits the maximum "count" that users may pass as an argument
|
||||||
|
| to fields that are paginated with the @paginate directive.
|
||||||
|
| A setting of "null" means the count is unrestricted.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'paginate_max_count' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Pagination Amount Argument
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Set the name to use for the generated argument on paginated fields
|
||||||
|
| that controls how many results are returned.
|
||||||
|
| This setting will be removed in v5.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'pagination_amount_argument' => 'first',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Debug
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Control the debug level as described in http://webonyx.github.io/graphql-php/error-handling/
|
||||||
|
| Debugging is only applied if the global Laravel debug config is set to true.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'debug' => \GraphQL\Error\Debug::INCLUDE_DEBUG_MESSAGE | \GraphQL\Error\Debug::INCLUDE_TRACE,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Error Handlers
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Register error handlers that receive the Errors that occur during execution
|
||||||
|
| and handle them. You may use this to log, filter or format the errors.
|
||||||
|
| The classes must implement \Nuwave\Lighthouse\Execution\ErrorHandler
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'error_handlers' => [
|
||||||
|
\Nuwave\Lighthouse\Execution\ExtensionErrorHandler::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Global ID
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The name that is used for the global id field on the Node interface.
|
||||||
|
| When creating a Relay compliant server, this must be named "id".
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'global_id_field' => 'id',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Batched Queries
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| GraphQL query batching means sending multiple queries to the server in one request,
|
||||||
|
| You may set this flag to either process or deny batched queries.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'batched_queries' => true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Transactional Mutations
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Sets default setting for transactional mutations.
|
||||||
|
| You may set this flag to have @create|@update mutations transactional or not.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'transactional_mutations' => true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| GraphQL Subscriptions
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you can define GraphQL subscription "broadcasters" and "storage" drivers
|
||||||
|
| as well their required configuration options.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'subscriptions' => [
|
||||||
|
/*
|
||||||
|
* Determines if broadcasts should be queued by default.
|
||||||
|
*/
|
||||||
|
'queue_broadcasts' => env('LIGHTHOUSE_QUEUE_BROADCASTS', true),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default subscription storage.
|
||||||
|
*
|
||||||
|
* Any Laravel supported cache driver options are available here.
|
||||||
|
*/
|
||||||
|
'storage' => env('LIGHTHOUSE_SUBSCRIPTION_STORAGE', 'redis'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default subscription broadcaster.
|
||||||
|
*/
|
||||||
|
'broadcaster' => env('LIGHTHOUSE_BROADCASTER', 'pusher'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Subscription broadcasting drivers with config options.
|
||||||
|
*/
|
||||||
|
'broadcasters' => [
|
||||||
|
'log' => [
|
||||||
|
'driver' => 'log',
|
||||||
|
],
|
||||||
|
'pusher' => [
|
||||||
|
'driver' => 'pusher',
|
||||||
|
'routes' => \Nuwave\Lighthouse\Subscriptions\SubscriptionRouter::class.'@pusher',
|
||||||
|
'connection' => 'pusher',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
16
init.php
Normal file
16
init.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if(!function_exists("join_paths")) {
|
||||||
|
function join_paths()
|
||||||
|
{
|
||||||
|
$paths = array();
|
||||||
|
|
||||||
|
foreach (func_get_args() as $arg) {
|
||||||
|
if ($arg !== '') {
|
||||||
|
$paths[] = $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return preg_replace('#/+#', '/', join('/', $paths));
|
||||||
|
}
|
||||||
|
}
|
||||||
9
lang/en/lang.php
Normal file
9
lang/en/lang.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php return [
|
||||||
|
'plugin' => [
|
||||||
|
'name' => 'GraphQL',
|
||||||
|
'description' => '',
|
||||||
|
],
|
||||||
|
'menu' => [
|
||||||
|
'main' => 'GraphQL',
|
||||||
|
],
|
||||||
|
];
|
||||||
6
plugin.yaml
Normal file
6
plugin.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
plugin:
|
||||||
|
name: 'germanairlinesva.graphql::lang.plugin.name'
|
||||||
|
description: 'germanairlinesva.graphql::lang.plugin.description'
|
||||||
|
author: 'German Airlines VA'
|
||||||
|
icon: oc-icon-database
|
||||||
|
homepage: ''
|
||||||
2
updates/version.yaml
Normal file
2
updates/version.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
1.0.1:
|
||||||
|
- Initialize plugin.
|
||||||
Loading…
x
Reference in New Issue
Block a user