Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/upstream/8.x-1.x' into allow-ex…
Browse files Browse the repository at this point in the history
…plicit-entity-bundles-attachment

# Conflicts:
#	src/Plugin/Deriver/Fields/ViewDeriver.php
  • Loading branch information
das-peter committed Jan 7, 2020
2 parents fc620dc + a78f8fd commit 7f2fb62
Show file tree
Hide file tree
Showing 14 changed files with 707 additions and 243 deletions.
42 changes: 22 additions & 20 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ language: php
sudo: false

php:
- 7.3
- 7.2
- 7.1
- 7
- 5.6
- 7.0

services:
- mysql

env:
global:
Expand All @@ -13,24 +17,23 @@ env:
- SIMPLETEST_DB=mysql://root:@127.0.0.1/graphql
- TRAVIS=true
matrix:
- DRUPAL_CORE=8.4.x
- DRUPAL_CORE=8.5.x
- DRUPAL_CORE=8.6.x
- DRUPAL_CORE=8.7.x
- DRUPAL_CORE=8.8.x

matrix:
# Don't wait for the allowed failures to build.
fast_finish: true
include:
- php: 7.1
- php: 7.3
env:
- DRUPAL_CORE=8.6.x
- DRUPAL_CORE=8.7.x
# Only run code coverage on the latest php and drupal versions.
- WITH_PHPDBG_COVERAGE=true
allow_failures:
# Allow the code coverage report to fail.
- php: 7.1
- php: 7.3
env:
- DRUPAL_CORE=8.6.x
- DRUPAL_CORE=8.7.x
# Only run code coverage on the latest php and drupal versions.
- WITH_PHPDBG_COVERAGE=true

Expand All @@ -54,14 +57,6 @@ before_install:
else export PHPINI=$HOME/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini;
fi

# PHP Deprecated: Automatically populating $HTTP_RAW_POST_DATA is deprecated
# and will be removed in a future version. To avoid this warning set
# 'always_populate_raw_post_data' to '-1' in php.ini and use the php://input
# stream instead.
- if [[ "$TRAVIS_PHP_VERSION" == "5.6" ]];
then echo always_populate_raw_post_data = -1 >> $PHPINI;
fi;

# Disable the default memory limit.
- echo memory_limit = -1 >> $PHPINI

Expand Down Expand Up @@ -92,10 +87,17 @@ install:

# Bring in the module dependencies without requiring a merge plugin. The
# require also triggers a full 'composer install'.
- composer --working-dir=$DRUPAL_BUILD_DIR require webonyx/graphql-php:^0.12.6
- composer --working-dir=$DRUPAL_BUILD_DIR require webonyx/graphql-php:^0.12.5

# For Drupal < 8.8 we have to manually upgrade zend-stdlib to avoid PHP 7.3
# incompatibilities.
- if [[ "$DRUPAL_CORE" = "8.6.x" || "$DRUPAL_CORE" = "8.7.x" ]];
then composer --working-dir=$DRUPAL_BUILD_DIR require zendframework/zend-stdlib:3.2.1;
fi

# Update PHPUnit for Drupal version >= 8.5.0
- if [[ "$DRUPAL_CORE" != "8.4.x" ]];
# For Drupal < 8.8 we have to manually upgrade phpunit to avoid PHP 7.3
# incompatibilities.
- if [[ "$DRUPAL_CORE" = "8.6.x" || "$DRUPAL_CORE" = "8.7.x" ]];
then composer --working-dir=$DRUPAL_BUILD_DIR run-script drupal-phpunit-upgrade;
fi

