Your IP : 216.73.216.229


Current Path : /home/jeromecohp/www/tmp/yooessentials/modules/core/src/Source/
Upload File :
Current File : /home/jeromecohp/www/tmp/yooessentials/modules/core/src/Source/SourceResolver.php

<?php
/**
 * @package   Essentials YOOtheme Pro (Freemium) 1.6.8
 * @author    ZOOlanders https://www.zoolanders.com
 * @copyright Copyright (C) Joolanders, SL
 * @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
 */

namespace ZOOlanders\YOOessentials\Source;

use YOOtheme\Arr;
use YOOtheme\Builder\Source;
use YOOtheme\Builder\Source\SourceQuery;
use YOOtheme\Builder\Source\SourceTransform;
use YOOtheme\Event;

class SourceResolver
{
    /**
     * @var Source
     */
    protected $source;

    /**
     * @var SourceTransform
     */
    protected $sourceTransform;

    public function __construct(Source $source, SourceTransform $sourceTransform)
    {
        $this->source = $source;
        $this->sourceTransform = $sourceTransform;
    }

    public function setSource(Source $source)
    {
        $this->source = $source;
    }

    /**
     * Render callback.
     *
     * @param object $node
     * @param array  $params
     */
    public function resolveNode($node, array $params = []): object
    {
        $node = $this->prepareNode($node);

        if (!$result = $this->querySource($node, $params)) {
            return $node;
        }

        $name = $node->source->query->name;

        // add field name
        if (isset($node->source->query->field)) {
            $name .= ".{$node->source->query->field->name}";
        }

        // get source data
        if (is_array($data = Arr::get($result, "data.{$name}"))) {
            // map source properties
            if ($data) {
                $this->mapSource($node, $params + compact('data'));
            }
        }

        return $node;
    }

    /**
     * Map source properties.
     *
     * @param object $node
     * @param array  $params
     *
     * @return object|bool
     */
    protected function mapSource($node, array $params): object
    {
        if (empty($params['data'][0])) {
            $this->sourceTransform->mapSource($node, $params);
        } else {
            $nodes = [];

            // clone node for each item
            foreach ($params['data'] as $data) {
                $clone = clone $node;
                $clone->source = (object) [
                    'props' => $node->source->props,
                ];

                if ($this->sourceTransform->mapSource($clone, compact('data') + $params)) {
                    $nodes[] = $clone;
                }
            }

            $values = array_column($nodes, 'props');

            foreach (($node->source->props ?? []) as $name => $prop) {
                $node->props[$name] = array_column($values, $name);
            }
        }

        return $node;
    }

    /**
     * Query source data.
     *
     * @param object $node
     * @param array  $params
     *
     * @return array|void
     */
    public function querySource($node, array $params)
    {
        if (empty($node->source->query->name) || empty($node->source->props)) {
            return;
        }

        // execute query without validation rules
        $query = (new SourceQuery())->create($node);
        $result = $this->source->query(
            [
                'kind' => 'Document',
                'definitions' => [$query],
            ],
            $params,
            new \ArrayObject(),
            null,
            null,
            null,
            []
        );

        if (!empty($result->errors)) {
            Event::emit('source.error', $result->errors, $node);
        }

        return $result->toArray();
    }

    protected function toString($str)
    {
        if (is_scalar($str) || is_callable([$str, '__toString'])) {
            return (string) $str;
        }

        return '';
    }

    protected function prepareNode($node): object
    {
        $node = json_decode(json_encode($node), false);
        $node->props = (array) $node->props;

        return $node;
    }
}