From f6d65e533c62f6deb21342d4901ece24497b433e Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Thu, 4 Jun 2015 07:31:04 +0200 Subject: Update to MediaWiki 1.25.1 --- includes/libs/ObjectFactory.php | 93 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 includes/libs/ObjectFactory.php (limited to 'includes/libs/ObjectFactory.php') diff --git a/includes/libs/ObjectFactory.php b/includes/libs/ObjectFactory.php new file mode 100644 index 00000000..ec8c36a1 --- /dev/null +++ b/includes/libs/ObjectFactory.php @@ -0,0 +1,93 @@ + + * @copyright © 2014 Bryan Davis and Wikimedia Foundation. + */ +class ObjectFactory { + + /** + * Instantiate an object based on a specification array. + * + * The specification array must contain a 'class' key with string value + * that specifies the class name to instantiate or a 'factory' key with + * a callable (is_callable() === true). It can optionally contain + * an 'args' key that provides arguments to pass to the + * constructor/callable. + * + * Object construction using a specification having both 'class' and + * 'args' members will call the constructor of the class using + * ReflectionClass::newInstanceArgs. The use of ReflectionClass carries + * a performance penalty and should not be used to create large numbers of + * objects. If this is needed, consider introducing a factory method that + * can be called via call_user_func_array() instead. + * + * Values in the arguments collection which are Closure instances will be + * expanded by invoking them with no arguments before passing the + * resulting value on to the constructor/callable. This can be used to + * pass DatabaseBase instances or other live objects to the + * constructor/callable. This behavior can be suppressed by adding + * closure_expansion => false to the specification. + * + * @param array $spec Object specification + * @return object + * @throws InvalidArgumentException when object specification does not + * contain 'class' or 'factory' keys + * @throws ReflectionException when 'args' are supplied and 'class' + * constructor is non-public or non-existent + */ + public static function getObjectFromSpec( $spec ) { + $args = isset( $spec['args'] ) ? $spec['args'] : array(); + + if ( !isset( $spec['closure_expansion'] ) || + $spec['closure_expansion'] === true + ) { + $args = array_map( function ( $value ) { + if ( is_object( $value ) && $value instanceof Closure ) { + // If an argument is a Closure, call it. + return $value(); + } else { + return $value; + } + }, $args ); + } + + if ( isset( $spec['class'] ) ) { + $clazz = $spec['class']; + if ( !$args ) { + $obj = new $clazz(); + } else { + $ref = new ReflectionClass( $clazz ); + $obj = $ref->newInstanceArgs( $args ); + } + } elseif ( isset( $spec['factory'] ) ) { + $obj = call_user_func_array( $spec['factory'], $args ); + } else { + throw new InvalidArgumentException( + 'Provided specification lacks both factory and class parameters.' + ); + } + + return $obj; + } +} -- cgit v1.2.3-54-g00ecf