master

laravel/framework

Last updated at: 29/12/2023 09:24

ConditionallyLoadsAttributes.php

TLDR

The ConditionallyLoadsAttributes.php file in the Illuminate\Http\Resources namespace contains a trait called ConditionallyLoadsAttributes. This trait provides methods for filtering and manipulating data.

Methods

filter

This method filters the given data, removing any optional values.

mergeData

This method merges the given data in at the given index.

removeMissingValues

This method removes the missing values from the filtered data.

when

This method retrieves a value if the given "condition" is truthy.

unless

This method retrieves a value if the given "condition" is falsy.

merge

This method merges a value into the array.

mergeWhen

This method merges a value if the given condition is truthy.

mergeUnless

This method merges a value unless the given condition is truthy.

attributes

This method merges the given attributes.

whenHas

This method retrieves an attribute if it exists on the resource.

whenNull

This method retrieves a model attribute if it is null.

whenNotNull

This method retrieves a model attribute if it is not null.

whenAppended

This method retrieves an accessor when it has been appended.

whenLoaded

This method retrieves a relationship if it has been loaded.

whenCounted

This method retrieves a relationship count if it exists.

whenAggregated

This method retrieves a relationship aggregated value if it exists.

whenPivotLoaded

This method executes a callback if the given pivot table has been loaded.

whenPivotLoadedAs

This method executes a callback if the given pivot table with a custom accessor has been loaded.

hasPivotLoaded

This method determines if the resource has the specified pivot table loaded.

hasPivotLoadedAs

This method determines if the resource has the specified pivot table loaded with a custom accessor.

transform

This method transforms the given value if it is present.

<?php

namespace Illuminate\Http\Resources;

use Illuminate\Support\Arr;
use Illuminate\Support\Str;

trait ConditionallyLoadsAttributes
{
    /**
     * Filter the given data, removing any optional values.
     *
     * @param  array  $data
     * @return array
     */
    protected function filter($data)
    {
        $index = -1;

        foreach ($data as $key => $value) {
            $index++;

            if (is_array($value)) {
                $data[$key] = $this->filter($value);

                continue;
            }

            if (is_numeric($key) && $value instanceof MergeValue) {
                return $this->mergeData(
                    $data, $index, $this->filter($value->data),
                    array_values($value->data) === $value->data
                );
            }

            if ($value instanceof self && is_null($value->resource)) {
                $data[$key] = null;
            }
        }

        return $this->removeMissingValues($data);
    }

    /**
     * Merge the given data in at the given index.
     *
     * @param  array  $data
     * @param  int  $index
     * @param  array  $merge
     * @param  bool  $numericKeys
     * @return array
     */
    protected function mergeData($data, $index, $merge, $numericKeys)
    {
        if ($numericKeys) {
            return $this->removeMissingValues(array_merge(
                array_merge(array_slice($data, 0, $index, true), $merge),
                $this->filter(array_values(array_slice($data, $index + 1, null, true)))
            ));
        }

        return $this->removeMissingValues(array_slice($data, 0, $index, true) +
                $merge +
                $this->filter(array_slice($data, $index + 1, null, true)));
    }

    /**
     * Remove the missing values from the filtered data.
     *
     * @param  array  $data
     * @return array
     */
    protected function removeMissingValues($data)
    {
        $numericKeys = true;

        foreach ($data as $key => $value) {
            if (($value instanceof PotentiallyMissing && $value->isMissing()) ||
                ($value instanceof self &&
                $value->resource instanceof PotentiallyMissing &&
                $value->isMissing())) {
                unset($data[$key]);
            } else {
                $numericKeys = $numericKeys && is_numeric($key);
            }
        }

        if (property_exists($this, 'preserveKeys') && $this->preserveKeys === true) {
            return $data;
        }

        return $numericKeys ? array_values($data) : $data;
    }

    /**
     * Retrieve a value if the given "condition" is truthy.
     *
     * @param  bool  $condition
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MissingValue|mixed
     */
    protected function when($condition, $value, $default = null)
    {
        if ($condition) {
            return value($value);
        }

        return func_num_args() === 3 ? value($default) : new MissingValue;
    }

    /**
     * Retrieve a value if the given "condition" is falsy.
     *
     * @param  bool  $condition
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MissingValue|mixed
     */
    public function unless($condition, $value, $default = null)
    {
        $arguments = func_num_args() === 2 ? [$value] : [$value, $default];

        return $this->when(! $condition, ...$arguments);
    }

    /**
     * Merge a value into the array.
     *
     * @param  mixed  $value
     * @return \Illuminate\Http\Resources\MergeValue|mixed
     */
    protected function merge($value)
    {
        return $this->mergeWhen(true, $value);
    }

    /**
     * Merge a value if the given condition is truthy.
     *
     * @param  bool  $condition
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MergeValue|mixed
     */
    protected function mergeWhen($condition, $value, $default = null)
    {
        if ($condition) {
            return new MergeValue(value($value));
        }

        return func_num_args() === 3 ? new MergeValue(value($default)) : new MissingValue();
    }

    /**
     * Merge a value unless the given condition is truthy.
     *
     * @param  bool  $condition
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MergeValue|mixed
     */
    protected function mergeUnless($condition, $value, $default = null)
    {
        $arguments = func_num_args() === 2 ? [$value] : [$value, $default];

        return $this->mergeWhen(! $condition, ...$arguments);
    }

