Passed
Push — master ( 2e24ad...4769bc )
by Aimeos
06:11
created

Base   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 40
c 3
b 0
f 0
dl 0
loc 113
rs 10
wmc 15

3 Methods

Rating   Name   Duplication   Size   Complexity  
A addRuleDecorators() 0 23 4
A getProvider() 0 30 5
A apply() 0 25 6
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2021
6
 * @package MShop
7
 * @subpackage Rule
8
 */
9
10
11
namespace Aimeos\MShop\Rule\Manager;
12
13
14
/**
15
 * Abstract class for rule managers.
16
 *
17
 * @package MShop
18
 * @subpackage Service
19
 */
20
abstract class Base
21
	extends \Aimeos\MShop\Common\Manager\Base
22
{
23
	private $rules = [];
24
25
26
	/**
27
	 * Applies the rules for modifying items dynamically
28
	 *
29
	 * @param \Aimeos\Map|\Aimeos\MShop\Common\Item\Iface $items Item or list of items
30
	 * @param string $type Type of rules to apply to the items (e.g. "basket" or "catalog")
31
	 * @return \Aimeos\Map|\Aimeos\MShop\Common\Item\Iface Modified item or list of items
32
	 */
33
	public function apply( $items, string $type = 'catalog' )
34
	{
35
		if( !isset( $this->rules[$type] ) )
36
		{
37
			$manager = $this->getObject();
38
39
			$filter = $manager->filter( true )->add( ['rule.type' => $type] )
40
				->order( 'rule.position' )->slice( 0, 10000 );
41
42
			foreach( $manager->search( $filter ) as $id => $ruleItem ) {
43
				$this->rules[$type][$id] = $manager->getProvider( $ruleItem, $type );
44
			}
45
		}
46
47
		foreach( $this->rules[$type] as $rule )
48
		{
49
			foreach( map( $items ) as $item )
50
			{
51
				if( $rule->apply( $item ) ) {
52
					return $items;
53
				}
54
			}
55
		}
56
57
		return $items;
58
	}
59
60
61
	/**
62
	 * Returns the rule provider which is responsible for the rule item.
63
	 *
64
	 * @param \Aimeos\MShop\Rule\Item\Iface $item Rule item object
65
	 * @param string $type Rule type code
66
	 * @return \Aimeos\MShop\Rule\Provider\Iface Returns the decoratad rule provider object
67
	 * @throws \Aimeos\MShop\Rule\Exception If provider couldn't be found
68
	 */
69
	public function getProvider( \Aimeos\MShop\Rule\Item\Iface $item, string $type ) : \Aimeos\MShop\Rule\Provider\Iface
70
	{
71
		$type = ucwords( $type );
72
		$names = explode( ',', $item->getProvider() );
73
74
		if( ctype_alnum( $type ) === false ) {
75
			throw new \Aimeos\MShop\Rule\Exception( sprintf( 'Invalid characters in type name "%1$s"', $type ) );
76
		}
77
78
		if( ( $provider = array_shift( $names ) ) === null ) {
79
			throw new \Aimeos\MShop\Rule\Exception( sprintf( 'Provider in "%1$s" not available', $item->getProvider() ) );
80
		}
81
82
		if( ctype_alnum( $provider ) === false ) {
83
			throw new \Aimeos\MShop\Rule\Exception( sprintf( 'Invalid characters in provider name "%1$s"', $provider ) );
84
		}
85
86
		$classname = '\Aimeos\MShop\Rule\Provider\\' . $type . '\\' . $provider;
87
88
		if( class_exists( $classname ) === false ) {
89
			throw new \Aimeos\MShop\Rule\Exception( sprintf( 'Class "%1$s" not available', $classname ) );
90
		}
91
92
		$context = $this->getContext();
93
		$provider = new $classname( $context, $item );
94
95
		self::checkClass( \Aimeos\MShop\Rule\Provider\Factory\Iface::class, $provider );
96
		$provider = $this->addRuleDecorators( $item, $provider, $names, $type );
97
98
		return $provider->setObject( $provider );
99
	}
100
101
102
	/**
103
	 *
104
	 * @param \Aimeos\MShop\Rule\Item\Iface $ruleItem Rule item object
105
	 * @param \Aimeos\MShop\Rule\Provider\Iface $provider Rule provider object
106
	 * @param array $names List of decorator names that should be wrapped around the rule provider object
107
	 * @param string $type Rule type code
108
	 * @return \Aimeos\MShop\Rule\Provider\Iface Rule provider object
109
	 */
110
	protected function addRuleDecorators( \Aimeos\MShop\Rule\Item\Iface $ruleItem,
111
		\Aimeos\MShop\Rule\Provider\Iface $provider, array $names, string $type ) : \Aimeos\MShop\Rule\Provider\Iface
112
	{
113
		$classprefix = '\Aimeos\MShop\Rule\Provider\\' . $type . '\Decorator\\';
114
115
		foreach( $names as $name )
116
		{
117
			if( ctype_alnum( $name ) === false ) {
118
				throw new \Aimeos\MShop\Rule\Exception( sprintf( 'Invalid characters in class name "%1$s"', $name ) );
119
			}
120
121
			$classname = $classprefix . $name;
122
123
			if( class_exists( $classname ) === false ) {
124
				throw new \Aimeos\MShop\Rule\Exception( sprintf( 'Class "%1$s" not available', $classname ) );
125
			}
126
127
			$provider = new $classname( $this->getContext(), $ruleItem, $provider );
128
129
			self::checkClass( $classprefix . 'Iface', $provider );
130
		}
131
132
		return $provider;
133
	}
134
}
135