/** * Parse a single resource using given modes * @param array $modes * @param mixed $resource * @param array $root * @param string $fullPropertyPath * @return mixed */ private function parseResource(array $modes, &$resource, &$root, $fullPropertyPath = '') { foreach ($modes as $relation => $mode) { $modeResolver = $this->resolveMode($mode); $steps = explode('.', $relation); // Get the first resource in the relation // TODO: Refactor $property = array_shift($steps); if (is_array($resource)) { if ($resource[$property] === null) { continue; } $object =& $resource[$property]; } else { if ($resource->{$property} === null) { continue; } $object =& $resource->{$property}; } if (empty($steps)) { // This is the deepest level. Resolve it. $fullPropertyPath .= $relation; $object = $this->modeResolvers[$mode]->resolve($relation, $object, $root, $fullPropertyPath); } else { // More levels exist in this relation. // We want a drill down and resolve the deepest level first. $path = implode('.', $steps); $modes = [$path => $mode]; // Add the previous levels to the full path so it can be used // to populate the root level properly. $fullPropertyPath .= $property . '.'; if (Utility::isCollection($object)) { $object = $this->parseCollection($modes, $object, $root, $fullPropertyPath); } else { $object = $this->parseResource($modes, $object, $root, $fullPropertyPath); } } // Reset the full property path after running a full relation $fullPropertyPath = ''; Utility::setProperty($resource, $property, $object); } return $resource; }