Marcelgwerder\ApiHandler\Parser::parseWith PHP Метод

parseWith() защищенный Метод

Parse the with parameter
protected parseWith ( string $withParam ) : void
$withParam string
Результат void
    protected function parseWith($withParam)
    {
        $fields = $this->query->columns;
        $fieldsCount = count($fields);
        $baseModel = $this->builder->getModel();
        $withHistory = [];
        foreach (explode(',', $withParam) as $with) {
            //Use ArrayObject to be able to copy the array (for array_splice)
            $parts = new ArrayObject(explode('.', $with));
            $lastKey = count($parts) - 1;
            for ($i = 0; $i <= $lastKey; $i++) {
                $part = $parts[$i];
                $partsCopy = $parts->getArrayCopy();
                //Get the previous history path (e.g. if current is a.b.c the previous is a.b)
                $previousHistoryPath = implode('.', array_splice($partsCopy, 0, $i));
                //Get the current history part based on the previous one
                $currentHistoryPath = $previousHistoryPath ? $previousHistoryPath . '.' . $part : $part;
                //Create new history element
                if (!isset($withHistory[$currentHistoryPath])) {
                    $withHistory[$currentHistoryPath] = ['fields' => []];
                }
                //Get all given fields related to the current part
                $withHistory[$currentHistoryPath]['fields'] = array_filter($this->additionalFields, function ($field) use($part) {
                    return preg_match('/' . $part . '\\..+$/', $field);
                });
                //Get all given sorts related to the current part
                $withHistory[$currentHistoryPath]['sorts'] = array_filter($this->additionalSorts, function ($pair) use($part) {
                    return preg_match('/' . $part . '\\..+$/', $pair[0]);
                });
                if (!isset($previousModel)) {
                    $previousModel = $baseModel;
                }
                //Throw a new ApiHandlerException if the relation doesn't exist
                //or is not properly marked as a relation
                if (!$this->isRelation($previousModel, $part)) {
                    throw new ApiHandlerException('UnknownResourceRelation', ['relation' => $part]);
                }
                $relation = call_user_func([$previousModel, $part]);
                $relationType = $this->getRelationType($relation);
                if ($relationType === 'BelongsTo') {
                    $firstKey = $relation->getQualifiedForeignKey();
                    $secondKey = $relation->getQualifiedParentKeyName();
                } else {
                    if ($relationType === 'HasMany' || $relationType === 'HasOne') {
                        $firstKey = $relation->getQualifiedParentKeyName();
                        $secondKey = $relation->getForeignKey();
                    } else {
                        if ($relationType === 'BelongsToMany') {
                            $firstKey = $relation->getQualifiedParentKeyName();
                            $secondKey = $relation->getRelated()->getQualifiedKeyName();
                        } else {
                            if ($relationType === 'HasManyThrough') {
                                $firstKey = $relation->getHasCompareKey();
                                $secondKey = null;
                            } else {
                                die('Relation type not supported!');
                            }
                        }
                    }
                }
                //Check if we're on level 1 (e.g. a and not a.b)
                if ($firstKey !== null && $previousHistoryPath == '') {
                    if ($fieldsCount > 0 && !in_array($firstKey, $fields)) {
                        $fields[] = $firstKey;
                    }
                } else {
                    if ($firstKey !== null) {
                        if (count($withHistory[$previousHistoryPath]['fields']) > 0 && !in_array($firstKey, $withHistory[$previousHistoryPath]['fields'])) {
                            $withHistory[$previousHistoryPath]['fields'][] = $firstKey;
                        }
                    }
                }
                if ($secondKey !== null && count($withHistory[$currentHistoryPath]['fields']) > 0 && !in_array($secondKey, $withHistory[$currentHistoryPath]['fields'])) {
                    $withHistory[$currentHistoryPath]['fields'][] = $secondKey;
                }
                $previousModel = $relation->getModel();
            }
            unset($previousModel);
        }
        //Apply the withHistory to using the laravel "with" function
        $withsArr = [];
        foreach ($withHistory as $withHistoryKey => $withHistoryValue) {
            $withsArr[$withHistoryKey] = function ($query) use($withHistory, $withHistoryKey) {
                //Reduce field values to fieldname
                $fields = array_map(function ($field) {
                    $pos = strpos($field, '.');
                    return $pos !== false ? substr($field, $pos + 1) : $field;
                }, $withHistory[$withHistoryKey]['fields']);
                if (count($fields) > 0 && is_array($fields)) {
                    $query->select($fields);
                }
                //Attach sorts
                foreach ($withHistory[$withHistoryKey]['sorts'] as $pair) {
                    $pos = strpos($pair[0], '.');
                    $pair = $pos !== false ? [substr($pair[0], $pos + 1), $pair[1]] : $pair;
                    call_user_func_array([$query, 'orderBy'], $pair);
                }
            };
        }
        $this->builder->with($withsArr);
        //Merge the base fields
        if (count($fields) > 0) {
            if (!is_array($this->query->columns)) {
                $this->query->columns = [];
            }
            $this->query->columns = array_merge($this->query->columns, $fields);
        }
    }