Seditio Source
Root |
./othercms/phpBB3/vendor/s9e/text-formatter/src/Configurator/BundleGenerator.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;

use
s9e\TextFormatter\Configurator;
use
s9e\TextFormatter\Configurator\RendererGenerators\PHP;

class
BundleGenerator
{
   
/**
    * @var Configurator Configurator this instance belongs to
    */
   
protected $configurator;

   
/**
    * @var callable Callback used to serialize the objects
    */
   
public $serializer = 'serialize';

   
/**
    * @var string Callback used to unserialize the serialized objects (must be a string)
    */
   
public $unserializer = 'unserialize';

   
/**
    * Constructor
    *
    * @param  Configurator $configurator Configurator
    */
   
public function __construct(Configurator $configurator)
    {
       
$this->configurator = $configurator;
    }

   
/**
    * Create and return the source of a bundle based on given Configurator instance
    *
    * Options:
    *
    *  - autoInclude: automatically load the source of the PHP renderer (default: true)
    *
    * @param  string $className Name of the bundle class
    * @param  array  $options   Associative array of optional settings
    * @return string            PHP source for the bundle
    */
   
public function generate($className, array $options = [])
    {
       
// Add default options
       
$options += ['autoInclude' => true];

       
// Copy the PHP files header if applicable
       
if ($this->configurator->rendering->engine instanceof PHP)
        {
           
$this->configurator->rendering->engine->phpHeader = $this->configurator->phpHeader;
        }

       
// Get the parser and renderer
       
$objects  = $this->configurator->finalize();
       
$parser   = $objects['parser'];
       
$renderer = $objects['renderer'];

       
// Split the bundle's class name and its namespace
       
$namespace = '';
        if (
preg_match('#(.*)\\\\([^\\\\]+)$#', $className, $m))
        {
           
$namespace = $m[1];
           
$className = $m[2];
        }

       
// Start with the standard header
       
$php   = [];
       
$php[] = $this->configurator->phpHeader;

        if (
$namespace)
        {
           
$php[] = 'namespace ' . $namespace . ';';
           
$php[] = '';
        }

       
// Generate and append the bundle class
       
$php[] = 'abstract class ' . $className . ' extends \\s9e\\TextFormatter\\Bundle';
       
$php[] = '{';
       
$php[] = '    /**';
       
$php[] = '    * @var s9e\\TextFormatter\\Parser Singleton instance used by parse()';
       
$php[] = '    */';
       
$php[] = '    protected static $parser;';
       
$php[] = '';
       
$php[] = '    /**';
       
$php[] = '    * @var s9e\\TextFormatter\\Renderer Singleton instance used by render()';
       
$php[] = '    */';
       
$php[] = '    protected static $renderer;';
       
$php[] = '';

       
// Add the event callbacks if applicable
       
$events = [
           
'beforeParse'
               
=> 'Callback executed before parse(), receives the original text as argument',
           
'afterParse'
               
=> 'Callback executed after parse(), receives the parsed text as argument',
           
'beforeRender'
               
=> 'Callback executed before render(), receives the parsed text as argument',
           
'afterRender'
               
=> 'Callback executed after render(), receives the output as argument',
           
'beforeUnparse'
               
=> 'Callback executed before unparse(), receives the parsed text as argument',
           
'afterUnparse'
               
=> 'Callback executed after unparse(), receives the original text as argument'
       
];
        foreach (
$events as $eventName => $eventDesc)
        {
            if (isset(
$options[$eventName]))
            {
               
$php[] = '    /**';
               
$php[] = '    * @var ' . $eventDesc;
               
$php[] = '    */';
               
$php[] = '    public static $' . $eventName . ' = ' . var_export($options[$eventName], true) . ';';
               
$php[] = '';
            }
        }

        if (isset(
$objects['js']))
        {
           
$php[] = '    /**';
           
$php[] = '    * {@inheritdoc}';
           
$php[] = '    */';
           
$php[] = '    public static function getJS()';
           
$php[] = '    {';
           
$php[] = '        return ' . var_export($objects['js'], true) . ';';
           
$php[] = '    }';
           
$php[] = '';
        }

       
$php[] = '    /**';
       
$php[] = '    * {@inheritdoc}';
       
$php[] = '    */';
       
$php[] = '    public static function getParser()';
       
$php[] = '    {';

        if (isset(
$options['parserSetup']))
        {
           
$php[] = '        $parser = ' . $this->exportObject($parser) . ';';
           
$php[] = '        ' . $this->exportCallback($namespace, $options['parserSetup'], '$parser') . ';';
           
$php[] = '';
           
$php[] = '        return $parser;';
        }
        else
        {
           
$php[] = '        return ' . $this->exportObject($parser) . ';';
        }

       
$php[] = '    }';
       
$php[] = '';
       
$php[] = '    /**';
       
$php[] = '    * {@inheritdoc}';
       
$php[] = '    */';
       
$php[] = '    public static function getRenderer()';
       
$php[] = '    {';

       
// If this is a PHP renderer and we know where it's saved, automatically load it as needed
       
if (!empty($options['autoInclude'])
         &&
$this->configurator->rendering->engine instanceof PHP
         
&& isset($this->configurator->rendering->engine->lastFilepath))
        {
           
$className = get_class($renderer);
           
$filepath  = realpath($this->configurator->rendering->engine->lastFilepath);

           
$php[] = '        if (!class_exists(' . var_export($className, true) . ', false)';
           
$php[] = '         && file_exists(' . var_export($filepath, true) . '))';
           
$php[] = '        {';
           
$php[] = '            include ' . var_export($filepath, true) . ';';
           
$php[] = '        }';
           
$php[] = '';
        }

        if (isset(
$options['rendererSetup']))
        {
           
$php[] = '        $renderer = ' . $this->exportObject($renderer) . ';';
           
$php[] = '        ' . $this->exportCallback($namespace, $options['rendererSetup'], '$renderer') . ';';
           
$php[] = '';
           
$php[] = '        return $renderer;';
        }
        else
        {
           
$php[] = '        return ' . $this->exportObject($renderer) . ';';
        }

       
$php[] = '    }';
       
$php[] = '}';

        return
implode("\n", $php);
    }

   
/**
    * Export a given callback as PHP code
    *
    * @param  string   $namespace Namespace in which the callback is execute
    * @param  callable $callback  Original callback
    * @param  string   $argument  Callback's argument (as PHP code)
    * @return string              PHP code
    */
   
protected function exportCallback($namespace, callable $callback, $argument)
    {
        if (
is_array($callback) && is_string($callback[0]))
        {
           
// Replace ['foo', 'bar'] with 'foo::bar'
           
$callback = $callback[0] . '::' . $callback[1];
        }

        if (!
is_string($callback))
        {
            return
'call_user_func(' . var_export($callback, true) . ', ' . $argument . ')';
        }

       
// Ensure that the callback starts with a \
       
if ($callback[0] !== '\\')
        {
           
$callback = '\\' . $callback;
        }

       
// Replace \foo\bar::baz() with bar::baz() if we're in namespace foo
       
if (substr($callback, 0, 2 + strlen($namespace)) === '\\' . $namespace . '\\')
        {
           
$callback = substr($callback, 2 + strlen($namespace));
        }

        return
$callback . '(' . $argument . ')';
    }

   
/**
    * Serialize and export a given object as PHP code
    *
    * @param  object $obj Original object
    * @return string      PHP code
    */
   
protected function exportObject($obj)
    {
       
// Serialize the object
       
$str = call_user_func($this->serializer, $obj);

       
// Export the object's source
       
$str = var_export($str, true);

        return
$this->unserializer . '(' . $str . ')';
    }
}