View source
<?php
namespace Drupal\jsonapi_defaults\Controller;
use Drupal\Component\Serialization\Json;
use Drupal\jsonapi\Controller\EntityResource as JsonApiEntityResourse;
use Drupal\jsonapi\Query\OffsetPage;
use Drupal\jsonapi\ResourceType\ResourceType;
use Drupal\jsonapi\Routing\Routes;
use Drupal\jsonapi_extras\Entity\JsonapiResourceConfig;
use Drupal\jsonapi_extras\ResourceType\ConfigurableResourceType;
use Symfony\Component\HttpFoundation\Request;
class EntityResource extends JsonApiEntityResourse {
protected function getJsonApiParams(Request $request, ResourceType $resource_type) {
$related_field = $request->attributes
->get('_on_relationship') ? NULL : $request->attributes
->get('related');
try {
$resource_type = static::correctResourceTypeOnRelated($related_field, $resource_type);
} catch (\LengthException $e) {
watchdog_exception('jsonapi_defaults', $e);
$resource_type = NULL;
}
if (!$resource_type instanceof ConfigurableResourceType) {
return parent::getJsonApiParams($request, $resource_type);
}
$resource_config = $resource_type
->getJsonapiResourceConfig();
if (!$resource_config instanceof JsonapiResourceConfig) {
return parent::getJsonApiParams($request, $resource_type);
}
$default_filter_input = $resource_config
->getThirdPartySetting('jsonapi_defaults', 'default_filter', []);
$default_sorting_input = $resource_config
->getThirdPartySetting('jsonapi_defaults', 'default_sorting', []);
$default_filter = [];
$default_sorting = [];
foreach ($default_filter_input as $key => $value) {
if (substr($key, 0, 6) === 'filter') {
$key = str_replace('filter:', '', $key);
$this
->setFilterValue($default_filter, $key, $value);
}
}
foreach ($default_sorting_input as $key => $value) {
if (substr($key, 0, 4) === 'sort') {
$key = str_replace('sort:', '', $key);
$this
->setFilterValue($default_sorting, $key, $value);
}
}
$filters = array_merge($default_filter, $request->query
->get('filter', []));
$sorting = array_merge($default_sorting, $request->query
->get('sort', []));
if (!empty($filters)) {
$request->query
->set('filter', $filters);
}
if (!empty($sorting)) {
$request->query
->set('sort', $sorting);
}
$params = parent::getJsonApiParams($request, $resource_type);
$this
->setPageLimit($request, $resource_config, $params);
return $params;
}
public function getIncludes(Request $request, $data) {
if (($resource_type = $request
->get(Routes::RESOURCE_TYPE_KEY)) && $resource_type instanceof ConfigurableResourceType && !$request
->get('_on_relationship')) {
try {
$resource_type = static::correctResourceTypeOnRelated($request
->get('related'), $resource_type);
} catch (\LengthException $e) {
watchdog_exception('jsonapi_defaults', $e);
return parent::getIncludes($request, $data);
}
if (!$resource_type instanceof ConfigurableResourceType) {
return parent::getIncludes($request, $data);
}
$resource_config = $resource_type
->getJsonapiResourceConfig();
if (!$resource_config instanceof JsonapiResourceConfig) {
return parent::getIncludes($request, $data);
}
$default_includes = $resource_config
->getThirdPartySetting('jsonapi_defaults', 'default_include', []);
if (!empty($default_includes) && $request->query
->get('include') === NULL) {
$includes = array_unique(array_filter(array_merge($default_includes, explode(',', $request->query
->get('include', '')))));
$request->query
->set('include', implode(',', $includes));
}
}
return parent::getIncludes($request, $data);
}
public static function correctResourceTypeOnRelated($related_field, ResourceType $resource_type) {
if (!$related_field) {
return $resource_type;
}
$relatable_resource_types = $resource_type
->getRelatableResourceTypesByField($related_field);
if (count($relatable_resource_types) > 1) {
$message = sprintf('%s -- %s', 'Impossible to apply defaults on a related resource with heterogeneous resource types.', Json::encode([
'related_field' => $related_field,
'host_resource_type' => $resource_type
->getPath(),
'target_resource_types' => array_map(function (ResourceType $resource_type) {
return $resource_type
->getPath();
}, $relatable_resource_types),
]));
throw new \LengthException($message);
}
return isset($relatable_resource_types[0]) ? $relatable_resource_types[0] : NULL;
}
private function setFilterValue(array &$arr, $path, $value) {
$keys = explode('#', $path);
foreach ($keys as $key) {
$arr =& $arr[$key];
}
$arr = $value;
}
protected function determinePageLimit(array $page_params, JsonapiResourceConfig $resource_config) {
$query_limit = !empty($page_params['limit']) ? (int) $page_params['limit'] : OffsetPage::SIZE_MAX;
$page_limit = $resource_config
->getThirdPartySetting('jsonapi_defaults', 'page_limit') ?: OffsetPage::SIZE_MAX;
return min($query_limit, (int) $page_limit);
}
protected function setPageLimit(Request $request, JsonapiResourceConfig $resource_config, array &$params) {
if ($request->query
->has('page')) {
$page_params = $request->query
->get('page');
$offset = array_key_exists(OffsetPage::OFFSET_KEY, $page_params) ? (int) $page_params[OffsetPage::OFFSET_KEY] : OffsetPage::DEFAULT_OFFSET;
$params[OffsetPage::KEY_NAME] = new OffsetPage($offset, $this
->determinePageLimit($page_params, $resource_config));
}
}
}