Subversion Repositories PHPX

Compare Revisions

Last modification

Ignore whitespace Rev 26 → Rev 27

/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: trunk/Registry.php
===================================================================
--- trunk/Registry.php (nonexistent)
+++ trunk/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