Passed
Push — master ( 62fde5...4f02ab )
by Aimeos
05:13
created

Traits::call()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 7
rs 10
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2021
6
 * @package MW
7
 * @subpackage Macro
8
 */
9
10
11
namespace Aimeos\MW\Macro;
12
13
14
/**
15
 * Common trait for objects supporting macros
16
 *
17
 * @package MW
18
 * @subpackage Macro
19
 */
20
trait Traits
21
{
22
	private static $macros = [];
23
24
25
	/**
26
	 * Registers a custom macro that has access to the class properties if called non-static
27
	 *
28
	 * Examples:
29
	 *  SomeClass::macro( 'test', function( $name ) {
30
	 *      return $this->getConfigValue( $name ) ? true : false;
31
	 *  } );
32
	 *
33
	 * @param string $name Macro name
34
	 * @param \Closure|null $function Anonymous function
35
	 * @return \Closure|null Registered function
36
	 */
37
	public static function macro( string $name, \Closure $function = null ) : ?\Closure
38
	{
39
		$self = get_called_class();
40
41
		if( $function ) {
42
			self::$macros[$self][$name] = $function;
43
		}
44
45
		foreach( array_merge( [$self], class_parents( static::class ) ) as $class )
46
		{
47
			if( isset( self::$macros[$class][$name] ) ) {
48
				return self::$macros[$class][$name];
49
			}
50
		}
51
52
		return null;
53
	}
54
55
56
	/**
57
	 * Passes unknown method calls to the custom macros
58
	 *
59
	 * @param string $name Method name
60
	 * @param array $args Method arguments
61
	 * @return mixed Result or macro call
62
	 */
63
	public function __call( string $name, array $args )
64
	{
65
		if( $fcn = static::macro( $name ) ) {
66
			return call_user_func_array( $fcn->bindTo( $this, self::class ), $args );
67
		}
68
69
		$msg = 'Called unknown macro "%1$s" on class "%2$s"';
70
		throw new \BadMethodCallException( sprintf( $msg, $name, get_class( $this ) ) );
71
	}
72
73
74
	/**
75
	 * Passes method calls to the custom macros
76
	 *
77
	 * @param string $name Macro name
78
	 * @param array $args Macro arguments
79
	 * @return mixed Result or macro call
80
	 */
81
	protected function call( string $name, ...$args )
82
	{
83
		if( $fcn = static::macro( $name ) ) {
84
			return call_user_func_array( $fcn->bindTo( $this, self::class ), $args );
85
		}
86
87
		return $this->$name( ...$args );
88
	}
89
}
90