From 119d5a1995ca1a565e89f6ea0dc16cddc3504335 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 25 Aug 2008 18:55:50 +0000 Subject: [PATCH] - renamed configuration keys result:object, result:withtables and format:* to resultObject resp. resultWithTables (due compatibility with PHP 5.3 INI parser) - updated class Object --- dibi/Nette/Object.php | 105 +++++++++++++++++++++++++---------- dibi/dibi.php | 2 +- dibi/drivers/sqlite.php | 8 +-- dibi/libs/DibiConnection.php | 20 +++++-- dibi/libs/DibiResult.php | 6 +- dibi/libs/DibiTable.php | 2 +- examples/connect.php | 2 +- examples/datetime.demo.php | 4 +- 8 files changed, 104 insertions(+), 45 deletions(-) diff --git a/dibi/Nette/Object.php b/dibi/Nette/Object.php index a4e0f9da..78a80abe 100644 --- a/dibi/Nette/Object.php +++ b/dibi/Nette/Object.php @@ -51,9 +51,9 @@ * Adding method to class (i.e. to all instances) works similar to JavaScript * prototype property. The syntax for adding a new method is: * - * function MyClass_prototype_newMethod(MyClass $obj, $arg, ...) { ... } + * MyClass::extensionMethod('newMethod', function(MyClass $obj, $arg, ...) { ... }); * $obj = new MyClass; - * $obj->newMethod($x); // equivalent to MyClass_prototype_newMethod($obj, $x); + * $obj->newMethod($x); * * * @author David Grudl @@ -62,15 +62,19 @@ */ abstract class Object { + /** @var array (method => array(type => callback)) */ + private static $extMethods; + + /** * Returns the name of the class of this object. * * @return string */ - final public function getClass() + final public /*static*/ function getClass() { - return get_class($this); + return /*get_called_class()*/ /**/get_class($this)/**/; } @@ -104,7 +108,7 @@ abstract class Object } // event functionality - if (self::hasEvent($class, $name)) { + if (property_exists($class, $name) && preg_match('#^on[A-Z]#', $name)) { $list = $this->$name; if (is_array($list) || $list instanceof Traversable) { foreach ($list as $handler) { @@ -114,15 +118,11 @@ abstract class Object return; } - // object prototypes support Class__method() - // (or use class Class__method { static function ... } with autoloading?) - $cl = $class; - do { - if (function_exists($nm = $cl . '_prototype_' . $name)) { - array_unshift($args, $this); - return call_user_func_array($nm, $args); - } - } while ($cl = get_parent_class($cl)); + // extension methods + if ($cb = self::extensionMethod("$class::$name")) { + array_unshift($args, $this); + return call_user_func_array($cb, $args); + } throw new /*::*/MemberAccessException("Call to undefined method $class::$name()."); } @@ -145,6 +145,69 @@ abstract class Object + /** + * Adding method to class. + * + * @param string method name + * @param mixed callback or closure + * @return mixed + */ + public static function extensionMethod($name, $callback = NULL) + { + if (self::$extMethods === NULL || $name === NULL) { // for backwards compatibility + $list = get_defined_functions(); + foreach ($list['user'] as $fce) { + $pair = explode('_prototype_', $fce); + if (count($pair) === 2) { + self::$extMethods[$pair[1]][$pair[0]] = $fce; + self::$extMethods[$pair[1]][''] = NULL; + } + } + if ($name === NULL) return; + } + + $name = strtolower($name); + $a = strrpos($name, ':'); // search :: + if ($a === FALSE) { + $class = strtolower(get_called_class()); + $l = & self::$extMethods[$name]; + } else { + $class = substr($name, 0, $a - 1); + $l = & self::$extMethods[substr($name, $a + 1)]; + } + + if ($callback !== NULL) { // works as setter + $l[$class] = $callback; + $l[''] = NULL; + return; + } + + // works as getter + if (empty($l)) { + return FALSE; + + } elseif (isset($l[''][$class])) { // cached value + return $l[''][$class]; + } + $cl = $class; + do { + $cl = strtolower($cl); + if (isset($l[$cl])) { + return $l[''][$class] = $l[$cl]; + } + } while (($cl = get_parent_class($cl)) !== FALSE); + + foreach (class_implements($class) as $cl) { + $cl = strtolower($cl); + if (isset($l[$cl])) { + return $l[''][$class] = $l[$cl]; + } + } + return $l[''][$class] = FALSE; + } + + + /** * Returns property value. Do not call directly. * @@ -260,18 +323,4 @@ abstract class Object return isset($cache[$c][$m]); } - - - /** - * Is property an event? - * - * @param string class name - * @param string method name - * @return bool - */ - private static function hasEvent($c, $m) - { - return preg_match('#^on[A-Z]#', $m) && property_exists($c, $m); - } - } diff --git a/dibi/dibi.php b/dibi/dibi.php index e3d9d5a7..8905f037 100644 --- a/dibi/dibi.php +++ b/dibi/dibi.php @@ -196,7 +196,7 @@ class dibi /** * Creates a new DibiConnection object and connects it to specified database. * - * @param array|string|Nette::Collections::Hashtable connection parameters + * @param array|string|ArrayObject connection parameters * @param string connection name * @return DibiConnection * @throws DibiException diff --git a/dibi/drivers/sqlite.php b/dibi/drivers/sqlite.php index de1cc3fb..67a2e533 100644 --- a/dibi/drivers/sqlite.php +++ b/dibi/drivers/sqlite.php @@ -27,8 +27,8 @@ * - 'persistent' - try to find a persistent link? * - 'unbuffered' - sends query without fetching and buffering the result rows automatically? * - 'lazy' - if TRUE, connection will be established only when required - * - 'format:date' - how to format date in SQL (@see date) - * - 'format:datetime' - how to format datetime in SQL (@see date) + * - 'formatDate' - how to format date in SQL (@see date) + * - 'formatDateTime' - how to format datetime in SQL (@see date) * * @author David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl @@ -87,8 +87,8 @@ class DibiSqliteDriver extends /*Nette::*/Object implements IDibiDriver public function connect(array &$config) { DibiConnection::alias($config, 'database', 'file'); - $this->fmtDate = isset($config['format:date']) ? $config['format:date'] : 'U'; - $this->fmtDateTime = isset($config['format:datetime']) ? $config['format:datetime'] : 'U'; + $this->fmtDate = isset($config['formatDate']) ? $config['formatDate'] : 'U'; + $this->fmtDateTime = isset($config['formatDateTime']) ? $config['formatDateTime'] : 'U'; $errorMsg = ''; if (empty($config['persistent'])) { diff --git a/dibi/libs/DibiConnection.php b/dibi/libs/DibiConnection.php index 4784189f..e1395087 100644 --- a/dibi/libs/DibiConnection.php +++ b/dibi/libs/DibiConnection.php @@ -58,7 +58,7 @@ class DibiConnection extends /*Nette::*/Object /** * Creates object and (optionally) connects to a database. * - * @param array|string|Nette::Collections::Hashtable connection parameters + * @param array|string|ArrayObject connection parameters * @param string connection name * @throws DibiException */ @@ -72,11 +72,11 @@ class DibiConnection extends /*Nette::*/Object if (is_string($config)) { parse_str($config, $config); - } elseif ($config instanceof /*Nette::Collections::*/Hashtable) { + } elseif ($config instanceof ArrayObject) { $config = (array) $config; } elseif (!is_array($config)) { - throw new InvalidArgumentException('Configuration must be array, string or Nette::Collections::Hashtable.'); + throw new InvalidArgumentException('Configuration must be array, string or ArrayObject.'); } if (!isset($config['driver'])) { @@ -93,10 +93,20 @@ class DibiConnection extends /*Nette::*/Object } } + if (isset($config['result:withtables'])) { + $config['resultWithTables'] = $config['result:withtables']; + unset($config['result:withtables']); + } + if (isset($config['result:objects'])) { + $config['resultObjects'] = $config['result:objects']; + unset($config['result:objects']); + } + + if (isset($config['resultObjects'])) { // normalize - $val = $config['result:objects']; - $config['result:objects'] = is_string($val) && !is_numeric($val) ? $val : (bool) $val; + $val = $config['resultObjects']; + $config['resultObjects'] = is_string($val) && !is_numeric($val) ? $val : (bool) $val; } $config['name'] = $name; diff --git a/dibi/libs/DibiResult.php b/dibi/libs/DibiResult.php index 35c9c764..5e1278b4 100644 --- a/dibi/libs/DibiResult.php +++ b/dibi/libs/DibiResult.php @@ -89,12 +89,12 @@ class DibiResult extends /*Nette::*/Object implements IDataSource { $this->driver = $driver; - if (!empty($config['result:withtables'])) { + if (!empty($config['resultWithTables'])) { $this->setWithTables(TRUE); } - if (isset($config['result:objects'])) { - $this->setObjects($config['result:objects']); + if (isset($config['resultObjects'])) { + $this->setObjects($config['resultObjects']); } } diff --git a/dibi/libs/DibiTable.php b/dibi/libs/DibiTable.php index f6f78034..15f55be2 100644 --- a/dibi/libs/DibiTable.php +++ b/dibi/libs/DibiTable.php @@ -254,7 +254,7 @@ abstract class DibiTable extends /*Nette::*/Object $row = $this->blankRow; $row[$this->primary] = NULL; - if ($class = $this->connection->getConfig('result:objects')) { + if ($class = $this->connection->getConfig('resultObjects')) { if ($class === TRUE) { $row = (object) $row; } else { diff --git a/examples/connect.php b/examples/connect.php index 62414272..b4f7082e 100644 --- a/examples/connect.php +++ b/examples/connect.php @@ -10,7 +10,7 @@ try { dibi::connect(array( 'driver' => 'sqlite', 'database' => 'sample.sdb', - 'result:objects' => TRUE, // fetch rows as objects + 'resultObjects' => TRUE, // fetch rows as objects )); echo 'OK'; diff --git a/examples/datetime.demo.php b/examples/datetime.demo.php index 978414a8..e17d169d 100644 --- a/examples/datetime.demo.php +++ b/examples/datetime.demo.php @@ -13,8 +13,8 @@ date_default_timezone_set('Europe/Prague'); dibi::connect(array( 'driver' => 'sqlite', 'database' => 'sample.sdb', - 'format:date' => "'Y-m-d'", - 'format:datetime' => "'Y-m-d H-i-s'", + 'formatDate' => "'Y-m-d'", + 'formatDateTime' => "'Y-m-d H-i-s'", ));