<commit_before><?php


namespace CatLab\Charon\Laravel\JsonApi\Controllers;

use CatLab\Base\Helpers\ArrayHelper;
use CatLab\Charon\Collections\ResourceCollection;
use CatLab\Charon\Collections\RouteCollection;
use CatLab\Charon\Enums\Action;
use CatLab\Charon\Enums\Cardinality;
use CatLab\Charon\Exceptions\EntityNotFoundException;
use CatLab\Charon\Factories\ResourceFactory;
use CatLab\Charon\Interfaces\RESTResource;
use CatLab\Charon\Laravel\Contracts\Response as ResponseContract;
use CatLab\Charon\Laravel\Controllers\CrudController;
use CatLab\Charon\Laravel\Controllers\ResourceController;
use CatLab\Charon\Laravel\JsonApi\InputParsers\JsonApiInputParser;
use CatLab\Charon\Laravel\JsonApi\Models\JsonApiContext;
use CatLab\Charon\Laravel\JsonApi\Models\JsonApiResource;
use CatLab\Charon\Laravel\JsonApi\Models\JsonApiResourceCollection;
use CatLab\Charon\Laravel\JsonApi\Models\JsonApiResponse;
use CatLab\Charon\Laravel\JsonApi\Processors\PaginationProcessor;
use CatLab\Charon\Laravel\Models\ResourceResponse;
use CatLab\Charon\Laravel\JsonApi\Resolvers\JsonApiRequestResolver;
use CatLab\Charon\Laravel\Resolvers\PropertyResolver;
use CatLab\Charon\Laravel\Resolvers\PropertySetter;
use CatLab\Charon\Laravel\Resolvers\QueryAdapter;
use CatLab\Charon\Laravel\ResourceTransformer;
use CatLab\Charon\Models\Context;
use CatLab\Charon\Models\Properties\RelationshipField;
use CatLab\Charon\Models\StaticResourceDefinitionFactory;
use CatLab\Charon\Pagination\PaginationBuilder;
use CatLab\Requirements\Exceptions\ResourceValidationException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Response;

/**
 * Trait JsonApiResourceController
 * @package CatLab\Charon\Laravel\Controllers
 */
trait JsonApiResourceController
{
    use ResourceController, CrudController {
        CrudController::getRequest insteadof ResourceController;
    }

    /**
     * @param RouteCollection $routes
     * @param $resourceDefinition
     * @param $path
     * @param $resourceId
     * @param null $controller
     * @param null $options
     * @return RouteCollection
     * @throws \CatLab\Charon\Exceptions\InvalidContextAction
     * @throws \CatLab\Charon\Exceptions\InvalidResourceDefinition
     */
    public static function setJsonApiRoutes(
        RouteCollection $routes,
        $resourceDefinition,
        $path,
        $resourceId,
        $controller = null,
        $options = []
    ) {
        $resourceDefinitionFactory = StaticResourceDefinitionFactory::getFactoryOrDefaultFactory($resourceDefinition);

        if (!isset($controller)) {
            $controller = class_basename(static::class);
        }

        if (!isset($options[RouteCollection::OPTIONS_IDENTIFIER_NAME])) {
            $options[RouteCollection::OPTIONS_IDENTIFIER_NAME] = $resourceId;
        }

        if (!isset($options[RouteCollection::OPTIONS_ONLY_INCLUDE_METHODS])) {
            $options[RouteCollection::OPTIONS_ONLY_INCLUDE_METHODS] = [
                RouteCollection::OPTIONS_METHOD_INDEX,
                RouteCollection::OPTIONS_METHOD_VIEW,
                RouteCollection::OPTIONS_METHOD_STORE,
                RouteCollection::OPTIONS_METHOD_PATCH,
                RouteCollection::OPTIONS_METHOD_DESTROY
            ];
        }

        $childResource = $routes->resource(
            $resourceDefinitionFactory,
            $path,
            $controller,
            $options
        );

        // we need to create a ResourceDefinition object to create the 'linkable' endpoints
        $resourceDefinitionObject = $resourceDefinitionFactory->getDefault();
        foreach ($resourceDefinitionObject->getFields()->getRelationships() as $field)  {
            self::addLinkRelationshipEndpoint($childResource, $field, $path, $resourceId, $controller, $options);
        }

        // add support for batch update
        if (in_array(RouteCollection::OPTIONS_METHOD_PATCH, $options[RouteCollection::OPTIONS_ONLY_INCLUDE_METHODS])) {
            $childResource->patch($path, $controller . '@batchEdit')
                ->summary(function () use ($resourceDefinitionObject) {
                    $entityName = $resourceDefinitionObject->getEntityName(true);

                    return 'Batch update multiple ' . $entityName;
                })
                ->parameters()->resource($resourceDefinitionObject)->many()->required()
                ->returns()->statusCode(200)->many($resourceDefinitionFactory->getDefault());
        }

        return $childResource;
    }