Expand Down
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@
[![Code Coverage](https://img.shields.io/codecov/c/github/drupal-graphql/graphql-views.svg)](https://codecov.io/gh/drupal-graphql/graphql-views)
[![Code Quality](https://img.shields.io/scrutinizer/g/drupal-graphql/graphql-views.svg)](https://scrutinizer-ci.com/g/drupal-graphql/graphql-views/?branch=8.x-1.x)

Please refer to the main [Drupal GraphQL] module for further information.

[Drupal GraphQL]: https://github.com/drupal-graphql/graphql

With `graphql_views` enabled a `GraphQL` views display can be added to any view in the system.

Results can be sorted, filtered based on content fields, and relationships can be added. There is also the option to return either the full entities, just a selection of fields, or even search results taken straight from a search server.

Any `GraphQL` views display will provide a field that will adapt to the views configuration:

- The fields name will be composed of the views and displays machine names or configured manually.
- If the view is configured with pagination, the field will accept pager arguments and return the result list and count field instead of the entity list directly.
- Any exposed filters will be added to the `filters` input type that can be used to pass filter values into the view.
- Any contextual filters will be added to the `contextual_filters` input type.
- If a contextual filters validation criteria match an existing GraphQL type, the field will be added to this type too, and the value will be populated from the current result context.

Read more on:
- https://www.amazeelabs.com/en/blog/graphql-drupalers-part-4-fetching-entities
- https://www.amazeelabs.com/en/blog/drupal-graphql-batteries-included

Please also refer to the main [Drupal GraphQL] module for further information.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "drupal/graphql-views",
"name": "drupal/graphql_views",
"type": "drupal-module",
"description": "Exposes your Drupal Views data model through a GraphQL schema.",
"homepage": "http://drupal.org/project/graphql_views",
Expand Down
214 changes: 7 additions & 207 deletions src/Plugin/Deriver/ViewDeriverBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Drupal\graphql_views\Plugin\views\row\GraphQLEntityRow;
use Drupal\graphql_views\Plugin\views\row\GraphQLFieldRow;
use Drupal\graphql\Utility\StringHelper;
use Drupal\graphql_views\ViewDeriverHelperTrait;
use Drupal\views\Plugin\views\display\DisplayPluginInterface;
use Drupal\views\ViewEntityInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
Expand All @@ -18,6 +19,9 @@
* Base class for graphql view derivers.
*/
abstract class ViewDeriverBase extends DeriverBase implements ContainerDeriverInterface {
use ViewDeriverHelperTrait {
getRowResolveType as private traitGetRowResolveType;
}
/**
* The entity type manager.
*
Expand Down Expand Up @@ -65,52 +69,6 @@ public function __construct(
$this->entityTypeManager = $entityTypeManager;
}

/**
* Check if a pager is configured.
*
* @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
* The display configuration.
*
* @return bool
* Flag indicating if the view is configured with a pager.
*/
protected function isPaged(DisplayPluginInterface $display) {
$pagerOptions = $display->getOption('pager');
return isset($pagerOptions['type']) && in_array($pagerOptions['type'], ['full', 'mini']);
}

/**
* Get the configured default limit.
*
* @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
* The display configuration.
*
* @return int
* The default limit.
*/
protected function getPagerLimit(DisplayPluginInterface $display) {
$pagerOptions = $display->getOption('pager');
return NestedArray::getValue($pagerOptions, [
'options', 'items_per_page',
]) ?: 0;
}

/**
* Get the configured default offset.
*
* @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
* The display configuration.
*
* @return int
* The default offset.
*/
protected function getPagerOffset(DisplayPluginInterface $display) {
$pagerOptions = $display->getOption('pager');
return NestedArray::getValue($pagerOptions, [
'options', 'offset',
]) ?: 0;
}

/**
* Retrieves the entity type id of an entity by its base or data table.
*
Expand Down Expand Up @@ -142,172 +100,14 @@ protected function getEntityTypeByTable($table) {
*
* @param \Drupal\views\ViewEntityInterface $view
* The view entity.
* @param $displayId
* The id of the current display.
* @param string $displayId
* Interface plugin manager.
*
* @return null|string
* The name of the type or NULL if the type could not be derived.
*/
protected function getRowResolveType(ViewEntityInterface $view, $displayId) {
/** @var \Drupal\graphql_views\Plugin\views\display\GraphQL $display */
$display = $this->getViewDisplay($view, $displayId);
$rowPlugin = $display->getPlugin('row');

if ($rowPlugin instanceof GraphQLFieldRow) {
return StringHelper::camelCase($display->getGraphQLRowName());
}

if ($rowPlugin instanceof GraphQLEntityRow) {
$executable = $view->getExecutable();
$executable->setDisplay($displayId);

if ($entityType = $executable->getBaseEntityType()) {
$typeName = $entityType->id();
$typeNameCamel = StringHelper::camelCase($typeName);
if ($this->interfaceExists($typeNameCamel)) {
$filters = $executable->getDisplay()->getOption('filters');
$dataTable = $entityType->getDataTable();
$bundleKey = $entityType->getKey('bundle');

foreach ($filters as $filter) {
$isBundleFilter = $filter['table'] == $dataTable && $filter['field'] == $bundleKey;
$isSingleValued = is_array($filter['value']) && count($filter['value']) == 1;
$isExposed = isset($filter['exposed']) && $filter['exposed'];
if ($isBundleFilter && $isSingleValued && !$isExposed) {
$bundle = reset($filter['value']);
$typeName .= "_$bundle";
break;
}
}

return StringHelper::camelCase($typeName);
}
}

return 'Entity';
}

return NULL;
}

/**
* Check if a certain interface exists.
*
* @param string $interface
* The GraphQL interface name.
*
* @return bool
* Boolean flag indicating if the interface exists.
*/
protected function interfaceExists($interface) {
return (bool) array_filter($this->interfacePluginManager->getDefinitions(), function($definition) use ($interface) {
return $definition['name'] === $interface;
});
return $this->traitGetRowResolveType($view, $displayId, $this->interfacePluginManager);
}

/**
* Returns a view display object.
*
* @param \Drupal\views\ViewEntityInterface $view
* The view object.
* @param string $displayId
* The display ID to use.
*
* @return \Drupal\views\Plugin\views\display\DisplayPluginInterface
* The view display object.
*/
protected function getViewDisplay(ViewEntityInterface $view, $displayId) {
$viewExecutable = $view->getExecutable();
$viewExecutable->setDisplay($displayId);
return $viewExecutable->getDisplay();
}

/**
* Returns a view style object.
*
* @param \Drupal\views\ViewEntityInterface $view
* The view object.
* @param string $displayId
* The display ID to use.
*
* @return \Drupal\views\Plugin\views\style\StylePluginBase
* The view style object.
*/
protected function getViewStyle(ViewEntityInterface $view, $displayId) {
$viewExecutable = $view->getExecutable();
$viewExecutable->setDisplay($displayId);
return $viewExecutable->getStyle();
}

/**
* Returns cache metadata plugin definitions.
*
* @param \Drupal\views\ViewEntityInterface $view
* The view object.
*
* @return array
* The cache metadata definitions for the plugin definition.
*/
protected function getCacheMetadataDefinition(ViewEntityInterface $view, DisplayPluginInterface $display) {
$metadata = $display->getCacheMetadata()
->addCacheTags($view->getCacheTags())
->addCacheContexts($view->getCacheContexts())
->mergeCacheMaxAge($view->getCacheMaxAge());

return [
'schema_cache_tags' => $metadata->getCacheTags(),
'schema_cache_max_age' => $metadata->getCacheMaxAge(),
'response_cache_contexts' => array_filter($metadata->getCacheContexts(), function ($context) {
// Don't emit the url cache contexts.
return $context !== 'url' && strpos($context, 'url.') !== 0;
}),
];
}

/**
* Returns information about view arguments (contextual filters).
*
* @param array $viewArguments
* The "arguments" option of a view display.
*
* @return array
* Arguments information keyed by the argument ID. Subsequent array keys:
* - index: argument index.
* - entity_type: target entity type.
* - bundles: target bundles (can be empty).
*/
protected function getArgumentsInfo(array $viewArguments) {
$argumentsInfo = [];

$index = 0;
foreach ($viewArguments as $argumentId => $argument) {
$info = [
'index' => $index,
'entity_type' => NULL,
'bundles' => [],
];

if (isset($argument['entity_type']) && isset($argument['entity_field'])) {
$entityType = $this->entityTypeManager->getDefinition($argument['entity_type']);
if ($entityType) {
$idField = $entityType->getKey('id');
if ($idField === $argument['entity_field']) {
$info['entity_type'] = $argument['entity_type'];
if (
$argument['specify_validation'] &&
strpos($argument['validate']['type'], 'entity:') === 0 &&
!empty($argument['validate_options']['bundles'])
) {
$info['bundles'] = $argument['validate_options']['bundles'];
}
}
}
}

$argumentsInfo[$argumentId] = $info;
$index++;
}

return $argumentsInfo;
}
}
Loading

0 comments on commit 7f2fb62

Please sign in to comment.