master

laravel/framework

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

CompilesJsonPaths.php

TLDR

This file, located at src/Illuminate/Database/Concerns/CompilesJsonPaths.php, contains a trait called CompilesJsonPaths. This trait provides methods for manipulating JSON selectors and paths.

Methods

wrapJsonFieldAndPath

This method takes a JSON selector as input and splits it into the field and the optional path. It then wraps each part separately.

wrapJsonPath

This method wraps a given JSON path. It takes the path value and an optional delimiter as input. It replaces any occurrences of backslashes and single quotes in the path value. It then splits the path into segments using the delimiter, wraps each segment, and joins them with a dot. Finally, it returns the wrapped JSON path.

wrapJsonPathSegment

This method wraps a given JSON path segment. It takes the path segment as input. If the segment ends with one or more square brackets (indicating array access), it separates the key and the brackets. If the key is not empty, it wraps it with double quotes. It then returns the wrapped path segment.

<?php

namespace Illuminate\Database\Concerns;

use Illuminate\Support\Str;

trait CompilesJsonPaths
{
    /**
     * Split the given JSON selector into the field and the optional path and wrap them separately.
     *
     * @param  string  $column
     * @return array
     */
    protected function wrapJsonFieldAndPath($column)
    {
        $parts = explode('->', $column, 2);

        $field = $this->wrap($parts[0]);

        $path = count($parts) > 1 ? ', '.$this->wrapJsonPath($parts[1], '->') : '';

        return [$field, $path];
    }

    /**
     * Wrap the given JSON path.
     *
     * @param  string  $value
     * @param  string  $delimiter
     * @return string
     */
    protected function wrapJsonPath($value, $delimiter = '->')
    {
        $value = preg_replace("/([\\\\]+)?\\'/", "''", $value);

        $jsonPath = collect(explode($delimiter, $value))
            ->map(fn ($segment) => $this->wrapJsonPathSegment($segment))
            ->join('.');

        return "'$".(str_starts_with($jsonPath, '[') ? '' : '.').$jsonPath."'";
    }

    /**
     * Wrap the given JSON path segment.
     *
     * @param  string  $segment
     * @return string
     */
    protected function wrapJsonPathSegment($segment)
    {
        if (preg_match('/(\[[^\]]+\])+$/', $segment, $parts)) {
            $key = Str::beforeLast($segment, $parts[0]);

            if (! empty($key)) {
                return '"'.$key.'"'.$parts[0];
            }

            return $parts[0];
        }

        return '"'.$segment.'"';
    }
}