tapestry-cloud/tapestry

View on GitHub
src/Plates/Template.php

Summary

Maintainability
B
4 hrs
Test Coverage
C
75%
<?php

namespace Tapestry\Plates;

use Exception;
use Throwable;
use LogicException;
use Tapestry\Entities\File;
use League\Plates\Template\Template as PlatesTemplate;

/**
 * Class Template.
 */
class Template extends PlatesTemplate
{
    /**
     * Instance of the template engine.
     * @var Engine
     */
    protected $engine;

    /**
     * @var File|null
     */
    private $file = null;

    /**
     * Create new Template instance.
     *
     * @param Engine $engine
     * @param string $name
     */
    public function __construct(Engine $engine, $name)
    {
        parent::__construct($engine, $name);
    }

    /**
     * Returns the content for a section block.
     *
     * @param string $name    Section name
     * @param string $default Default section content
     *
     * @return string|null
     */
    public function section($name, $default = null)
    {
        if ($name === 'content' && ! isset($this->sections['content']) && isset($this->data['content'])) {
            return $this->data['content'];
        }

        if (! isset($this->sections[$name])) {
            return $default;
        }

        return $this->sections[$name];
    }

    public function getFile()
    {
        return $this->file;
    }

    public function setFile(File $file)
    {
        $this->file = $file;
    }

    /**
     * Render the File.
     *
     * @param File $file
     * @param array $data
     * @return string
     * @throws Exception
     * @throws Throwable
     */
    public function renderFile(File $file, array $data = [])
    {
        $this->data($data);
        unset($data);

        $this->file = $file;
        $tmpDirectory = $this->engine->getProject()->currentWorkingDirectory.DIRECTORY_SEPARATOR.'.tmp';

        if ($layoutName = $file->getData('layout')) {
            $this->layoutName = (strpos('_templates', $layoutName) === false) ? '_templates'.DIRECTORY_SEPARATOR.$layoutName : $layoutName;
            $this->layoutData = $file->getData();
            $this->engine->getProject()->get('file_layout_cache')->merge([$this->file->getUid() => [$this->layoutName]]);
        }

        try {
            $tmpPathName = $tmpDirectory.DIRECTORY_SEPARATOR.time().'-'.sha1($file->getUid()).'.phtml';

            if (! file_exists($tmpDirectory)) {
                mkdir($tmpDirectory);
            }

            file_put_contents($tmpPathName, $file->getContent());

            $this->data($file->getData());
            $this->data([
                'permalink'     => $file->getCompiledPermalink(),
                'raw_permalink' => $file->getPermalink(),
            ]);

            extract($this->data);

            $level = ob_get_level();
            ob_start();
            include $tmpPathName;
            $content = ob_get_clean();

            if (isset($this->layoutName)) {
                $layout = $this->engine->make($this->layoutName);
                $layout->setFile($this->file);
                $layout->sections = array_merge($this->sections, ['content' => $content]);
                $content = $layout->render($this->layoutData);
            }

            return $content;
        } catch (Throwable $e) {
            while (ob_get_level() > $level) {
                ob_end_clean();
            }

            throw $e;
        } catch (Exception $e) {
            while (ob_get_level() > $level) {
                ob_end_clean();
            }

            throw $e;
        }
    }

    /**
     * Render the template and layout.
     * @param  array  $data
     * @throws \Throwable
     * @throws \Exception
     * @return string
     */
    public function render(array $data = [])
    {
        $this->data($data);
        unset($data);
        extract($this->data);

        if (! $this->exists()) {
            throw new LogicException(
                'The template "'.$this->name->getName().'" could not be found at "'.$this->path().'".'
            );
        }

        try {
            $level = ob_get_level();
            ob_start();

            include $this->path();

            $content = ob_get_clean();

            if (isset($this->layoutName)) {
                $layout = $this->engine->make($this->layoutName);
                $layout->setFile($this->file);
                $layout->sections = array_merge($this->sections, ['content' => $content]);
                $content = $layout->render($this->layoutData);
            }

            return $content;
        } catch (Throwable $e) {
            while (ob_get_level() > $level) {
                ob_end_clean();
            }

            throw $e;
        } catch (Exception $e) {
            while (ob_get_level() > $level) {
                ob_end_clean();
            }

            throw $e;
        }
    }

    /**
     * Set the template's layout.
     * @param  string $name
     * @param  array $data
     * @return void
     */
    public function layout($name, array $data = [])
    {
        $this->layoutName = $name;
        $this->layoutData = $data;
        $this->engine->getProject()->get('file_layout_cache')->merge([$this->file->getUid() => [$this->layoutName]]);
    }
}