    /**
     * Merge the given attributes.
     *
     * @param  array  $attributes
     * @return \Illuminate\Http\Resources\MergeValue
     */
    protected function attributes($attributes)
    {
        return new MergeValue(
            Arr::only($this->resource->toArray(), $attributes)
        );
    }

    /**
     * Retrieve an attribute if it exists on the resource.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MissingValue|mixed
     */
    public function whenHas($attribute, $value = null, $default = null)
    {
        if (func_num_args() < 3) {
            $default = new MissingValue;
        }

        if (! array_key_exists($attribute, $this->resource->getAttributes())) {
            return value($default);
        }

        return func_num_args() === 1
                ? $this->resource->{$attribute}
                : value($value, $this->resource->{$attribute});
    }

    /**
     * Retrieve a model attribute if it is null.
     *
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MissingValue|mixed
     */
    protected function whenNull($value, $default = null)
    {
        $arguments = func_num_args() == 1 ? [$value] : [$value, $default];

        return $this->when(is_null($value), ...$arguments);
    }

    /**
     * Retrieve a model attribute if it is not null.
     *
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MissingValue|mixed
     */
    protected function whenNotNull($value, $default = null)
    {
        $arguments = func_num_args() == 1 ? [$value] : [$value, $default];

        return $this->when(! is_null($value), ...$arguments);
    }

    /**
     * Retrieve an accessor when it has been appended.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MissingValue|mixed
     */
    protected function whenAppended($attribute, $value = null, $default = null)
    {
        if ($this->resource->hasAppended($attribute)) {
            return func_num_args() >= 2 ? value($value) : $this->resource->$attribute;
        }

        return func_num_args() === 3 ? value($default) : new MissingValue;
    }

    /**
     * Retrieve a relationship if it has been loaded.
     *
     * @param  string  $relationship
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MissingValue|mixed
     */
    protected function whenLoaded($relationship, $value = null, $default = null)
    {
        if (func_num_args() < 3) {
            $default = new MissingValue;
        }

        if (! $this->resource->relationLoaded($relationship)) {
            return value($default);
        }

        if (func_num_args() === 1) {
            return $this->resource->{$relationship};
        }

        if ($this->resource->{$relationship} === null) {
            return;
        }

        return value($value);
    }

    /**
     * Retrieve a relationship count if it exists.
     *
     * @param  string  $relationship
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MissingValue|mixed
     */
    public function whenCounted($relationship, $value = null, $default = null)
    {
        if (func_num_args() < 3) {
            $default = new MissingValue;
        }

        $attribute = (string) Str::of($relationship)->snake()->finish('_count');

        if (! isset($this->resource->getAttributes()[$attribute])) {
            return value($default);
        }

        if (func_num_args() === 1) {
            return $this->resource->{$attribute};
        }

        if ($this->resource->{$attribute} === null) {
            return;
        }

        return value($value, $this->resource->{$attribute});
    }

    /**
     * Retrieve a relationship aggregated value if it exists.
     *
     * @param  string  $relationship
     * @param  string  $column
     * @param  string  $aggregate
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MissingValue|mixed
     */
    public function whenAggregated($relationship, $column, $aggregate, $value = null, $default = null)
    {
        $attribute = (string) Str::of($relationship)->snake()->append('_')->append($aggregate)->append('_')->finish($column);

        if (! isset($this->resource->getAttributes()[$attribute])) {
            return value($default);
        }

        if (func_num_args() === 3) {
            return $this->resource->{$attribute};
        }

        if ($this->resource->{$attribute} === null) {
            return;
        }

        return value($value, $this->resource->{$attribute});
    }

    /**
     * Execute a callback if the given pivot table has been loaded.
     *
     * @param  string  $table
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MissingValue|mixed
     */
    protected function whenPivotLoaded($table, $value, $default = null)
    {
        return $this->whenPivotLoadedAs('pivot', ...func_get_args());
    }

    /**
     * Execute a callback if the given pivot table with a custom accessor has been loaded.
     *
     * @param  string  $accessor
     * @param  string  $table
     * @param  mixed  $value
     * @param  mixed  $default
     * @return \Illuminate\Http\Resources\MissingValue|mixed
     */
    protected function whenPivotLoadedAs($accessor, $table, $value, $default = null)
    {
        if (func_num_args() === 3) {
            $default = new MissingValue;
        }

        return $this->when(
            $this->hasPivotLoadedAs($accessor, $table),
            ...[$value, $default]
        );
    }

    /**
     * Determine if the resource has the specified pivot table loaded.
     *
     * @param  string  $table
     * @return bool
     */
    protected function hasPivotLoaded($table)
    {
        return $this->hasPivotLoadedAs('pivot', $table);
    }

    /**
     * Determine if the resource has the specified pivot table loaded with a custom accessor.
     *
     * @param  string  $accessor
     * @param  string  $table
     * @return bool
     */
    protected function hasPivotLoadedAs($accessor, $table)
    {
        return isset($this->resource->$accessor) &&
            ($this->resource->$accessor instanceof $table ||
            $this->resource->$accessor->getTable() === $table);
    }

    /**
     * Transform the given value if it is present.
     *
     * @param  mixed  $value
     * @param  callable  $callback
     * @param  mixed  $default
     * @return mixed
     */
    protected function transform($value, callable $callback, $default = null)
    {
        return transform(
            $value, $callback, func_num_args() === 3 ? $default : new MissingValue
        );
    }
}