<?php
/**
 * Classe para minimizar códigos PHP
 * 
 * @version 0.1
 * @author Tarcísio Xavier Gruppi <tarcisio@txgruppi.com>
 * @link http://blog.txgruppi.com/php-packer
 */
class Packer {
    
/**
     * Guarda o caminho para o arquivo alvo
     *
     * @var string
     */
    
protected $file;
    
    
/**
     * Guarda o código fonte do arquivo alvo
     *
     * @var string
     */
    
protected $source;
    
    
/**
     * Guarda os tokens to arquivo alvo
     *
     * @var array
     */
    
protected $tokens;
    
    
/**
     * Guarda os tokens após a limpesa
     *
     * @var string
     */
    
protected $parsedTokens = array();
    
    
/**
     * Método construtor, recebe como parâmetro o caminho para o arquivo alvo
     *
     * @param string $file
     */
    
public function __construct($file) {
        
$this->file $file;
        
$this->loadContent();
        
$this->getTokens();
        
$this->parseTokens();
    }
    
    
/**
     * Retorna o código fonte minimizado
     *
     * @return string
     */
    
public function getSource() {
        if (empty(
$this->parsedTokens)) return false;
        
        
$out "";
        foreach (
$this->parsedTokens as $t) {
            if (
is_array($t)) {
                
$out .= $t[1];
            } else {
                
$out .= $t;
            }
        }
        return 
trim($out);
    }
    
    
/**
     * Limpa o código fonte
     *
     */
    
protected function parseTokens() {
        
$newTokens = array();
        foreach (
$this->tokens as $k=>$t) {
            if (
is_array($t)) {
                
$token $t[0];
            } else {
                
$token ';';
            }
            
            if (
$token == T_WHITESPACE) {
                if (isset(
$this->tokens[$k-1])) {
                    if (
is_array($this->tokens[$k-1])) {
                        if (
$this->tokens[$k-1][0] == T_IF) continue;
                        if (
$this->tokens[$k-1][0] == T_FOREACH) continue;
                        if (
$this->tokens[$k-1][0] == T_CONCAT_EQUAL) continue;
                        if (
$this->tokens[$k-1][0] == T_IS_EQUAL) continue;
                        if (
$this->tokens[$k-1][0] == T_BOOLEAN_AND) continue;
                        if (
$this->tokens[$k-1][0] == T_BOOLEAN_OR) continue;
                    } else {
                        if (
$this->tokens[$k-1] == ';') continue;
                        if (
$this->tokens[$k-1] == '{') continue;
                        if (
$this->tokens[$k-1] == '}') continue;
                        if (
$this->tokens[$k-1] == '(') continue;
                        if (
$this->tokens[$k-1] == ')') continue;
                        if (
$this->tokens[$k-1] == '=') continue;
                        if (
$this->tokens[$k-1] == ',') continue;
                    }
                }
                if (isset(
$this->tokens[$k+1])) {
                    if (
is_array($this->tokens[$k+1])) {
                        if (
$this->tokens[$k+1][0] == T_CONCAT_EQUAL) continue;
                        if (
$this->tokens[$k+1][0] == T_IS_EQUAL) continue;
                        if (
$this->tokens[$k+1][0] == T_BOOLEAN_AND) continue;
                        if (
$this->tokens[$k+1][0] == T_BOOLEAN_OR) continue;
                    } else {
                        if (
$this->tokens[$k+1] == '=') continue;
                        if (
$this->tokens[$k+1] == '{') continue;
                        if (
$this->tokens[$k+1] == '(') continue;
                        if (
$this->tokens[$k+1] == ',') continue;
                    }
                }
                if (isset(
$this->tokens[$k-3])) {
                    if (
is_array($this->tokens[$k-3])) {
                        if (
$this->tokens[$k-3][0] == T_CLASS) continue;
                    }
                }
            }
            if (!isset(
$this->tokens[$k+1])) {
                if (
is_array($t) && $t[0] == T_CLOSE_TAG) continue;
            }
            
$newTokens[] = $t;
        }
        
$this->parsedTokens $newTokens;
    }
    
    
/**
     * Separa os tokens do código fonte
     *
     */
    
protected function getTokens() {
        
$this->tokens token_get_all($this->source);
    }
    
    
/**
     * Carrega o conteúdo do arquivo alvo e já remove os comentários
     *
     */
    
protected function loadContent() {
        if (empty(
$this->file)) return;
        if (!
file_exists($this->file)) return;
        if (!
is_readable($this->file)) return;
        
        
$this->source php_strip_whitespace($this->file);
        
$this->source preg_replace("'^([^\s]+)\s+'","$1 ",$this->source);
        
$this->source trim($this->source);
    }
}