    /**
     * @param RouteCollection $routes
     * @param RelationshipField $field
     * @param $path
     * @param $resourceId
     * @param null $controller
     * @param null $options
     * @throws \CatLab\Charon\Exceptions\InvalidContextAction
     * @throws \CatLab\Charon\Exceptions\InvalidResourceDefinition
     */
    protected static function addLinkRelationshipEndpoint(
        RouteCollection $routes,
        RelationshipField $field,
        $path,
        $resourceId,
        $controller = null,
        $options = null
    ) {
        $resourceDefinitionFactory = StaticResourceDefinitionFactory::getFactoryOrDefaultFactory($field->getResourceDefinition());

        $only = $options[RouteCollection::OPTIONS_ONLY_INCLUDE_METHODS] ?? [<commit_msg>Fix resource definition for relationships in json-api.<commit_after><?php


namespace CatLab\Charon\Laravel\JsonApi\Controllers;

use CatLab\Base\Helpers\ArrayHelper;
use CatLab\Charon\Collections\ResourceCollection;
use CatLab\Charon\Collections\RouteCollection;
use CatLab\Charon\Enums\Action;
use CatLab\Charon\Enums\Cardinality;
use CatLab\Charon\Exceptions\EntityNotFoundException;
use CatLab\Charon\Factories\ResourceFactory;
use CatLab\Charon\Interfaces\RESTResource;
use CatLab\Charon\Laravel\Contracts\Response as ResponseContract;
use CatLab\Charon\Laravel\Controllers\CrudController;
use CatLab\Charon\Laravel\Controllers\ResourceController;
use CatLab\Charon\Laravel\JsonApi\InputParsers\JsonApiInputParser;
use CatLab\Charon\Laravel\JsonApi\Models\JsonApiContext;
use CatLab\Charon\Laravel\JsonApi\Models\JsonApiResource;
use CatLab\Charon\Laravel\JsonApi\Models\JsonApiResourceCollection;
use CatLab\Charon\Laravel\JsonApi\Models\JsonApiResponse;
use CatLab\Charon\Laravel\JsonApi\Processors\PaginationProcessor;
use CatLab\Charon\Laravel\Models\ResourceResponse;
use CatLab\Charon\Laravel\JsonApi\Resolvers\JsonApiRequestResolver;
use CatLab\Charon\Laravel\Resolvers\PropertyResolver;
use CatLab\Charon\Laravel\Resolvers\PropertySetter;
use CatLab\Charon\Laravel\Resolvers\QueryAdapter;
use CatLab\Charon\Laravel\ResourceTransformer;
use CatLab\Charon\Models\Context;
use CatLab\Charon\Models\Properties\RelationshipField;
use CatLab\Charon\Models\StaticResourceDefinitionFactory;
use CatLab\Charon\Pagination\PaginationBuilder;
use CatLab\Requirements\Exceptions\ResourceValidationException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Response;

/**
 * Trait JsonApiResourceController
 * @package CatLab\Charon\Laravel\Controllers
 */
trait JsonApiResourceController
{
    use ResourceController, CrudController {
        CrudController::getRequest insteadof ResourceController;
    }

    /**
     * @param RouteCollection $routes
     * @param $resourceDefinition
     * @param $path
     * @param $resourceId
     * @param null $controller
     * @param null $options
     * @return RouteCollection
     * @throws \CatLab\Charon\Exceptions\InvalidContextAction
     * @throws \CatLab\Charon\Exceptions\InvalidResourceDefinition
     */
    public static function setJsonApiRoutes(
        RouteCollection $routes,
        $resourceDefinition,
        $path,
        $resourceId,
        $controller = null,
        $options = []
    ) {
        $resourceDefinitionFactory = StaticResourceDefinitionFactory::getFactoryOrDefaultFactory($resourceDefinition);

        if (!isset($controller)) {
            $controller = class_basename(static::class);
        }

        if (!isset($options[RouteCollection::OPTIONS_IDENTIFIER_NAME])) {
            $options[RouteCollection::OPTIONS_IDENTIFIER_NAME] = $resourceId;
        }

        if (!isset($options[RouteCollection::OPTIONS_ONLY_INCLUDE_METHODS])) {
            $options[RouteCollection::OPTIONS_ONLY_INCLUDE_METHODS] = [
                RouteCollection::OPTIONS_METHOD_INDEX,
                RouteCollection::OPTIONS_METHOD_VIEW,
                RouteCollection::OPTIONS_METHOD_STORE,
                RouteCollection::OPTIONS_METHOD_PATCH,
                RouteCollection::OPTIONS_METHOD_DESTROY
            ];
        }

        $childResource = $routes->resource(
            $resourceDefinitionFactory,
            $path,
            $controller,
            $options
        );

        // we need to create a ResourceDefinition object to create the 'linkable' endpoints
        $resourceDefinitionObject = $resourceDefinitionFactory->getDefault();
        foreach ($resourceDefinitionObject->getFields()->getRelationships() as $field)  {
            self::addLinkRelationshipEndpoint($childResource, $field, $path, $resourceId, $controller, $options);
        }

        // add support for batch update
        if (in_array(RouteCollection::OPTIONS_METHOD_PATCH, $options[RouteCollection::OPTIONS_ONLY_INCLUDE_METHODS])) {
            $childResource->patch($path, $controller . '@batchEdit')
                ->summary(function () use ($resourceDefinitionObject) {
                    $entityName = $resourceDefinitionObject->getEntityName(true);

                    return 'Batch update multiple ' . $entityName;
                })
                ->parameters()->resource($resourceDefinitionObject)->many()->required()
                ->returns()->statusCode(200)->many($resourceDefinitionFactory->getDefault());
        }

        return $childResource;
    }

    /**
     * @param RouteCollection $routes
     * @param RelationshipField $field
     * @param $path
     * @param $resourceId
     * @param null $controller
     * @param null $options
     * @throws \CatLab\Charon\Exceptions\InvalidContextAction
     * @throws \CatLab\Charon\Exceptions\InvalidResourceDefinition
     */
    protected static function addLinkRelationshipEndpoint(
        RouteCollection $routes,
        RelationshipField $field,
        $path,
        $resourceId,
        $controller = null,
        $options = null
    ) {
        $resourceDefinitionFactory = StaticResourceDefinitionFactory::getFactoryOrDefaultFactory($field->getChildResourceDefinition());

        $only = $options[RouteCollection::OPTIONS_ONLY_INCLUDE_METHODS] ?? [
{'fraction_non_alphanumeric': 0.09842738205365402, 'fraction_numerical': 0.0005550416281221092, 'mean_word_length': 3.5906581740976646, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6715718', 'n_tokens_mistral': 3052, 'n_tokens_neox': 2916, 'n_words': 456}