<?php

/*

    Object Oriented Manhim's Framework
    Copyright (C) 2009 Marc AndrĂ© 'Manhim' Audet

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

/*****************************************************
***  Configuration part
*****************************************************/

$cfg['allowed_main_modules'] = array();
$cfg['allowed_main_modules'][] = 'Main';
$cfg['output_buffering'] = true;
$cfg['gz_output'] = true;
$cfg['mb_output'] = true;
$cfg['default_module'] = 'Main';
$cfg['default_args'] = array();
$cfg['on_error_module'] = 'Main';
$cfg['on_error_args'] = array();
$cfg['allow_bench_mode'] = true;


/*****************************************************
***  Edit the rest at your own risks
*****************************************************/

error_reporting(E_ALL & ~E_NOTICE);
define('IN_MANHIM_FRAMEWORK'true);

$message 'Wrong configuration in Manhim\'s Framework.';
$pattern '/([a-zA-Z0-9_-]+)(.*)/';

if (!
is_array($cfg['allowed_main_modules'])) exit ($message);
if (!
is_array($cfg['default_args'])) exit ($message);
if (!
is_bool($cfg['output_buffering'])) exit ($message);
if (!
is_bool($cfg['gz_output'])) exit ($message);
if (!
is_bool($cfg['mb_output'])) exit ($message);
preg_match($pattern$cfg['default_module'], $matches); if (!isset($matches[2])) exit ($message);
preg_match($pattern$cfg['on_error_module'], $matches); if (!isset($matches[2])) exit ($message);
if (!
is_array($cfg['default_args'])) exit ($message);
if (!
is_array($cfg['on_error_args'])) exit ($message);
if (!
is_bool($cfg['allow_bench_mode'])) exit ($message);
define ('IN_MANHIM_FRAMEWORK'true);


/*****************************************************
***  Use GZ encoding callback using the output buffer
*****************************************************/

// steve at mrclay dot org
function isBuggyIe() {
    
$ua $_SERVER['HTTP_USER_AGENT'];

    if (
!== strpos($ua'Mozilla/4.0 (compatible; MSIE ')
        || 
false !== strpos($ua'Opera')) {
        return 
false;
    }

    
$version = (float)substr($ua30); 
    return (
        
$version 6
        
|| ($version == 6  && false === strpos($ua'SV1'))
    );
}

