Added framework from es-matrix
/trunk/View.php |
---|
0,0 → 1,190 |
<?php |
require_once 'Application.php'; |
require_once 'AbstractModel.php'; |
/** |
* A general view handled by a controller according to the MVC pattern |
* |
* @author tlahn |
*/ |
class View |
{ |
/** |
* Default template resource path |
* |
* @var string |
*/ |
protected $_template = ''; |
/** |
* Content that can be inserted in the template |
* |
* @var string |
*/ |
protected $_content = ''; |
/** |
* Template variables. The variable name serves as item key, the item's value |
* is the variable value. |
* |
* @var array |
*/ |
protected $_template_vars = array(); |
/** |
* Creates a new view |
* |
* @param string $template |
* Template resource path |
*/ |
public function __construct($template) |
{ |
$this->_template = $template; |
} |
/** |
* Magic setter method used for defining template variables |
* |
* @param string $name |
* Variable name |
* @param mixed $value |
* Variable value |
*/ |
public function __set($name, $value) |
{ |
$this->_template_vars[$name] = $value; |
} |
/** |
* Magic getter method used for retrieving values of template variables |
* |
* @param string $name |
* Variable name |
*/ |
public function __get($name) |
{ |
return $this->_template_vars[$name]; |
} |
/** |
* Returns <var>$v</var> with occurences of '&' (ampersand), '"' (double quote), |
* "'" (single quote), '<' (less than), and '>' (greater than) replaced by their |
* HTML character entity references, if any, or their numeric HTML character |
* reference (as required primarily in HTML for attribute values and element |
* content). |
* |
* @param mixed $value |
*/ |
public function escape($value) |
{ |
if (is_array($value)) |
{ |
return array_map(array('self', 'escape'), $value); |
} |
else if (is_object($value)) |
{ |
if ($value instanceof AbstractModel) |
{ |
foreach ($value->getPropertyVars() as $varName) |
{ |
$value->$varName = self::escape($value->$varName); |
} |
} |
return $value; |
} |
else |
{ |
if (is_string($value)) |
{ |
$encoding = mb_detect_encoding($value); |
if ($encoding === 'ASCII') |
{ |
$encoding = 'ISO-8859-1'; |
} |
return htmlspecialchars($value, ENT_QUOTES, $encoding); |
} |
return $value; |
} |
} |
/** |
* Assigns a value to a template variable |
* |
* @param string $name |
* Variable name |
* @param mixed $value |
* Variable value |
* @param bool $escape |
* If <code>true</code>, replace all potentially conflicting characters |
* in <var>$value</var> with their HTML entity references. The default is |
* <code>false</code>. |
* @return mixed The assigned value (after possible HTML encoding) |
* @see View::escape() |
*/ |
public function assign($name, $value, $escape = false) |
{ |
if ($escape) |
{ |
$value = $this->escape($value); |
} |
$this->$name = $value; |
return $value; |
} |
/** |
* Renders the view by including a template |
* |
* @param string $template |
* Optional alternative template resource path. |
* If not provided, the default template ($template property) will be used. |
* @throws Exception if no template has been defined before |
*/ |
public function render($template = null, $content = null) |
{ |
if (!is_null($content)) |
{ |
ob_start(); |
require_once $content; |
$this->_content = ob_get_contents(); |
ob_end_clean(); |
} |
if (!is_null($template)) |
{ |
require $template; |
} |
elseif ($this->_template) |
{ |
require $this->_template; |
} |
else |
{ |
throw new Exception('No template defined'); |
} |
} |
/** |
* Returns the content for insertion into the template |
*/ |
public function getContent() |
{ |
return $this->_content; |
} |
/** |
* @param string[optional] $controller |
* @param string[optional] $action |
* @param int[optional] $id |
* @see Application::getURL() |
*/ |
public function getURL($controller = null, $action = null, $id = null) |
{ |
return Application::getInstance()->getURL($controller, $action, $id); |
} |
} |
?> |
/trunk/Db/MySQLDB.php |
---|
0,0 → 1,85 |
<?php |
require_once 'lib/Db/Database.php'; |
class MySQLDB extends Database |
{ |
/** |
* Database host |
* @var string |
*/ |
protected $_host; |
/** |
* Database name |
* @var string |
*/ |
protected $_dbname; |
/** |
* Username to access the database |
* @var string |
*/ |
protected $_username; |
/** |
* Password to access the database |
* @var string |
*/ |
protected $_password; |
/* |
* Optional charset parameter value |
*/ |
protected $_charset = null; |
public function __construct() |
{ |
$this->_dsn = "mysql:host={$this->_host}" |
. (!is_null($this->_dbname) ? ";dbname={$this->_dbname}" : '') |
. (!is_null($this->_charset) ? ";charset={$this->_charset}" : ''); |
if (!is_null($this->_charset)) |
{ |
$this->_options[PDO::MYSQL_ATTR_INIT_COMMAND] = "SET NAMES " . $this->_charset; |
} |
parent::__construct(); |
} |
/** |
* Escapes a database name so that it can be used in a query. |
* |
* @param string $name |
* The name to be escaped |
* @return string |
* The escaped name |
*/ |
public function escapeName($name) |
{ |
return '`' . $name . '`'; |
} |
/** |
* (non-PHPdoc) |
* @see Database::_escapeAliasArray() |
*/ |
protected function _escapeAliasArray(array &$array) |
{ |
foreach ($array as $column => &$value) |
{ |
$value = $value . ' AS `' . $column . '`'; |
} |
return $array; |
} |
/** |
* (non-PHPdoc) |
* @see Database::_escapeValueArray() |
*/ |
protected function _escapeValueArray(array &$array, $suffix = '', array &$escape = array('`', '`')) |
{ |
return parent::_escapeValueArray($array, $suffix, $escape); |
} |
} |
/trunk/Db/ODBCDB.php |
---|
0,0 → 1,53 |
<?php |
require_once 'lib/Db/Database.php'; |
class ODBCDB extends Database |
{ |
/** |
* ODBC alias |
* @var string |
*/ |
protected $_alias; |
public function __construct() |
{ |
$this->_connection = @odbc_connect($this->_alias, "" ,""); |
} |
/** |
* Escapes a database name so that it can be used in a query. |
* |
* @param string $name |
* The name to be escaped |
* @return string |
* The escaped name |
*/ |
public function escapeName($name) |
{ |
return '[' . $name . ']'; |
} |
/** |
* (non-PHPdoc) |
* @see Database::_escapeAliasArray() |
*/ |
protected function _escapeAliasArray(array &$array) |
{ |
foreach ($array as $column => &$value) |
{ |
$value = $value . ' AS [' . $column . ']'; |
} |
return $array; |
} |
/** |
* (non-PHPdoc) |
* @see Database::_escapeValueArray() |
*/ |
protected function _escapeValueArray(array &$array, $suffix = '', array &$escape = array('`', '`')) |
{ |
return parent::_escapeValueArray($array, $suffix, $escape); |
} |
} |
/trunk/Db/Adapter.php |
---|
0,0 → 1,101 |
<?php |
require_once 'lib/Model.php'; |
abstract class Adapter |
{ |
/** |
* Database used by the adapter |
* @var Database |
*/ |
protected $_database = null; |
/** |
* Constructs the adapter, associating a {@link Database} with it |
* @param Database $database |
*/ |
/* Singleton */ |
protected function __construct(Database $database) |
{ |
$this->_database = $database; |
} |
/** |
* Selects data from one or more tables |
* |
* @return array |
* @see Database::select() |
*/ |
public function select($table, $columns = null, $where = null, $order = null, $limit = null) |
{ |
return $this->_database->select($table, $columns, $where, $order, $limit); |
} |
/** |
* Finds all records matching the set properties of a model object |
* |
* @param Model $object |
* @return array[Model] |
*/ |
public function findAll(Model $object, $order = null, $limit = null) |
{ |
$properties = $object->getPropertyVars(); |
$where = array(); |
foreach ($properties as $property) |
{ |
if (!is_null($object->$property)) |
{ |
$where[$property] = $object->$property; |
} |
} |
$class = get_class($object); |
$query_result = $this->select($class::persistentTable, null, $where, $order, $limit); |
$num_results = count($query_result); |
if ($num_results === 0) |
{ |
return null; |
} |
$result = array(); |
foreach ($query_result as $row) |
{ |
$result[] = new $class($row); |
} |
return $result; |
} |
/** |
* Finds the record for a model object by its primary key |
* |
* @param Model $object |
* @return Model |
* The filled object if the primary key value could be found, |
* <code>null</code> otherwise |
*/ |
public function find(Model $object) |
{ |
$class = get_class($object); |
$primaryKey = $class::persistentPrimaryKey; |
if (is_array($primaryKey)) |
{ |
/* TODO */ |
} |
$result = $this->select($class::persistentTable, null, array($primaryKey => $object->$primaryKey)); |
if (0 == count($result)) |
{ |
return null; |
} |
$row = $result[0]; |
$object->map($row); |
return $object; |
} |
} |
/trunk/Db/Database.php |
---|
0,0 → 1,777 |
<?php |
require_once 'lib/global.inc'; |
require_once 'lib/AbstractModel.php'; |
/** |
* Generic database model class using PDO (PHP Data Objects) |
* |
* @property-read array $lastError |
* Last error information of the database operation. |
* See {@link PDOStatement::errorInfo()}. |
* @property-read string $lastInsertId |
* ID of the last inserted row, or the last value from a sequence object, |
* depending on the underlying driver. May not be supported by all databases. |
* @property-read array $lastResult |
* Last result of the database operation |
* @property-read boolean $lastSuccess |
* Last success value of the database operation |
* @author Thomas Lahn |
*/ |
class Database extends AbstractModel |
{ |
/** |
* DSN of the database |
* @var string |
*/ |
protected $_dsn = ''; |
/** |
* Username to access the database |
* @var string |
*/ |
protected $_username; |
/** |
* Password to access the database |
* @var string |
*/ |
protected $_password; |
/** |
* PDO driver-specific options |
* @var array |
*/ |
protected $_options = array(); |
/** |
* Database connection |
* @var PDO |
*/ |
protected $_connection; |
/** |
* Last success value of the database operation |
* @var boolean |
*/ |
protected $_lastSuccess; |
/** |
* Last error information of the database operation |
* @var array |
*/ |
protected $_lastError; |
/** |
* Last result of the database operation |
* @var array |
*/ |
protected $_lastResult; |
/** |
* ID of the last inserted row, or the last value from a sequence object, |
* depending on the underlying driver. May not be supported by all databases. |
* @var string |
*/ |
protected $_lastInsertId = ''; |
public function __construct() |
{ |
$this->_connection = |
new PDO($this->_dsn, $this->_username, $this->_password, $this->_options); |
} |
/** |
* Initiates a transaction |
* |
* @return bool |
* @see PDO::beginTransaction() |
*/ |
public function beginTransaction() |
{ |
return $this->_connection->beginTransaction(); |
} |
/** |
* Rolls back a transaction |
* |
* @return bool |
* @see PDO::rollBack() |
*/ |
public function rollBack() |
{ |
return $this->_connection->rollBack(); |
} |
/** |
* Commits a transaction |
* |
* @return bool |
* @see PDO::commit() |
*/ |
public function commit() |
{ |
return $this->_connection->commit(); |
} |
/** |
* Prepares a statement for execution with the database |
* @param string $query |
*/ |
public function prepare($query, array $driver_options = array()) |
{ |
return $this->_connection->prepare($query, $driver_options); |
} |
/** |
* Returns the ID of the last inserted row, or the last value from |
* a sequence object, depending on the underlying driver. |
* |
* @return int |
*/ |
public function getLastInsertId() |
{ |
return $this->_lastInsertId; |
} |
/** |
* Escapes a database name so that it can be used in a query. |
* |
* @param string $name |
* The name to be escaped |
* @return string |
* The escaped name |
*/ |
public function escapeName($name) |
{ |
return $name; |
} |
/** |
* Determines if an array is associative (has not all integer keys). |
* |
* @author |
* Algorithm courtesy of squirrel, <http://stackoverflow.com/a/5969617/855543>. |
* @param array $a |
* @return boolean |
* <code>true</code> if <var>$a</var> is associative, |
* <code>false</code> otherwise |
*/ |
protected function _isAssociativeArray(array $a) |
{ |
for (reset($a); is_int(key($a)); next($a)); |
return !is_null(key($a)); |
} |
/** |
* Escapes an associative array so that its string representation can be used |
* as list with table or column aliases in a query. |
* |
* This method does not actually escape anything; it only inserts the |
* 'AS' keyword. It should be overridden by inheriting methods. |
* |
* NOTE: This method intentionally does not check whether the array actually |
* is associative. |
* |
* @param array &$array |
* The array to be escaped |
* @return array |
* The escaped array |
*/ |
protected function _escapeAliasArray(array &$array) |
{ |
foreach ($array as $column => &$value) |
{ |
$value = $value . ' AS ' . $column; |
} |
return $array; |
} |
/** |
* @param array $a |
* @param string $prefix |
*/ |
private static function _expand(array $a, $prefix) |
{ |
$a2 = array(); |
foreach ($a as $key => $value) |
{ |
$a2[] = ':' . $prefix . ($key + 1); |
} |
return $a2; |
} |
/** |
* Escapes an associative array so that its string representation can be used |
* as value list in a query. |
* |
* This method should be overridden by inheriting classes to escape |
* column names as fitting for the database schema they support. It is |
* strongly recommended that the overriding methods call this method with |
* an appropriate <var>$escape</var> parameter, pass all other parameters |
* on unchanged, and return its return value. |
* |
* NOTE: Intentionally does not check whether the array actually is associative! |
* |
* @param array &$array |
* The array to be escaped |
* @param string $suffix |
* The string to be appended to the column name for the value placeholder. |
* The default is the empty string. |
* @param array $escape |
* The strings to use left-hand side (index 0) and right-hand side (index 1) |
* of the column name. The default is the empty string, respectively. |
* @return array |
* The escaped array |
*/ |
protected function _escapeValueArray(array &$array, $suffix = '', array &$escape = array('', '')) |
{ |
$result = array(); |
foreach ($array as $column => $value) |
{ |
$op = '='; |
$placeholder = ":{$column}"; |
if (is_array($value) && $this->_isAssociativeArray($value)) |
{ |
reset($value); |
$op = ' ' . key($value) . ' '; |
$value = $value[key($value)]; |
} |
if (is_array($value)) |
{ |
$placeholder = '(' . implode(',', self::_expand($value, $column)) . ')'; |
} |
$result[] = $escape[0] . $column . $escape[1] . "{$op}{$placeholder}{$suffix}"; |
} |
return $result; |
} |
/** |
* Constructs the WHERE part of a query |
* |
* @param string|array $where |
* Condition |
* @param string $suffix |
* The string to be appended to the column name for the value placeholder, |
* passed on to {@link Database::_escapeValueArray()}. The default is |
* the empty string. |
* @return string |
* @see Database::_escapeValueArray() |
*/ |
protected function _where($where, $suffix = '') |
{ |
if (!is_null($where)) |
{ |
if (is_array($where)) |
{ |
if (count($where) < 1) |
{ |
return ''; |
} |
if ($this->_isAssociativeArray($where)) |
{ |
$where = $this->_escapeValueArray($where, $suffix); |
} |
$where = '(' . implode(') AND (', $where) . ')'; |
} |
return ' WHERE ' . $where; |
} |
return ''; |
} |
/** |
* Selects data from one or more tables; the resulting records are stored |
* in the <code>result</code> property and returned as an associative array, |
* where the keys are the column (alias) names. |
* |
* @param string|array[string] $tables Table(s) to select from |
* @param string|array[string] $columns Column(s) to select from (optional) |
* @param string|array $where Condition (optional) |
* @param string $order Sort order (optional) |
* If provided, MUST start with ORDER BY or GROUP BY |
* @param string $limit Limit (optional) |
* @param int $fetch_style |
* The mode that should be used for {@link PDOStatement::fetchAll()}. |
* The default is {@link PDO::FETCH_ASSOC}. |
* @return array |
* @see Database::prepare() |
* @see PDOStatement::fetchAll() |
*/ |
public function select($tables, $columns = null, $where = null, |
$order = null, $limit = null, $fetch_style = PDO::FETCH_ASSOC) |
{ |
if (is_null($columns)) |
{ |
$columns = array('*'); |
} |
if (is_array($columns)) |
{ |
if ($this->_isAssociativeArray($columns)) |
{ |
$columns = $this->_escapeAliasArray($columns); |
} |
$columns = implode(',', $columns); |
} |
if (is_array($tables)) |
{ |
if ($this->_isAssociativeArray($columns)) |
{ |
$columns = $this->_escapeAliasArray($columns); |
} |
$tables = implode(',', $tables); |
} |
$query = "SELECT {$columns} FROM {$tables}" . $this->_where($where); |
if (!is_null($order)) |
{ |
if (is_array($order)) |
{ |
$order = 'ORDER BY ' . implode(',', $order); |
} |
$query .= " $order"; |
} |
if (!is_null($limit)) |
{ |
$query .= " LIMIT $limit"; |
} |
$stmt = $this->prepare($query); |
$params = array(); |
if (is_array($where) && $this->_isAssociativeArray($where)) |
{ |
foreach ($where as $column => $condition) |
{ |
if (is_array($condition) && $this->_isAssociativeArray($condition)) |
{ |
reset($condition); |
$condition = $condition[key($condition)]; |
if (is_array($condition)) |
{ |
foreach (self::_expand($condition, $column) as $param_index => $param_name) |
{ |
$params[$param_name] = $condition[$param_index]; |
} |
} |
} |
else |
{ |
$params[":{$column}"] = $condition; |
} |
} |
} |
/* DEBUG */ |
if (defined('DEBUG') && DEBUG > 1) |
{ |
debug(array( |
'query' => $query, |
'params' => $params |
)); |
} |
$success =& $this->_lastSuccess; |
$success = $stmt->execute($params); |
$errorInfo =& $this->_lastError; |
$errorInfo = $stmt->errorInfo(); |
$result =& $this->_lastResult; |
$result = $stmt->fetchAll($fetch_style); |
if (defined('DEBUG') && DEBUG > 1) |
{ |
debug(array( |
'_lastSuccess' => $success, |
'_lastError' => $errorInfo, |
'_lastResult' => $result |
)); |
} |
return $result; |
} |
/** |
* Sets and returns the ID of the last inserted row, or the last value from |
* a sequence object, depending on the underlying driver. |
* |
* @param string $name |
* Name of the sequence object from which the ID should be returned. |
* @return string |
*/ |
protected function _setLastInsertId($name = null) |
{ |
return ($this->_lastInsertId = $this->_connection->lastInsertId($name)); |
} |
/** |
* Resets the the ID of the last inserted row, or the last value from |
* a sequence object, depending on the underlying driver. |
* |
* @return string |
* The default value |
*/ |
protected function _resetLastInsertId() |
{ |
return ($this->_lastInsertId = ''); |
} |
/** |
* Updates one or more records |
* |
* @param string|array $tables |
* Table name |
* @param array $values |
* Associative array of column-value pairs |
* @param array|string $where |
* Only the records matching this condition are updated |
* @return bool |
*/ |
public function update($tables, $updates, $where = null) |
{ |
if (!$tables) |
{ |
throw new InvalidArgumentException('No table specified'); |
} |
if (is_array($tables)) |
{ |
$tables = implode(',', $tables); |
} |
if (!$updates) |
{ |
throw new InvalidArgumentException('No values specified'); |
} |
$params = array(); |
if ($this->_isAssociativeArray($updates)) |
{ |
foreach ($updates as $key => $condition) |
{ |
$params[":{$key}"] = $condition; |
} |
} |
$updates = implode(',', $this->_escapeValueArray($updates)); |
/* TODO: Should escape table names with escapeName(), but what about aliases? */ |
$query = "UPDATE {$tables} SET {$updates}" . $this->_where($where, '2'); |
$stmt = $this->prepare($query); |
if (is_array($where) && $this->_isAssociativeArray($where)) |
{ |
foreach ($where as $column => $condition) |
{ |
if (is_array($condition) && $this->_isAssociativeArray($condition)) |
{ |
reset($condition); |
$condition = $condition[key($condition)]; |
if (is_array($condition)) |
{ |
foreach (self::_expand($condition, $column) as $param_index => $param_name) |
{ |
$params[$param_name] = $condition[$param_index]; |
} |
} |
} |
else |
{ |
$params[":{$column}2"] = $condition; |
} |
} |
} |
/* DEBUG */ |
if (defined('DEBUG') && DEBUG > 1) |
{ |
debug(array( |
'query' => $query, |
'params' => $params |
)); |
} |
$success =& $this->_lastSuccess; |
$success = $stmt->execute($params); |
$errorInfo =& $this->_lastError; |
$errorInfo = $stmt->errorInfo(); |
$this->_resetLastInsertId(); |
$result =& $this->_lastResult; |
$result = $stmt->fetchAll(); |
if (defined('DEBUG') && DEBUG > 1) |
{ |
debug(array( |
'_lastSuccess' => $success, |
'_lastError' => $errorInfo, |
'_lastResult' => $result |
)); |
} |
return $success; |
} |
/** |
* Inserts a record into a table.<p>The AUTO_INCREMENT value of the inserted |
* row, if any (> 0), is stored in the {@link $lastInsertId} property of |
* the <code>Database</code> instance.</p> |
* |
* @param string $table |
* Table name |
* @param array|string $values |
* Associative array of column-value pairs, indexed array, |
* or comma-separated list of values. If <var>$values</var> is not |
* an associative array, <var>$cols</var> must be passed if the |
* values are not in column order (see below). |
* @param array|string $cols |
* Indexed array, or comma-separated list of column names. |
* Needs only be passed if <var>$values</var> is not an associative array |
* and the values are not in column order (default: <code>null</code>); |
* is ignored otherwise. <strong>You SHOULD NOT rely on column order.</strong> |
* @return bool |
* <code>true</code> if successful, <code>false</code> otherwise |
* @see PDOStatement::execute() |
*/ |
public function insert($table, $values, $cols = null) |
{ |
if ($cols != null) |
{ |
$cols = ' (' |
. (is_array($cols) |
? implode(',', array_map(create_function('$s', 'return "`$s`";'), $cols)) |
: $cols) . ')'; |
} |
else |
{ |
$cols = ''; |
} |
/* DEBUG */ |
if (defined('DEBUG') && DEBUG > 2) |
{ |
debug(array('values' => $values)); |
} |
$params = array(); |
if (is_array($values)) |
{ |
if ($this->_isAssociativeArray($values)) |
{ |
foreach ($values as $key => $condition) |
{ |
$params[":{$key}"] = $condition; |
} |
$values = $this->_escapeValueArray($values); |
$cols = ''; |
$values = 'SET ' . implode(', ', $values); |
} |
else |
{ |
foreach ($values as &$value) |
{ |
if (is_string($value)) |
{ |
$value = "'" . $value . "'"; |
} |
} |
$values = ' VALUES (' . implode(', ', $values) . ')'; |
} |
} |
/* TODO: Should escape table names with escapeName(), but what about aliases? */ |
$query = "INSERT INTO {$table} {$cols} {$values}"; |
$stmt = $this->prepare($query); |
/* DEBUG */ |
if (defined('DEBUG') && DEBUG > 1) |
{ |
debug(array( |
'query' => $query, |
'params' => $params |
)); |
} |
$success =& $this->_lastSuccess; |
$success = $stmt->execute($params); |
$errorInfo =& $this->_lastError; |
$errorInfo = $stmt->errorInfo(); |
$this->_setLastInsertId(); |
$result =& $this->_lastResult; |
$result = $stmt->fetchAll(); |
if (defined('DEBUG') && DEBUG > 1) |
{ |
debug(array( |
'_lastSuccess' => $success, |
'_lastError' => $errorInfo, |
'_lastInsertId' => $this->_lastInsertId, |
'_lastResult' => $result |
)); |
} |
return $success; |
} |
/** |
* Retrieves all rows from a table |
* |
* @param int[optional] $fetch_style |
* @param int[optional] $column_index |
* @param array[optional] $ctor_args |
* @return array |
* @see PDOStatement::fetchAll() |
*/ |
public function fetchAll($table, $fetch_style = null, $column_index = null, array $ctor_args = null) |
{ |
/* NOTE: Cannot use table name as statement parameter */ |
$stmt = $this->prepare("SELECT * FROM $table"); |
$this->_lastSuccess = $stmt->execute(); |
$this->_lastError = $stmt->errorInfo(); |
$result =& $this->_lastResult; |
if (is_null($fetch_style)) |
{ |
$fetch_style = PDO::FETCH_ASSOC; |
} |
if (!is_null($ctor_args)) |
{ |
$result = $stmt->fetchAll($fetch_style, $column_index, $ctor_args); |
} |
else if (!is_null($column_index)) |
{ |
$result = $stmt->fetchAll($fetch_style, $column_index); |
} |
else if (!is_null($fetch_style)) |
{ |
$result = $stmt->fetchAll($fetch_style); |
} |
else |
{ |
$result = $stmt->fetchAll(); |
} |
return $result; |
} |
/** |
* Deletes one or more records |
* |
* @param string|array $tables |
* Table name(s) |
* @param array|string $where |
* Only the records matching this condition are deleted |
* @return bool |
* @see PDOStatement::execute() |
*/ |
public function delete($tables, $where = null) |
{ |
if (!$tables) |
{ |
throw new InvalidArgumentException('No table specified'); |
} |
if (is_array($tables)) |
{ |
$tables = implode(',', $tables); |
} |
$params = array(); |
$query = "DELETE FROM {$tables}" . $this->_where($where); |
$stmt = $this->prepare($query); |
if ($this->_isAssociativeArray($where)) |
{ |
foreach ($where as $column => $condition) |
{ |
if (is_array($condition) && $this->_isAssociativeArray($condition)) |
{ |
reset($condition); |
$condition = $condition[key($condition)]; |
if (is_array($condition)) |
{ |
foreach (self::_expand($condition, $column) as $param_index => $param_name) |
{ |
$params[$param_name] = $condition[$param_index]; |
} |
} |
} |
else |
{ |
$params[":{$column}"] = $condition; |
} |
} |
} |
/* DEBUG */ |
if (defined('DEBUG') && DEBUG > 1) |
{ |
debug(array( |
'query' => $query, |
'params' => $params |
)); |
} |
$success =& $this->_lastSuccess; |
$success = $stmt->execute($params); |
$result =& $this->_lastResult; |
$result = $stmt->fetchAll(); |
$errorInfo =& $this->_lastError; |
$errorInfo = $stmt->errorInfo(); |
if (defined('DEBUG') && DEBUG > 1) |
{ |
debug(array( |
'_lastSuccess' => $success, |
'_lastError' => $errorInfo, |
'_lastResult' => $result |
)); |
} |
return $success; |
} |
} |
/trunk/Db/Mapper.php |
---|
0,0 → 1,88 |
<?php |
require_once 'lib/Db/Table.php'; |
/** |
* Generic abstract database mapper class |
* |
* @author Thomas Lahn |
*/ |
abstract class Mapper |
{ |
/** |
* Class name of the associated table model |
* |
* @var string |
*/ |
protected $_table = 'Table'; |
protected $_dbTable; |
/** |
* Sets the {@link Table} for this mapper |
* @param string|Table $dbTable |
* Class name of the new instance, or an existing instance |
* @throws Exception if <var>$dbTable</var> is not a <code>Table</code> |
*/ |
public function setDbTable($table) |
{ |
if (is_string($table)) |
{ |
$table = new $table(); |
} |
if (!($table instanceof Table)) { |
throw new Exception('Invalid table data gateway provided'); |
} |
$this->_dbTable = $table; |
} |
/** |
* Gets the {@link Table} for this mapper |
* |
* @param string|Table $table |
* Class name of the new instance or an existing instance. |
* The default is the value of the <code>$_table</code> property. |
* @return Table |
* @throws Exception if <var>$dbTable</var> is not a <code>Table</code> |
* @see Mapper::setDbTable() |
*/ |
public function getDbTable($table = null) |
{ |
if (is_null($this->_dbTable)) |
{ |
if (is_null($table)) |
{ |
$table = $this->_table; |
} |
$this->setDbTable($table); |
} |
return $this->_dbTable; |
} |
/** |
* Sorts an array of objects by the property of the nested object. |
* To be used with the u*sort() functions. |
* |
* @param object $a First operand of the comparison |
* @param object $b Second operand of the comparison |
* @param string $property |
* Name of the property of the nested object by which to sort the outer array |
* @return int |
* 0 if <var>$a</var> and <var>$b</var> are "equal", |
* <code>-1</code> if <var>$a</var> is "less" than <var>$b</var>, |
* <code>1</code> otherwise. |
*/ |
protected static function sortByProperty($a, $b, $property) |
{ |
if ($a->$property === $b->$property) |
{ |
return 0; |
} |
return ($a->$property < $b->$property) ? -1 : 1; |
} |
} |
/trunk/Db/MySQLAdapter.php |
---|
0,0 → 1,17 |
<?php |
require_once 'lib/Db/Adapter.php'; |
require_once 'lib/Db/MySQLDB.php'; |
class MySQLAdapter extends Adapter |
{ |
/** |
* Constructs the adapter, associating a {@link MySQLDB} with it |
* @param MySQLDB $database |
*/ |
/* Singleton */ |
protected function __construct(MySQLDB $database) |
{ |
parent::__construct($database); |
} |
} |
/trunk/Db/Table.php |
---|
0,0 → 1,198 |
<?php |
require_once 'lib/AbstractModel.php'; |
/** |
* Generic database table model class |
* |
* @author Thomas Lahn |
* @property-read int $lastInsertId |
* ID of the last inserted row, or the last value from |
a sequence object, depending on the underlying driver. |
*/ |
abstract class Table extends AbstractModel |
{ |
/** |
* Name of the table |
*/ |
protected $_name = ''; |
/** |
* Database of the table |
* @var Database |
*/ |
protected $_database; |
protected $_id = 'id'; |
public function __construct() |
{ |
$this->_database = Application::getInstance()->getDefaultDatabase(); |
} |
/** |
* Returns the database for the table |
* @return Database |
*/ |
public function getDatabase() |
{ |
return $this->_database; |
} |
/** |
* Initiates a transaction |
* |
* @return bool |
* @see Database::beginTransaction() |
*/ |
public function beginTransaction() |
{ |
return $this->_database->beginTransaction(); |
} |
/** |
* Rolls back a transaction |
* |
* @return bool |
* @see Database::rollBack() |
*/ |
public function rollBack() |
{ |
return $this->_database->rollBack(); |
} |
/** |
* Commits a transaction |
* |
* @return bool |
* @see Database::commit() |
*/ |
public function commit() |
{ |
return $this->_database->commit(); |
} |
/** |
* Retrieves all rows from the table |
* |
* @return array |
* @see Database::fetchAll() |
*/ |
public function fetchAll($fetch_style = null, $column_index = null, array $ctor_args = null) |
{ |
return $this->_database->fetchAll($this->_name, $fetch_style, $column_index, $ctor_args); |
} |
/** |
* Selects data from one or more tables |
* |
* @return array |
* @see Database::select() |
*/ |
public function select($columns = null, $where = null, $order = null, $limit = null) |
{ |
return $this->_database->select($this->_name, $columns, $where, $order, $limit); |
} |
/** |
* Updates records in one or more tables |
* |
* @return bool |
* @see Database::update() |
*/ |
public function update($data, $condition) |
{ |
return $this->_database->update($this->_name, $data, $condition); |
} |
/** |
* Inserts a record into the table |
* |
* @return bool |
* @see Database::insert() |
*/ |
public function insert($data, $cols = null) |
{ |
return $this->_database->insert($this->_name, $data, $cols); |
} |
/** |
* Returns the ID of the last inserted row, or the last value from |
* a sequence object, depending on the underlying driver. |
* |
* @return int |
* @see Database::getLastInsertId() |
*/ |
public function getLastInsertId() |
{ |
return $this->_database->lastInsertId; |
} |
/** |
* Delete a record from the table |
* |
* @param int $id |
* ID of the record to delete. May be <code>null</code>, |
* in which case <var>$condition</var> must specify |
* the records to be deleted. |
* @param array[optional] $condition |
* Conditions that must be met for a record to be deleted. |
* Ignored if <var>$id</var> is not <code>null</code>. |
* @return bool |
* @throws InvalidArgumentException if both <var>$id</var> and |
* <var>$condition</var> are <code>null</code>. |
* @see Database::delete() |
*/ |
public function delete($id, array $condition = null) |
{ |
if (!is_null($id)) |
{ |
$condition = array($this->_id => $id); |
} |
else if (is_null($condition)) |
{ |
throw new InvalidArgumentException( |
'$id and $condition cannot both be null'); |
} |
return $this->_database->delete($this->_name, $condition); |
} |
/** |
* Inserts a row into the table or updates an existing one |
* |
* @param array $data |
* Associative array of column-value pairs to be updated/inserted |
* @param string|array $condition |
* If there are no records matching this condition, a row will be inserted; |
* otherwise matching records are updated |
* @return bool |
* @see Table::update() |
* @see Table::insert() |
*/ |
public function updateOrInsert($data, array $condition = null) |
{ |
if ($this->select($this->_id, $condition)) |
{ |
return $this->update($data, $condition); |
} |
return $this->insert($data); |
} |
/** |
* Finds a record by ID |
* |
* @param mixed $id |
*/ |
public function find($id) |
{ |
/* DEBUG */ |
if (defined('DEBUG') && DEBUG > 0) |
{ |
debug($id); |
} |
return $this->select(null, array($this->_id => $id)); |
} |
} |
/trunk/Db/database.class.php |
---|
0,0 → 1,527 |
<?php |
require_once 'global.inc'; |
/* NOTE: Obsolete with autoloader */ |
//require_once 'Zend/Registry.php'; |
//require_once 'Zend/Db/Table.php'; |
/** |
* @property-read array $lastId The last generated ID |
* @property-read array $result The result of the last query |
* |
* @author rvejseli, tlahn |
*/ |
class Database |
{ |
private $db_host = DB_HOST; |
private $db_user = DB_USER; |
private $db_pass = DB_PASS; |
private $db_name = DB_NAME; |
private $connection = false; |
private $_result = array(); |
/** |
* The last inserted ID |
* |
* @var int |
*/ |
private $_lastId; |
/* Anlegen der Instanz */ |
private static $instance = NULL; |
/* Konstruktor private, damit die Klasse nur aus sich selbst heraus instanziiert werden kann. */ |
private function __construct() |
{ |
$this->connect(); |
$this->_resetLastID(); |
} |
/** |
* Returns a singleton Database instance |
* @return Database |
*/ |
public static function getInstance() |
{ |
if (self::$instance === NULL) |
{ |
self::$instance = new self; |
} |
return self::$instance; |
} |
/* Klonen per 'clone()' von aussen verbieten. */ |
private function __clone() {} |
/** |
* Universal getter |
* |
* @param string $name |
*/ |
public function __get($name) |
{ |
switch ($name) |
{ |
case 'lastId': |
case 'result': |
return $this->{"_$name"}; |
} |
} |
/** |
* Connects to the Database |
*/ |
public function connect() |
{ |
if (!$this->connection) |
{ |
$myconn = @mysql_connect($this->db_host, $this->db_user, $this->db_pass); |
if ($myconn) |
{ |
$seldb = @mysql_select_db($this->db_name, $myconn); |
if ($seldb) |
{ |
$this->connection = true; |
return true; |
} |
else |
{ |
return false; |
} |
} |
else |
{ |
return false; |
} |
} |
else |
{ |
return true; |
} |
} |
/** |
* Resets the last ID to a default value, indicating that no rows where inserted |
*/ |
private function _resetLastID() |
{ |
$this->_lastId = -1; |
} |
public function setDatabase($name) |
{ |
if ($this->connection) |
{ |
if (@mysql_close()) |
{ |
$this->connection = false; |
$this->_result = null; |
$this->db_name = $name; |
$this->connect(); |
} |
} |
} |
/** |
* Makes an encoding-safe database query |
* |
* @param string $query |
* @param string encoding |
* The encoding in which the query result should be returned from the DBMS. |
* The default is 'utf8'. |
* @return resource|null |
* The query result if successful, <code>null</code> otherwise |
*/ |
private function _query($query, $encoding = 'utf8') |
{ |
$this->_resetLastID(); |
if (mysql_query("SET CHARACTER SET $encoding")) |
{ |
if (DEBUG > 1) |
{ |
echo "<pre>$query</pre>"; |
} |
return @mysql_query($query); |
} |
else |
{ |
/* DEBUG */ |
echo mysql_errno() . ':' . mysql_error(); |
exit; |
} |
return null; |
} |
private function _tableExists($table) |
{ |
$tablesInDb = $this->_query("SHOW TABLES FROM {$this->db_name} LIKE '{$table}'"); |
if ($tablesInDb) |
{ |
if (mysql_num_rows($tablesInDb) == 1) |
{ |
return true; |
} |
else |
{ |
return false; |
} |
} |
} |
/** |
* Determines if an array is associative (does not have a '0' key) |
* |
* @param array $a |
* @return boolean |
* <code>true</code> if <var>$a</var> is associative, |
* <code>false</code> otherwise |
*/ |
private function _isAssociativeArray(array $a) |
{ |
return !array_key_exists(0, $a); |
} |
/** |
* Escapes an associative array so that its string representation can be used |
* in a query. |
* |
* NOTE: Intentionally does not check whether the array actually is associative! |
* |
* @param array &$array |
* The array to be escaped |
* @return array |
* The escaped array |
*/ |
private function _escapeArray(array &$array) |
{ |
foreach ($array as $column => &$value) |
{ |
if (is_string($value)) |
{ |
$value = mysql_real_escape_string($value); |
} |
$value = "`" . mysql_real_escape_string($column) . "`='{$value}'"; |
} |
return $array; |
} |
/** |
* Constructs the WHERE part of a query |
* |
* @param string|array $where Condition |
* @return string |
*/ |
private function _where($where) |
{ |
if (!is_null($where)) |
{ |
if (is_array($where)) |
{ |
if (count($where) < 1) |
{ |
return ''; |
} |
if ($this->_isAssociativeArray($where)) |
{ |
$this->_escapeArray($where); |
} |
$where = '(' . join(') AND (', $where) . ')'; |
} |
return ' WHERE ' . $where; |
} |
return ''; |
} |
/** |
* Selects data from one or more tables; the resulting records are stored |
* in the <code>result</code> property. |
* |
* @param string|array[string] $tables Table(s) to select from |
* @param string|array[string] $columns Column(s) to select from (optional) |
* @param string|array $where Condition (optional) |
* @param string $order Sort order (optional) |
* @param string $limit Limit (optional) |
* @return bool |
* @throws <code>Exception</code> if the query fails |
*/ |
public function select($tables, $columns = null, $where = null, $order = null, $limit = null) |
{ |
$this->_result = array(); |
if (is_null($columns)) |
{ |
$columns = array('*'); |
} |
if (!is_array($columns)) |
{ |
$columns = array($columns); |
} |
$columns = join(',', $columns); |
if (!is_array($tables)) |
{ |
$tables = array($tables); |
} |
$tables = join(',', $tables); |
$q = "SELECT $columns FROM $tables" . $this->_where($where); |
if (!is_null($order)) |
{ |
$q .= " ORDER BY $order"; |
} |
if (!is_null($limit)) |
{ |
$q .= " LIMIT $limit"; |
} |
if (DEBUG > 1) |
{ |
echo "<pre>$q</pre>"; |
} |
/* DEBUG */ |
// debug($q); |
$_result = $this->_query($q); |
if ($_result) |
{ |
$this->numResults = mysql_num_rows($_result); |
for ($i = 0, $len = $this->numResults; $i < $len; ++$i) |
{ |
$_results = mysql_fetch_array($_result); |
/* DEBUG */ |
// debug($_results); |
$keys = array_keys($_results); |
foreach ($keys as $key) |
{ |
if (!is_int($key)) |
{ |
if (mysql_num_rows($_result) > 0) |
{ |
$this->_result[$i][$key] = $_results[$key]; |
} |
else if (mysql_num_rows($_result) < 1) |
{ |
$this->_result = null; |
} |
} |
} |
} |
return $q; |
} |
else |
{ |
throw new Exception(mysql_error() . ". Query: " . $q); |
} |
} |
/** |
* Inserts a record into a table.<p>The AUTO_INCREMENT value of the inserted |
* row, if any (> 0), is stored in the {@link $lastId} property of |
* the <code>Database</code> instance.</p> |
* |
* @param string $table |
* Table name |
* @param array|string $values |
* Associative array of column-value pairs, indexed array, |
* or comma-separated list of values. If <var>$values</var> is not |
* an associative array, <var>$cols</var> must be passed if the |
* values are not in column order (see below). |
* @param array|string $cols |
* Indexed array, or comma-separated list of column names. |
* Needs only be passed if <var>$values</var> is not an associative array |
* and the values are not in column order (default: <code>null</code>); |
* is ignored otherwise. <strong>You SHOULD NOT rely on column order.</strong> |
* @return bool |
* <code>true</code> if successful, <code>false</code> otherwise |
*/ |
public function insert($table, $values, $cols = null) |
{ |
if ($cols != null) |
{ |
$cols = ' (' |
. (is_array($cols) |
? join(',', array_map(create_function('$s', 'return "`$s`";'), $cols)) |
: $cols) . ')'; |
} |
else |
{ |
$cols = ''; |
} |
/* DEBUG */ |
// debug($values); |
if ($this->_isAssociativeArray($values)) |
{ |
$this->_escapeArray($values); |
$cols = ''; |
$values = 'SET ' . join(', ', $values); |
} |
else |
{ |
foreach ($values as &$value) |
{ |
if (is_string($value)) |
{ |
$value = "'" . mysql_real_escape_string($value) . "'"; |
} |
} |
$values = ' VALUES (' . join(', ', $values) . ')'; |
} |
$insert = "INSERT INTO `{$table}` {$cols} {$values}"; |
/* DEBUG */ |
// echo "Insert:<br>"; |
// debug($insert); |
$ins = $this->_query($insert); |
$this->_lastId = mysql_insert_id(); |
if ($ins) |
{ |
return true; |
} |
else |
{ |
return false; |
} |
} |
/** |
* Deletes records from a table |
* |
* @param string $table |
* @param string|array|null $where Condition for deletion |
* @return bool |
*/ |
public function delete($table, $where = null) |
{ |
$delete = "DELETE FROM `{$table}`" . $this->_where($where); |
/* DEBUG */ |
// debug($delete); |
// $result = true; |
$result = $this->_query($delete); |
return ($result) ? true : false; |
} |
/** |
* Updates one or more records |
* |
* @param string|array $tables |
* Table name |
* @param array $values |
* Associative array of column-value pairs |
* @param array|string $where |
* Only the records matching this condition are updated |
* @return string|bool |
*/ |
public function update($tables, $updates, $where = null) |
{ |
if (!$tables) |
{ |
throw new InvalidArgumentException('No table specified'); |
} |
if (is_array($tables)) |
{ |
$tables = join(',', $tables); |
} |
if (!$updates) |
{ |
throw new InvalidArgumentException('No values specified'); |
} |
$updates = join(',', $this->_escapeArray($updates)); |
$query = "UPDATE {$tables} SET {$updates}" . $this->_where($where); |
/* DEBUG */ |
// echo "Update:<br>"; |
// debug($query); |
$_result = $this->_query($query); |
if (!$_result) |
{ |
//debug(mysql_error()); |
return false; |
} |
return $query; |
} |
/** |
* Inserts a row into a table or updates an existing one |
* |
* @param string $sTable |
* Table name |
* @param array $aValues |
* Associative array of column-value pairs to be updated/inserted |
* @param string|array $condition |
* If there are no records matching this condition, a row will be inserted; |
* otherwise matching records are updated |
* @return mixed |
*/ |
public function updateOrInsert($sTable, $aValues, $condition) |
{ |
$result = $this->select($sTable, '*', $condition); |
if (!$result) |
{ |
exit; |
} |
// debug($this->result); |
if (count($this->result) > 0) |
{ |
$result = $this->update($sTable, $aValues, $condition); |
} |
else |
{ |
$result = $this->insert($sTable, $aValues); |
} |
return $result; |
} |
/** |
* @see Database::updateOrInsert() |
*/ |
public function insertOrUpdate($sTable, $aValues, $condition) |
{ |
return $this->updateOrInsert($sTable, $aValues, $condition); |
} |
public function getResult() |
{ |
return $this->result; |
} |
} |
?> |
/trunk/Model.php |
---|
0,0 → 1,44 |
<?php |
/** |
* Abstract model class |
* |
* Provides basic setters and getters for protected/private properties |
* and a constructor to initialize properties using setters and getters. |
* |
* @author Thomas Lahn |
*/ |
abstract class Model extends AbstractModel |
{ |
/* ORM */ |
const persistentPrimaryKey = 'id'; |
/** |
* @var Adapter |
*/ |
protected static $persistentAdapter; |
/** |
* Creates a new model object |
* |
* @param array $data Initialization data (optional) |
* @param array $mapping Mapping for initialization data (optional) |
*/ |
public function __construct(array $data = null, array $mapping = null) |
{ |
$this->setAdapter(); |
parent::__construct($data, $mapping); |
} |
/** |
* Finds the record for the model object in a database, and fills the object |
* with missing data |
* @see Adapter::find(Model) |
*/ |
public function find() |
{ |
$class = get_class($this); |
return $class::$persistentAdapter->find($this); |
} |
} |
/trunk/Application.php |
---|
0,0 → 1,288 |
<?php |
require_once 'lib/AbstractModel.php'; |
require_once 'lib/Registry.php'; |
/** |
* Basic application class |
* |
* @author Thomas Lahn |
*/ |
class Application |
{ |
/** |
* Relative path to the controllers directory |
* @var string |
*/ |
protected $_controllerPath = 'application/controllers'; |
/** |
* Default controller of the application |
* @var string |
*/ |
protected $_defaultController = 'Index'; |
/** |
* Registry key for the default database of the application |
* @var string |
*/ |
protected $_defaultDatabase; |
/** |
* Currently active controller of this application |
* @var Controller |
*/ |
protected $_currentController; |
/** |
* Singleton |
* |
* @var Application |
*/ |
private static $_instance; |
protected function __construct() |
{ |
/* Singleton pattern */ |
} |
/** |
* Gets a reference to the <code>Application</code> instance |
* |
* @param Application $instance |
* The instance to be used as application. The default is a new |
* application. This parameter is ignored if the application was |
* already initialized. |
* @return Application |
*/ |
public static function getInstance(Application $instance = null) |
{ |
if (is_null(self::$_instance)) |
{ |
self::$_instance = ($instance === null) ? new self() : $instance; |
} |
return self::$_instance; |
} |
/** |
* Getter for properties |
* |
* @param string $name |
* @throws ModelPropertyException |
* @return mixed |
*/ |
public function __get($name) |
{ |
/* Support for Object-Relational Mappers */ |
if (strpos($name, 'persistent') === 0) |
{ |
$class = get_class($this); |
return $class::${ |
$name}; |
} |
$method = 'get' . ucfirst($name); |
if (method_exists($this, $method)) |
{ |
return $this->$method(); |
} |
if (property_exists($this, "_$name")) |
{ |
return $this->{"_$name"}; |
} |
return $this->$name; |
} |
/** |
* Setter for properties |
* |
* @param string $name |
* @param mixed $value The new property value before assignment |
* @throws ModelPropertyException |
*/ |
public function __set($name, $value) |
{ |
$method = 'set' . ucfirst($name); |
if (method_exists($this, $method)) |
{ |
return $this->$method($value); |
} |
if (property_exists($this, "_$name")) |
{ |
$this->{"_$name"} = $value; |
return $this->{"_$name"}; |
} |
/* NOTE: Attempts to set other properties are _silently_ _ignored_ */ |
} |
/** |
* Runs the application, setting up session management and |
* constructing the controller indicated by the URI |
*/ |
public function run() |
{ |
$this->startSession(); |
$controller = self::getParam('controller', $_REQUEST); |
if (!$controller) |
{ |
$controller = $this->_defaultController; |
} |
$controller = ucfirst($controller); |
$controller = $controller . 'Controller'; |
require_once "{$this->_controllerPath}/{$controller}.php"; |
$this->_currentController = new $controller(); |
return $this; |
} |
protected function startSession() |
{ |
session_start(); |
} |
/** |
* Gets a request parameter |
* |
* @param string $key |
* Key to look up in the array |
* @param array $array |
* Array where to look up <var>$key</var>. |
* The default is <code>$_GET</code>. |
* @return mixed |
* <code>null</code> if there is no such <var>$key</var> |
* in <var>$array</var> |
*/ |
public static function getParam($key, array $array = null) |
{ |
if (is_null($array)) |
{ |
$array = $_GET; |
} |
return isset($array[$key]) ? $array[$key] : null; |
} |
/** |
* Registers a database |
* |
* @param string $key |
* @param Database $database |
*/ |
public function registerDatabase($key, Database $database) |
{ |
Registry::set($key, $database); |
} |
/** |
* Sets the default database |
* @param key Registry key to refer to the {@link Database} |
*/ |
public function setDefaultDatabase($key) |
{ |
$this->_defaultDatabase = $key; |
} |
/** |
* Sets the current controller for this application |
* |
* @param Controller $controller |
* @return Application |
*/ |
public function setCurrentController(Controller $controller) |
{ |
$this->_currentController = $controller; |
return $this; |
} |
/** |
* Returns the current controller for this application |
* |
* @return Controller |
*/ |
public function getCurrentController() |
{ |
return $this->_currentController; |
} |
/** |
* Returns the default database for this application |
* |
* @return Database |
*/ |
public function getDefaultDatabase() |
{ |
return Registry::get($this->_defaultDatabase); |
} |
/** |
* Returns a relative URI reference for an action of the |
* application |
* |
* @param string[optional] $controller |
* @param string[optional] $action |
* @param int[optional] $id |
*/ |
public function getURL($controller = null, $action = null, $id = null) |
{ |
/* Apache module */ |
$url = self::getParam('SCRIPT_URL', $_SERVER); |
if ($url === null) |
{ |
/* FastCGI */ |
$url = self::getParam('URL', $_SERVER); |
if ($url === null) |
{ |
throw new Exception( |
'Neither $_SERVER["SCRIPT_URL"] nor $_SERVER["URL"] is available, cannot continue.'); |
} |
} |
$query = (!is_null($controller) ? 'controller=' . $controller : '') |
. (!is_null($action) ? '&action=' . $action : '') |
. (!is_null($id) ? '&id=' . $id : ''); |
return $url . ($query ? '?' . $query : ''); |
} |
/** |
* Performs a server-side redirect within the application |
*/ |
public static function redirect($query = '') |
{ |
$script_uri = self::getParam('SCRIPT_URI', $_SERVER); |
if (is_null($script_uri)) |
{ |
/* Server/PHP too old, compute URI */ |
if (preg_match('/^[^?]+/', |
self::getParam('REQUEST_URI', $_SERVER), $matches) > 0) |
{ |
$query_prefix = $matches[0]; |
} |
else |
{ |
/* Has .php in it, but at least it works */ |
$query_prefix = self::getParam('SCRIPT_NAME', $_SERVER); |
} |
/* TODO: Let user decide which ports map to which URI scheme */ |
$script_uri = (self::getParam('SERVER_PORT', $_SERVER) == 443 |
? 'https://' |
: 'http://') |
. self::getParam('HTTP_HOST', $_SERVER) |
. $query_prefix; |
} |
header('Location: ' . $script_uri |
. ($query ? (substr($query, 0, 1) === '?' ? '' : '?') . $query : '')); |
} |
} |
/trunk/Controller.php |
---|
0,0 → 1,112 |
<?php |
require_once 'lib/Application.php'; |
require_once 'lib/View.php'; |
/* lcfirst() is unavailable before PHP 5.3 */ |
if (false === function_exists('lcfirst')) |
{ |
/** |
* Make a string's first character lowercase |
* |
* @param string $str The input string. |
* @return string The resulting string. |
* @link http://www.php.net/manual/en/function.lcfirst.php |
*/ |
function lcfirst($str) |
{ |
return strtolower(substr($str, 0, 1)) . substr($str, 1); |
} |
} |
/** |
* A general controller that can handle views according to |
* the MVC pattern |
* |
* @author tlahn |
*/ |
abstract class Controller |
{ |
/** |
* Default action of the controller |
* @var string |
*/ |
protected $_defaultAction = 'index'; |
/** |
* The {@link View} used by this controller |
* |
* @var View |
*/ |
protected $_view = null; |
/** |
* Constructs a controller, initializes the related view, |
* and calls the controller's URI-indicated action method. |
* |
* @param string $viewClass |
* View class. The default is <code>'View'</code>. |
* @param string $template |
* Resource path of the template for the view. The default |
* is the empty string. |
*/ |
protected function __construct($viewClass = 'View', |
$template = null) |
{ |
$this->_view = new $viewClass($template); |
Application::getInstance()->setCurrentController($this); |
$action = Application::getParam('action', $_REQUEST); |
/* NOTE: No `==='; treat empty action like no specific action */ |
if ($action == null) |
{ |
$action = $this->_defaultAction; |
} |
$this->{lcfirst($action) . 'Action'}(); |
} |
/** |
* Assigns a value to a template variable (after this, |
* <var>$value</var> is available through |
* <code>$this-><var>$name</var></code> in the view's template). |
* <code>Controller</code>s should call this method instead of |
* {@link View::assign()}. |
* |
* @param string $name |
* Variable name |
* @param mixed $value |
* Variable value |
* @param bool $encodeHTML |
* If <code>true</code>, replace all potentially conflicting |
* characters in <var>$value</var> with their HTML entity |
* references. The default is <code>false</code>. |
* @return mixed The assigned value (after possible HTML encoding) |
* @see View::encodeHTML() |
*/ |
protected function assign($name, $value, $encodeHTML = false) |
{ |
return $this->_view->assign($name, $value, $encodeHTML); |
} |
/** |
* Renders the {@link View} associated with this controller |
* by including the <code>View</code>'s template. |
* <code>Controller</code>s should call this method instead of |
* <code>View::render()</code>. |
* |
* @param string $template |
* Optional alternative template resource path. |
* If not provided, the default template (the |
* <code>View</code>'s <code>$template</code> property) |
* will be used. |
*/ |
public function render($template = null, $content = null) |
{ |
$this->_view->render($template, $content); |
} |
} |
?> |
/trunk/AbstractModel.php |
---|
0,0 → 1,192 |
<?php |
/** |
* Interface to be implemented if the model should be localizable |
*/ |
interface ILocalizable |
{ |
/** |
* Localizes this model. The actual implementation is left to the model class |
* implementing this interface. |
*/ |
function localize(); |
} |
/** |
* Abstract model class |
* |
* Provides basic setters and getters for protected/private properties |
* and a constructor to initialize properties using setters and getters. |
* |
* @author Thomas Lahn |
*/ |
abstract class AbstractModel |
{ |
/** |
* Creates a new model object |
* |
* @param array $data Initialization data (optional) |
* @param array $mapping Mapping for initialization data (optional) |
*/ |
public function __construct(array $data = null, array $mapping = null) |
{ |
if (!is_null($data)) |
{ |
$this->map($data, $mapping); |
} |
} |
/** |
* Getter for properties |
* |
* @param string $name |
* @throws ModelPropertyException |
* @return mixed |
*/ |
public function __get($name) |
{ |
/* Support for Object-Relational Mappers */ |
if (strpos($name, 'persistent') === 0) |
{ |
$class = get_class($this); |
return $class::${$name}; |
} |
$method = 'get' . ucfirst($name); |
if (method_exists($this, $method)) |
{ |
return $this->$method(); |
} |
if (property_exists($this, "_$name")) |
{ |
return $this->{"_$name"}; |
} |
return $this->$name; |
} |
/** |
* Setter for properties |
* |
* @param string $name |
* @param mixed $value The new property value before assignment |
* @throws ModelPropertyException |
*/ |
public function __set($name, $value) |
{ |
$method = 'set' . ucfirst($name); |
if (method_exists($this, $method)) |
{ |
return $this->$method($value); |
} |
if (property_exists($this, "_$name")) |
{ |
$this->{"_$name"} = $value; |
return $this->{"_$name"}; |
} |
/* NOTE: Attempts to set other properties are _silently_ _ignored_ */ |
} |
/** |
* Returns <code>true</code> if a variable name is a property variable name |
* (starts with <tt>$_</tt>), <code>false</code> otherwise. |
* |
* @param string $varName |
* @return boolean |
* @see getPropertyVars() |
*/ |
private static function _isPropertyVar($varName) |
{ |
return preg_match('/^_\\w/', $varName) > 0; |
} |
/** |
* Returns <code>true</code> if a variable name is a property variable name |
* (starts with <tt>$_</tt>), <code>false</code> otherwise. |
* |
* @param string $varName |
* @return string |
* @see getPropertyVars() |
*/ |
private static function _toPropertyVar($varName) |
{ |
return preg_replace('/^_(\\w)/', '\\1', $varName); |
} |
/** |
* Returns the public names of the property variables of a {@link Model} |
* as an array of strings |
* |
* @return array |
*/ |
public function getPropertyVars() |
{ |
return array_map( |
array('self', '_toPropertyVar'), |
array_filter( |
array_keys(get_object_vars($this)), |
array('self', '_isPropertyVar') |
) |
); |
} |
/** |
* Maps the values of an associative array to a model object |
* |
* @param array $data |
* @param array $mapping = null |
* <p>If <var>$mapping</var> is not provided, or <code>null</code> (default), |
* the values of <var>$data</var> are mapped to properties of |
* the model object as specified by the keys of <var>$data</var>.</p> |
* <p>If <var>$mapping</var> is provided and an array, the keys of |
* <var>$data</var> are mapped to properties as specified by |
* the corresponding values of <var>$mapping</var>. If a value of |
* <var>$mapping</var> is <code>null</code>, the corresponding value |
* in <var>$data</var> is not mapped; if a key is missing in |
* <var>$mapping</var>, the value is mapped as if <var>$mapping</var> |
* was <code>null</code>.</p> |
* @param bool $exclusive |
* If <code>true</code>, <em>only</em> the keys of $data that are present |
* in $mapping are mapped. |
* @throws InvalidArgumentException if <var>$mapping</var> is neither |
* <code>null</code> nor an array. |
*/ |
public function map($data, $mapping = null, $exclusive = false) |
{ |
if (is_null($mapping)) |
{ |
foreach ($data as $key => $value) |
{ |
$this->$key = $value; |
} |
} |
else if (is_array($mapping)) |
{ |
foreach ($data as $key => $value) |
{ |
if (array_key_exists($key, $mapping)) |
{ |
if ($exclusive || !is_null($mapping[$key])) |
{ |
$this->{$mapping[$key]} = $value; |
} |
} |
else |
{ |
$this->$key = $value; |
} |
} |
} |
else |
{ |
throw new InvalidArgumentException( |
'Expected null or array for $mapping, saw <pre>' |
. print_r($mapping, true) . '</pre>'); |
} |
} |
} |
/trunk/.settings/org.eclipse.php.core.prefs |
---|
0,0 → 1,5 |
#Tue Jun 14 23:13:36 CEST 2011 |
eclipse.preferences.version=1 |
include_path=0;/PHPX |
phpVersion=php5 |
useShortTags=false |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: Registry.php |
=================================================================== |
--- Registry.php (nonexistent) |
+++ Registry.php (revision 27) |
@@ -0,0 +1,37 @@ |
+<?php |
+ |
+/** |
+ * Basic registry class |
+ * |
+ * @author Thomas Lahn |
+ */ |
+abstract class Registry |
+{ |
+ /** |
+ * Data storage |
+ * @var array |
+ */ |
+ protected static $_data = array(); |
+ |
+ /** |
+ * Puts data in storage |
+ * |
+ * @param string $key |
+ * @param mixed $value |
+ */ |
+ public static function set($key, $value) |
+ { |
+ self::$_data[$key] = $value; |
+ } |
+ |
+ /** |
+ * Gets data from storage |
+ * |
+ * @param string $key |
+ * @return mixed |
+ */ |
+ public static function get($key) |
+ { |
+ return self::$_data[$key]; |
+ } |
+} |
\ No newline at end of file |