src/Lud/Press/PressRenderer.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php namespace Lud\Press;

use Closure;
use Michelf\Markdown;
use Michelf\MarkdownExtra;
use Skriv\Markup\Renderer as SkrivRenderer;
use Twig_Environment;
use Twig_Loader_Array;

class PressRenderer
{

    /**
     * Registers Closure instances to get HTML content to inject into the
     * rendered content. Different instances are often user to render & pre-
     * render (one for twig, the other for markdown), so we share the generators
     * and the references (see below).
     * @var array
     */
    private static $prerenderedContentFuns = [];

    /**
     * A reference to identify registered content generators
     * @var integer
     */
    private static $generatorRef = 0;

    // treats the content as a full content document and transforms it to HTML
    public function transform($parserType, $preRendered)
    {
        $config = PressFacade::getConf($parserType, []);
        $method = 'transform'.lcfirst($parserType);
        return $html = call_user_func([$this,$method], $preRendered, $config);
    }

    // treats the content as a twig template and renders it
    public function preRender($tplStr, MetaWrapper $meta, MetaWrapper $parentMeta = null)
    {
        $twigData = [
            'article' => $meta,
            'press' => new PressTwigApi($this, $meta),
            'parent' => $parentMeta
        ];
        $twigLoader = new Twig_Loader_Array([
            '__article_content' => $tplStr
        ]);
        $twig = new Twig_Environment($twigLoader, [
            'autoescape' => false,
            // 'strict_variables' => true,
            'optimizations' => 0
        ]);
        return $preRendered = $twig->render('__article_content', $twigData);
    }

    protected function transformMarkdown($str, $config)
    {
        $html = MarkdownExtra::defaultTransform($str);
        //@todo refactor parsers functions
        $trsf = new PressHTMLTransformer($this);
        $trsf->load($html);
        $trsf->applyTransforms();
        // There is no way to extract footnotes from the class, so we will get
        // them from the HTML parser
        $footnotes_html = $trsf->stripMarkdownExtraFootNotes();
        return ['html' => $trsf->toHTML(), 'footnotes_html' => $footnotes_html];
    }

    protected function transformSkriv($str, $config)
    {
        $renderer = SkrivRenderer::factory('html', $config);
        $html = $renderer->render($str);
        $footnotes_html = $renderer->getFootnotes();
        if ($footnotes_html) {
            $footnotes_html = PressHTMLTransformer::unwrapFootnotes($footnotes_html);
        }
        return ['html' => $html, 'footnotes_html' => $footnotes_html];
    }

    protected function transformHtml($str, $config)
    {
        $trsf = new PressHTMLTransformer($this);
        $trsf->load($str);
        $trsf->applyTransforms();
        return ['html' => $trsf->toHTML(), 'footnotes_html' => ''];
    }

    public function insertRenderedBlockPlaceholder(Closure $contentGenerator, $format = 'md')
    {
        $ref = $this->registerContentGenerator($contentGenerator);
        $tag = PressHTMLTransformer::PRESS_INSERT_TAG;
        switch ($format) {
            // we just return a tag that will be replaced by the generated
            // content in the render phase. We need a block that will be left
            // as-is by the markdown parser

            case 'md':
                return "<$tag markdown=\"1\" press-ref='$ref'></$tag>";
            default:
                throw new \Exception("Unknown target format '$md'");
        }
    }

    public function getGeneratedContent($ref)
    {
        $generate = self::$prerenderedContentFuns[$ref];
        return $generate();
    }

    protected function registerContentGenerator(Closure $contentGenerator)
    {
        // Every generator registered use anincrement of the reference so there
        // are no index clashes in the static array
        $ref = self::$generatorRef += 1;
        self::$prerenderedContentFuns[$ref] = $contentGenerator;
        return $ref;
    }
}