<?php
/*
* Phramework Copyright (C) 2005 GodsArmor.com
*
* This library 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 2.1 of the License, or (at your option) any
* later version.
*
* This library 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 this library; if not, write to theFree Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
$config = new PropertiesParser('config.properties');
$arrAlreadyIncluded = array();
// set the config object in globals so anyone can get to it
$GLOBALS["properties"] = $config;
//find other config files and add them to the properties
if ($GLOBALS["properties"]->containsKey('phramework.config.files')) {
$configFiles = $GLOBALS["properties"]->getProperty('phramework.config.files', null, true);
if (is_array($configFiles)) {
foreach($configFiles as $configFile) {
$props = new PropertiesParser($configFile);
$GLOBALS["properties"]->merge($props);
}
} elseif (strlen($configFiles) > 0) {
$props = new PropertiesParser($configFiles);
$GLOBALS["properties"]->merge($props);
}
}
// get the import extenseions and convert to array. Default to .php if no extensions found
$importExtensions = $GLOBALS["properties"]->getProperty('phramework.import.extensions', 'php', true);
// 1. Set the classpath
$GLOBALS["WindowsOS"] = (substr(PHP_OS, 0, 3) == "WIN");
if ($GLOBALS["WindowsOS"]) {
define("INCLUDE_PATH_SEPARATOR", ";");
} else {
define("INCLUDE_PATH_SEPARATOR", ":");
}
$classpath = str_replace('|', INCLUDE_PATH_SEPARATOR, $GLOBALS["properties"]->getProperty('phramework.classpath'));
if (strlen($classpath) > 0) {
ini_set("include_path", ini_get("include_path").INCLUDE_PATH_SEPARATOR.$classpath);
}
// 2. Get the request variable that contains the action class to instantiate. Default to
// 'action' if config parameter not found
$actionKey = $GLOBALS["properties"]->getProperty('phramework.page.identifier', 'action');
$actionClassKey = "default";
if (isset($_REQUEST[$actionKey])) {
$actionClassKey = $_REQUEST[$actionKey];
}
$actionFile = $GLOBALS["properties"]->getProperty("action.$actionClassKey");
// 3. Import the action class
$actionClass = import($actionFile);
if (!is_array($actionClass) && strlen($actionClass) > 0) {
// 4. Instantiate an instance of the class. It must extend the Action class
$action = new $actionClass();
if (is_a($action, 'Action')) {
// 5. Execute the action and get the result. The result should be of type ActionResult
$result = $action->execute();
if (is_a($result, 'ActionResult')) {
$viewMapping = $result->getViewMapping();
//first try to find the view based on the action class key
$viewClassKey = "view.$actionClassKey.$viewMapping";
if ($GLOBALS["properties"]->containsKey($viewClassKey)) {
$viewFile = $GLOBALS["properties"]->getProperty($viewClassKey);
} else {
$viewFile = $GLOBALS["properties"]->getProperty("global.view.$viewMapping");
}
if ($viewFile != null) {
$viewHandlerPlugin = getViewPlugin($viewFile);
if ($viewHandlerPlugin == "") {
$viewClass = import($viewFile);
$view = new $viewClass();
if (is_a($view, 'View')) {
$view->processView($result->getResultData());
} else {
echo "<br/> The view class $viewClass must be a subclass of View.";
}
} else {
$viewClass = import($GLOBALS["properties"]->getProperty($viewHandlerPlugin));
$view = new $viewClass();
if (is_a($view, 'ViewPlugin')) {
$params = getPluginInitParams($viewHandlerPlugin);
$view->init($params);
$view->processView($viewFile, $result->getResultData());
} else {
echo "<br/> The view plugin class $viewClass must be a subclass of ViewPlugin.";
}
}
} else {
echo "<br/> The mapping element $viewClassKey obtained from $actionClass::execute is not a valid mapping to a view.";
}
} else {
echo "<br/> The result from $actionClass::execute must return a result of type ActionResult.";
}
} else {
echo "<br/> The class defined for $actionClassKey ($actionFile) must be a subclass of Action.";
}
} else {
echo "<br/> Wildcards are not allowed for action classes or the class was not defined for action: $actionClassKey ($actionFile).";
}
function getViewPlugin($viewItem) {
$result = "";
//get the extension of this item. note that it could be a PHP class in
//which case the extension should not match any of the available plugins.
$itemExt = substr($viewItem, strrpos($viewItem, ".") + 1);
$configKeys = $GLOBALS["properties"]->getKeys();
foreach ($configKeys as $key) {
$viewPlugin = strpos($key, "viewplugin");
if ($viewPlugin !== false && $viewPlugin == 0 && substr_count($key, ".") == 1) {
//found a plugin. check the extension it handles
$pluginExts = $GLOBALS["properties"]->getProperty("$key.extensions", '', true);
if (isset($pluginExts)) {
if (is_array($pluginExts)) {
foreach ($pluginExts as $pluginExt) {
if (strcasecmp(trim($pluginExt), trim($itemExt)) == 0) {
$result = $key;
return $result;
}
}
} else {
if (strcasecmp(trim($pluginExts), trim($itemExt)) == 0) {
$result = $key;
return $result;
}
}
}
}
}
return $result;
}
function getPluginInitParams($viewHandlerPlugin) {
$configKeys = $GLOBALS["properties"]->getKeys();
$paramsIdent = "$viewHandlerPlugin.initparams.";
$strlen = strlen($paramsIdent);
foreach ($configKeys as $key) {
$param = strpos($key, $paramsIdent);
if ($param !== false && $param == 0) {
$realKey = substr($key, $strlen);
$result[$realKey] = $GLOBALS["properties"]->getProperty($key);
}
}
return isset($result) ? $result : array();
print_r($result);
}
function import($path) {
global $arrAlreadyIncluded;
$result = null;
// get the import extenseions
$importExtensions = $GLOBALS["properties"]->getProperty('phramework.import.extensions', '', true);
if (substr($path, -1) == "*") {
$subpath = str_replace(".", "/", substr($path, 0, strlen($path) - 1));
$arrIncludePath = split(INCLUDE_PATH_SEPARATOR, ini_get("include_path"));
$fullpath = '';
foreach ($arrIncludePath as $includePath) {
if (is_dir("$includePath/$subpath") && $fullpath == '') {
$fullpath = "$includePath/$subpath";
break;
}
}
if ($fullpath != '') {
if ($dh = opendir($fullpath)) {
while (($file = readdir($dh)) !== false) {
if ($file != '.' && $file != '..') {
if (isset($importExtensions)) {
if (is_array($importExtensions)) {
foreach ($importExtensions as $ext) {
$extLen = strlen($ext);
if (substr($file, -1*$extLen, $extLen) == $ext) {
$arrFiles[] = "$fullpath/$file";
$result[] = substr($file, 0, strrpos($file, "."));
}
}
} elseif (strlen($importExtensions) > 0) {
$extLen = strlen($importExtensions);
if (substr($file, -1*$extLen, $extLen) == $importExtensions) {
$arrFiles[] = "$fullpath/$file";
$result[] = substr($file, 0, strrpos($file, "."));
}
}
}
}
}
closedir($dh);
}
}
} else {
$subpath = str_replace(".", "/", $path);
$subdir = substr($subpath, 0, strrpos($subpath, "/"));
$arrIncludePath = split(INCLUDE_PATH_SEPARATOR, ini_get("include_path"));
$fullpath = '';
$finished = false;
foreach ($arrIncludePath as $includePath) {
if (is_dir("$includePath/$subdir")) {
$fullpath = "$includePath/$subpath";
if (isset($importExtensions)) {
if (is_array($importExtensions)) {
foreach ($importExtensions as $ext) {
$file = $fullpath.".".$ext;
if (file_exists($file)) {
$arrFiles[] = $file;
$finished = true;
break;
}
}
} elseif (strlen($importExtensions) > 0) {
$file = $fullpath.".".$importExtensions;
if (file_exists($file)) {
$arrFiles[] = $file;
}
}
}
$result = substr($fullpath, strrpos($fullpath, "/") + 1);
if ($finished) {
break;
}
}
}
}
if (is_array($arrFiles)) {
foreach ($arrFiles as $file) {
if ($GLOBALS["WindowsOS"] && !in_array(strtoupper($file), $arrAlreadyIncluded)) {
/*
* windows is not case sensitive in file names, but require_once is
* meaning it will attempt to include both A.php and a.php which on
* windows is the same file violating the require_once method
* concept. very bad. try to fix that here.
*/
require_once($file);
$arrAlreadyIncluded[] = strtoupper($file);
} elseif (!$GLOBALS["WindowsOS"]) {
require_once($file);
}
}
}
return $result;
}
//All action classes must extend this class and override its execute method
class Action {
function Action() {}
function execute() {}
}
//All actions should return an object of type ActionResult which is then used
//to get the view class
class ActionResult {
var $mapping;
var $data;
function ActionResult($mapping, $data) {
$this->mapping = $mapping;
$this->data = $data;
}
function getViewMapping() {return $this->mapping;}
function getResultData() {return $this->data;}
}
//All view classes must extend this class and override the processView method
class View {
function View() {}
function processView($data) {}
}
//All view plugins must extend this class and override its methods
class ViewPlugin {
function ViewPlugin() {}
function init($params) {/*subclasses implement this*/}
function destroy() {/*sublcasses implement this*/}
function processView($viewValue, $data) {/*subclasses implement this*/}
}
/**
* Parses a java style properties file
*/
class PropertiesParser {
var $arrList;
function PropertiesParser($file) {
if (file_exists($file)) {
$fh = fopen($file, "r");
while (!feof($fh)) {
$buffer = trim(fgets($fh));
if (strlen($buffer) > 0 && substr($buffer, 0, 1) != ';' && strpos($buffer, "=") !== false) {
list($key, $value) = split('=', $buffer, 2);
$this->arrList[$key] = $value;
}
}
fclose($fh);
}
}
function getProperty($key, $default=null, $split=false) {
$result = $default;
if ($this->containsKey($key)) {
$origValue = $this->arrList[$key];
$result = $this->__checkDynamicProperties($this->arrList[$key]);
if ($origValue != $result) {
$this->arrList[$key] = $result;
}
if ($split) {
//pipe separated list. add to properties as array
$result = explode('|', trim($result));
}
}
return $result;
}
function __checkDynamicProperties($value) {
$str = $value;
if (strpos($value, '${') !== false) {
$str = '';
$arr = explode('${', $value);
foreach ($arr as $item) {
$pos = strpos($item, '}');
if ($pos === false) {
$str .= $item;
} else {
list($prop, $static) = explode('}', $item);
$str .= $this->getProperty($prop, '') . $static;
}
}
}
return $str;
}
function containsKey($key) {
return array_key_exists($key, $this->arrList);
}
function getKeys() {
return array_keys($this->arrList);
}
function toString() {
return print_r($this->arrList, true);
}
function toArray() {
return $this->arrList;
}
function merge($propertiesParser) {
if (is_a($propertiesParser, 'PropertiesParser')) {
array_merge($this->arrList, $propertiesParser->toArray());
}
}
}
?>