/branches/0.9/lib/Enumeration/EnumUtils.php
# · PHP · 289 lines · 131 code · 19 blank · 139 comment · 18 complexity · 9a023ba8def1bb6c206b5a3db3495c6e MD5 · raw file
- <?php
- /**
- * @package Curly
- * @subpackage Enumeration
- * @version 0.9
- * @link http://curly.codeplex.com/
- * @license http://curly.codeplex.com/license The MIT License
- * @author Dawid Zawada
- */
-
- namespace Curly\Enumeration
- {
- /**
- * Static utility class for working with enumerations
- *
- * @package Curly
- * @subpackage Enumeration
- * @license http://curly.codeplex.com/license The MIT License
- */
- class EnumUtils
- {
- /**
- * Creates a new enumeration with the name given in the first parameter
- * and member names given in the second one
- *
- * If you want the enumeration to be created in a specific namespace, include the namespace
- * in the $className param.
- *
- * The new enumeration name must obey the rules for class names of the PHP language.
- * Member names of the new enumeration must obey the rules for method names of the PHP language.
- *
- * @example Example of use:
- * <code>
- * use Enumeration\EnumUtils;
- *
- * EnumUtils::createEnum( "Fruit", array( "Apple", "Orange" ) );
- *
- * function isAnApple( Fruit $fruit )
- * {
- * if( $fruit == Fruit::Apple() )
- * {
- * return "Yes, it is";
- * }
- * else
- * {
- * return "No, it isn't";
- * }
- * }
- *
- * echo isAnApple( Friut::Orange() );
- * </code>
- *
- * @param string $className Enumeration name
- * @param array $names Array of member names
- * @throws \InvalidArgumentException
- */
- public static function createEnum( $className, array $names )
- {
- static::validateNewClassName( $className );
-
- $namespace = static::extractNamespace( $className );
-
- $code = "namespace {$namespace} { final class {$className} extends " . __NAMESPACE__ . "\\Enum {";
- foreach( $names as $name )
- {
- static::validateName( $name );
- $code .= "public static function {$name}() { return parent::___getInstance( __FUNCTION__ ); }";
- }
- $code .= "} }";
-
- eval( $code );
- }
-
- /**
- * Returns names of members of the given enumeration class
- *
- * The class must exist and must inherit from the Enum class
- *
- * @param string $className Enumeration name
- * @return array
- * @throws \InvalidArgumentException
- */
- public static function getNames( $className )
- {
- static::validateClassName( $className );
-
- $class = new \ReflectionClass( $className );
- $methods = $class->getMethods( \ReflectionMethod::IS_STATIC );
- $methods = array_filter( $methods, function( $method ) {
- return $method->isPublic();
- } );
- array_walk( $methods, function( &$method ) {
- $method = $method->name;
- } );
-
- return array_values( $methods );
- }
-
- /**
- * Returns an array of members of the given enumeration class
- *
- * The class must exist and must inherit from the Enum class
- *
- * @param string $className Enumeration name
- * @return array
- * @throws \InvalidArgumentException
- */
- public static function getValues( $className )
- {
- $methods = static::getNames( $className );
- $methods = array_flip( $methods );
- array_walk( $methods, function( &$item, $key ) {
- $item = $className::$key();
- } );
-
- return $methods;
- }
-
- /**
- * Determines whether the given enumeration class contains a member
- * with the specified name
- *
- * The class must exist and must inherit from the Enum class
- *
- * @param string $className Enumeration name
- * @param string $name Member name
- * @return bool
- * @throws \InvalidArgumentException
- */
- public static function isDefined( $className, $name )
- {
- static::validateClassName( $className );
-
- $class = new \ReflectionClass( $className );
- if( $class->hasMethod( $name ) )
- {
- $method = $class->getMethod( $name );
- return $method->isStatic() && $method->isPublic();
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Returns the value of the member of the given enumeration class
- *
- * The class must exist and must inherit from the Enum class.
- * The member must exist in the enumeration.
- *
- * @param string $className Enumeration name
- * @param string $name Member name
- * @return Curly\Enumeration\Enum
- * @throws \InvalidArgumentException
- */
- public static function parse( $className, $name )
- {
- if( static::isDefined( $className, $name ) )
- {
- return $className::$name();
- }
- else
- {
- throw new \InvalidArgumentException( "Member '{$name}' not found in the {$className} enumeration" );
- }
- }
-
- /**
- * Returns the namespace part of the given class name
- *
- * This method also subtracts the namespace part from the variable
- * passed by a reference
- *
- * @param string $className
- * @return string
- */
- protected static function extractNamespace( &$className )
- {
- $namespace = "";
- $lastNsSeparatorPos = strrpos( $className, "\\" );
- if( $lastNsSeparatorPos !== false )
- {
- $namespace = substr( $className, 0, $lastNsSeparatorPos );
- $className = substr( $className, $lastNsSeparatorPos + 1 );
-
- if( !empty( $namespace ) && $namespace[0] != "\\" )
- {
- $namespace = "\\{$namespace}";
- }
- }
-
- return $namespace;
- }
-
- /**
- * Throws an exception if the given member name has incorrect format
- *
- * Throws an exception if:
- * the name is empty or
- * the name does not obey the rules for method names of the PHP language or
- * the name starts with more than one underscore character
- *
- * @internal
- * @param string $name Member name
- * @throws \InvalidArgumentException
- */
- public static function _validateName( $name )
- {
- if( empty( $name ) )
- {
- throw new \InvalidArgumentException( "Name of an enumeration member cannot be empty" );
- }
- if( !preg_match( "~^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$~", $name ) )
- {
- // the name doesn't obey the rules for method names of the PHP language
- throw new \InvalidArgumentException( "Name of an enumeration member contains illegal characters. The name must obey the rules for method names of the PHP language" );
- }
- if( strpos( $name, "__" ) === 0 )
- {
- // the name starts with more than one underscore character
- throw new \InvalidArgumentException( "Name of an enumeration member cannot start with more than one underscore character" );
- }
- }
-
- /**
- * Throws an exception if there is no enumeration with the given name
- *
- * Throws an exception if:
- * the name is empty or
- * a class with the specified name doesn't exist or
- * the class doesn't inherit from the Enum class
- *
- * @param string $className Enumeration name
- * @throws \InvalidArgumentException
- */
- protected static function validateClassName( $className )
- {
- if( empty( $className ) )
- {
- throw new \InvalidArgumentException( "Class name cannot be empty" );
- }
- if( !class_exists( $className ) )
- {
- throw new \InvalidArgumentException( "Class '{$className}' does not exist" );
- }
- if( !is_subclass_of( $className, __NAMESPACE__ . "\\Enum" ) )
- {
- throw new \InvalidArgumentException( "Class '{$className}' must be a child of the '" . __NAMESPACE__ . "\\Enum' class" );
- }
- }
-
- /**
- * Throws an exception if there already is an enumeration with the given name
- *
- * Throws an exception if:
- * the name is empty or
- * the name does not obey the rules for class names of the PHP language or
- * a class with the specified name already exists
- *
- * @param string $className Enumeration name
- * @throws \InvalidArgumentException
- */
- protected static function validateNewClassName( $className )
- {
- if( empty( $className ) )
- {
- throw new \InvalidArgumentException( "Class name cannot be empty" );
- }
- if( !preg_match( "~^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$~", $className ) )
- {
- // the name doesn't obey the rules for class names of the PHP language
- throw new \InvalidArgumentException( "Class name contains illegal characters. The name must obey the rules for class names of the PHP language" );
- }
- if( class_exists( $className ) )
- {
- throw new \InvalidArgumentException( "Class '{$className}' already exists" );
- }
- }
-
- /**
- * We don't want this class and its subclasses to be instantiated
- */
- private final function __construct()
- {
- throw new \LogicException( "'EnumUtils' class cannot be instantiated" );
- }
- }
- }