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: 
<?php

include_once(__DIR__.'/../Common/StaticCopies.php');

class Packager_Phar_ResultCompleter extends Packager_Common_StaticCopies
{
    private static $_pharNotAllowedMsg = [
        "It is not allowed to create PHAR archive on your computer.",
        "Go to 'php.ini' and allow PHAR archive creation by set up 'phar.readonly = 0'."
    ];
    private $_jsonResult;
    protected function mainJob ($params = []) {
        // clean all files in release directory
        $this->cleanReleaseDir();
        // statically copy files and folders
        $this->copyStaticFilesAndFolders();
        // complete result file
        $firstJobResult = $this->executeJobAndGetResult(
            'completingJob', []
        );
        if ($firstJobResult instanceof stdClass && $firstJobResult->success) {
            $pharAbsPath = $firstJobResult->data->phar;
            $phpAbsPath = $firstJobResult->data->php;
            $secondJobResult = $this->executeJobAndGetResult(
                'renameJob', 
                [
                    'phar'  => $pharAbsPath,
                    'php'   => $phpAbsPath,
                ],
                'json'
            );
            if ($secondJobResult instanceof stdClass && $secondJobResult->success) {
                // notify about success
                $this->notify($firstJobResult->data->incl);
            } else {
                if ($secondJobResult->type == 'json') {
                    $this->sendResult(
                        $secondJobResult->data[0], $secondJobResult->data[1], 'error'
                    );
                } else {
                    $this->sendResult(
                        $secondJobResult->message, $secondJobResult->data, 'error'
                    );
                }
            }
        } else {
            if ($firstJobResult->type == 'json') {
                $this->sendResult(
                    $firstJobResult->data[0], $firstJobResult->data[1], 'error'
                );
            } else {
                $this->sendResult(
                    $firstJobResult->message, $firstJobResult->data, 'error'
                );
            }
        }
    }
    protected function completingJob ($params = []) {
        $this->_jsonResult = (object) [
            'success'   => TRUE,
            'data'      => [],
        ];
        $this->completeAllFiles();
        $this->_processPhpCode();
        list($releaseDir, $releaseFileNameWithoutExt) = $this->_completeBuildPaths();
        $this->_buildPharArchive($releaseDir, $releaseFileNameWithoutExt);
        $this->sendJsonResultAndExit($this->_jsonResult);
    }
    protected function renameJob ($params = []) {
        $result = (object) [
            'success'   => TRUE,
            'data'      => [],
        ];
        try {
            clearstatcache(TRUE, $params['phar']);
            clearstatcache(TRUE, $params['php']);
            rename($params['phar'],  $params['php']);
        } catch (Exception $e) {
            $result->success = FALSE;
            $result->data = [
                $e->getMessage(),
                $e->getTrace(),
            ];
        }
        $this->sendJsonResultAndExit($result);
    }
    private function _processPhpCode () {
        foreach ($this->files as $fullPath => $fileInfo) {
            if ($fileInfo->extension != 'php' && !in_array($fileInfo->extension, static::$templatesExtensions, TRUE)) continue;
            if ($this->cfg->patternReplacements) {
                foreach ($this->cfg->patternReplacements as $pattern => $replacement) {
                    if (is_numeric($pattern)) {
                        // if there is numeric key - values is always pattern to replace with empty string
                        $patternLocal = $replacement;
                        while (preg_match($patternLocal, $fileInfo->content)) {
                            $fileInfo->content = preg_replace($patternLocal, '', $fileInfo->content);
                        }
                    } else {
                        while (preg_match($pattern, $fileInfo->content)) {
                            $fileInfo->content = preg_replace($pattern, $replacement, $fileInfo->content);
                        }
                    }
                }
            }
            if ($this->cfg->stringReplacements) {
                foreach ($this->cfg->stringReplacements as $from => $to) {
                    $fileInfo->content = str_replace($from, $to, $fileInfo->content);
                }
            }
            if ($this->cfg->minifyPhp) {
                $fileInfo->content = $this->shrinkPhpCode($fileInfo->content);
            }
            if ($this->cfg->minifyTemplates && in_array($fileInfo->extension, static::$templatesExtensions, TRUE)) {
                //include_once(__DIR__.'/../Libs/Minify/HTML.php');
                @include_once('vendor/autoload.php');
                $fileInfo->content = Minify_HTML::minify($fileInfo->content);
            }
            $this->files[$fullPath] = $fileInfo;
        }
    }
    private function _completeBuildPaths () {
        $releaseDir = $this->cfg->releaseDir;
        $releaseFileName = $this->cfg->releaseFileName;
        
        $releaseFileNameExpl = explode('.', $releaseFileName);
        unset($releaseFileNameExpl[count($releaseFileNameExpl) - 1]);
        $releaseFileNameWithoutExt = implode('.', $releaseFileNameExpl);
        
        $releaseFilePhp = $releaseDir . '/' . $releaseFileNameWithoutExt . '.php';
        $releaseFilePhar = $releaseDir . '/' . $releaseFileNameWithoutExt . '.phar';
        clearstatcache(TRUE, $releaseFilePhp);
        clearstatcache(TRUE, $releaseFilePhar);
        if (file_exists($releaseFilePhp)) unlink($releaseFilePhp);
        if (file_exists($releaseFilePhar))  unlink($releaseFilePhar);

        return [
            $releaseDir, $releaseFileNameWithoutExt
        ];
    }
    private function _buildPharArchive ($releaseDir, $releaseFileNameWithoutExt) {
        $archive = NULL;

        try {
            $archive = new Phar(
                $releaseDir . '/' . $releaseFileNameWithoutExt . '.phar', 
                0, 
                $releaseFileNameWithoutExt . '.phar'
            );
        } catch (UnexpectedValueException $e1) {
            $m = $e1->getMessage();
            if (mb_strpos($m, 'disabled by the php.ini setting phar.readonly') !== FALSE) {
                $this->_jsonResult->success = FALSE;
                $phpIniLoadedFile = str_replace('\\', '/', php_ini_loaded_file());
                $this->_jsonResult->data = [
                    self::$_pharNotAllowedMsg[0],
                    str_replace('php.ini', $phpIniLoadedFile, self::$_pharNotAllowedMsg[1]),
                ];
            } else {
                $this->_jsonResult->success = FALSE;
                $this->_jsonResult->data = [
                    $e1->getMessage(),
                    $e1->getTrace(),
                ];
            }
        } catch (Exception $e2) {
            $this->_jsonResult->success = FALSE;
            $this->_jsonResult->data = [
                $e2->getMessage(),
                $e2->getTrace(),
            ];
        } finally {
            if ($this->_jsonResult->data) return;
        }
        
        $incScripts = [];
        $incStatics = [];
        $archive->startBuffering();
        foreach ($this->files as $fileInfo) {
            $archive[$fileInfo->relPath] = $fileInfo->content;
            if ($fileInfo->extension == 'php') {
                $incScripts[] = $fileInfo->relPath;
            } else {
                $incStatics[] = $fileInfo->relPath;
            }
        }
        
        $archive->setStub('<'.'?php '
            .PHP_EOL.'Phar::mapPhar();'
            .'include_once("phar://' . $releaseFileNameWithoutExt . '.phar/index.php");'
            .'__HALT_COMPILER();');

        $archive->stopBuffering();
        
        //$archive->compressFiles(Phar::GZ);
        //@$archive->buildFromIterator(); // writes archive on hard drive
        
        unset($archive); // frees memory, run rename operation without any conflict
        
        $this->_jsonResult->data = [
            'phar'      => $releaseDir . '/' . $releaseFileNameWithoutExt . '.phar', 
            'php'       => $releaseDir . '/' . $releaseFileNameWithoutExt . '.php',
            'incl'      => [
                'scripts'   => $incScripts,
                'statics'   => $incStatics,
            ],
        ];
    }
    protected function notify ($incFiles) {
        $scriptsCount = count($incFiles->scripts);
        $staticsCount = count($incFiles->statics);
        $staticallyCopiedCount = count($this->staticallyCopiedFiles);
        $totalCount = $scriptsCount + $staticsCount;
        if (php_sapi_name() == 'cli') {
            $content = "Total included PHP and static files in package: $totalCount\n"
                . "Statically copied files into release directory: $staticallyCopiedCount\n\n"
                . "\nIncluded PHP files in package ($scriptsCount):\n\n"
                . implode("\n", $incFiles->scripts)
                . "\n\n\nIncluded static files in package ($staticsCount):\n\n"
                . implode("\n", $incFiles->statics)
                . "\n\n\nStatically copied files into release directory ($staticallyCopiedCount):\n\n"
                . implode("\n", $this->staticallyCopiedFiles)
                . "\n\n\nDONE";
            $this->sendResult('Successfully packed', $content);
        } else {
            $content = "<div>Total included PHP and static files in package: $totalCount</div>"
                . "<div>Statically copied files into release directory: $staticallyCopiedCount</div>"
                . "<h2>Included PHP files in package ($scriptsCount):</h2>"
                . '<div class="files">'
                    . implode('<br />', $incFiles->scripts)
                . "</div>"
                . "<h2>Included static files in package ($staticsCount):</h2>"
                . '<div class="files">'
                    . implode('<br />', $incFiles->statics)
                . "</div>"
                . "<h2>Statically copied files into release directory ($staticallyCopiedCount):</h2>"
                . '<div class="files">'
                    . implode('<br />', $this->staticallyCopiedFiles)
                . "</div>"
                . "<h2>DONE</h2>";
            $this->sendResult('Successfully packed', $content, 'success');
        }
    }
}
Packager API Documentation API documentation generated by ApiGen