<commit_before><?php

namespace SkyaTura\EloquentREST\Traits;

use Illuminate\Http\Request;

trait ResourceTrait
{
    use DefaultActionsTrait;
    /**
     * @var Request
     */
    protected $request;

    /**
     * The requested resource path
     *
     * @var array
     */
    protected $resourcePath;

    /**
     * @var array
     */
    public $customActions;

    /**
     * @var array
     */
    private $defaultMethods = [
        'GET' => ['index', 'show'],
        'POST' => ['store', null],
        'PUT' => [null, 'replace'],
        'PATCH' => [null, 'update'],
        'DELETE' => [null, 'delete'],
    ];

    /**
     * @var string
     */
    protected $ref;
    protected $relationResource;

    /**
     * @param Request $request
     * @param string $path
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function resource(Request $request, $path = '')
    {
        $path = explode('/', $path);
        $resourcePath = [];
        if (!empty($path)) {
            $this->ref = array_splice($path, 0, 1)[0];
            while (!empty($path)) {
                if (count($path) >= 2) {
                    $relationship = array_splice($path, 0, 2);
                    $resourcePath[$relationship[0]] = $relationship[1];
                } else {
                    $this->relationResource = array_splice($path, 0, 1)[0];
                }
            }
        }
        $this->resourcePath = $resourcePath;
        $this->request = $request;

        $method = $this->getAction($request->method());
        $parameters = array_prepend($resourcePath, $request);
        return $this->callAction($method, $parameters);
    }

    protected function getAction($method)
    {
        $ref = $this->ref;
        $methodPath = strtolower($method . ($ref) ? '.' . $ref : '');
        if (!empty($this->customActions[$methodPath]))
            return $this->customActions[$methodPath];

        if(empty($this->defaultMethods[$method]))
            return '__call';

        $actions = $this->defaultMethods[$method];
        $action = empty($ref)?$actions[0]:$actions[1];

        return $action?$action:'__call';
    }

    /**
     * @param array $params
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function defaultModel($params = [])
    {
        return new $this->defaultModel($params);
    }

    private function findOrCreate($model, $ref){
        if(empty($ref)) return is_string($model)? new $model : $model;
        if(is_string($model)) $model = $model::query();

        switch ($ref){
            case 'first':
                return $model->take(1);
            case 'last':
                return $model->latest()->take(1);
            default:
                return $model->whereKey($ref)->take(1);
        }
    }

    /**
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function model()
    {
        $params = $this->resourcePath;
        $model = $this->defaultModel();
        $relationResource = $this->relationResource;
        $ref = $this->ref;

        $obj = $this->findOrCreate($model, $ref);

        if (!empty($params)) {
            foreach ($params as $rel => $id)
                $obj = $this->findOrCreate($obj->$rel(), $id);
        }

        return (empty($relationResource)) ? $obj : $obj->$relationResource();
    }
}<commit_msg>fix: Query first before get relations<commit_after><?php

namespace SkyaTura\EloquentREST\Traits;

use Illuminate\Http\Request;

trait ResourceTrait
{
    use DefaultActionsTrait;
    /**
     * @var Request
     */
    protected $request;

    /**
     * The requested resource path
     *
     * @var array
     */
    protected $resourcePath;

    /**
     * @var array
     */
    public $customActions;

    /**
     * @var array
     */
    private $defaultMethods = [
        'GET' => ['index', 'show'],
        'POST' => ['store', null],
        'PUT' => [null, 'replace'],
        'PATCH' => [null, 'update'],
        'DELETE' => [null, 'delete'],
    ];

    /**
     * @var string
     */
    protected $ref;
    protected $relationResource;

    /**
     * @param Request $request
     * @param string $path
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function resource(Request $request, $path = '')
    {
        $path = explode('/', $path);
        $resourcePath = [];
        if (!empty($path)) {
            $this->ref = array_splice($path, 0, 1)[0];
            while (!empty($path)) {
                if (count($path) >= 2) {
                    $relationship = array_splice($path, 0, 2);
                    $resourcePath[$relationship[0]] = $relationship[1];
                } else {
                    $this->relationResource = array_splice($path, 0, 1)[0];
                }
            }
        }
        $this->resourcePath = $resourcePath;
        $this->request = $request;

        $method = $this->getAction($request->method());
        $parameters = array_prepend($resourcePath, $request);
        return $this->callAction($method, $parameters);
    }

    protected function getAction($method)
    {
        $ref = $this->ref;
        $methodPath = strtolower($method . ($ref) ? '.' . $ref : '');
        if (!empty($this->customActions[$methodPath]))
            return $this->customActions[$methodPath];

        if(empty($this->defaultMethods[$method]))
            return '__call';

        $actions = $this->defaultMethods[$method];
        $action = empty($ref)?$actions[0]:$actions[1];

        return $action?$action:'__call';
    }

    /**
     * @param array $params
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function defaultModel($params = [])
    {
        return new $this->defaultModel($params);
    }

    private function findOrCreate($model, $ref){
        if(empty($ref)) return is_string($model)? new $model : $model;
        if(is_string($model)) $model = $model::query();

        switch ($ref){
            case 'first':
                return $model->take(1);
            case 'last':
                return $model->latest()->take(1);
            default:
                return $model->whereKey($ref)->take(1);
        }
    }

    /**
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function model()
    {
        $params = $this->resourcePath;
        $model = $this->defaultModel();
        $relationResource = $this->relationResource;
        $ref = $this->ref;

        $obj = $this->findOrCreate($model, $ref);

        if (!empty($params)) {
            foreach ($params as $rel => $id)
                $obj = $this->findOrCreate($obj->get(['*'])->first()->$rel(), $id);
        }

        return (empty($relationResource)) ? $obj : $obj->get(['*'])->first()->$relationResource();
    }
}
{'fraction_non_alphanumeric': 0.16916519694297472, 'fraction_numerical': 0.004703115814226925, 'mean_word_length': 1.9612706701479548, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 73, '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': '6512453', 'n_tokens_mistral': 2019, 'n_tokens_neox': 1957, 'n_words': 385}