mirror of
https://github.com/dg/dibi.git
synced 2025-09-08 05:10:40 +02:00
added new Nette exceptions
This commit is contained in:
132
dibi/Nette/NException.php
Normal file
132
dibi/Nette/NException.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl aka -dgx- (http://www.dgx.cz)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @license http://nettephp.com/license Nette license
|
||||
* @link http://nettephp.com/
|
||||
* @package Nette
|
||||
*/
|
||||
|
||||
// namespace Nette;
|
||||
|
||||
|
||||
/**
|
||||
* Nette Exception base class.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @license http://nettephp.com/license Nette license
|
||||
* @link http://nettephp.com/
|
||||
* @package Nette
|
||||
*/
|
||||
class NException extends Exception
|
||||
{
|
||||
/** @var Exception */
|
||||
private $cause;
|
||||
|
||||
/** @var callback */
|
||||
private static $oldHandler;
|
||||
|
||||
/** @var string */
|
||||
private static $handlerClass;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the cause of this throwable to the specified value.
|
||||
*
|
||||
* @param Exception
|
||||
* @return void
|
||||
*/
|
||||
public function initCause(Exception $cause)
|
||||
{
|
||||
if ($this->cause === NULL) {
|
||||
$this->cause = $cause;
|
||||
} else {
|
||||
throw new InvalidStateException('Cause was already assigned.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Exception instance that caused the current exception.
|
||||
*
|
||||
* @return Exception
|
||||
*/
|
||||
public function getCause()
|
||||
{
|
||||
return $this->cause;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns string represenation of exception.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return parent::__toString() . ($this->cause === NULL ? '' : "\nCaused by " . $this->cause->__toString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Enables converting all PHP errors to exceptions.
|
||||
*
|
||||
* @param Exception class to be thrown
|
||||
* @return void
|
||||
*/
|
||||
public static function catchError($class = __CLASS__)
|
||||
{
|
||||
self::$oldHandler = set_error_handler(array(__CLASS__, '_errorHandler'), E_ALL);
|
||||
self::$handlerClass = $class;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disables converting errors to exceptions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function restore()
|
||||
{
|
||||
if (self::$oldHandler !== NULL) {
|
||||
set_error_handler(self::$oldHandler);
|
||||
self::$oldHandler = NULL;
|
||||
} else {
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Internal error handler.
|
||||
*/
|
||||
public static function _errorHandler($code, $message, $file, $line, $context)
|
||||
{
|
||||
self::restore();
|
||||
|
||||
if (ini_get('html_errors')) {
|
||||
$message = strip_tags($message);
|
||||
}
|
||||
|
||||
throw new self::$handlerClass($message, $code);
|
||||
}
|
||||
|
||||
}
|
261
dibi/Nette/NObject.php
Normal file
261
dibi/Nette/NObject.php
Normal file
@@ -0,0 +1,261 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl aka -dgx- (http://www.dgx.cz)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @license http://nettephp.com/license Nette license
|
||||
* @link http://nettephp.com/
|
||||
* @package Nette
|
||||
*/
|
||||
|
||||
// namespace Nette;
|
||||
|
||||
|
||||
/**
|
||||
* NObject is the ultimate ancestor of all instantiable classes.
|
||||
*
|
||||
* It defines some handful methods and enhances object core of PHP:
|
||||
* - access to undeclared members throws exceptions
|
||||
* - support for conventional properties with getters and setters
|
||||
* - support for event raising functionality
|
||||
* - ability to add new methods to class (extension methods)
|
||||
*
|
||||
* Properties is a syntactic sugar which allows access public getter and setter
|
||||
* methods as normal object variables. A property is defined by a getter method
|
||||
* and optional setter method (no setter method means read-only property).
|
||||
* <code>
|
||||
* $val = $obj->label; // equivalent to $val = $obj->getLabel();
|
||||
* $obj->label = 'Nette'; // equivalent to $obj->setLabel('Nette');
|
||||
* </code>
|
||||
* Property names are case-sensitive, and they are written in the camelCaps
|
||||
* or PascalCaps.
|
||||
*
|
||||
* Event functionality is provided by declaration of property named 'on{Something}'
|
||||
* Multiple handlers are allowed.
|
||||
* <code>
|
||||
* public $onClick; // declaration in class
|
||||
* $this->onClick[] = 'callback'; // attaching event handler
|
||||
* if (!empty($this->onClick)) ... // are there any handlers?
|
||||
* $this->onClick($sender, $arg); // raises the event with arguments
|
||||
* </code>
|
||||
*
|
||||
* Adding method to class (i.e. to all instances) works similar to JavaScript
|
||||
* prototype property. The syntax for adding a new method is:
|
||||
* <code>
|
||||
* function MyClass_prototype_newMethod(MyClass $obj, $arg, ...) { ... }
|
||||
* $obj = new MyClass;
|
||||
* $obj->newMethod($x); // equivalent to MyClass_prototype_newMethod($obj, $x);
|
||||
* </code>
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @license http://nettephp.com/license Nette license
|
||||
* @link http://nettephp.com/
|
||||
* @package Nette
|
||||
*/
|
||||
abstract class NObject
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the name of the class of this object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final public function getClass()
|
||||
{
|
||||
return get_class($this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Access to reflection.
|
||||
*
|
||||
* @return ReflectionObject
|
||||
*/
|
||||
final public function getReflection()
|
||||
{
|
||||
return new ReflectionObject($this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Call to undefined method.
|
||||
*
|
||||
* @param string method name
|
||||
* @param array arguments
|
||||
* @return mixed
|
||||
* @throws MemberAccessException
|
||||
*/
|
||||
protected function __call($name, $args)
|
||||
{
|
||||
if ($name === '') {
|
||||
throw new MemberAccessException("Call to method without name.");
|
||||
}
|
||||
|
||||
$class = get_class($this);
|
||||
|
||||
// event functionality
|
||||
if (self::hasEvent($class, $name)) {
|
||||
$list = $this->$name;
|
||||
if (is_array($list) || $list instanceof Traversable) {
|
||||
foreach ($list as $handler) {
|
||||
call_user_func_array($handler, $args);
|
||||
}
|
||||
}
|
||||
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));
|
||||
|
||||
throw new MemberAccessException("Call to undefined method $class::$name().");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns property value. Do not call directly.
|
||||
*
|
||||
* @param string property name
|
||||
* @return mixed property value
|
||||
* @throws MemberAccessException if the property is not defined.
|
||||
*/
|
||||
protected function &__get($name)
|
||||
{
|
||||
if ($name === '') {
|
||||
throw new MemberAccessException("Cannot read an property without name.");
|
||||
}
|
||||
|
||||
// property getter support
|
||||
$class = get_class($this);
|
||||
$m = 'get' . $name;
|
||||
if (self::hasAccessor($class, $m)) {
|
||||
// ampersands:
|
||||
// - using &__get() because declaration should be forward compatible (e.g. with NHtml)
|
||||
// - not using &$this->$m because user could bypass property setter by: $x = & $obj->property; $x = 'new value';
|
||||
$val = $this->$m();
|
||||
return $val;
|
||||
|
||||
} else {
|
||||
throw new MemberAccessException("Cannot read an undeclared property $class::\$$name.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets value of a property. Do not call directly.
|
||||
*
|
||||
* @param string property name
|
||||
* @param mixed property value
|
||||
* @return void
|
||||
* @throws MemberAccessException if the property is not defined or is read-only
|
||||
*/
|
||||
protected function __set($name, $value)
|
||||
{
|
||||
if ($name === '') {
|
||||
throw new MemberAccessException('Cannot assign to an property without name.');
|
||||
}
|
||||
|
||||
// property setter support
|
||||
$class = get_class($this);
|
||||
if (self::hasAccessor($class, 'get' . $name)) {
|
||||
$m = 'set' . $name;
|
||||
if (self::hasAccessor($class, $m)) {
|
||||
$this->$m($value);
|
||||
|
||||
} else {
|
||||
throw new MemberAccessException("Cannot assign to a read-only property $class::\$$name.");
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new MemberAccessException("Cannot assign to an undeclared property $class::\$$name.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Is property defined?
|
||||
*
|
||||
* @param string property name
|
||||
* @return bool
|
||||
*/
|
||||
protected function __isset($name)
|
||||
{
|
||||
return $name !== '' && self::hasAccessor(get_class($this), 'get' . $name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Access to undeclared property.
|
||||
*
|
||||
* @param string property name
|
||||
* @return void
|
||||
* @throws MemberAccessException
|
||||
*/
|
||||
protected function __unset($name)
|
||||
{
|
||||
$class = get_class($this);
|
||||
throw new MemberAccessException("Cannot unset an property $class::\$$name.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Has property an accessor?
|
||||
*
|
||||
* @param string class name
|
||||
* @param string method name
|
||||
* @return bool
|
||||
*/
|
||||
private static function hasAccessor($c, $m)
|
||||
{
|
||||
static $cache;
|
||||
if (!isset($cache[$c])) {
|
||||
// get_class_methods returns private, protected and public methods of NObject (doesn't matter)
|
||||
// and ONLY PUBLIC methods of descendants (perfect!)
|
||||
// but returns static methods too (nothing doing...)
|
||||
// and is much faster than reflection
|
||||
// (works good since 5.0.4)
|
||||
$cache[$c] = array_flip(get_class_methods($c));
|
||||
}
|
||||
// case-sensitive checking, capitalize the fourth character
|
||||
$m[3] = $m[3] & "\xDF";
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
119
dibi/Nette/exceptions.php
Normal file
119
dibi/Nette/exceptions.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Nette Framework
|
||||
*
|
||||
* Copyright (c) 2004, 2008 David Grudl aka -dgx- (http://www.dgx.cz)
|
||||
*
|
||||
* This source file is subject to the "Nette license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://nettephp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @license http://nettephp.com/license Nette license
|
||||
* @link http://nettephp.com/
|
||||
* @category Nette
|
||||
* @package Nette
|
||||
*/
|
||||
|
||||
// no namespace;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
some useful SPL exception:
|
||||
|
||||
- LogicException
|
||||
- InvalidArgumentException
|
||||
- LengthException
|
||||
- RuntimeException
|
||||
- OutOfBoundsException
|
||||
- UnexpectedValueException
|
||||
|
||||
other SPL exceptions are ambiguous; do not use them
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The exception that is thrown when the value of an argument is
|
||||
* outside the allowable range of values as defined by the invoked method.
|
||||
*/
|
||||
class ArgumentOutOfRangeException extends InvalidArgumentException
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The exception that is thrown when a method call is invalid for the object's
|
||||
* current state, method has been invoked at an illegal or inappropriate time.
|
||||
*/
|
||||
class InvalidStateException extends RuntimeException // or InvalidOperationException?
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The exception that is thrown when a requested method or operation is not implemented.
|
||||
*/
|
||||
class NotImplementedException extends LogicException
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The exception that is thrown when an invoked method is not supported. For scenarios where
|
||||
* it is sometimes possible to perform the requested operation, see InvalidStateException.
|
||||
*/
|
||||
class NotSupportedException extends LogicException
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The exception that is thrown when accessing a class member (property or method) fails.
|
||||
*/
|
||||
class MemberAccessException extends LogicException
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The exception that is thrown when an I/O error occurs.
|
||||
*/
|
||||
class IOException extends RuntimeException
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The exception that is thrown when accessing a file that does not exist on disk.
|
||||
*/
|
||||
class FileNotFoundException extends IOException
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The exception that is thrown when part of a file or directory cannot be found.
|
||||
*/
|
||||
class DirectoryNotFoundException extends IOException
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* User attempt to terminate the current script
|
||||
*/
|
||||
class AbortException extends RuntimeException
|
||||
{
|
||||
}
|
Reference in New Issue
Block a user