Seditio Source
Root |
./othercms/phpBB3/vendor/s9e/text-formatter/src/Configurator/RendererGenerators/PHP.php
<?php

/**
* @package   s9e\TextFormatter
* @copyright Copyright (c) 2010-2021 The s9e authors
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
*/
namespace s9e\TextFormatter\Configurator\RendererGenerators;

use
DOMElement;
use
s9e\TextFormatter\Configurator\Helpers\TemplateHelper;
use
s9e\TextFormatter\Configurator\Helpers\TemplateParser;
use
s9e\TextFormatter\Configurator\RendererGenerator;
use
s9e\TextFormatter\Configurator\RendererGenerators\PHP\ControlStructuresOptimizer;
use
s9e\TextFormatter\Configurator\RendererGenerators\PHP\Optimizer;
use
s9e\TextFormatter\Configurator\RendererGenerators\PHP\Quick;
use
s9e\TextFormatter\Configurator\RendererGenerators\PHP\Serializer;
use
s9e\TextFormatter\Configurator\RendererGenerators\PHP\SwitchStatement;
use
s9e\TextFormatter\Configurator\Rendering;
use
s9e\TextFormatter\Configurator\TemplateNormalizer;

class
PHP implements RendererGenerator
{
   
/**
    * XSL namespace
    */
   
const XMLNS_XSL = 'http://www.w3.org/1999/XSL/Transform';

   
/**
    * @var string Directory where the renderer's source is automatically saved if set, and if filepath is not set
    */
   
public $cacheDir;

   
/**
    * @var string Name of the class to be created. If null, a random name will be generated
    */
   
public $className;

   
/**
    * @var ControlStructuresOptimizer Control structures optimizer
    */
   
public $controlStructuresOptimizer;

   
/**
    * @var string Prefix used when generating a default class name
    */
   
public $defaultClassPrefix = 'Renderer_';

   
/**
    * @var bool Whether to enable the Quick renderer
    */
   
public $enableQuickRenderer = true;

   
/**
    * @var string If set, path to the file where the renderer will be saved
    */
   
public $filepath;

   
/**
    * @var string Name of the last class generated
    */
   
public $lastClassName;

   
/**
    * @var string Path to the last file saved
    */
   
public $lastFilepath;

   
/**
    * @var TemplateNormalizer
    */
   
protected $normalizer;

   
/**
    * @var Optimizer Optimizer
    */
   
public $optimizer;

   
/**
    * @var string File header
    */
   
public $phpHeader = '/**
* @package   s9e\TextFormatter
* @copyright Copyright (c) 2010-2021 The s9e authors
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
*/'
;

   
/**
    * @var Serializer Serializer
    */
   
public $serializer;

   
/**
    * Constructor
    *
    * @param string $cacheDir If set, path to the directory where the renderer will be saved
    */
   
public function __construct($cacheDir = null)
    {
       
$this->cacheDir = $cacheDir ?? sys_get_temp_dir();
        if (
extension_loaded('tokenizer'))
        {
           
$this->controlStructuresOptimizer = new ControlStructuresOptimizer;
           
$this->optimizer = new Optimizer;
        }
       
$this->serializer = new Serializer;
       
$this->normalizer = new TemplateNormalizer(['RemoveLivePreviewAttributes']);
    }

   
/**
    * {@inheritdoc}
    */
   
public function getRenderer(Rendering $rendering)
    {
       
// Generate the source file
       
$php = $this->generate($rendering);

       
// Save the file if applicable
       
if (isset($this->filepath))
        {
           
$filepath = $this->filepath;
        }
        else
        {
           
$filepath = $this->cacheDir . '/' . str_replace('\\', '_', $this->lastClassName) . '.php';
        }

       
file_put_contents($filepath, "<?php\n" . $php);
       
$this->lastFilepath = realpath($filepath);

       
// Execute the source to create the class if it doesn't exist
       
if (!class_exists($this->lastClassName, false))
        {
            include
$filepath;
        }

        return new
$this->lastClassName;
    }

   
/**
    * Generate the source for a PHP class that renders an intermediate representation according to
    * given rendering configuration
    *
    * @param  Rendering $rendering
    * @return string
    */
   
public function generate(Rendering $rendering)
    {
       
// Compile the templates to PHP
       
$compiledTemplates = array_map([$this, 'compileTemplate'], $rendering->getTemplates());

       
// Start the code right after the class name, we'll prepend the header when we're done
       
$php = [];
       
$php[] = ' extends \\s9e\\TextFormatter\\Renderers\\PHP';
       
$php[] = '{';
       
$php[] = '    protected $params=' . self::export($rendering->getAllParameters()) . ';';
       
$php[] = '    protected function renderNode(\\DOMNode $node)';
       
$php[] = '    {';
       
$php[] = '        ' . SwitchStatement::generate('$node->nodeName', $compiledTemplates, '$this->at($node);');
       
$php[] = '    }';

       
// Append the Quick renderer if applicable
       
if ($this->enableQuickRenderer)
        {
           
$php[] = Quick::getSource($compiledTemplates);
        }

       
// Close the class definition
       
$php[] = '}';

       
// Assemble the source
       
$php = implode("\n", $php);

       
// Finally, optimize the control structures
       
if (isset($this->controlStructuresOptimizer))
        {
           
$php = $this->controlStructuresOptimizer->optimize($php);
        }

       
// Generate a name for that class if necessary, and save it
       
$className = (isset($this->className))
                   ?
$this->className
                   
: $this->defaultClassPrefix . sha1($php);
       
$this->lastClassName = $className;

       
// Prepare the header
       
$header = "\n" . $this->phpHeader . "\n";

       
// Declare the namespace and class name
       
$pos = strrpos($className, '\\');
        if (
$pos !== false)
        {
           
$header .= 'namespace ' . substr($className, 0, $pos) . ";\n\n";
           
$className = substr($className, 1 + $pos);
        }

       
// Prepend the header and the class name
       
$php = $header . 'class ' . $className . $php;

        return
$php;
    }

   
/**
    * Export given array as PHP code
    *
    * @param  array  $value Original value
    * @return string        PHP code
    */
   
protected static function export(array $value)
    {
       
$pairs = [];
        foreach (
$value as $k => $v)
        {
           
$pairs[] = var_export($k, true) . '=>' . var_export($v, true);
        }

        return
'[' . implode(',', $pairs) . ']';
    }

   
/**
    * Compile a template to PHP
    *
    * @param  string $template Original template
    * @return string           Compiled template
    */
   
protected function compileTemplate($template)
    {
       
$template = $this->normalizer->normalizeTemplate($template);

       
// Parse the template
       
$ir = TemplateParser::parse($template);

       
// Serialize the representation to PHP
       
$php = $this->serializer->serialize($ir->documentElement);
        if (isset(
$this->optimizer))
        {
           
$php = $this->optimizer->optimize($php);
        }

        return
$php;
    }
}