├── COPYING-MIT.txt ├── README.md ├── TODO ├── composer.json ├── runtests.php ├── src ├── lib │ ├── compactfile.php │ └── compactor.php └── phpcompactor.php └── tests ├── commenttest.in.php ├── commenttest.out.php ├── echoquotevartest.in.php ├── echoquotevartest.out.php ├── requiretest.help.php ├── requiretest.in.php ├── requiretest.out.php ├── switchtest.in.php └── switchtest.out.php /COPYING-MIT.txt: -------------------------------------------------------------------------------- 1 | PHPCompactor 2 | Matt Butcher 3 | Copyright (C) 2009-2010 Matt Butcher 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | You are expressly forbidden from removing this copyright message from 20 | this or any Caryatid file without explicit written permission from the 21 | copyright holder. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHPCompactor: A tool for compacting PHP source files 2 | 3 | Authors: M Butcher (matt@aleph-null.tv), J Pruis (email@jurriaanpruis.nl) 4 | 5 | Copyright (c) 2009-2010. Licensed under an MIT-style license. See COPYING-MIT.txt 6 | 7 | ## About this package 8 | 9 | This package provides a very simple PHP code compressor. It reads a single source file and then loads that source, along with all of the other locally included files, into one bigger file. The larger file is compacted by removing as much superfluous data as possible, including comments and whitespace. 10 | 11 | ## Using this tool 12 | 13 | Usage: 14 | 15 | php ./src/phpcompactor.php compressed_file.php source_file.php 16 | 17 | This will compress `source_file.php` and all of its dependencies into `compressed_file.php`. -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | / make testcases 2 | * more tokens.. for example T_PRINT & T_ECHO (Problems when printing constants) echo'test'; and echo$test; are allowed, echoENT_QUOTES; not (of course) 3 | 11 | Becomes 12 | )\s+(?=<)/) 19 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "technosophos/PHPCompressor", 3 | "description": "A simple PHP compressor that removes unnecessary data from PHP source code.", 4 | "type": "library", 5 | "keywords": ["utility", "compressor"], 6 | "license": "MIT", 7 | "homepage": "https://github.com/technosophos/PHPCompactor", 8 | 9 | "authors": [ 10 | {"name": "M Butcher (technosophos)", "homepage": "http://technosophos.com"}, 11 | {"name": "J Pruis", "email": "email@jurriaanpruis.nl"} 12 | ], 13 | 14 | "require": { 15 | "php": ">=5.2.6" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /runtests.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/lib/compactfile.php: -------------------------------------------------------------------------------- 1 | filename = $filename; 24 | $this->filesize = filesize($filename); 25 | $this->out = $out; 26 | if($filterfunc == null) { 27 | $filterfunc = function ($in) {return $in;}; 28 | } 29 | $this->filterfunc = $filterfunc; 30 | } 31 | 32 | /** 33 | * Compacts $filename. 34 | */ 35 | public function compact() { 36 | $tokens = $this->getTokens(); 37 | $removenext = false; // Remove next whitespace 38 | $start = ftell($this->out); // Position in output 39 | $len = count($tokens); 40 | for ($i=0;$len > $i;$i++) { 41 | $token = $tokens[$i]; 42 | $nexttoken = ($i+1 < $len)?$tokens[$i+1]:''; 43 | $prevtoken = ($i-1 > -1)?$tokens[$i-1]:''; 44 | 45 | if (is_string($token)) { 46 | if(in_array($token,Compactor::$safechar)) $removenext = true; 47 | $this->write($token); 48 | } else if($token[0] == T_WHITESPACE) { 49 | if(!$removenext) { 50 | if(is_string($nexttoken)) { 51 | if(!in_array($nexttoken,Compactor::$safechar) && !(in_array($nexttoken,Compactor::$semisafe) && in_array($prevtoken[0],Compactor::$keyword))) { 52 | $this->write(' '); 53 | } 54 | } else if(!in_array($nexttoken[0],Compactor::$beforetoken)) { 55 | $this->write(' '); 56 | } 57 | } 58 | } else if(in_array($token[0],Compactor::$aftertoken)) { 59 | $removenext = true; 60 | $this->write($token[1]); 61 | } else if(in_array($token[0],Compactor::$removable)) { 62 | $removenext = true; 63 | } else if(in_array($token[0],Compactor::$requires)) { // Remove require + everything until ';', maybe not safe? 64 | for ($i2 = $i;$len > $i2;$i2++) { 65 | $rtoken = &$tokens[$i2]; 66 | if($rtoken == ';') { 67 | $rtoken = ''; 68 | break; 69 | } else { 70 | $rtoken = ''; 71 | } 72 | } 73 | } else { 74 | $removenext = false; 75 | $this->write($token[1]); 76 | } 77 | } 78 | $this->compressedsize = ftell($this->out) - $start; 79 | } 80 | 81 | private function write($string) { 82 | fwrite($this->out, $string); 83 | } 84 | 85 | private function getTokens() { 86 | $func = $this->filterfunc; 87 | return token_get_all($func(trim(file_get_contents($this->filename)))); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/lib/compactor.php: -------------------------------------------------------------------------------- 1 | ','<','.','-','+','*','%','/'); 12 | public static $semisafe = array('"','\''); 13 | public static $removable = array(T_COMMENT,T_COMMENT,T_DOC_COMMENT,T_OPEN_TAG,T_CLOSE_TAG); 14 | public static $requires = array();//array(T_REQUIRE_ONCE,T_INCLUDE_ONCE); // use require_once and include_once for including of static files 15 | public static $aftertoken = array(T_BOOLEAN_OR, T_BOOLEAN_AND, T_IS_EQUAL, T_IS_GREATER_OR_EQUAL, 16 | T_IS_IDENTICAL, T_IS_NOT_EQUAL, T_IS_NOT_IDENTICAL, T_IS_SMALLER_OR_EQUAL, 17 | T_PLUS_EQUAL, T_MINUS_EQUAL, T_OR_EQUAL, T_DEC, T_DOUBLE_ARROW, 18 | T_ENCAPSED_AND_WHITESPACE, T_CURLY_OPEN, T_INC, T_IF, T_CONCAT_EQUAL,T_WHITESPACE); 19 | public static $beforetoken = array(T_BOOLEAN_OR, T_BOOLEAN_AND, T_IS_EQUAL, T_IS_GREATER_OR_EQUAL, 20 | T_IS_IDENTICAL, T_IS_NOT_EQUAL, T_IS_NOT_IDENTICAL, T_IS_SMALLER_OR_EQUAL, 21 | T_PLUS_EQUAL, T_MINUS_EQUAL, T_OR_EQUAL, T_DEC, T_DOUBLE_ARROW, 22 | T_ENCAPSED_AND_WHITESPACE, T_CURLY_OPEN, T_INC, T_IF, T_CONCAT_EQUAL,T_WHITESPACE, 23 | T_VARIABLE, T_CONSTANT_ENCAPSED_STRING); 24 | public static $keyword = array(T_ECHO,T_PRINT,T_CASE); 25 | 26 | private $compacted = array(); 27 | private $handle; 28 | private $basepath,$filter = null; 29 | /** The files excluded during a {@link compactAll()}. */ 30 | protected $excludes = array(); 31 | 32 | /** 33 | * Creates a new Compactor object. 34 | * 35 | * @param string $output 36 | * The file to which the compressed output is written 37 | */ 38 | public function __construct($output,$header='') { 39 | $this->handle = fopen($output, 'w'); 40 | fwrite($this->handle, 'filter = $filter; 44 | } 45 | 46 | /** 47 | * Compacts a single file. 48 | * 49 | * @param string $file 50 | * The file to compact. 51 | */ 52 | public function compact($file) { 53 | $compact = new CompactFile($file,$this->handle,$this->filter); 54 | $compact->compact(); 55 | $this->compacted[] = $compact; 56 | } 57 | /** 58 | * Returns the compacted files. 59 | */ 60 | 61 | public function getCompactedFiles() { 62 | return $this->compacted; 63 | } 64 | /** 65 | * Exclude this file from compacting. 66 | * 67 | * @param array $files 68 | * An array of files to exclude. 69 | */ 70 | public function exclude($file) { 71 | 72 | $this->excludes[] = $file; 73 | 74 | } 75 | 76 | /** 77 | * Returns the expanded exclusion list. 78 | 79 | public function getExcludedFiles() { 80 | return $this->excludes; 81 | } 82 | */ 83 | 84 | /** 85 | * Compact the given file and all included files. 86 | * 87 | * Files specified in the 'excludes' list will not be compacted here. 88 | * 89 | * @param string $baseFile 90 | * The base file to exclude. 91 | */ 92 | public function compactAll($baseFile) { 93 | $before = get_included_files(); 94 | include $baseFile; 95 | $this->basepath = dirname($baseFile); 96 | $this->excludes = array_unique($this->excludes); 97 | 98 | $files = array_diff(get_included_files(),$before); 99 | 100 | foreach($files as $file) { 101 | if(!in_array(str_replace($this->basepath.'/','',$file),$this->excludes)) $this->compact($file); 102 | } 103 | } 104 | 105 | /** 106 | * Displays a report with information about the compressed files 107 | */ 108 | public function report() { 109 | $lenbefore = 0; 110 | $lenafter = 0; 111 | echo "\nReport:\n=======\n"; 112 | foreach($this->compacted as $compact) { 113 | printf("Compacted %s -- filesize: %dB, compressed size: %dB, %.2f%%\n", basename($compact->filename), $compact->filesize,$compact->compressedsize,(($compact->compressedsize/$compact->filesize) - 1)*100); 114 | $lenbefore += $compact->filesize; 115 | } 116 | $filecount = count($this->compacted); 117 | $lenafter = ftell($this->handle); 118 | $percent = sprintf('%.2f%%', (($lenafter/$lenbefore) - 1)*100); 119 | echo "Compacted $filecount files into one \n"; 120 | echo "Filesize report: $lenbefore bytes to $lenafter bytes ($percent)\n"; 121 | echo "Done.\n"; 122 | } 123 | 124 | /** 125 | * Closes the file 126 | */ 127 | public function close() { 128 | fclose($this->handle); 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/phpcompactor.php: -------------------------------------------------------------------------------- 1 | exclude(array('*')); 24 | //print_r($compactor->getExcludedFiles()); 25 | /* 26 | // Use filters like this (Useable for things like stripping debug-only logging): 27 | $compactor->setFilter(function ($in) 28 | { 29 | $in = preg_replace('/.*\/\/ DEBUG ONLY/','',$in); 30 | return preg_replace('/.*->logger->.*/','',$in); 31 | }); 32 | */ 33 | $compactor->exclude('framework.php'); 34 | $compactor->compactAll($source); 35 | 36 | 37 | $compactor->report(); 38 | $compactor->close(); 39 | -------------------------------------------------------------------------------- /tests/commenttest.in.php: -------------------------------------------------------------------------------- 1 |