<?php
/*
=============================================================================================================================================
| This file is part of a project released under the terms of the Xyndravandria PHP License (XyndravandriaPHPLicense.txt). |
| |
| You should be given a copy of the Xyndravandria PHP License (XyndravandriaPHPLicense.txt) within the same directory as the README.md; |
| if not, you can get a copy at http://Xyndravandria.ohost.de/XyndravandriaPHPLicense.txt . |
| |
| The copyright (c) of this project is owned by Mauro Di Girolamo <maurodigirolamo@.web.de>. |
============================================================================================================================================|
Xyndravandria Erozaver
----------------------
Alpha 0.0.0
Xyndravandria is the name of a collection of projects designed and developed by Mauro Di Girolamo (maurodigirolamo@web.de); he is therefore the copyright (c) owner of Xyndravandria itself and all of its projects.
Xyndravandria Erozaver is released under the terms of the Xyndravandria PHP License (XyndravandriaPHPLicense.txt). You should be given a copy of the Xyndravandria PHP License (XyndravandriaPHPLicense.txt) within the same directory as the README.md; if not, you can get a copy at http://Xyndravandria.ohost.de/XyndravandriaPHPLicense.txt . There might be a release under a freer license for a later, more stable version.
The documentation is either included in ./admin_media/Documentation/ or can be read at http://Xyndravandria.ohost.de/Erozaver/Documentation/.
All projects:
Xyndravandria Averazain
http://github.com/MauroDiGirolamo/Xyndravandria_Averazain
PHP
Averazain is an Ajax framework supporting also JavaScript disabled clients perfectly - including search engines like Google.
Xyndravandria Dyverath
http://github.com/MauroDiGirolamo/Xyndravandria_Dyverath
PHP
Dyverath is a database access wrapper.
Xyndravandria Erozaver
http://github.com/MauroDiGirolamo/Xyndravandria_Erozaver
PHP
Erozaver is a class extending the type hinting given by the PHP engine (additional support for basic type hinting and size constraints).
Xyndravandria Mondraviel
http://github.com/MauroDiGirolamo/Xyndravandria_Mondraviel
PHP
Mondraviel is a class used to separate HTML from PHP code by firstly register models - files containing place holders embedded in HTML code - and then later fill them dynamically with content by passing values for the place holders.
*/
namespace Xyndravandria\Erozaver;
// TODO: Thing about enabling settype( ) again.
/// Erozaver extends the type hinting (see
/// http://de3.php.net/manual/language.oop5.typehinting.php
/// to know what type hinting is) given by PHP engine:
/// <ul><li>Makes basic type hinting possible</li>
/// <li>Allows size constraints</li></ul>
/// The syntax of size constraints is: @verbatim
/// Type\Operator_Length $Variable @endverbatim
/// Operator can either be SizeEqual, SizeMaximum,
/// SizeMinimum or SizeInterval. @n
/// When using SizeInterval, the syntax will be
/// @verbatim Type\SizeInterval_Minimum_Maximum @endverbatim
/// Example: @verbatim function Test( integer\SizeInterval_5_10 $Value ) { } @endverbatim
/// $Value will have to be an integer and its size has
/// to be between 4 and 11. @n @n
/// Whenever there is an invalid argument in type and
/// or length passed to a function or method, an
/// XyndravandriaErozaverException is thrown. @n @n
/// If you want to use size constraints within type
/// hintings for your own classes, they have to
/// implement the HasLength interface and, as a
/// consequence, offer a Length( ) method.
/// @note
/// @verbatim \set_error_handler( 'Xyndravandria\Erozaver\Erozaver::HandleError' ); @endverbatim
/// will be called when this class is loaded. @n
/// To use your own error handler, see @ref
/// Xyndravandria::Erozaver::Erozaver::RegisterHandler( )
/// "Erozaver::RegisterHandler( )".
/// @abstract
abstract class Erozaver {
/// An exception handler which has been registered by
/// a user of the framework. @n
/// It is called when an Exception thrown does not
/// come from the framework.
/// <dl class = "type"><dt><b>%Type:</b></dt>
/// <dd>callback</dd></dl>
/// @private
/// @static
private static $UserExceptionHandler = null;
/// Calls the exception handler registered in
/// Erozaver::$UserExceptionHandler.
/// @public
/// @static
/// @param array $Argument: The arguments to be passed to
/// the exception handler.
/// @returns mixed
/// @note $Argument is an optional parameter.
public static function UserExceptionHandler( array $Argument = array( ) ) {
return \is_null( self::$UserExceptionHandler ) ? false : \call_user_func_array( self::$UserExceptionHandler, $Argument );
}
/// An error handler which has been registered by a
/// user of the framework. @n
/// It is called when an error occurs which does not
/// come from the framework.
/// <dl class = "type"><dt><b>%Type:</b></dt>
/// <dd>callback</dd></dl>
/// @private
/// @static
private static $UserErrorHandler = null;
/// Calls the error handler registered in
/// Erozaver::$UserErrorHandler.
/// @public
/// @static
/// @param array $Argument: The arguments to be passed
/// to the error handler.
/// @returns mixed
/// @note $Argument is an optional parameter.
public static function UserErrorHandler( array $Argument ) {
return \is_null( self::$UserErrorHandler ) ? false : \call_user_func_array( self::$UserErrorHandler, $Argument );
}
/// Used as an argument for Erozaver::RegisterHandler( )
/// to register an exception handler.
const Type_ExceptionHandler = 1;
/// Used as an argument for Erozaver::RegisterHandler( )
/// to register an error handler.
const Type_ErrorHandler = 2;
/// Registers a user handler to Erozaver.
/// @public
/// @static
/// @param callback $Handler: The handler to be
/// registered.
/// @param integer $Type: The type of the handler to
/// be registered. @n
/// Currently, it can either be
/// Erozaver::Type_ExceptionHandler or
/// Erozaver::Type_ErrorHandler.
public static function RegisterHandler( $Handler, $Type ) {
try {
$ReflectionFunction = new ReflectionFunction( $Handler );
} catch( \Exception $Exception ) {
throw new XyndravandriaErozaverException( $Exception->getMessage( ) );
}
if( \count( $ReflectionFunction::getParameters( ) ) != 1 )
throw new XyndravandriaErozaverException( 'The given handler wants more than one parameter.' );
elseif( $Type == self::Type_ExceptionHandler )
self::$UserExceptionHandler = $Handler;
elseif( $Type == self::Type_ErrorHandler )
self::$UserErrorHandler = $Handler;
else
throw new XyndravandriaErozaverException( '$Type is not either Erozaver::Type_ExceptionHandler or Erozaver::Type_ErrorHandler.' );
return;
}
/// Method which is registered as an error handler.
/// @public
/// @static
/// @param $Level: The error level of the error
/// occured.
/// @param $Message: The message of the error occured.
/// @note Calls Erozaver::$UserErrorHandler if the
/// error does not concern extended type hinting.
public static function HandleError( $Level, $Message ) {
// TODO: Replace regex with a more high-performance algorithmn based on string functions / char by char looping.
if( $Level == E_RECOVERABLE_ERROR ) { // TODO: Syntax \ and namespaces within object type hints.
if( ! \preg_match( '#^Argument (\d+) passed to (.+) must be an instance of (.+)((\w+)_(\w+))?, (instance of)?(\w+) given#U', $Message, $Match ) ) // TODO: Optimise regex.
return false;
else {
list( $PartUseless, $File, $Line ) = \preg_match( '#called in (.+) on line (\d+) and defined#U', $Message, $FileInformation ) ? $FileInformation : array( '', 'Unknown', 'Unknown' );
list( $Message, $ArgumentNumber, $FunctionOrMethod, $Hint, $SizeConstraint, $Operator, $HintedSize, $Useless, $Given ) = $Match;
if( ! empty( $SizeConstraint ) ) {
$Hint[ \strlen( $Hint ) - 1 ] == '\\' && $Hint = \substr( $Hint, 0, \strlen( $Hint ) - 1 );
if( \in_array( $Hint, array( 'boolean', 'resource', 'NULL', 'unknown type' ) ) ) {
throw new XyndravandriaErozaverException( 'Size constraints are only possible for integers, doubles, strings, arrays and objects.' );
return true;
} else {
$Backtrace = \debug_backtrace( );
$Argument = $Backtrace[ 1 ][ 'args' ][ $ArgumentNumber - 1 ];
$ArgumentString = '';
if( $Hint == 'array' )
$ArgumentSize = \count( $Argument );
elseif( \class_exists( $Hint ) ) {
if( ! ( $Argument instanceof HasLength ) ) {
throw new XyndravandriaErozaverException( 'If you want to use size constraints within type hintings for your own classes, they have to implement the HasLength interface and, as a consequence, offer a Length( ) method.' );
return true;
} else
$ArgumentSize = $Argument->Length( );
} else {
$ArgumentString = \strval( $Argument );
\gettype( $Argument ) == 'double' && $ArgumentString = \str_replace( '.', '', $ArgumentString );
$ArgumentSize = \strlen( $ArgumentString );
}
switch( $Operator ) { // TODO: Validate that $HintedSize is an integer.
case 'SizeEquals' :
$SizeInvalid = $ArgumentSize != $HintedSize;
$OperatorError = 'hinted size and argument size are not equal';
break;
case 'SizeMaximum' :
$SizeInvalid = $ArgumentSize > $HintedSize;
$OperatorError = 'argument size is bigger than hinted size, but should be smaller or equal';
break;
case 'SizeMinimum' :
$SizeInvalid = $ArgumentSize < $HintedSize;
$OperatorError = 'argument size is smaller than hinted size, but should be bigger or equal';
break;
case 'SizeInterval' :
$Explode = explode( '_', $HintedSize );
if( \count( $Explode ) != 2 ) {
throw new XyndravandriaErozaverException( 'Syntax error in type hint; missing _. File: ' . $File . '. Line: ' . $Line . '. Function or method called: ' . $FunctionOrMethod . '. Argument number: ' . $ArgumentNumber . '. Argument value: ' . ( \class_exists( $Hint ) ? '*object*' : $Argument ) . '.' );
return true;
} else {
list( $Minimum, $Maximum ) = $Explode;
$SizeInvalid = ! ( $ArgumentSize >= $Minimum && $ArgumentSize <= $Maximum );
$OperatorError = 'argument size is ' . $ArgumentSize . ', but has to be between ( ' . $Minimum . ' - 1 ) and ( ' . $Maximum . ' + 1 )';
break;
}
default :
throw new XyndravandriaErozaverException( 'Unknown operator \'' . $Operator . '\' within type hint. File: ' . $File . '. Line: ' . $Line . '. Function or method called: ' . $FunctionOrMethod . '. Argument number: ' . $ArgumentNumber . '. Argument value: ' . ( \class_exists( $Hint ) ? '*object*' : $Argument ) . '.' );
return true;
}
}
if( $SizeInvalid ) {
throw new XyndravandriaErozaverException( 'Invalid size of argument detected - ' . $OperatorError . '. File: ' . $File . '. Line ' . $Line . '. Function or method called: ' . $FunctionOrMethod . '. Argument number: ' . $ArgumentNumber . '. Argument value: ' . ( \class_exists( $Hint ) ? '*object*' : $Argument ) . '. Operator: ' . $Operator . '. Hinted size: ' . $HintedSize . '. Argument size: ' . $ArgumentSize . '.' );
return true;
}
}
return $Hint == $Given ? true : Erozaver::UserErrorHandler( array( $Level, $Message ) );
}
} else
return false;
}
}
\set_error_handler( 'Xyndravandria\Erozaver\Erozaver::HandleError' );
?>
|