vendor/assetic/src/Assetic/Factory/Loader/BasePhpFormulaLoader.php
author cavaliet
Mon, 07 Jul 2014 17:23:47 +0200
changeset 122 d672f7dd74dc
parent 0 7f95f8617b0b
permissions -rwxr-xr-x
Added tag V00.17 for changeset ada5f3d8b5b4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
<?php
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
/*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 * This file is part of the Assetic package, an OpenSky project.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 * (c) 2010-2011 OpenSky Project Inc
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
 * For the full copyright and license information, please view the LICENSE
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
 * file that was distributed with this source code.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
namespace Assetic\Factory\Loader;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
use Assetic\Factory\AssetFactory;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
use Assetic\Factory\Resource\ResourceInterface;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
/**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
 * Loads asset formulae from PHP files.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
 * @author Kris Wallsmith <kris.wallsmith@gmail.com>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
abstract class BasePhpFormulaLoader implements FormulaLoaderInterface
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
{
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
    protected $factory;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
    protected $prototypes;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
    public function __construct(AssetFactory $factory)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
        $this->factory = $factory;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
        $this->prototypes = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
        foreach ($this->registerPrototypes() as $prototype => $options) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
            $this->addPrototype($prototype, $options);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
    public function addPrototype($prototype, array $options = array())
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
        $tokens = token_get_all('<?php '.$prototype);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
        array_shift($tokens);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
        $this->prototypes[$prototype] = array($tokens, $options);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
    public function load(ResourceInterface $resource)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
        if (!$nbProtos = count($this->prototypes)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
            throw new \LogicException('There are no prototypes registered.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
        $buffers = array_fill(0, $nbProtos, '');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
        $bufferLevels = array_fill(0, $nbProtos, 0);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
        $buffersInWildcard = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
        $tokens = token_get_all($resource->getContent());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
        $calls = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
        while ($token = array_shift($tokens)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
            $current = self::tokenToString($token);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
            // loop through each prototype (by reference)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
            foreach (array_keys($this->prototypes) as $i) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
                $prototype =& $this->prototypes[$i][0];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
                $options = $this->prototypes[$i][1];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
                $buffer =& $buffers[$i];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
                $level =& $bufferLevels[$i];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
                if (isset($buffersInWildcard[$i])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
                    switch ($current) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
                        case '(': ++$level; break;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
                        case ')': --$level; break;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
                    $buffer .= $current;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
                    if (!$level) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
                        $calls[] = array($buffer.';', $options);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
                        $buffer = '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
                        unset($buffersInWildcard[$i]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
                } elseif ($current == self::tokenToString(current($prototype))) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
                    $buffer .= $current;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
                    if ('*' == self::tokenToString(next($prototype))) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
                        $buffersInWildcard[$i] = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
                        ++$level;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
                    reset($prototype);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
                    unset($buffersInWildcard[$i]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
                    $buffer = '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
        $formulae = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
        foreach ($calls as $call) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
            $formulae += call_user_func_array(array($this, 'processCall'), $call);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
        return $formulae;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
    private function processCall($call, array $protoOptions = array())
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
        $tmp = tempnam(sys_get_temp_dir(), 'assetic');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
        file_put_contents($tmp, implode("\n", array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
            '<?php',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
            $this->registerSetupCode(),
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
            $call,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
            'echo serialize($_call);',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
        )));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
        $args = unserialize(shell_exec('php '.escapeshellarg($tmp)));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
        unlink($tmp);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
        $inputs  = isset($args[0]) ? self::argumentToArray($args[0]) : array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
        $filters = isset($args[1]) ? self::argumentToArray($args[1]) : array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
        $options = isset($args[2]) ? $args[2] : array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
        if (!isset($options['debug'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
            $options['debug'] = $this->factory->isDebug();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
        if (!is_array($options)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
            throw new \RuntimeException('The third argument must be omitted, null or an array.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
        // apply the prototype options
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
        $options += $protoOptions;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
        if (!isset($options['name'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
            $options['name'] = $this->factory->generateAssetName($inputs, $filters, $options);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
        return array($options['name'] => array($inputs, $filters, $options));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
     * Returns an array of prototypical calls and options.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
     * @return array Prototypes and options
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
    abstract protected function registerPrototypes();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
     * Returns setup code for the reflection scriptlet.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
     * @return string Some PHP setup code
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
    abstract protected function registerSetupCode();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
    static protected function tokenToString($token)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
        return is_array($token) ? $token[1] : $token;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
    static protected function argumentToArray($argument)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
        return is_array($argument) ? $argument : array_filter(array_map('trim', explode(',', $argument)));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
}