kai-jacobsen/kontentblocks

View on GitHub
core/Frontend/Renderer/SlotRenderer.php

Summary

Maintainability
A
45 mins
Test Coverage
<?php

namespace Kontentblocks\Frontend\Renderer;

use Kontentblocks\Backend\Environment\PostEnvironment;
use Kontentblocks\Frontend\AreaRenderSettings;
use Kontentblocks\Frontend\ModuleIterator;
use Kontentblocks\Frontend\ModuleRenderSettings;
use Kontentblocks\Modules\Module;
use Kontentblocks\Modules\ModuleNode;
use Kontentblocks\Utils\Utilities;

/**
 * internal working name: SlotMachine
 * Experimental way to render modules manually for an given area
 * The SlotMachine works by providing a index to the ::slot($pos) method,
 * which will get the actual module from the iterator and call render on it
 *
 * Modules are ordered as they were added on the backend
 *
 * Usage:
 * Instantiate a new SlotMachine in your template file and provide
 * arguments for the area and the current post id
 * $SlotMachine = new \Kontentblocks\Frontend\SlotMachine('my-area-id', 66);
 *
 * To render a specific position just call
 * $SlotMachine->slot($pos);
 *
 * Case of use:
 * If you need to create very specific layouts and need fine control, and you actually know
 * what kind and how many modules are present.
 *
 *
 * Class SlotRenderer
 * @package Kontentblocks\Frontend
 */
class SlotRenderer
{

    public $done = array();
    /**
     * internal pointer
     * @var int
     */
    protected $position = 1;
    /**
     * @var array
     */
    protected $addArgs;

    /**
     * Class Constructor
     * @param ModuleIterator $iterator
     * @param AreaRenderSettings $areaSettings
     * @param ModuleRenderSettings $moduleSettings
     */
    public function __construct(
        ModuleIterator $iterator,
        AreaRenderSettings $areaSettings,
        ModuleRenderSettings $moduleSettings
    ) {
        $this->areaSettings = $areaSettings;
        $this->moduleSettings = $moduleSettings;
        $this->iterator = $iterator;
    }

    /**
     * @param int $number
     * @param array $args
     * @return array
     */
    public function getBatch($number = 1, $args = array())
    {
        $collect = array();
        for ($i = 0; $i < $number; $i++) {
            $collect[] = $this->slot($this->position, true, $args);
            $this->next();
        }
        return $collect;
    }

    /**
     * Actual method to handle the stuff
     * @param $pos
     * @param bool $returnModule
     * @param array $args
     * @return bool|string
     * @since 0.1.0
     */
    public function slot($pos = null, $returnModule = false, $args = array())
    {
        if (is_null($pos)) {
            $pos = $this->position;
        }
        $module = $this->iterator->setPosition($pos);
        if (is_a($module, Module::class)) {
            if (in_array($module->getId(), $this->done)) {
                return null;
            }
            $this->moduleSettings->import($args);
            $module->context->setRenderer($this);
            $module->context->set(array('renderPosition' => $this->position));
            $module->context->set(array('renderSettings' => $this->moduleSettings));
            $renderer = new SingleModuleRenderer($module, $this->moduleSettings);
            $module->toJSON();
            array_push($this->done, $module->getId());

            if ($returnModule) {
                return $renderer;
            }

            if ($out = $renderer->render()) {
                return $out;
            }
        }
    }

    /**
     * Simply render the next module
     * @since 0.1.0
     */
    public function next()
    {
        $this->position++;
        return $this;

    }

    /**
     * @return $this
     */
    public function prev()
    {
        $this->position--;
        return $this;
    }

    /**
     * @return $this
     */
    public function forward()
    {
        $count = count($this->iterator);
        $this->position = ($count > 0) ? $count - 1 : 0;
        return $this;

    }

    /**
     * @return $this
     */
    public function rewind()
    {
        $this->position = 0;
        return $this;

    }

    /**
     * @return bool|string
     */
    public function module()
    {
        $res = $this->slot();
        $this->next();
        return $res;
    }

    /**
     * @return bool
     */
    public function hasModule()
    {
        return ($this->iterator->next() !== false) ? true : false;
    }

    /**
     * @return mixed
     */
    public function getNextModule()
    {
        $next = $this->iterator->next();
        $this->iterator->prev();
        return $next;
    }

}