if (
$cfg['output_buffering'] === true)
{
    if (!
isBuggyIe() || $cfg['gz_output'] === trueob_start('ob_gzhandler');
    else 
ob_start();

    if (
$cfg['mb_output'] === true)
    {
        
mb_http_output('UTF-8');
        
ob_start('mb_output_handler');
    }
    else 
ob_start();
}


/*****************************************************
***  8-Bit Unicode Transformation Format
*****************************************************/

header('Content-type: text/html; charset=utf-8');
session_start();


/*****************************************************
***  Verify and parse the query string
*****************************************************/

$pattern '/([a-zA-Z0-9_-]+)(.*)/';
preg_match($pattern$_SERVER['QUERY_STRING'], $matches);

if (isset(
$matches[2]))
{
    
$pattern '/([a-zA-Z0-9_-]+)=([a-zA-Z0-9_-]+)/';
    
preg_match_all($pattern$matches[2], $matches2);
}

if (isset(
$matches[1]))
{
    
$module $matches[1];
    if (isset(
$matches[2]) && isset($matches2[0]) && count($matches2[0]) > 0)
    {
        
$args = array();
        for (
$i=0$i<count($matches2[0]); $i++)
        {
            
$args['' $matches2[1][$i] . ''] = $matches2[2][$i];
        }
    }
    else
        
$args null;
}
else
{
    
$module $cfg['default_module'];
    
$args $cfg['default_args'];
}

$bench_mode false;
if (
$cfg['allow_bench_mode'] && $cfg['output_buffering'] && $args['benchmark'] == '1')
{
    
$bench_mode true;
}


/*****************************************************
***  The OO class and interface
*****************************************************/

interface iMfwModule
{
    function 
__construct();
    function 
Run();
    function 
__destruct();
}

abstract class 
MfwModule
{
    private 
$_Args = array();
    private 
$_In = array();
    
    private 
$_LockArgs false;
    private 
$_LockIn false;
    
    public function 
setArgs($args)
    {
        if ((
is_array($args) || $args === null) && $this->_LockArgs != true)
            
$this->_Args $args;
    }
    
    public function 
lockArgs()
    {
        
$this->_LockArgs true;
    }
    
    protected function 
getArgs()
    {
        return 
$this->_Args;
    }
    
    public function 
setIn(&$in)
    {
        if ((
is_array($in) || $in === null) && $this->_LockIn != true)
            
$this->_In = &$in;
    }
    
    public function 
lockIn()
    {
        
$this->_LockIn true;
    }
    
    protected function 
getIn()
    {
        return 
$this->_In;
    }
    
    private 
$_IsMainModule;
    private 
$_Dependencies;
    private 
$_ReturnByReference;
    
    protected function 
setIsMainModule($isMainModule)
    {
        if (
is_bool($isMainModule))
            
$this->_IsMainModule $isMainModule;
    }
    
    protected function 
setDependencies($dependencies)
    {
        if (
is_array($dependencies) || $dependencies === null)
            
$this->_Dependencies $dependencies;
    }
    
    protected function 
setReturnByReference($returnByReference)
    {
        if (
is_bool($returnByReference))
            
$this->_ReturnByReference $returnByReference;
    }
    
    public function 
getIsMainModule()
    {
        return 
$this->_IsMainModule;
    }
    
    public function 
getDependencies()
    {
        return 
$this->_Dependencies;
    }
    
    public function 
getReturnByReference()
    {
        return 
$this->_ReturnByReference;
    }
}


/*****************************************************
***  Construct the modules and their dependencies
*****************************************************/

if ($bench_mode)
{
    
ob_start();
    
$tmp explode(' 'microtime());
    
$b_Start $tmp[1] + $tmp[0];
    
$b = array();
    
$b_name = array();
}

$dependencies = array();
$in = array();

if (!
in_array($module$cfg['allowed_main_modules'], true)) 
    
$dependencies[] = $cfg['on_error_module'];
else
    
$dependencies[] = $module;
    
if (
$bench_mode)
{
    
$b_name[] = 'space';
    
$b[] = 0;
        
    
$b_name[] = '<span style="color:green"><b>Preparing to construct the modules</b></span>';
    
$tmp explode(' 'microtime());
    
$b[] = $tmp[1] + $tmp[0];
}

$i 0;
while (
true)
{
    
$in['' $dependencies[$i] . ''] = require 'Modules/' $dependencies[$i] . '.inc.php';
    
$in['' $dependencies[$i] . '']->setArgs($args);    
    
$in['' $dependencies[$i] . '']->lockArgs();
    
    if (
$i == && ($in['' $dependencies[$i] . '']->getIsMainModule() != true))
        die(
'The target module is not a main module, therefore Manhim\'s framework can\'t open it.');
    
    
$t_dependencies $in['' $dependencies[$i] . '']->getDependencies();
    
    if (
$t_dependencies !== null)
        for (
$j 0$j count($t_dependencies); $j++)
            if (!
in_array($t_dependencies[$j], $dependencies))
                
$dependencies[] = $t_dependencies[$j];

    
$i++;
  
    if (
count($dependencies) == $i)
        break;
}

if (
$bench_mode)
{
    
$b_name[] = '<span style="color:green"><b>Finished to construct the modules</b></span>';
    
$tmp explode(' 'microtime());
    
$b[] = $tmp[1] + $tmp[0];

    
$b_name[] = 'space';
    
$b[] = 0;
}


/*****************************************************
***  Run the modules
*****************************************************/

$in_keys array_keys($in);
$nin = array();

for (
$i count($in_keys) - 1$i >= 0$i--)
{
    
$nin['' $in_keys[$i] . ''] = $in['' $in_keys[$i] . ''];
}

$in $nin;
$in_keys array_keys($in);

$return_values = array();
$loaded = array();

if (
$bench_mode)
{
    
$b_name[] = '<span style="color:purple"><b>Preparing to run the modules</b></span>';
    
$tmp explode(' 'microtime());
    
$b[] = $tmp[1] + $tmp[0];
}

for (
$i 0$i count($in_keys); $i++)
{
    
$d_list $in['' $in_keys[$i] . '']->getDependencies();
    
    
$s_in = array();
    
$not_all_loaded false;
    for (
$j 0$j count($d_list); $j++)
    {
        if (!isset(
$loaded['' $d_list[$j] . ''])) 
        {
            
$not_all_loaded true;
            break;
        }
    }
    
    if (
$bench_mode)
    {
        
$b_name[] = '<span style="color:darkorange">Testing module</span>: ' $in_keys[$i];
        
$tmp explode(' 'microtime());
        
$b[] = $tmp[1] + $tmp[0];
    }
    
    if (
$not_all_loaded == false)
    {
        for (
$j 0$j count($d_list); $j++)
        {
            if (
$in['' $d_list[$j] . '']->getReturnByReference() === true)
                
$s_in['' $d_list[$j] . ''] = &$return_values['' $d_list[$j] . ''];
            else if (
$in['' $d_list[$j] . '']->getReturnByReference() === false && is_object($return_values['' $d_list[$j] . '']))
                
$s_in['' $d_list[$j] . ''] = clone $return_values['' $d_list[$j] . ''];
            else if (
$in['' $d_list[$j] . '']->getReturnByReference() === false)
                
$s_in['' $d_list[$j] . ''] = $return_values['' $d_list[$j] . ''];
            else
                die(
'Wrong ReturnByReference value in the module ' $d_list[$j]);
        }

        
$in['' $in_keys[$i] . '']->setIn($s_in);    
        
$in['' $in_keys[$i] . '']->lockIn();
        
$return_values['' $in_keys[$i] . ''] = $in['' $in_keys[$i] . '']->Run();
        
$loaded['' $in_keys[$i] . ''] = true;
        
        if (
$bench_mode)
        {
            
$b_name[] = '<span style="color:purple">Running module</span>: ' $in_keys[$i];
            
$tmp explode(' 'microtime());
            
$b[] = $tmp[1] + $tmp[0];
        }
    }
    else
    {
        
$in_keys[] = $in_keys[$i];
    }
}

if (
$bench_mode)
{
    
$b_name[] = '<span style="color:purple"><b>Finished to run the modules</b></span>';
    
$tmp explode(' 'microtime());
    
$b[] = $tmp[1] + $tmp[0];

    
$b_name[] = 'space';
    
$b[] = 0;
}


/*****************************************************
***  Destroy the constructed modules in order
*****************************************************/

if ($bench_mode)
{
    
$b_name[] = '<span style="color:red"><b>Starting to destroy the modules</b></span>';
    
$tmp explode(' 'microtime());
    
$b[] = $tmp[1] + $tmp[0];
}

for (
$i 0$i count($in); $i++)
{
    
$in['' $in_keys[$i] . ''] = null;
}

if (
$bench_mode)
{
    
$b_name[] = '<span style="color:red"><b>Finished to destroy the modules</b></span>';
    
$tmp explode(' 'microtime());
    
$b[] = $tmp[1] + $tmp[0];

    
$b_name[] = 'space';
    
$b[] = 0;

    
$content ob_get_contents();
    
ob_end_clean();
    
    
$b_name[] = 'End';
    
$tmp explode(' 'microtime());
    
$b[] = $tmp[1] + $tmp[0];
    
    echo 
'<div style="background: #eee; border: 1px solid black; padding: 10px; color: #000;">
    <table width="100%" style="margin: 0; padding: 0; background: #000" cellspacing="1">
    <tr>
        <td width="50%" style="border-bottom: 2px solid black; background: #eee;"><center><b>Description</b></center></td>
        <td width="25%" style="border-bottom: 2px solid black; background: #eee;"><center><b>Time since start</b></center></td>
        <td width="25%" style="border-bottom: 2px solid black; background: #eee;"><center><b>Time since last</b></center></td>
    </td>'
;
    
    echo 
'<tr><td style="background: #fff">Start</td>';
    echo 
'<td style="background: #fff">0</td>';
    echo 
'<td style="background: #fff">X</td></tr>';
    
    
$last $b_Start;
    for (
$i 0$i count($b); $i++)
    {
        if (
$b_name[$i] != 'space')
        {
            
$s_start number_format($b[$i] - $b_Start5'.''');
            
$s_last number_format($b[$i] - $last5'.''');
            
            if (
$s_start >= 0.1)
                
$s_start_c 'red';
            else if (
$s_start >= 0.05)
                
$s_start_c 'darkorange';
            else if (
$s_start >= 0.01)
                
$s_start_c 'green';
            else
                
$s_start_c 'black';
                
            if (
$s_last >= 0.05)
                
$s_last_c 'red';
            else if (
$s_last >= 0.005)
                
$s_last_c 'darkorange';
            else if (
$s_last >= 0.0005)
                
$s_last_c 'green';
            else
                
$s_last_c 'black';
            
            echo 
'<tr><td style="background: #fff">' $b_name[$i] . '</td>';
            echo 
'<td style="background: #fff; color: ' $s_start_c '">' $s_start '</td>';
            echo 
'<td style="background: #fff; color: ' $s_last_c '">' $s_last '</td></tr>';
            
$last $b[$i];
        }
        else
        {
            echo 
'<tr><td colspan="3" style="background: #fff">&nbsp;</td></tr>';
        }
    }
    
    echo 
'</table></div>';
    echo 
$content;
}

?>