MOON
Server: Apache
System: Linux server1.studioinfinity.com.br 2.6.32-954.3.5.lve1.4.90.el6.x86_64 #1 SMP Tue Feb 21 12:26:30 UTC 2023 x86_64
User: artinside (517)
PHP: 7.4.33
Disabled: exec,passthru,shell_exec,system
Upload Files
File: /home/artinside/sites.artinside.com.br/paliar/vendor/aplus/database/src/Manipulation/With.php
<?php declare(strict_types=1);
/*
 * This file is part of Aplus Framework Database Library.
 *
 * (c) Natan Felles <natanfelles@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Framework\Database\Manipulation;

use Closure;
use Framework\Database\Result;
use InvalidArgumentException;
use LogicException;

/**
 * Class With.
 *
 * @see https://mariadb.com/kb/en/with/
 *
 * @package database
 */
class With extends Statement
{
    /**
     * @see https://mariadb.com/kb/en/recursive-common-table-expressions-overview/
     */
    public const string OPT_RECURSIVE = 'RECURSIVE';

    protected function renderOptions() : ?string
    {
        if (!$this->hasOptions()) {
            return null;
        }
        $options = $this->sql['options'];
        foreach ($options as &$option) {
            $input = $option;
            $option = \strtoupper($option);
            if ($option !== static::OPT_RECURSIVE) {
                throw new InvalidArgumentException("Invalid option: {$input}");
            }
        }
        return \implode(' ', $options);
    }

    /**
     * Adds a table reference.
     *
     * @param Closure|string $table
     * @param Closure $alias
     *
     * @see https://mariadb.com/kb/en/non-recursive-common-table-expressions-overview/
     * @see https://mariadb.com/kb/en/recursive-common-table-expressions-overview/
     *
     * @return static
     */
    public function reference(Closure | string $table, Closure $alias) : static
    {
        $this->sql['references'][] = [
            'table' => $table,
            'alias' => $alias,
        ];
        return $this;
    }

    protected function renderReference() : string
    {
        if (!isset($this->sql['references'])) {
            throw new LogicException('References must be set');
        }
        $references = [];
        foreach ($this->sql['references'] as $reference) {
            $references[] = $this->renderIdentifier($reference['table'])
                . ' AS ' . $this->renderAsSelect($reference['alias']);
        }
        return \implode(', ', $references);
    }

    private function renderAsSelect(Closure $subquery) : string
    {
        return '(' . $subquery(new Select($this->database)) . ')';
    }

    /**
     * Sets the SELECT statement part.
     *
     * @param Closure $select
     *
     * @return static
     */
    public function select(Closure $select) : static
    {
        $this->sql['select'] = $select(new Select($this->database));
        return $this;
    }

    protected function renderSelect() : string
    {
        if (!isset($this->sql['select'])) {
            throw new LogicException('SELECT must be set');
        }
        return $this->sql['select'];
    }

    /**
     * Renders the WITH statement.
     *
     * @return string
     */
    public function sql() : string
    {
        $sql = 'WITH' . \PHP_EOL;
        $part = $this->renderOptions();
        if ($part) {
            $sql .= $part . \PHP_EOL;
        }
        $sql .= $this->renderReference() . \PHP_EOL;
        $sql .= $this->renderSelect();
        return $sql;
    }

    /**
     * Runs the WITH statement.
     *
     * @return Result
     */
    public function run() : Result
    {
        return $this->database->query($this->sql());
    }
}