1 <?php
 2 
 3 /**
 4  * Factory trait.
 5  *
 6  * Example child class:
 7  * <code>
 8  * class rex_example
 9  * {
10  *     use rex_factory;
11  *
12  *     private function __construct($param)
13  *     {
14  *         // ...
15  *     }
16  *
17  *     public static function factory($param)
18  *     {
19  *         $class = self::getFactoryClass();
20  *         return new $class($param);
21  *     }
22  * }
23  * </code>
24  *
25  * @author gharlan
26  *
27  * @package redaxo\core
28  */
29 trait rex_factory_trait
30 {
31     /**
32      * @var array
33      */
34     private static $factoryClasses = [];
35 
36     /**
37      * Sets the class for the factory.
38      *
39      * @param string $subclass Classname
40      *
41      * @throws InvalidArgumentException
42      */
43     public static function setFactoryClass($subclass)
44     {
45         if (!is_string($subclass)) {
46             throw new InvalidArgumentException('Expecting $subclass to be a string, ' . gettype($subclass) . ' given!');
47         }
48         $calledClass = static::class;
49         if ($subclass != $calledClass && !is_subclass_of($subclass, $calledClass)) {
50             throw new InvalidArgumentException('$class "' . $subclass . '" is expected to define a subclass of ' . $calledClass . '!');
51         }
52         self::$factoryClasses[$calledClass] = $subclass;
53     }
54 
55     /**
56      * Returns the class for the factory.
57      *
58      * @return string
59      */
60     public static function getFactoryClass()
61     {
62         $calledClass = static::class;
63         return isset(self::$factoryClasses[$calledClass]) ? self::$factoryClasses[$calledClass] : $calledClass;
64     }
65 
66     /**
67      * Returns if the class has a custom factory class.
68      *
69      * @return bool
70      */
71     public static function hasFactoryClass()
72     {
73         $calledClass = static::class;
74         return isset(self::$factoryClasses[$calledClass]) && self::$factoryClasses[$calledClass] != $calledClass;
75     }
76 
77     /**
78      * Calls the factory class with the given method and arguments.
79      *
80      * @param string $method    Method name
81      * @param array  $arguments Array of arguments
82      *
83      * @return mixed Result of the callback
84      */
85     protected static function callFactoryClass($method, array $arguments)
86     {
87         $class = static::getFactoryClass();
88         return call_user_func_array([$class, $method], $arguments);
89     }
90 }
91