My name is Mike Whiting (aka Mikey White). I am a full stack LAMP (Linux, Apache, MySQL, PHP) programmer with six years of experience. Yes, I also know how to code HTML, CSS and JavaScript and I can use Photoshop. (Perhaps that makes me a front-end developer too.) Here is some of my PHP code. It's for a simple MVC that I started to produce over four years ago, which I am currently working towards turning into a documented Pear package/public Git repository. It's about 3000 lines long and merely requires a simple YAML library (spyc) and the Smarty template engine to produce robust and cleanly architected web applications. (More info to come at http://empathyphp.co.uk.) I have experience with a wide range of technologies including backend and frontend systems, frameworks, libraries, tools and scripts.

Follow me at mikejw.


define('TEST_APP', '/var/www/sites/eaa');

date_default_timezone_set('Europe/London');


require('Empathy/Util/TestUnit.php');


class TestApp extends TestUnit
{
  protected $controller;

  protected function setUp()
  {
    $this->controller = TEST_APP.'/public_html/index.php';
    parent::setUp();
  }
  
  public function testDefault()
  {    
    $this->setRequest('blah');
    $this->doRequest();

    $resp = $this->getResponse();
    $matches = preg_grep('/Error found/', explode('\n', $resp));

    $this->assertTrue(sizeof($matches) == 1);     
  }
}

require_once 'PHPUnit/Extensions/OutputTestCase.php';

class BootstrapTest extends PHPUnit_Framework_TestCase
{

  protected function setUp()
  {


  }


  public function testSomething()
  {
    $this->assertTrue(true);
  }
}

echo get_include_path();


namespace Empathy\Plugin;
use Empathy\Plugin as Plugin;

class Pheanstalk
{

  public function __construct()
  {   
    require('pheanstalk/pheanstalk_init.php');
  }


}

namespace Empathy\Plugin;
use Empathy\Plugin as Plugin;

class EDefault extends Plugin implements PreDispatch
{
  public function __construct()
  {
    //
  }

  public function onPreDispatch()
  {    
    date_default_timezone_set('Europe/London');
    header('Cache-Control: no-cache, must-revalidate'); // HTTP/1.1
    header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
  }
}

namespace Empathy\Plugin;
use Empathy\Plugin as Plugin;

class Phirehose
{

  public function __construct()
  {     	  
	require('phirehose/Phirehose.php');
  }


}

namespace Empathy\Plugin;
use Empathy\Plugin as Plugin;

class Doctrine extends Plugin implements PreDispatch
{
  private $d_conn;
  private $d_man;

  public function __construct()
  {
    spl_autoload_register(array($this, 'loadModel'));
  }

  public function loadModel($class)
  {
    $location = array(
		      DOC_ROOT.'/models',
		      DOC_ROOT.'/models/generated'		
		      );
    $load_error = 1;
    $i = 0;
    while($i < sizeof($location) && $load_error == 1)
      {
	$class_file = $location[$i].'/'.$class.'.php';           	
	if(@include($class_file))
	  {		
	    $load_error = 0;
	  }
	$i++;
      }
  }
 
  private function isIP($server)
  {
    $ip = false;
    $count = 0;
    $stripped = str_replace('.', '', DB_SERVER, $count);
    if($count)
      {	
	if(is_numeric($stripped))
	  {
	    $ip = true;
	  }	
      }
    return $ip;
  }
  

  public function onPreDispatch()
  {       
    if(!$this->isIP(DB_SERVER))
      {	   
	throw new \Empathy\Exception('Database server must be an IP address.');
      }	            
            
    $dsn = 'mysql://'.DB_USER.':'.DB_PASS.'@'.DB_SERVER.'/'.DB_NAME;
    $this->d_conn = \Doctrine_Manager::connection($dsn, 'c_'.NAME);

    $this->d_man = \Doctrine_Manager::getInstance();
    $this->d_man->setAttribute(\Doctrine::ATTR_VALIDATE, \Doctrine::VALIDATE_ALL);
    $this->d_man->setAttribute(\Doctrine::ATTR_EXPORT, \Doctrine::EXPORT_ALL);
    $this->d_man->setAttribute(\Doctrine::ATTR_MODEL_LOADING, \Doctrine::MODEL_LOADING_CONSERVATIVE);
    $this->d_man->setAttribute(\Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE, true);
    
    
    if(isset($_SERVER['argc']) && $_SERVER['argc'] > 1)
      {
	switch($_SERVER['argv'][1])
	  {
	  case 'doctrine_models':
	    \Doctrine::generateModelsFromDb(DOC_ROOT.'/models', array('c_'.NAME), array('generateTableClasses' => true));
	    exit(1);
	    break;
	  case 'doctrine_yaml':
	    \Doctrine::generateYamlFromModels(DOC_ROOT.'/schema.yml', DOC_ROOT.'/models');
	    exit(1);
	    break;
	  case 'doctrine_generate':
	    \Doctrine::dropDatabases();
	    \Doctrine::createDatabases();
	    \Doctrine::generateModelsFromYaml(DOC_ROOT.'/schema.yml', DOC_ROOT.'/models');
	    \Doctrine::createTablesFromModels(DOC_ROOT.'/models');		
	    exit(1);
	    break;
	  default:
	    die('No valid command line operation specified.'."\n");
	    break;
	  }	    
      }

    if(file_exists(DOC_ROOT.'/models'))
      {
	\Doctrine::loadModels(DOC_ROOT.'/models');	
      }
  }
}

// uses abraham-twitteroauth
// https://github.com/abraham/twitteroauth

namespace Empathy\Plugin;
use Empathy\Plugin as Plugin;

class TwitterOAuth
{

  public function __construct()
  {
    require('twitteroauth/twitteroauth.php');
  }

  


}

namespace Empathy\Plugin;
use Empathy\Plugin as Plugin;

class Smarty extends Plugin implements PreDispatch, Presentation
{
  private $smarty;

  public function __construct()
  {
    $this->smarty = new \Smarty();
  }


  public function onPreDispatch()
  {
    $this->smarty->debugging = SMARTY_DEBUGGING;    
    $this->smarty->template_dir = DOC_ROOT."/presentation";
    $this->smarty->compile_dir = DOC_ROOT."/tpl/templates_c";
    $this->smarty->cache_dir = DOC_ROOT."/tpl/cache";
    $this->smarty->config_dir = DOC_ROOT."/tpl/configs";   

    if(defined('SMARTY_CACHING') && SMARTY_CACHING == true)
      {
	$this->smarty->caching = 1; 
      }

    // assign constants
    $this->assign('NAME', NAME);
    $this->assign('WEB_ROOT', WEB_ROOT);
    $this->assign('PUBLIC_DIR', PUBLIC_DIR);
    $this->assign('DOC_ROOT', DOC_ROOT);
    $this->assign('MVC_VERSION', MVC_VERSION);
  }


  public function assign($name, $data)
  {
    $this->smarty->assign($name, $data);
  }

  public function clear_assign($name)
  {
    $this->smarty->clear_assign($name);
  }

  public function display($template)
  {
    $this->smarty->display($template);
  }

  public function loadFilter($type, $name)
  {
    $this->smarty->load_filter($type, $name);
  }

  public function switchInternal($i)
  {
    if($i)
      {        
	$this->smarty->template_dir = realpath(dirname(__FILE__));
      }
  }
}

namespace Empathy;

class Validate
{  
  const TEXT =  1;
  const ALNUM = 2;
  const NUM = 3;
  const EMAIL = 4;
  const TEL = 5;
  const USERNAME = 6;
  const URL = 7;
 
  public $error = array();
  private $email_pattern;
  private $allowed_pattern_1;
  private $unix_username_pattern;
  private $twitter_style_username;


  public function __construct()
  {
    $this->email_pattern = '/^[^@\s<&>]+@([-a-z0-9]+\.)+[a-z]{2,}$/i';
    $this->allowed_pattern_1 = '/["\/-\s:,\']/';
    $this->unix_username_pattern = '/^[a-z][_a-zA-Z0-9-]{3,7}$/';
    $this->twitter_style_username = '/^\w{1,15}$/';

    // taken from http://bit.ly/AQFAn
    $this->url_pattern = '|https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?|';
  }

  public function valType($type, $field, $data, $optional)
  {
    $valid = true;
    if(!$optional || $data != '')
      {
	switch($type)
	  {
	  case self::TEXT:
	    if(!ctype_alnum(preg_replace($this->allowed_pattern_1, '', $data)))
	      {
		$this->addError('Invalid '.$field, $field);
		$valid = false;
	      }	
	    break;
	  case self::ALNUM:
	    if(!ctype_alnum($data))
	      {
		$this->addError('Invalid '.$field, $field);
		$valid = false;
	      }	
	    break;
	  case self::NUM:
	    if(!is_numeric($data)) // consider ctype_digit instead?
	      {
		$this->addError('Invalid '.$field, $field);		
		$valid = false;
	      }	    
	    break;
	  case self::EMAIL:
	    if(!preg_match($this->email_pattern, $data))
	      {
		$this->addError('Invalid '.$field, $field);
		$valid = false;
	      }
	    break;
	  case self::TEL:
	    if(!ctype_digit(preg_replace('/\s/', '', $data)))
	      {
		$this->addError('Invalid '.$field, $field);
		$valid = false;
	      }
	    break;
	  case self::USERNAME:
	    //if(!preg_match($this->unix_username_pattern, $data))
	    if(!preg_match($this->twitter_style_username, $data))
	      {
		$this->addError('Invalid '.$field, $field);
		$valid = false;
	      }
	    break;
	  case self::URL:
	    if(!preg_match($this->url_pattern, $data))
	      {
		$this->addError('Invalid '.$field, $field);
		$valid = false;
	      }
	    break;
	  default:
	    die('No valid validation type specified.');
	    break;
	  }
      }
    return $valid;
  }
  
  public function addError($message, $field)
  {
    if($field != '')
      {
	if(isset($this->error['field']))
	  {
	    die('Attempt to overwrite error field.');
	  }
	else
	  {
	    $this->error[$field] = $message;
	  }	  
      }
    else
      {
	array_push($this->error, $message);
      }
  }

  public function hasErrors()
  {
    return (sizeof($this->error) > 0);
  }

  public function getErrors()
  {
    return $this->error;
  }

}

namespace Empathy;

class SectionItemStandAlone extends Entity
{
  public $id;
  public $module;
  public $type;
  public $parent_id;
  public $position;
  public $label;
  public $friendly_url;
  public $template;
  public $hidden;
  public $owns_inline;
  public $link;

  public static $table = "section_item";

  public function getURIData()
  {
    $sql = "SELECT id, label, friendly_url FROM ".SectionItemStandAlone::$table;
    $error = "Could not get URI data.";
    $result = $this->query($sql, $error);
    $i = 0;
    foreach($result as $row)
    {
      $uri_data[$i] = $row;
      $i++;
    }
    return $uri_data;
  }

  public function getItem($id)
  {
    $sql = "SELECT * FROM ".SectionItemStandAlone::$table." WHERE id = $id";
    $error = "Could not load record.";
    $result = $this->query($sql, $error);
    if(1 == $result->rowCount())
    {
      $row = $result->fetch();
      foreach($row as $index => $value)
      {
	$this->$index = $value;
      }
      $this->url_name = str_replace(" ", "", $this->label);
      $this->url_name = strtolower($this->url_name);
    }
    else
    {
      //echo "Whoops!";
    }
  }
  
}

namespace Empathy;

class ErrorException extends \Exception
{





}



  // Copyright 2008 Mike Whiting (mail@mikejw.co.uk).
  // This file is part of the Empathy MVC framework.

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

  // Empathy 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 Lesser General Public License for more details.

  // You should have received a copy of the GNU Lesser General Public License
  // along with Empathy.  If not, see .

namespace Empathy;

class Bootstrap
{
  private $controller = null;
  private $defaultModule;
  private $dynamicModule;
  private $uri;
  private $mvc;
  private $plugins;
  private $plugin_manager;
  private $issuingException;
  private $presenter;
  private $persistent_mode;

  public function __construct($bootOptions, $plugins, $mvc)
  {    
    $this->persistent_mode = $mvc->getPersistentMode();
    $this->issuingException = false;
    $this->mvc = $mvc;
    $this->plugins = $plugins;
    $this->plugin_manager = new PluginManager();    

    if(isset($bootOptions['default_module']))
      {
	$this->defaultModule = $bootOptions['default_module'];
      }
    if(isset($bootOptions['dynamic_module']))
      {
	$this->dynamicModule = $bootOptions['dynamic_module'];
      }
  } 

  public function dispatch()
  {
    $this->uri = new URI($this->defaultModule, $this->dynamicModule);
    $error = $this->uri->getError();

    if($error == URI::MISSING_CLASS
       && isset($this->dynamicModule)
       && $this->dynamicModule != '')
      {	
	    $error = $this->uri->dynamicSection();	
      }    
    if($error > 0)
      {
	throw new Exception('Dispatch error '.$error.' : '.$this->uri->getErrorMessage());
      }
    $controller_name = $this->uri->getControllerName();
    $this->controller = new $controller_name($this);     
    $this->controller->$_GET['event']();
    if($this->mvc->hasErrors())
      {	
	throw new ErrorException($this->mvc->errorsToString());
      }
    else
      {
	$this->display(false);    
      }
  }

  public function dispatchException($e)
  {    
    $this->issuingException = true;
    $this->controller = new Controller($this);   
    $this->controller->setTemplate('../empathy.tpl');
    $this->controller->assign('error', $e->getMessage());    
    $this->display(true);  
  }
  
  private function display($i)
  {    
    /*
    if(PNG_OUTPUT == 1)
      {
	$this->controller->presenter->loadFilter('output', 'png_image');
      }
    */
    $this->controller->initDisplay($i);
  }


  public function initPlugins()
  {    
    $plugin_manager = $this->plugin_manager;
    $plugins = $this->plugins;

    try
      {
	if(!$plugin_manager->getInitialised())
	  {
	    $plugin_manager->init();
	    foreach($plugins as $p)
	      {
		if(isset($p['class_path']))
		  {
		    require($p['class_path']);
		    if(isset($p['loader']) && $p['loader'] != '')
		      {
			spl_autoload_register(array($p['class_name'], $p['loader']));	
		      }
		  }	    	
		$plugin_path = realpath(dirname(realpath(__FILE__)).'/../').'/plugins/'.$p['name'].'-'.$p['version'].'.php';
		if(file_exists($plugin_path))
		  {
		    require($plugin_path);
		    $plugin = 'Empathy\\Plugin\\'.$p['name'];
		    $n = new $plugin();
		    $plugin_manager->register($n);
		  }
	      }               
	    $plugin_manager->preDispatch();	
	  }
	$this->presenter = $plugin_manager->getView();   	
      }
    catch(\Exception $e)
      {		
	    throw new \Empathy\SafeException($e->getMessage());       
      }
  }


  public function getPersistentMode()
  {
    return $this->persistent_mode;
  }

  public function getPresenter()
  {
    return $this->presenter;
  }


  public function getIssuingException()
  {
    return $this->issuingException;
  }

  public function getURIError()
  {
    return $this->uri->getError();
  }

  public function getURICliMode()
  {
    return $this->uri->getCliMode();
  }

  public function getURIData()
  {
    return $this->uri->getData();
  }

  public function getPlugins()
  {
    return $this->plugins;
  }

  public function getPluginManager()
  {
    return $this->plugin_manager;
  }

  public function getELib()
  {
    return $this->elib;
  }

  /*
  public function getMVC()
  {
    return $this->mvc;
  }
  */


}

namespace Empathy;

class DBPool
{
  private static $pool = array();

  public static function addHost($s, $n, $u, $p, $host)
  {
    self::$pool[$host] = new DBC($s, $n, $u, $p);
  }

  private static function getHost($host)
  {
    return self::$pool[$host];
  }

  public static function getConnection($host)
  {
    $cx = self::getHost($host);
    return $cx->getHandle();
  }

  public static function getDefCX()
  {
    if(sizeof(self::$pool) < 1)
      {
	self::addHost(DB_SERVER, DB_NAME, DB_USER, DB_PASS, 'default');
      }    

    return self::getConnection('default');
  }
}

/*
usage:
include('Empathy/Util/Test.php');
$t = new Test('/var/www/proper/public_html/index.php');
$req = 'blah';
$t->setRequest($req, false);
$t->process();
echo $t;
*/

class Test
{
  private $request;
  private $response;
  private $t_request_start;
  private $t_request_finish;
  private $t_elapsed;
  private $front_controller;
  private $output;
  
  public function __construct($front, $output = false)
  {
    $this->front_controller = $front;
    $this->output = $output;
  }

  
  public function __toString()
  {
    if($this->output)
      {
	return $this->getResponse();
      }
    else
      {
	return $this->getStatus();
      }
  }
  

  public function setRequest($req)
  {
    $this->request = $req;
  }

  public function process()
  {    
    ob_start();
    $this->t_request_start = microtime();    
    $_SERVER['REQUEST_URI'] = $this->request;
    @include($this->front_controller);  
    $this->t_request_finish = microtime();
    $this->response = ob_get_contents();    
    ob_end_clean();
    $this->t_elapsed = ($this->t_request_finish - $this->t_request_start);    
  }
  
  public function getStatus()
  {
    $error = '';
    if(strpos($this->response, ''))
      {
	$error = 'Error found';
      }
    
    $status = 'Request was deat with in '.$this->t_elapsed.' microseconds...'."\n";
    $status .= 'Error information: '.$error."\n";
    return $status;    
  }

  public function getResponse()
  {
    return $this->response;
  }
}

require('PHPUnit/Extensions/OutputTestCase.php');
require('Empathy/Util/Test.php');


class TestUnit extends \PHPUnit_Framework_TestCase
{
  private $test;
  protected $controller;  
 
  protected function setUp()
  {
    // create new Test object
    // passing front controller path
    // and setting output mode to false
    $this->test = new Test($this->controller, false);  
  }

  protected function setRequest($req)
  {
    // set Test object request string
    $this->test->setRequest($req);
  }

  protected function doRequest()
  {   
    $this->test->process();
  }
  
  protected function getResponse()
  {    
    return $this->test->getStatus();
  }
 
}

namespace Empathy\Util;
use ELib\Util;


class ELib
{
  public static function getLibLocation()
  {
    return Util::getLocation();
  }
  



}

namespace Empathy\Util;

/* based on Util/Test.php
   (which is currently outside of namespacing) 
   
   usage: (from application subfolder. eg. '/scripts'.)
   // get into application-like context...
   include('Empathy/Empathy.php');
   $boot = new Empathy(realpath(dirname(realpath(__FILE__)).'/../'), true);
   // make admin
   \Empathy\Session::up();
   \Empathy\Session::set('user_id', 2);
   $output = \Empathy\Util\CLI::request($boot, $data['url']);
   // print output etc...
*/

class CLI
{
  
  // new function
  private static function realMicrotime()
  {
    list($micro, $seconds) = explode(' ', microtime());
    return ((float)$micro + (float)$seconds);
  }

  public static function request($e, $uri, $return_time = true)
  {
    ob_start();
    $t_request_start = self::realMicrotime();    
    $_SERVER['REQUEST_URI'] = $uri;

    $e->beginDispatch();
    $t_request_finish = self::realMicrotime();
    $response = ob_get_contents();    
    ob_end_clean();
    $t_elapsed = ($t_request_finish - $t_request_start);
    $t_elapsed = number_format($t_elapsed, 4);
    
    if($return_time === true)
      {
	return $t_elapsed;    
      }
    else
      {
	return $response;
      }    
  }
}


namespace Empathy;

class Plugin
{










}
  // Copyright 2008 Mike Whiting (mail@mikejw.co.uk).
  // This file is part of the Empathy MVC framework.

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

  // Empathy 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 Lesser General Public License for more details.

  // You should have received a copy of the GNU Lesser General Public License
  // along with Empathy.  If not, see .

use Empathy as Empathy;

const MVC_VERSION = '0.9.4';

require('spyc/spyc.php');

class Empathy
{
  private $boot;
  private $bootOptions;
  private $plugins;
  private $errors;
  private $persistent_mode;
  private static $elib;
  
  public function __construct($configDir, $persistent_mode = null)
  {
    $this->persistent_mode = $persistent_mode;
    spl_autoload_register(array($this, 'loadClass'));
    $this->loadConfig($configDir);    
    $this->loadConfig(realpath(dirname(realpath(__FILE__)).'/../config'));
    if(isset($this->bootOptions['use_elib']) &&
       $this->bootOptions['use_elib'])
      {
	self::$elib = true;
	\ELib\Config::load($configDir);
      }
    else
      {
	self::$elib = false;
      }

    if(isset($this->bootOptions['handle_errors']) &&
       $this->bootOptions['handle_errors'])
      {
	set_error_handler(array($this, 'errorHandler'));    
      }


    $this->boot = new Empathy\Bootstrap($this->bootOptions, $this->plugins, $this);	
    
    $this->initPlugins();
    
    if($this->persistent_mode !== true)
      {
	$this->beginDispatch();
      }
  }

  
  public function initPlugins()
  {
    try
      {
	$this->boot->initPlugins();
      }
    catch(\Exception $e)
      {
	$this->exceptionHandler($e);
      }
  }


  public function beginDispatch()
  {    
    try
      {       
	$this->boot->dispatch();
      }        
    catch(\Exception $e)
      {
	$this->exceptionHandler($e);
      }    
  }


  public function getPersistentMode()
  {
    return $this->persistent_mode;
  }


  public function getErrors()
  {
    return $this->errors;
  }

  public function hasErrors()
  {
    return (sizeof($this->errors) > 0);
  }

  public function errorsToString()
  {
    return implode('', $this->getErrors());
  }


  public function errorHandler($errno, $errstr, $errfile, $errline)
  {  
    if(error_reporting())
      {
	$msg = '';
	switch ($errno)
	  {
	  case E_ERROR:	
	  case E_USER_ERROR:
	    $msg = "Error: [$errno] $errstr";
	    $msg .= "  Fatal error on line $errline in file $errfile";
	    $msg .= ", PHP " . PHP_VERSION . " (" . PHP_OS . ")";
	    $msg .= " Aborting...";
	    die($msg);
	    break;	
	  case E_WARNING:
	  case E_USER_WARNING:
	    $msg = "Warning: [$errno] $errstr";
	    break;	    
	  case E_NOTICE:
	  case E_USER_NOTICE:
	    $msg = "Notice: [$errno] $errstr";
	    break;	           
	  case E_DEPRECATED:
	  case E_STRICT:
	    $msg = "Strict/Deprecated notice: [$errno] $errstr";	
	    break;
	  default:
	    $msg = "Unknown error type: [$errno] $errstr";
	    break;
	  }
	$msg .= " on line $errline in file $errfile";
	//$msg .= ", PHP " . PHP_VERSION . " (" . PHP_OS . ")";
	$this->errors[] = $msg;
      }
    return true;
  }

  private function exceptionHandler($e)
  {
    if($this->hasErrors())
      {
	$e = new ErrorException($this->errorsToString());
      }
   
    // force safe exception
    //$e = new Empathy\SafeException($e->getMessage());

    switch(get_class($e))
      {
      case 'Empathy\SafeException':
	echo 'Safe exception: '.$e->getMessage();
	exit();
	break;

      default:
	// redispatch to error page 
	/*
	$_GET['module'] = 'notfound';
	$_GET['class'] = 'notfound';
	$_GET['event'] = 'default_event';
	$this->beginDispatch();
	*/

	$this->boot->dispatchException($e);
	break;
      }
  }

  private function loadConfig($configDir)
  {
    $configFile = $configDir.'/config.yml';
    if(!file_exists($configFile))
      {
	die('Config error: '.$configFile.' does not exist');
      }
    $s = new \Spyc();
    $config = $s->YAMLLoad($configFile);      
    foreach($config as $index => $item)
      {
	if(!is_array($item))
	  {
	    define(strtoupper($index), $item);
	  }
      }   
    if(isset($config['boot_options']))
      {
	$this->bootOptions = $config['boot_options'];
      }

    if(isset($config['plugins']))
      {
	$this->plugins = $config['plugins'];
      }
  }


  public static function loadClass($class)
  {
    $i = 0;
    $load_error = 1;
    $location = array('');
    if(strpos($class, 'Controller\\')
       || strpos($class, 'Model\\'))
      {
	$class_arr = explode('\\', $class);
        $class = $class_arr[sizeof($class_arr)-1];

	if(isset($_GET['module']))
	  {
	    array_push($location, DOC_ROOT.'/application/'.$_GET['module'].'/');
	  }
	array_push($location, DOC_ROOT.'/storage/');
      }         
    elseif(strpos($class, 'Empathy') === 0 ||
	   (strpos($class, 'ELib') === 0 && self::$elib))
      {
	$class = str_replace('\\', '/', $class);	
      }
    array_push($location, DOC_ROOT.'/application/');

    
    while($i < sizeof($location) && $load_error == 1)
      {
	$class_file = $location[$i].$class.'.php';           

	//echo $class_file.'
'; if(@include($class_file)) { $class_file.": 1
\n"; $load_error = 0; } else { $class_file.": 0
\n"; } $i++; } } } namespace Empathy; class Stash { private $items; public function __construct() { $this->items = array(); } public function get($key) { return $this->items[$key]; } public function store($key, $data) { $this->items[$key] = $data; } } namespace Empathy\Plugin; use Empathy\Plugin as Plugin; class Doctrine extends Plugin implements PreDispatch { public function __construct() { // } public function onPreDispatch($c) { if(defined('USE_DOCTRINE') && USE_DOCTRINE == true) { $this->d_man = \Doctrine_Manager::getInstance(); $dsn = 'mysql://'.DB_USER.':'.DB_PASS.'@'.DB_SERVER.'/'.DB_NAME; $this->d_conn = \Doctrine_Manager::connection($dsn, 'c_'.NAME); $this->d_man->setAttribute(\Doctrine::ATTR_VALIDATE, \Doctrine::VALIDATE_ALL); $this->d_man->setAttribute(\Doctrine::ATTR_EXPORT, \Doctrine::EXPORT_ALL); $this->d_man->setAttribute(\Doctrine::ATTR_MODEL_LOADING, \Doctrine::MODEL_LOADING_CONSERVATIVE); $this->d_man->setAttribute(\Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE, true); if(isset($_SERVER['argc']) && $_SERVER['argc'] > 1) { switch($_SERVER['argv'][1]) { case 'doctrine_models': \Doctrine::generateModelsFromDb(DOC_ROOT.'/models', array('c_'.NAME), array('generateTableClasses' => true)); exit(1); break; case 'doctrine_yaml': \Doctrine::generateYamlFromModels(DOC_ROOT.'/schema.yml', DOC_ROOT.'/models'); exit(1); break; case 'doctrine_generate': \Doctrine::dropDatabases(); \Doctrine::createDatabases(); \Doctrine::generateModelsFromYaml(DOC_ROOT.'/schema.yml', DOC_ROOT.'/models'); \Doctrine::createTablesFromModels(DOC_ROOT.'/models'); exit(1); break; default: die('No valid command line operation specified.'."\n"); break; } } else { \Doctrine::loadModels(DOC_ROOT.'/models'); } } } } namespace Empathy\Plugin; use Empathy\Plugin as Plugin; require('Smarty/Smarty.class.php'); class Smarty extends Plugin implements PreDispatch, Presentation { private $smarty; public function __construct() { $this->smarty = new \Smarty(); } public function onPreDispatch($c) { $this->smarty->debugging = SMARTY_DEBUGGING; $this->smarty->template_dir = DOC_ROOT."/presentation"; $this->smarty->compile_dir = DOC_ROOT."/tpl/templates_c"; $this->smarty->cache_dir = DOC_ROOT."/tpl/cache"; $this->smarty->config_dir = DOC_ROOT."/tpl/configs"; $this->smarty->error_reporting = E_ALL & ~E_NOTICE; if(defined('SMARTY_CACHING') && SMARTY_CACHING == true) { $this->smarty->caching = 1; } // assign constants $this->assign('NAME', NAME); $this->assign('WEB_ROOT', WEB_ROOT); $this->assign('PUBLIC_DIR', PUBLIC_DIR); $this->assign('DOC_ROOT', DOC_ROOT); $this->assign('MVC_VERSION', MVC_VERSION); } public function templateExists($template) { return file_exists($this->smarty->template_dir.'/'.$template); } public function assign($name, $data) { $this->smarty->assign($name, $data); } public function clear_assign($name) { $this->smarty->clear_assign($name); } public function switchInternal($i) { if($i) { $this->smarty->template_dir = realpath(dirname(__FILE__)); } } public function display($template) { $this->smarty->display($this->smarty->template_dir.'/'.$template); } public function loadFilter($type, $name) { $this->smarty->load_filter($type, $name); } } namespace Empathy\Plugin; interface Presentation { public function __construct(); public function assign($name, $data); public function display($template); } namespace Empathy\Plugin; interface PreDispatch { public function onPreDispatch(); } namespace Empathy; class Model { protected static $db_handle = null; protected static function connectModel($model, $host) { // cached handle is not null // and new host is null // use cached if(self::$db_handle !== null && $host === null) { $model->setDBH(self::$db_handle); } // use a new host elseif($host !== null) { $model->setDBH(DBPool::getConnection($host)); } // db_handle is null and host is null // (initiate default) elseif(self::$db_handle == null && $host == null) { $handle = DBPool::getDefCX(); $model->setDBH($handle); self::$db_handle = $handle; } } public static function load($model, $host = null) { $class = '\Empathy\\Model\\'.$model; $storage_object = new $class(); self::connectModel($storage_object, $host); return $storage_object; } public static function getTable($model) { $class = '\\Empathy\\Model\\'.$model; return $class::TABLE; } } namespace Empathy; class Exception extends \Exception { } // Copyright 2008 Mike Whiting (mail@mikejw.co.uk). // This file is part of the Empathy MVC framework. // Empathy is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Empathy 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 Lesser General Public License for more details. // You should have received a copy of the GNU Lesser General Public License // along with Empathy. If not, see . namespace Empathy; class URI { const MISSING_CLASS = 1; const MISSING_CLASS_DEF = 2; const MISSING_EVENT_DEF = 3; const ERROR_404 = 4; const NO_TEMPLATE = 5; const MAX_COMP = 4; // maxium relevant info stored in a URI // ie module, class, event, id private $full; private $uriString; private $uri; private $defaultModule; private $dynamicModule; private $error; private $internal = false; private $controllerPath = ''; private $controllerName = ''; private $cli_mode_detected; public function __construct($default_module, $dynamic_module) { $this->cli_mode_detected = false; $this->sanity($default_module); $removeLength = strlen(WEB_ROOT.PUBLIC_DIR); $this->defaultModule = $default_module; $this->dynamicModule = $dynamic_module; if(isset($_SERVER['HTTP_HOST'])) { $this->full = $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; $this->uriString = substr($this->full, $removeLength + 1); } else { if(isset($_SERVER['REQUEST_URI'])) // request has been faked { $this->uriString = $_SERVER['REQUEST_URI']; } else { $this->cli_mode_detected = true; } } $this->error = 0; $this->processRequest(); $this->setController(); //$this->printRouting(); } public function getData() { return $this->uri; } public function getCliMode() { return $this->cli_mode_detected; } public function getError() { return $this->error; } public function getControllerName() { return $this->controllerName; } public function printRouting() { echo "
\n";
    echo "Module:\t\t\t".$_GET['module']."\n";
    echo "Class:\t\t\t".$_GET['class']."\n";
    echo "Event:\t\t\t".$_GET['event']."\n\n";   
    echo "Controller Path:\t".$this->controllerPath."\n";
    echo "Controller Name:\t".$this->controllerName."\n";
    echo "Error:\t\t\t".$this->error."\n
"; } public function processRequest() { if(isset($_GET['module'])) { $this->setModule($_GET['module']); } elseif($this->uriString == '' || strpos($this->uriString, '.')) { $this->setModule($this->defaultModule); } else { $this->formURI(); $this->analyzeURI(); } } public function formURI() { $uri = explode('/', $this->uriString); $size = sizeof($uri) - 1; // remove empty element caused by trailing slash if($uri[$size] == '') { array_pop($uri); $size--; } // ignore any args if(preg_match('/\?/', $uri[$size])) { $start_args = strpos($uri[$size], '?'); $uri[$size] = substr($uri[$size], 0, $start_args); if($uri[$size] == '') { array_pop($uri); } } $this->uri = $uri; } public function analyzeURI() { $modIndex = 0; $completed = 0; $j = 0; $i = 0; $current = ''; $length = sizeof($this->uri); if($length > URI::MAX_COMP) { $length = URI::MAX_COMP; } while($i < $length) { $current = $this->uri[$i]; if(!isset($_GET['id']) && is_numeric($current)) { $_GET['id'] = $current; $i++; continue; } if(!isset($_GET['module'])) { /* while($j < sizeof($this->module) && $current != $this->module[$j]) { $j++; } $modIndex = $j; if($modIndex == sizeof($this->module)) { $modIndex = DEF_MOD; $_GET['class'] = $current; $this->error = URI::MISSING_CLASS; } */ $this->setModule($current); $i++; continue; } if(!isset($_GET['class'])) { $_GET['class'] = $current; $i++; continue; } if(!isset($_GET['event'])) { $_GET['event'] = $current; } $i++; } if(!isset($_GET['module'])) { // only present url param is an id $this->setModule($this->defaultModule); } } private function setModule($module) { $_GET['module'] = $module; if($_GET['module'] == 'empathy') { $this->internal = true; } } public function setControllerPath() { $this->controllerPath = DOC_ROOT.'/application/'.$_GET['module'].'/'.$_GET['class'].'.php'; } private function setController() { if(!(isset($_GET['class'])) && isset($_GET['module'])) { $_GET['class'] = $_GET['module']; } if(isset($_GET['class'])) { $this->controllerName = $_GET['class']; $this->setControllerPath(); } if(!is_file($this->controllerPath)) { if(isset($_GET['class'])) { $_GET['event'] = $_GET['class']; } // module must be set? if(isset($_GET['module'])) { $_GET['class'] = $_GET['module']; $this->controllerName = $_GET['module']; $this->setControllerPath(); } if(!is_file($this->controllerPath)) { $this->error = URI::MISSING_CLASS; } } $this->controllerName = 'Empathy\\Controller\\'.$this->controllerName; if(!$this->error) { if(!class_exists($this->controllerName)) { $this->error = URI::MISSING_CLASS_DEF; } } $this->assertEventIsSet(); if(!$this->error) { $r = new \ReflectionClass($this->controllerName); if(!$r->hasMethod($_GET['event'])) { $this->error = URI::MISSING_EVENT_DEF; } } } public function assertEventIsSet() { if(!(isset($_GET['event'])) || $_GET['event'] == '') { $_GET['event'] = 'default_event'; } } public function dynamicSection() { // code still needed to assert correct section path - else throw 404 $this->error = 0; // temporary hack to provide object so that entity will assume it has a controller // and connect to database $section = new SectionItemStandAlone(new \stdClass()); if(!isset($this->dynamicModule) || $this->dynamicModule == '') { throw new Exception("Failed to find name of dynamic module."); } else { $_GET['module'] = $this->dynamicModule; } if(sizeof($this->uri) > 0) { $section_index = (sizeof($this->uri) - 1); if(is_numeric($this->uri[$section_index])) { $_GET['id'] = $this->uri[$section_index--]; } if($section_index >= 0) { $section_uri = $this->uri[$section_index]; } } elseif(defined('DEFAULT_SECTION')) { $section_uri = DEFAULT_SECTION; } $rows = $section->getURIData(); if(isset($section_uri)) { for($i = 0; $i < sizeof($rows); $i++) { if($rows[$i]['friendly_url'] != NULL) { $comp = str_replace(" ", "", strtolower($rows[$i]['friendly_url'])); } else { $comp = str_replace(" ", "", strtolower($rows[$i]['label'])); } if($comp == $section_uri) { $_GET['section'] = $rows[$i]['id']; } } } if(isset($_GET['section'])) { $section->getItem($_GET['section']); } // section id is not set / found if(!(is_numeric($section->id))) { $this->error = URI::ERROR_404; } if(isset($section->url_name)) { $_GET['section_uri'] = $section->url_name; } if($this->error < 1) { if($section->template == "") { $this->error = URI::NO_TEMPLATE; } else { if($section->template == '0') // section in 'specialised' { $controllerName = "template".$section->id; } else { $controllerName = "template".$section->template; } } } if(isset($controllerName)) { $_GET['class'] = $controllerName; } $_GET['event'] = 'default_event'; $_GET['id'] = $section->id; if($this->error < 1) { $this->setController(); } return $this->error; } public function getErrorMessage() { $message = ''; switch($this->error) { case URI::MISSING_CLASS: $message = 'Missing class file'; break; case URI::MISSING_CLASS_DEF: $message = 'Missing or incorrect class definition'; break; case URI::MISSING_EVENT_DEF: $message = 'Controller event '.$_GET['event'].' has not been defined'; break; case URI::ERROR_404: $message = 'Error 404'; break; case URI::NO_TEMPLATE: $message = 'No DSection template specified'; break; default: break; } return $message; } public function sanity($default_module) { if(!isset($default_module)) { throw new SafeException('Dispatch error: No default module specified'); } if(!defined('WEB_ROOT')) { throw new SafeException('Dispatch error: Web root is not defined'); } if(!defined('PUBLIC_DIR')) { throw new SafeException('Dispatch error: Public dir is not defined'); } if(!defined('DOC_ROOT')) { throw new SafeException('Dispatch error: Doc root is not defined'); } if(!defined('SMARTY_DEBUGGING')) { throw new SafeException('Dispatch error: Smarty debugging is not defined'); } if(!defined('TITLE')) { throw new SafeException('Dispatch error: No fallback title is defined'); } if(!defined('NAME')) { throw new SafeException('Dispatch error: Web application needs a name'); } if(!defined('TPL_BY_CLASS')) { throw new SafeException('Dispatch error: TPL_BY_CLASS is not defined'); } } } namespace Empathy; class SafeException extends Exception { } // Copyright 2008 Mike Whiting (mail@mikejw.co.uk). // This file is part of the Empathy MVC framework. // Empathy is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Empathy 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 Lesser General Public License for more details. // You should have received a copy of the GNU Lesser General Public License // along with Empathy. If not, see . namespace Empathy; class Entity { const TABLE = ''; private $val; private $controller; private $rows; private $result; private $globally_ignored_property = array('id', 'table'); // leaving in table to support old models private $properties; private $dbh; protected static $table = ''; public function MYSQLTime() { return '\''.date('Y:m:d H:i:s', time()).'\''; } public function __construct($controller = NULL) { $this->val = new Validate(); $this->properties = array(); $this->controller = $controller; /* if(!is_object($controller) || !isset($this->controller->connected) || $this->controller->connected == false) { $this->dbConnect(); } */ if(is_object($controller)) { $this->dbConnect(); } $this->loadProperties(); } protected function insertId() { return $this->dbh->lastInsertId(); } private function loadProperties() { $r = new \ReflectionClass(get_class($this)); // get properties from all subclasses in the right order // (with a bit of hackery to make 'table' last) if($r->getParentClass()->getName() != 'Empathy\Entity') { $props = array(); while(($class = $r->getName()) != 'Empathy\Entity') { $props[] = $r->getProperties(); $r = $r->getParentClass(); } $props = array_reverse($props); $properties = array(); foreach($props as $p) { foreach($p as $rp) { $name = $rp->name; if(!in_array($name, $properties) && $name != 'table') { $properties[] = $name; } } } $properties[] = 'table'; $this->properties = $properties; //print_r($this->properties); exit(); } else // it's a straightforward single subclass { foreach($r->getProperties() as $item) { array_push($this->properties, $item->name); } } } public function dbConnect() { if(!defined('DB_SERVER') || DB_SERVER == '') { throw new SafeException('DB Error: No database host given'); } if(!defined('DB_NAME') || DB_NAME == '') { throw new SafeException('DB Error: No database name'); } if(!defined('DB_USER') || DB_USER == '') { throw new SafeException('DB Error: No database username'); } if(!defined('DB_PASS') || DB_PASS == '') { throw new SafeException('DB Error: No database password'); } $this->dbh = new \PDO('mysql:host='.DB_SERVER.';dbname='.DB_NAME, DB_USER, DB_PASS); } public function setDBH($dbh) { $this->dbh = $dbh; } public function query($sql, $error) { if(defined('ELIB_SQL_LOGGING') && ELIB_SQL_LOGGING == true) { \ELib\Util\SQLLog::log($sql); } /* needs to be elib specific extention $queries = YAML::load(DOC_ROOT.'/logs/sql_log'); $queries[] = $sql; YAML::save($queries, DOC_ROOT.'/logs/sql_log'); */ $result = NULL; if(($result = $this->dbh->query($sql)) == false) { $errors = $this->dbh->errorInfo(); if(is_object($this->controller)) { $this->controller->error("[".htmlentities($sql) ."]
MySQL: ($error): " .htmlentities($errors[2]), 0); } else { throw new \Exception("[".htmlentities($sql) ."]
MySQL: ($error): " .htmlentities($errors[2])); } } else { $this->result = $result; } return $result; } public function load($table = null) { if($table == null) { $c = get_class($this); $table = $c::TABLE; } $loaded = true; $table = $this->appendPrefix($table); $sql = "SELECT * FROM $table WHERE id = $this->id"; $error = "Could not load record from $table."; $result = $this->query($sql, $error); if($result->rowCount() > 0) { $row = $result->fetch(); foreach($row as $index => $value) { $this->$index = $value; } } else { $loaded = false; } return $loaded; } public function loadAsOptions($table, $field, $order = NULL) { $data = array(); $sql = 'SELECT id,'.$field.' FROM '.$table; if($order !== NULL && $order != '') { $sql .= ' ORDER BY '.$order; } else { $sql .= ' ORDER BY '.$field; } $error = 'Could not load '.$table.' as options';; $result = $this->query($sql, $error); foreach($result as $row) { $id = $row['id']; $data[$id] = $row[$field]; } return $data; } public function sanitize() { foreach($this->properties as $property) { if(isset($_POST[$property]) && !(is_numeric($property))) // && ($this->$property == $_POST[$property])) -> breaking where single quotes and break tags { $this->$property = mysql_escape_string($this->$property); } } } public function sanitizeNoPost() { foreach($this->properties as $property) { if(!in_array($property, $this->globally_ignored_property) && !is_numeric($property)) { $this->$property = mysql_escape_string($this->$property); } } } public function save($table, $format, $sanitize) { $table = $this->appendPrefix($table); $this->toXHTMLChris($format); if($sanitize == 1) { $this->sanitize(); } elseif($sanitize == 2) { $this->sanitizeNoPost(); } $sql = "UPDATE $table SET "; $properties = array(); foreach($this->properties as $property) { // if(!in_array($property, $this->globally_ignored_property) && $this->$property != '') if(!in_array($property, $this->globally_ignored_property)) { array_push($properties, $property); } } $i = 0; foreach($properties as $property) { $sql .= "$property = "; if(is_numeric($this->$property) && !is_string($this->$property)) { $sql .= $this->$property; } elseif($this->$property == '') { $sql .= 'NULL'; } elseif($this->$property == 'DEFAULT') { $sql .= 'DEFAULT'; } elseif($this->$property == 'MYSQLTIME') { $sql .= $this->MYSQLTime(); } else { $sql .= "'".$this->$property."'"; } if($i + 1 < sizeof($properties)) { $sql .= ", "; } $i++; } $sql .= " WHERE id = $this->id"; $error = "Could not update table '$table'"; $this->query($sql, $error); } public function insert($table, $id, $format, $sanitize) { $table = $this->appendPrefix($table); $this->toXHTMLChris($format); if($sanitize == 1) { $this->sanitize(); } elseif($sanitize == 2) { $this->sanitizeNoPost(); } $sql = 'INSERT INTO '.$table.' VALUES('; if($id) { $sql .= 'NULL, '; } $i = 0; $id = 0; foreach($this->properties as $property) { if(!in_array($property, $this->globally_ignored_property)) { if(is_numeric($this->$property) && !is_string($this->$property)) { $sql .= $this->$property; } elseif($this->$property == '') { $sql .= 'NULL'; } elseif($this->$property == 'DEFAULT') { $sql .= 'DEFAULT'; } elseif($this->$property == 'MYSQLTIME') { $sql .= $this->MYSQLTime(); } else { $sql .= "'".$this->$property."'"; } if(($i + sizeof($this->globally_ignored_property)) != sizeof($this->properties)) { $sql .= ", "; } } $i++; } $sql .= ")"; $error = "Could not insert to table '$table'"; if(($result = $this->query($sql, $error)) === false) { $errors = $this->dbh->errorInfo(); $this->controller->error("[".htmlentities($sql) ."]
MySQL: ($error): " .htmlentities($errors[2]), 0); } else { return $this->insertId(); } } public function appendPrefix($table) { return TBL_PREFIX.$table; } public function getRows(&$result) { $this->rows = $result->rowCount(); } public function getAll($table) { $all = array(); $sql = 'SELECT * FROM '.$table; $error = 'Could not get all rows from '.$table; $result = $this->query($sql, $error); $i = 0; foreach($result as $row) { $all[$i] = $row; $i++; } return $all; } public function getAllCustom($table, $sql_string) { $table = $this->appendPrefix($table); $all = array(); $sql = 'SELECT * FROM '.$table.' '.$sql_string; $error = 'Could not get all rows from '.$table; $result = $this->query($sql, $error); $i = 0; foreach($result as $row) { $all[$i] = $row; $i++; } return $all; } public function getPaginatePages($table, $sql_string, $page, $per_page) { $nav = array(); $sql = 'SELECT * FROM '.$table.' '.$sql_string; //$sql = 'SELECT FOUND_ROWS()'; $error = 'Could not get rows from '.$table; $result = $this->query($sql, $error); $rows = $result->rowCount(); $p_rows = $rows; $pages = ceil($rows / $per_page); $i = 1; while($i <= $pages) { if($i == $page) { $nav[$i] = 1; } else { $nav[$i] = 0; } $i++; } return $nav; } public function getPaginatePagesSimpleJoin($select, $table1, $table2, $sql_string, $page, $per_page) { $nav = array(); $sql = 'SELECT '.$select.' FROM '.$table1.' t1, '.$table2.' t2 '.$sql_string; $error = 'Could not get rows from '.$table1; $result = $this->query($sql, $error); $rows = $result->rowCount(); $p_rows = $rows; $pages = ceil($rows / $per_page); $i = 1; while($i <= $pages) { if($i == $page) { $nav[$i] = 1; } else { $nav[$i] = 0; } $i++; } return $nav; } public function getPaginatePagesMultiJoin($select, $table1, $table2, $table3, $sql_string, $page, $per_page) { $nav = array(); $sql = 'SELECT '.$select.' FROM '.$table1.' t1, '.$table2.' t2, '.$table3.' t3 '.$sql_string; $error = 'Could not get rows from '.$table1; $result = $this->query($sql, $error); $rows = $result->rowCount(); $p_rows = $rows; $pages = ceil($rows / $per_page); $i = 1; while($i <= $pages) { if($i == $page) { $nav[$i] = 1; } else { $nav[$i] = 0; } $i++; } return $nav; } public function getPaginatePagesMultiJoinGroup($select, $table1, $table2, $table3, $sql_string, $page, $per_page, $group, $order) { $nav = array(); $sql = 'SELECT '.$select.' FROM '.$table1.' t1, '.$table2.' t2, '.$table3.' t3 '.$sql_string; $sql .= ' GROUP BY '.$group.' ORDER BY '.$order; $error = 'Could not get rows from '.$table1; $result = $this->query($sql, $error); $rows = $result->rowCount(); $p_rows = $rows; $pages = ceil($rows / $per_page); $i = 1; while($i <= $pages) { if($i == $page) { $nav[$i] = 1; } else { $nav[$i] = 0; } $i++; } return $nav; } public function addTablePrefix($table) { return TBL_PREFIX.$table; } public function getAllCustomPaginate($table, $sql_string, $page, $per_page) { $table = $this->addTablePrefix($table); $all = array(); $start = ($page - 1) * $per_page; $sql = 'SELECT * FROM '.$table.' '.$sql_string.' LIMIT '.$start.', '.$per_page; //$sql = 'SELECT SQL_CALC_FOUND_ROWS * FROM '.$table.' '.$sql_string.' LIMIT '.$start.', '.$per_page; $error = 'Could not get rows from '.$table; $result = $this->query($sql, $error); $i = 0; foreach($result as $row) { $all[$i] = $row; $i++; } return $all; } public function getAllCustomPaginateSimpleJoin($select, $table1, $table2, $sql_string, $page, $per_page) { $all = array(); $start = ($page - 1) * $per_page; $sql = 'SELECT '.$select.' FROM '.$table1.' t1, '.$table2.' t2 '.$sql_string.' LIMIT '.$start.', '.$per_page; $error = 'Could not get rows from '.$table1; $result = $this->query($sql, $error); $i = 0; foreach($result as $row) { $all[$i] = $row; $i++; } return $all; } public function getAllCustomPaginateMultiJoin($select, $table1, $table2, $table3, $sql_string, $page, $per_page) { $all = array(); $start = ($page - 1) * $per_page; $sql = 'SELECT '.$select.' FROM '.$table1.' t1, '.$table2.' t2, '.$table3.' t3 '.$sql_string.' LIMIT '.$start.', '.$per_page; $error = 'Could not get rows from '.$table1; $result = $this->query($sql, $error); $i = 0; foreach($result as $row) { $all[$i] = $row; $i++; } return $all; } public function getAllCustomPaginateMultiJoinGroup($select, $table1, $table2, $table3, $sql_string, $page, $per_page, $group, $order) { $all = array(); $start = ($page - 1) * $per_page; $sql = 'SELECT '.$select.' FROM '.$table1.' t1, '.$table2.' t2, '.$table3.' t3 '.$sql_string.' GROUP BY '.$group .' ORDER BY '.$order.' LIMIT '.$start.', '.$per_page; $error = 'Could not get rows from '.$table1; $result = $this->query($sql, $error); $i = 0; foreach($result as $row) { $all[$i] = $row; $i++; } return $all; } public function assignFromPost($ignore) { foreach($this->properties as $property) { if(!in_array($property, $this->globally_ignored_property) && !in_array($property, $ignore)) { $this->$property = $_POST[$property]; } } } public function prepareOptions($first, $label, $table) { $option = array(); $data = $this->getAll($table); if($first != '') { $option[0] = $first; } foreach($data as $index => $value) { $id = $value['id']; $option[$id]= $value[$label]; } return $option; } public function toXHTMLChris($formatting) { $markup = ''; foreach($this->properties as $property) { if(!is_numeric($property) && in_array($property, $formatting)) { $markup = $this->$property; $markup = str_replace("\r", "\n", $markup); $markup = preg_replace("!\n\n+!", "\n", $markup); $markup = htmlentities($markup, ENT_QUOTES, 'UTF-8'); $markup = preg_replace('!<a +href="((?:ht|f)tps?://.*?)"(?: +title="(.*?)")? *>(.*?)</a>!m', '$3', $markup); $markup = preg_replace('!<img +src="(https?://.*?)?"(?: +id="(.*?)")?(?: +alt="(.*?)")? */>!m', '$3', $markup); $markup = preg_replace('/ +id=""/', '', $markup); $markup = preg_replace('!<strong>(.*?)</strong>!m', '$1', $markup); $markup = preg_replace('!<em>(.*?)</em>!m', '$1', $markup); $lines = explode("\n", $markup); foreach($lines as $key => $line) { $lines[$key] = "

{$line}

"; } $markup = implode("\n", $lines); $this->$property = $markup; } } } public function toXHTML($formatting) { foreach($this->properties as $property) { if(!(is_numeric($property))) { //$this->$property = ereg_replace(38, "&", $this->$property); if(in_array($property, $formatting)) { $this->$property = str_replace("\r\n", '
', $this->$property); } else { $this->$property = str_replace("\r\n", ' ', $this->$property); } } } } public function buildUnionString($ids) { $str = '(0,'; $i = 0; foreach($ids as $id) { $str .= $id; if(($i + 1) != sizeof($ids)) { $str .= ','; } $i++; } $str .= ')'; /* does this really fix anything? if($str == '(0,)') { $str = '(0)'; } */ return $str; } public function stripMSWordChars() { foreach($this->properties as $property) { if(!(is_numeric($property))) { /* $this->$property = ereg_replace(133, "…", $this->$property); // ellipses $this->$property = ereg_replace(8226, "″", $this->$property); // double prime $this->$property = ereg_replace(8216, "'", $this->$property); // left single quote $this->$property = ereg_replace(145, "'", $this->$property); // left single quote $this->$property = ereg_replace(8217, "'", $this->$property); // right single quote $this->$property = ereg_replace(146, "'", $this->$property); // right single quote $this->$property = ereg_replace(8220, """, $this->$property); // left double quote $this->$property = ereg_replace(147, """, $this->$property); // left double quote $this->$property = ereg_replace(8221, """, $this->$property); // right double quote $this->$property = ereg_replace(148, """, $this->$property); // right double quote $this->$property = ereg_replace(8226, "•", $this->$property); // bullet $this->$property = ereg_replace(149, "•", $this->$property); // bullet $this->$property = ereg_replace(8211, "–", $this->$property); // en dash $this->$property = ereg_replace(150, "–", $this->$property); // en dash $this->$property = ereg_replace(8212, "—", $this->$property); // em dash $this->$property = ereg_replace(151, "—", $this->$property); // em dash $this->$property = ereg_replace(8482, "™", $this->$property); // trademark $this->$property = ereg_replace(153, "™", $this->$property); // trademark $this->$property = ereg_replace(169, "©", $this->$property); // copyright mark $this->$property = ereg_replace(174, "®", $this->$property); // registration mark */ $this->$property = ereg_replace(133, "", $this->$property); // ellipses $this->$property = ereg_replace(8226, "", $this->$property); // double prime $this->$property = ereg_replace(8216, "", $this->$property); // left single quote $this->$property = ereg_replace(145, "", $this->$property); // left single quote $this->$property = ereg_replace(8217, "", $this->$property); // right single quote $this->$property = ereg_replace(146, "", $this->$property); // right single quote $this->$property = ereg_replace(8220, "", $this->$property); // left double quote $this->$property = ereg_replace(147, "", $this->$property); // left double quote $this->$property = ereg_replace(8221, "", $this->$property); // right double quote $this->$property = ereg_replace(148, "", $this->$property); // right double quote $this->$property = ereg_replace(8226, "", $this->$property); // bullet $this->$property = ereg_replace(149, "", $this->$property); // bullet $this->$property = ereg_replace(8211, "", $this->$property); // en dash $this->$property = ereg_replace(150, "", $this->$property); // en dash $this->$property = ereg_replace(8212, "", $this->$property); // em dash $this->$property = ereg_replace(151, "", $this->$property); // em dash $this->$property = ereg_replace(8482, "", $this->$property); // trademark $this->$property = ereg_replace(153, "", $this->$property); // trademark $this->$property = ereg_replace(169, "", $this->$property); // copyright mark $this->$property = ereg_replace(174, "", $this->$property); // registration mark } } } public function delete($table = null) { if($table == null) { $c = get_class($this); $table = $c::TABLE; } $sql = 'DELETE FROM '.$table.' WHERE id = '.$this->id; $error = 'Could not delete row.'; $this->query($sql, $error); } public function hasValErrors() { return $this->val->hasErrors(); } public function getValErrors() { return $this->val->getErrors(); } public function addValError($error, $field='') { $this->val->addError($error, $field); } public function doValType($type, $field, $data, $optional) { return $this->val->valType($type, $field, $data, $optional); } } namespace Empathy; class DBC { private $server; private $name; private $user; private $pass; private $handle; public function __construct($s, $n, $u, $p) { $this->server = $s; $this->name = $n; $this->user = $u; $this->pass = $p; $this->handle = new \PDO('mysql:host='.$this->server.';dbname='.$this->name, $this->user, $this->pass); } public function getHandle() { return $this->handle; } } namespace Empathy; class Store { private $object; public function __contruct() { $this->object = array(); } public function set($index, $value) { $this->object[$index] = $value; } public function get($index) { return $this->object[$index]; } } // Copyright 2008 Mike Whiting (mail@mikejw.co.uk). // This file is part of the Empathy MVC framework. // Empathy is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Empathy 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 Lesser General Public License for more details. // You should have received a copy of the GNU Lesser General Public License // along with Empathy. If not, see . namespace Empathy; class Controller { protected $module; protected $class; protected $event; private $templateFile; protected $title; public $presenter; public $connected; private $initError; protected $d_man; protected $d_conn; protected $cli_mode; protected $plugin_manager; protected $uri_data; protected $stash; protected $boot; public function __construct($boot) { $this->boot = $boot; $this->cli_mode = $boot->getURICliMode(); $this->initError = $boot->getURIError(); $this->uri_data = $boot->getURIData(); $this->stash = new Stash(); $this->connected = false; $this->module = $_GET['module']; $this->class = $_GET['class']; $this->event = $_GET['event']; $this->title = TITLE; if(TPL_BY_CLASS == 0) { $this->templateFile = $this->module.'.tpl'; } else { $this->templateFile = $this->class.'.tpl'; } Session::up(); // get presenter $this->presenter = $boot->getPresenter(); if($this->presenter !== null) { $this->assignSessionVar(); $this->assignControllerInfo(); $this->assignConstants(); } if(isset($_GET['section_uri'])) { $this->assign('section', $_GET['section_uri']); } } public function assignConstants() { $this->assign('NAME', NAME); $this->assign('WEB_ROOT', WEB_ROOT); $this->assign('PUBLIC_DIR', PUBLIC_DIR); $this->assign('DOC_ROOT', DOC_ROOT); $this->assign('MVC_VERSION', MVC_VERSION); $this->assign('TITLE', TITLE); } public function assignControllerInfo() { $this->assign('module', $this->module); $this->assign('class', $this->class); $this->assign('event', $this->event); } public function setTemplate($tpl) { $this->templateFile = $tpl; } public function initDisplay($i) { if(1 || !$this->boot->getPersistentMode()) // disabling this optimization for now { $this->presenter->switchInternal($i); $this->presenter->display($this->templateFile); } } public function assignSessionVar() { foreach($_SESSION as $index => $value) { $this->assign($index, $value); } } public function redirect($endString) { if(!$this->boot->getPersistentMode()) { session_write_close(); $location = 'Location: '; $location .= 'http://'.WEB_ROOT.PUBLIC_DIR.'/'; if($endString != '') { $location .= $endString; } header($location); exit(); } } public function redirect_cgi($endString) { session_write_close(); $location = 'Location: '; $location .= 'http://'.CGI.'/'; if($endString != '') { $location .= $endString; } header($location); exit(); } public function sessionDown() { Session::down(); } public function toggleEditMode() { if($_SESSION['edit_mode'] != 1) { $_SESSION['edit_mode'] = 1; } else { $_SESSION['edit_mode'] = 0; } } protected function setFailedURI($uri) { Session::set('failed_uri', $uri); } public function http_error($type) { $response = ''; $message = ''; switch($type) { case 400: $response = 'HTTP/1.1 400 bad request'; $message = 'Bad request'; break; case 404: $response = 'HTTP/1.0 404 Not Found'; $message = 'Sorry this page does not exist or is out of date.'; break; } header($response); $this->presenter->assign('message', $message); $this->presenter->assign('code', $type); $this->presenter->display('http_error.tpl'); exit(); } public function error($message) { if(DEBUG_MODE == 0) { $this->http_error(404); } else { if(isset($_SERVER['HTTP_HOST'])) { $this->setFailedURI($_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); } Session::set('app_error', array($this->module, $this->class, $message, date('U'))); //$this->redirect('empathy/error/'); throw new Exception('Couldn\'t dispatch: '.$message); } } public function loadUIVars($ui, $ui_array) { $new_app = Session::getNewApp(); foreach($ui_array as $setting) { if(isset($_GET[$setting])) { if(!$new_app) { $_SESSION[$ui][$setting] = $_GET[$setting]; } else { Session::setUISetting($ui, $setting, $_GET[$setting]); } } elseif(Session::getUISetting($ui, $setting) !== false) { $_GET[$setting] = Session::getUISetting($ui, $setting); } elseif(isset($_SESSION[$ui][$setting])) { $_GET[$setting] = $_SESSION[$ui][$setting]; } } } public function isXMLHttpRequest() { $request = 0; if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')) { $request = 1; } return $request; } public function initID($id, $def, $assertSet=false) // when $def is 0, valid is true when id is 0 { $valid = true; $assign_def = false; if(!isset($_GET[$id])) { $assign_def = true; if($assertSet) { $valid = false; } } elseif(!((string) $_GET[$id] === (string)(int) $_GET[$id]) || ($_GET[$id] == 0 && $def != 0) || $_GET[$id] < 0) { $assign_def = true; $valid = false; } if($assign_def) { $_GET[$id] = $def; } return $valid; } public function execScript($script, $args, $passthru=false) { $exec = 'cd '.DOC_ROOT.'/scripts; '; $exec .= PERL.' '.DOC_ROOT.'/scripts/'.$script.' '.implode(' ', $args); if(!$passthru) { exec($exec); } else { passthru($exec); } } public function assign($name, $data) { $this->presenter->assign($name, $data); } public function __destruct() { if(defined('ELIB_SQL_LOGGING') && ELIB_SQL_LOGGING == true) { \ELib\Util\SQLLog::log('----------END OF REQUEST---------'); } } /* public function internalRequest($uri) { $_SERVER['REQUEST_URI'] = $uri; $this->boot->getMVC()->beginDispatch(); } */ } namespace Empathy; class PluginManager { private $plugins; private $view_plugin; private $initialised; public function __construct() { $this->initialised = 0; $this->plugins = array(); $this->view_plugin = NULL; } public function init() { $this->initialised = 1; } public function register($p) { $this->plugins[] = $p; } public function preDispatch() { foreach($this->plugins as $p) { $r = new \ReflectionClass(get_class($p)); if(in_array('Empathy\Plugin\PreDispatch', $r->getInterfaceNames())) { $p->onPreDispatch(); } if(in_array('Empathy\Plugin\Presentation', $r->getInterfaceNames())) { $this->view_plugin = $p; } } } public function getInitialised() { return $this->initialised; } public function getView() { if($this->view_plugin === NULL) { throw new \Exception('No plugin loaded for view.'); } else { return $this->view_plugin; } } } namespace Empathy; class Session { public static $app = NAME; private static $up = false; public static function dump() { if(isset($_SESSION)) { echo "
\n";
	print_r($_SESSION);
	echo "
"; } } public static function up() { if(self::$up === false) { @session_start(); if(!isset($_SESSION['app']) || !isset($_SESSION['app'][self::$app])) { $_SESSION['app'][self::$app] = array(); } //self::dump(); self::$up = true; } } public static function getNewApp() { $new_app = false; if(sizeof($_SESSION['app'][self::$app]) > 0) { $new_app = true; } return $new_app; } public static function setUISetting($ui, $setting, $value) { $_SESSION['app'][self::$app][$ui][$setting] = $value; } public static function getUISetting($ui, $setting) { // echo $_SESSION['app'][self::$app][$ui][$setting]; if(isset($_SESSION['app'][self::$app][$ui][$setting])) { return $_SESSION['app'][self::$app][$ui][$setting]; } else { return false; } } public static function down() { // backwards compatibility $new_app = self::getNewApp(); // main logic unset($_SESSION['app'][self::$app]); if(sizeof($_SESSION['app']) == 0) { session_unset(); session_destroy(); } // backwards compatibility if(isset($_SESSION['user_id']) && !$new_app) { foreach($_SESSION as $index => $value) { if($index != 'app') { unset($_SESSION[$index]); } } } } public static function set($key, $value) { $_SESSION['app'][self::$app][$key] = $value; } public static function get($key) { if(!isset($_SESSION['app'][self::$app][$key])) { return false; } else { return $_SESSION['app'][self::$app][$key]; } } public static function clear($key) { unset($_SESSION['app'][self::$app][$key]); } // taken from controller public static function loadUIVars($ui, $ui_array) { $new_app = self::getNewApp(); foreach($ui_array as $setting) { if(isset($_GET[$setting])) { if(!$new_app) { $_SESSION[$ui][$setting] = $_GET[$setting]; } else { self::setUISetting($ui, $setting, $_GET[$setting]); } } elseif(self::getUISetting($ui, $setting) !== false) { $_GET[$setting] = self::getUISetting($ui, $setting); } elseif(isset($_SESSION[$ui][$setting])) { $_GET[$setting] = $_SESSION[$ui][$setting]; } } } } // Copyright 2008 Mike Whiting (mail@mikejw.co.uk). // This file is part of the Empathy MVC framework. // Empathy is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Empathy 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 Lesser General Public License for more details. // You should have received a copy of the GNU Lesser General Public License // along with Empathy. If not, see . namespace Empathy\Controller; class front extends CustomController { public function default_event() { // do nothing } } include('Empathy/Empathy.php'); $boot = new Empathy(realpath(dirname(realpath(__FILE__)).'/../'));