Overview

Classes

  • Packager_Common_Base
  • Packager_Common_StaticCopies
  • Packager_Phar
  • Packager_Phar_ResultCompleter
  • Packager_Php
  • Packager_Php_Base
  • Packager_Php_Completer
  • Packager_Php_Scripts_Completer
  • Packager_Php_Scripts_Dependencies
  • Packager_Php_Scripts_Order
  • Packager_Php_Scripts_Replacer
  • Packager_Php_Wrapper
  • Packager_Php_Wrapper_DirectoryIterator
  • Packager_Php_Wrapper_SplFileInfo

Exceptions

  • Packager_Php_Scripts_Throwable
  • Overview
  • Class
  • Tree
  • Todo
  • Deprecated
  • Download
  1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 
<?php

if(!defined('T_TRAIT')) define('T_TRAIT', 362);

class Packager_Php_Scripts_Replacer
{
    protected static $dynamicClassFnDeterminators = [
        'continueTokens'=> [
            T_WHITESPACE=> 1,
            T_COMMENT   => 1,
        ],
        'endingTokens'  => [
            T_PUBLIC    => 1,
            T_PROTECTED => 1,
            T_PRIVATE   => 1,
            T_ABSTRACT  => 1,
            T_FINAL     => 1,
        ],
    ];
    protected static $phpFunctionsToProcess = [];
    protected static $wrapperReplacements = [];
    protected static $phpReplacementsStatistics = [];
    protected static $wrapperClassName = '';
    protected $cfg;
    protected $result = [];
    protected $scriptContent = '';
    protected $statementEndOperator = ';';
    protected $fileInfo = NULL;
    protected $enabled = TRUE;
    protected $tokens = [];
    protected $namespaceState = 0;
    protected $classState = 0;
    protected $foreachState = 0;
    protected $classBracketsLevel = 0;
    protected $functionsStates = [0];
    protected $functionsOpenIndexes = [0];
    protected $functionsBracketsLevels = [0];
    public static function SetPhpFunctionsToProcess ($phpFunctionsToProcess = []) {
        self::$phpFunctionsToProcess = $phpFunctionsToProcess;
    }
    public static function SetWrapperReplacements ($wrapperReplacements = []) {
        self::$wrapperReplacements = $wrapperReplacements;
    }
    public static function SetWrapperClassName ($wrapperClassName = '') {
        self::$wrapperClassName = $wrapperClassName;
    }
    public static function GetReplacementsStatistics () {
        return self::$phpReplacementsStatistics;
    }
    public static function ProcessScriptsReplacements (& $fileInfo, & $cfg) {
        $instance = new self($fileInfo, $cfg, token_get_all($fileInfo->content));
        $instance->runReplacementsProcessing();
        return implode('', $instance->result);
    }
    public static function ProcessTemplatesReplacements (& $fileInfo, & $cfg) {
        $instance1 = new self($fileInfo, $cfg, token_get_all($fileInfo->content));
        $instance1->runReplacementsProcessing();
        $code = implode('', $instance1->result);
        $instance2 = new self($fileInfo, $cfg, token_get_all($code));
        $instance2->runTemplatesProcessing();
        return implode('', $instance2->result);
    }
    public static function ProcessNamespaces (& $fileInfo, & $cfg) {
        $instance = new self($fileInfo, $cfg, token_get_all("<"."?php\n".$fileInfo->content));
        $instance->runNamespacesProcessing();
        return implode('', $instance->result);
    }
    /* protected *************************************************************************************/
    public function __construct(& $fileInfo, $cfg, $tokens) {
        $this->fileInfo = & $fileInfo;
        $this->cfg = & $cfg;
        $this->tokens = & $tokens;
        $this->result = [];
        $this->classState = 0; // 0 not in class, 1 - between `class` or `trait` keyword and `{`, 2 inside class
        $this->classBracketsLevel = 0;
        $this->functionsStates = [0];
        $this->functionsBracketsLevels = [0];

        $this->classFnDynamicEnvironment = FALSE;
        $this->classFnDynamicMonitorIndex = -1;

        $this->classFnStaticEnvironment = FALSE;
        $this->classFnStaticMonitorIndex = -1;
    }
    public function & SetEnabled ($enabled) {
        $this->enabled = $enabled;
        return $this;
    }
    protected function runReplacementsProcessing () {
        $newPart = '';
        for ($i = 0, $l = count($this->tokens); $i < $l;) {
            $token = $this->tokens[$i];
            if (is_array($token)) {
                $tokenId = $token[0];
                $oldPart = $token[1];
                if (isset(self::$wrapperReplacements[$tokenId])) {
                    // if there is any part of php code for possible processing:
                    list ($i, $newPart) = $this->processPhpCodeReplacement(
                        $oldPart, $tokenId, $i
                    );
                } else {
                    // if there is not any part of php code for possible processing,
                    // just add php code part into result code string:
                    $newPart = $oldPart;
                }
            } else if (is_string($token)) {
                if ($token == '(') {
                    $this->statementEndOperator = ')';
                } else if ($token == ')') {
                    $this->statementEndOperator = ';';
                }
                $newPart = $token;
            }
            $this->monitorNamespace($token);
            $this->monitorClass($token, $i);
            $this->monitorFunctions($token, $i);
            $this->result[] = $newPart;
            $i += 1;
        }
        return $this;
    }
    protected function runNamespacesProcessing () {
        $newPart = '';
        for ($i = 0, $l = count($this->tokens); $i < $l; $i += 1) {
            $token = & $this->tokens[$i];
            if (is_array($token)) {
                $tokenId = $token[0];
                $newPart = $token[1];
                $token[3] = token_name($tokenId);
                if ($tokenId == T_NAMESPACE) {
                    if ($this->namespaceState > 0) {
                        $this->result[] = (!$this->cfg->minifyPhp ? "\n}\n" : '}');
                    }
                    $this->namespaceState = 1;
                }
                if ($tokenId == T_OPEN_TAG) $newPart = '';
            } else if (is_string($token)) {
                $newPart = $token;
                if ($this->namespaceState == 1 && $token == ';') {
                    $newPart = '{';
                    $this->namespaceState = 2;
                }
            }
            $this->result[] = $newPart;
        }
        if ($this->namespaceState == 2) {
            $this->result[] = (!$this->cfg->minifyPhp ? "\n}" : '}');
        }
        return $this;
    }
    protected function runTemplatesProcessing () {
        //$debug = mb_strpos($this->fileInfo->fullPath, 'layout.phtml') !== FALSE;
        $newPart = '';
        for ($i = 0, $l = count($this->tokens); $i < $l;) {
            $token = $this->tokens[$i];
            if (is_array($token)) {
                //if ($debug) var_dump($token);
                $tokenId = $token[0];
                $oldPart = $token[1];
                if ($this->foreachState !== 2) {
                    if ($tokenId == T_ISSET || $tokenId == T_UNSET) {
                        //var_dump("isset/unset()");
                        $subTokens = [];
                        $j = $i + 2;
                        $bracketLevel = 1;
                        while (TRUE) {
                            $subToken = & $this->tokens[$j];
                            if (is_array($subToken)) {
                                $subTokenValue = $subToken[1];
                                if ($subToken[0] == T_VARIABLE && $subTokenValue != '$this') {
                                    $subTokens[] = '$this->' . mb_substr($subTokenValue, 1);
                                } else {
                                    $subTokens[] = $subTokenValue;
                                }
                            } else if (is_string($subToken)) {
                                if ($subToken == '(') {
                                    $bracketLevel += 1;
                                } else if ($subToken == ')') {
                                    $bracketLevel -= 1;
                                }
                                $subTokens[] = $subToken;
                            }
                            if ($bracketLevel == 0) break;
                            $j += 1;
                        }
                        $newPart = ($tokenId == T_ISSET ? 'isset(' : 'unset(') . implode('', $subTokens);
                        $i = $j;
                    } else if ($tokenId == T_OPEN_TAG_WITH_ECHO) {
                        $nextToken = isset($this->tokens[$i + 1]) ? $this->tokens[$i + 1] : NULL;
                        $nextTokenId = is_array($nextToken) ? $nextToken[0] : NULL;
                        if ($nextTokenId == T_VARIABLE && $nextToken[1] != '$this') {
                            $oldPart = $nextToken[1];
                            $nextToken = isset($this->tokens[$i + 2]) ? $this->tokens[$i + 2] : NULL;
                            $openBracketToken = is_string($nextToken) && $nextToken == '(';
                            if ($openBracketToken) {
                                //  <?=$helper( or <%=$helper(
                                $newPart = '<' . '?php echo call_user_func($this->GetHelper(\'' . mb_substr($oldPart, 1) . '\'), ';
                                $i += 2;
                            } else {
                                //  <?=$variable or <%=$variable
                                $newPart = '<' . '?php echo call_user_func(function($__val){return $__val;},isset(' . $oldPart . ')?' . $oldPart . ':$this->' . mb_substr($oldPart, 1) . ')';
                                $i += 1;
                            }
                        } else {
                            //  <?= or <%=
                            $newPart = '<' . '?php echo ';
                        }
                    } else if ($tokenId == T_VARIABLE && $oldPart != '$this') {
                        $nextToken = isset($this->tokens[$i + 1]) ? $this->tokens[$i + 1] : NULL;
                        $openBracketToken = is_string($nextToken) && $nextToken == '(';
                        if ($openBracketToken) {
                            // $helper(
                            $newPart = 'call_user_func($this->GetHelper(\'' . mb_substr($oldPart, 1) . '\'),';
                            $i += 1;
                        } else {
                            // $variable
                            $newPart = 'call_user_func(function($__val){return $__val;},isset(' . $oldPart . ')?' . $oldPart . ':$this->' . mb_substr($oldPart, 1) . ')';
                        }
                    } else {
                        // if there is not any part of php code for possible processing,
                        // just add php code part into result code string:
                        $newPart = $oldPart;
                    }
                } else {
                    $newPart = $oldPart;
                }
                //if ($debug) var_dump("array;$tokenId;".$newPart);
            } else if (is_string($token)) {
                $newPart = $token;
                //if ($debug) var_dump("string;".$newPart);
            }
            $this->monitorForeachHead($token, $i);
            $this->result[] = $newPart;
            $i += 1;
        }
        /*if ($debug) {
            echo '<pre>';
            var_dump(implode('', $this->result));
            die();
        }*/
        return $this;
    }
    protected function monitorNamespace ($token) {
        if ($this->namespaceState > 2 || $this->fileInfo->extension !== 'php') return;
        if (is_array($token)) {
            $tokenId = $token[0];
            if ($this->namespaceState == 1 && $tokenId == T_STRING) {
                $this->namespaceState = 2;
            } else if ($tokenId == T_NAMESPACE) {
                $this->namespaceState = 1;
            }
        } else if (is_string($token)) {
            if ($this->namespaceState == 1) {
                if ($token == '{') {
                    $this->fileInfo->containsNamespace = Packager_Php::NAMESPACE_GLOBAL_CURLY_BRACKETS;
                    $this->namespaceState = 3;
                }
            } else if ($this->namespaceState == 2) {
                if ($token == ';') {
                    $this->fileInfo->containsNamespace = Packager_Php::NAMESPACE_NAMED_SEMICOLONS;
                    $this->namespaceState = 3;
                } else if ($token == '{') {
                    $this->fileInfo->containsNamespace = Packager_Php::NAMESPACE_NAMED_CURLY_BRACKETS;
                    $this->namespaceState = 3;
                }
            }
        }
    }
    protected function monitorClass ($token, $currentIndex) {
        //$debug = strpos($this->fileInfo->relPath, '/MvcCore/View/Rendering.php') !== FALSE;
        if (is_array($token)) {
            $tokenId = $token[0];
            // manage curly brackets (to determinate class closed moment to switch back $this->classState to "0")
            if ($this->classState > 0) {
                if ($tokenId === T_CURLY_OPEN || $tokenId === T_DOLLAR_OPEN_CURLY_BRACES) {
                    $this->classBracketsLevel += 1;
                }
            } else if ($tokenId === T_CLASS || $tokenId === T_TRAIT) {
                // if token is "class" or "trait" keyword - open stage
                $this->classState = 1;
                $this->classBracketsLevel = 0;
                // prepare bools for class methods
                $this->classFnDynamicEnvironment = FALSE;
                $this->classFnDynamicMonitorIndex = -1;
                $this->classFnStaticEnvironment = FALSE;
                $this->classFnStaticMonitorIndex = -1;
            }
        } else if (is_string($token)) {
            // manage curly brackets (to determinate class closed moment to switch back $this->classState to "0")
            if ($this->classState > 0) {
                if ($token === '{') {
                    if ($this->classState === 1) $this->classState = 2;
                    $this->classBracketsLevel += 1;
                } else if ($token === '}') {
                    $this->classBracketsLevel -= 1;
                }
            }
            //if ($debug && ($token == '{' || $token == '}')) var_dump([$token, $currentIndex, $this->classState, $this->classBracketsLevel]);
        }
        // determinate class closed moment - if class state is 2 and curly bracket counters are both 0
        if ($this->classState === 2 && $this->classBracketsLevel === 0) {
            $this->classState = 0;
        }
    }
    protected function monitorFunctions ($token, $currentIndex) {
        $monitorLastIndex = count($this->functionsStates) - 1;
        $functionsStatesLastRec = $this->functionsStates[$monitorLastIndex];
        if (is_array($token)) {
            $tokenId = $token[0];
            // manage curly brackets (to determinate class closed moment to switch back $this->classState to "0")
            if ($functionsStatesLastRec > 0) {
                if ($tokenId === T_CURLY_OPEN || $tokenId === T_DOLLAR_OPEN_CURLY_BRACES) {
                    $this->functionsBracketsLevels[$monitorLastIndex] += 1;
                }
            }
            // if token is "function" keyword - open stage
            if ($tokenId === T_FUNCTION) {
                $monitorLastIndex += 1;
                $this->functionsStates[$monitorLastIndex] = 1;
                $this->functionsBracketsLevels[$monitorLastIndex] = 0;
                // determinate if we are in class dynamic function
                $dynamicClassFn = FALSE;
                if ($this->classState > 0) {
                    if (!$this->classFnStaticEnvironment && !$this->classFnDynamicEnvironment) {
                        $dynamicClassFn = $this->getClassDynamicFunctionEnvironment($currentIndex);
                        if ($dynamicClassFn) {
                            $this->classFnDynamicEnvironment = TRUE;
                            $this->classFnDynamicMonitorIndex = $monitorLastIndex;
                        } else {
                            $this->classFnStaticEnvironment = TRUE;
                            $this->classFnStaticMonitorIndex = $monitorLastIndex;
                        }
                    }
                } else {
                    $this->classFnDynamicEnvironment = FALSE;
                    $this->classFnDynamicMonitorIndex = -1;
                    $this->classFnStaticEnvironment = FALSE;
                    $this->classFnStaticMonitorIndex = -1;
                }
            }
        } else if (is_string($token)) {
            // manage curly brackets (to determinate class closed moment to switch back $this->classState to "0")
            if ($functionsStatesLastRec > 0) {
                if ($token === '{') {
                    if ($functionsStatesLastRec === 1) $this->functionsStates[$monitorLastIndex] = 2;
                    $this->functionsBracketsLevels[$monitorLastIndex] += 1;
                } else if ($token === '}') {
                    $this->functionsBracketsLevels[$monitorLastIndex] -= 1;
                }
            }
        }
        // determinate class closed moment - if class state is 2 and curly bracket counters are both 0
        if ($this->functionsStates[$monitorLastIndex] === 2 && $this->functionsBracketsLevels[$monitorLastIndex] === 0) {
            // manage static vs dynamic class function bools
            if ($this->classFnDynamicEnvironment && $this->classFnDynamicMonitorIndex === $monitorLastIndex) {
                $this->classFnDynamicEnvironment = FALSE;
                $this->classFnDynamicMonitorIndex = -1;
            }
            if ($this->classFnStaticEnvironment && $this->classFnStaticMonitorIndex === $monitorLastIndex) {

                $this->classFnStaticEnvironment = FALSE;
                $this->classFnStaticMonitorIndex = -1;
            }

            // manage states and brackets records
            if ($monitorLastIndex > 0) {
                unset($this->functionsStates[$monitorLastIndex]);
                unset($this->functionsBracketsLevels[$monitorLastIndex]);
            } else {
                $this->functionsStates[0] = 0;
                $this->functionsBracketsLevels[0] = 0;
            }
        }
    }
    protected function monitorForeachHead($token, $currentIndex) {
        if (is_array($token)) {
            $tokenId = $token[0];
            if ($this->foreachState == 0 && $tokenId == T_FOREACH) {
                $this->foreachState = 1;
            } else if ($this->foreachState == 1 && $tokenId == T_AS) {
                $this->foreachState = 2;
            }
        } else if (is_string($token)) {
            if ($this->foreachState == 2 && ($token == ';' || $token == ':'))
                $this->foreachState = 0;
        }
    }
    protected function processPhpCodeReplacement ($oldPart, $tokenId, $i) {
        $newPart = '';
        $replacement = self::$wrapperReplacements[$tokenId];
        if (is_callable($replacement)) {
            // if there is configured item in replacements array in type: callable closure function,
            // there will be probably replacements for __FILE__ and __DIR__ replacements,
            // call these functions to process replacements
            $newPart = $replacement($this, $this->fileInfo, $oldPart);
        } else if (!$this->enabled) {
            $newPart = $oldPart;
        } else if (is_object($replacement)) {
            // if we have current php function call between php replacements
            $newPart = $this->processPhpCodeReplacementObjectType(
                $replacement, $oldPart, $i
            );
        } else if (is_array($replacement)) {
            // if there is configured item in replacements array in type: string,
            // there will be probably replacements for requires and includes or any other php statement
            // determinate if current statement is necessary to process by config
            // and fill $newPart variable with proper content
            list($i, $newPart) = $this->processPhpCodeReplacementArrayType(
                $replacement, $oldPart, $tokenId, $i
            );
        }
        return [$i, $newPart];
    }
    // php function calls - any_php_build_in_function() or programmerCustomFunction()
    // php class names, keywords, stdClass keys, TRUE/FALSE, public constants like PHP_EOL and other php shit...
    protected function processPhpCodeReplacementObjectType ($replacement, $oldPart, $i) {
        $newPart = '';
        if (isset($replacement->$oldPart)) {
            // determinate if current function call is necessary to process by config
            // and fill $newPart variable with proper content
            if (isset(self::$phpFunctionsToProcess[$oldPart])) {
                // yes - by configuration is necessary to replace this php function call - do it
                $newPart = str_replace('%WrapperClass%', self::$wrapperClassName, $replacement->$oldPart);
                // check if before replaced function call is backslash already and if backslash is also first char in new part
                if (mb_substr(self::$wrapperClassName, 0, 1) == '\\' && $i > 0) {
                    $previousToken = $this->tokens[$i - 1];
                    if (is_array($previousToken) && $previousToken[1] == '\\') {
                        // previous token is already a backslash - remove backslash from new part
                        $newPart = mb_substr($newPart, 1);
                    }
                }
                self::addToReplacementStatistics($oldPart);
            } else {
                // no - keep original php function call
                $newPart = $oldPart;
            }
        } else {
            // it is other php statement - do not replace anything
            $newPart = $oldPart;
        }
        return $newPart;
    }
    // All occurrences of require_once(), include_once(), require() and include() statements replace by configuration.
    protected function processPhpCodeReplacementArrayType ($replacement, $oldPart, $tokenId, $i) {
        $newPart = '';
        if ($replacement[0] == $oldPart) {
            // determinate if current function call is necessary to process by config
            // and fill $newPart variable with proper content
            $newPart = str_replace('%WrapperClass%', self::$wrapperClassName, $replacement[1]) . '(';
            $subTokens = [];
            $j = $i + 1;
            while (TRUE) {
                $subToken = & $this->tokens[$j];
                if (is_array($subToken)) {
                    $subTokenId = $subToken[0];
                    $subToken[3] = token_name($subTokenId);
                    $subTokens[] = & $subToken;
                } else if (is_string($subToken)) {
                    if ($subToken == $this->statementEndOperator) {
                        $subInstance = new self($this->fileInfo, $this->cfg, $subTokens);
                        $subInstance->runReplacementsProcessing();
                        $newSubPart = implode('', $subInstance->result);
                        /*
                        var_dump($this->classFnDynamicEnvironment);
                        var_dump([
                            'fileInfo->relPath'         => $this->fileInfo->relPath,
                            'namespaceState'            => $this->namespaceState,
                            'classState'                => $this->classState,
                            'classBracketsLevel'        => $this->classBracketsLevel,
                            'functionsStates'           => $this->functionsStates,
                            'functionsOpenIndexes'      => $this->functionsOpenIndexes,
                            'functionsBracketsLevels'   => $this->functionsBracketsLevels,
                            'tokens'                    => $this->tokens,
                        ]);
                        echo '<pre><code>';
                        echo $this->fileInfo->content;
                        echo '</code></pre>';
                        */
                        if ($this->classFnDynamicEnvironment) {
                            $newPart .= $newSubPart . ',$this)' . $this->statementEndOperator;
                        } else {
                            $newPart .= $newSubPart . ')' . $this->statementEndOperator;
                        }
                        $i = $j;
                        break;
                    } else {
                        $subTokens[] = $subToken;
                    }
                }
                $j += 1;
            }
            /*
            echo '<pre>';
            print_r($subTokens);
            echo '</pre>';
            */
            self::addToReplacementStatistics($oldPart);
        } else {
            // it is other php statement - do not replace anything
            $newPart = $oldPart;
        }
        return [$i, $newPart];
    }
    protected function getClassDynamicFunctionEnvironment ($functionIndex) {
        // go backwards and try to catch T_STATIC or not
        $staticCaught = FALSE;
        $continueTokens = self::$dynamicClassFnDeterminators['continueTokens'];
        $endingTokens = self::$dynamicClassFnDeterminators['endingTokens'];
        for ($i = $functionIndex - 1; $i > -1; $i -= 1) {
            $token = $this->tokens[$i];
            if (is_array($token)) {
                $tokenId = $token[0];
                if (isset($continueTokens[$tokenId])) {
                    continue;
                } else if (isset($endingTokens[$tokenId])) {
                    break;
                } else if ($tokenId == T_STATIC) {
                    $staticCaught = TRUE;
                    break;
                } else {
                    break;
                }
            } else if (is_string($token)) {
                if ($token == '&') {
                    continue;
                } else {
                    break;
                }
            }
        }
        return $staticCaught ? FALSE : TRUE;
    }
    protected static function addToReplacementStatistics ($replacementKey) {
        if (!isset(self::$phpReplacementsStatistics[$replacementKey])) {
            self::$phpReplacementsStatistics[$replacementKey] = 0;
        }
        self::$phpReplacementsStatistics[$replacementKey] += 1;
    }
}
Packager API Documentation API documentation generated by ApiGen