<commit_before><?php
namespace Czim\JsonApi\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\JsonResponse;
use Symfony\Component\Translation\TranslatorInterface;

class JsonApiRequest extends FormRequest
{
    /**
     * @var
     */
    protected $jsonApiContent;


    /**
     * @return array
     */
    public function rules()
    {
        return [];
    }

    /**
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Validation rules for general JSON-API structure and content.
     *
     * @return array
     */
    public function jsonApiRules()
    {
        $rules = [
            'errors'   => 'array|required_without_all:data,meta',
            'meta'     => 'array|jsonapi_meta|required_without_all:data,errors',
            'included' => 'array',
            'links'    => 'array|jsonapi_links',
            'jsonapi'  => 'array|jsonapi_jsonapi',
        ];

        // data validation depends on whether it is a list of resources or a single resource
        if ( ! isset($this->jsonApiContent['data']) || ! is_array($this->jsonApiContent['data'])) {

            $rules['data'] = 'array|required_without_all:meta,errors';

        } else {

            $keys = array_keys($this->jsonApiContent['data']);

            $resourceRule = (strtolower($this->method()) === 'post')
                          ?   'jsonapi_resource_create'
                          :   'jsonapi_resource';

            if (    count($keys)
                &&  count($keys) === count(array_filter($keys, function ($key) { return is_numeric($key); }))
            ) {
                foreach ($keys as $key) {
                    $rules[ 'data.' . $key ] = 'array|' . $resourceRule;
                }
            } else {
                $rules['data'] = 'array|' . $resourceRule;
            }
        }

        // included is a non-associative array with items that should each be a resource
        if (isset($this->jsonApiContent['included']) && is_array($this->jsonApiContent['included'])) {

            foreach (array_keys($this->jsonApiContent['included']) as $key) {
                $rules[ 'included.' . $key ] = 'array|jsonapi_resource';
            }
        }

        // errors is a non-associative array with items that should each be an error object
        if (isset($this->jsonApiContent['errors']) && is_array($this->jsonApiContent['errors'])) {

            foreach (array_keys($this->jsonApiContent['errors']) as $key) {
                $rules[ 'errors.' . $key ] = 'array|jsonapi_error';
            }
        }

        return $rules;
    }

    /**
     * @inheritDocs
     */
    public function validate()
    {
        $this->loadJsonApiContent();
        $this->validateJsonApiContent();

        parent::validate();
    }

    /**
     * Loads
     */
    protected function loadJsonApiContent()
    {
        $this->jsonApiContent = $this->json()->all();
    }


    /**
     * Validates the request's content as valid JSON-API content
     */
    protected function validateJsonApiContent()
    {
        if (empty($this->jsonApiContent)) return;


        $validator = app(
            JsonApiValidator::class,
            [ app(TranslatorInterface::class), $this->jsonApiContent, $this->jsonApiRules() ]
        );

        if ($validator->fails()) {
            dd($validator->messages());
        }

        // check if we have anything to validate (no content is fine)

        // check whether we have json

        // check whether the required structure is present
        // info, success or failure
        // different structure for post data
        //



        // check whether standard content is correct

    }

    /**<commit_msg>detect invalid json (nonempty, but json()->all() is empty)<commit_after><?php
namespace Czim\JsonApi\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exception\HttpResponseException;
use Illuminate\Http\JsonResponse;
use Symfony\Component\Translation\TranslatorInterface;

class JsonApiRequest extends FormRequest
{
    /**
     * @var
     */
    protected $jsonApiContent;


    /**
     * @return array
     */
    public function rules()
    {
        return [];
    }

    /**
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Validation rules for general JSON-API structure and content.
     *
     * @return array
     */
    public function jsonApiRules()
    {
        $rules = [
            'errors'   => 'array|required_without_all:data,meta',
            'meta'     => 'array|jsonapi_meta|required_without_all:data,errors',
            'included' => 'array',
            'links'    => 'array|jsonapi_links',
            'jsonapi'  => 'array|jsonapi_jsonapi',
        ];

        // data validation depends on whether it is a list of resources or a single resource
        if ( ! isset($this->jsonApiContent['data']) || ! is_array($this->jsonApiContent['data'])) {

            $rules['data'] = 'array|required_without_all:meta,errors';

        } else {

            $keys = array_keys($this->jsonApiContent['data']);

            $resourceRule = (strtolower($this->method()) === 'post')
                          ?   'jsonapi_resource_create'
                          :   'jsonapi_resource';

            if (    count($keys)
                &&  count($keys) === count(array_filter($keys, function ($key) { return is_numeric($key); }))
            ) {
                foreach ($keys as $key) {
                    $rules[ 'data.' . $key ] = 'array|' . $resourceRule;
                }
            } else {
                $rules['data'] = 'array|' . $resourceRule;
            }
        }

        // included is a non-associative array with items that should each be a resource
        if (isset($this->jsonApiContent['included']) && is_array($this->jsonApiContent['included'])) {

            foreach (array_keys($this->jsonApiContent['included']) as $key) {
                $rules[ 'included.' . $key ] = 'array|jsonapi_resource';
            }
        }

        // errors is a non-associative array with items that should each be an error object
        if (isset($this->jsonApiContent['errors']) && is_array($this->jsonApiContent['errors'])) {

            foreach (array_keys($this->jsonApiContent['errors']) as $key) {
                $rules[ 'errors.' . $key ] = 'array|jsonapi_error';
            }
        }

        return $rules;
    }

    /**
     * @inheritDocs
     */
    public function validate()
    {
        $this->loadJsonApiContent();
        $this->validateJsonApiContent();

        parent::validate();
    }

    /**
     * Loads
     */
    protected function loadJsonApiContent()
    {
        $this->jsonApiContent = $this->json()->all();
    }


    /**
     * Validates the request's content as valid JSON-API content
     */
    protected function validateJsonApiContent()
    {
        // check whether we may have content that is not valid json
        // and throw an exception if we do
        if ( ! $this->hasEmptyJsonContent() && empty($this->jsonApiContent)) {

            throw new HttpResponseException($this->response([
                'Request content is not valid JSON'
            ]));
        }

        // check if we have anything to validate (no content is fine)
        if (empty($this->jsonApiContent)) return;


        $validator = app(
            JsonApiValidator::class,
            [ app(TranslatorInterface::class), $this->jsonApiContent, $this->jsonApiRules() ]
        );

        if ( ! $validator->passes()) {
            $this->failedValidation($validator);
        }
    }

    /**
     * Returns whether the body content is empty (as json data)
     *
     * @return bool
     */
    protected function hasEmptyJsonContent()
    {
        if (empty(trim($this->content))) return true;

        return (bool) preg_match('#^\s*(\[\s*\]|\{\s*\})\s*&#i', $this->content);
    }

    /**
{'fraction_non_alphanumeric': 0.13744845682868925, 'fraction_numerical': 0.0, 'mean_word_length': 1.9350935093509352, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 59, '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': '645158', 'n_tokens_mistral': 2227, 'n_tokens_neox': 2157, 'n_words': 489}