Completed
Push — master ( d63021...7a62eb )
by Peter
04:31
created

ConditionDecorator::decorate()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 6
cts 6
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 7
nc 2
nop 2
crap 4
1
<?php
2
3
/**
4
 * This software package is licensed under AGPL or Commercial license.
5
 *
6
 * @package maslosoft/mangan
7
 * @licence AGPL or Commercial
8
 * @copyright Copyright (c) Piotr Masełkowski <[email protected]>
9
 * @copyright Copyright (c) Maslosoft
10
 * @copyright Copyright (c) Others as mentioned in code
11
 * @link https://maslosoft.com/mangan/
12
 */
13
14
namespace Maslosoft\Mangan\Criteria;
15
16
use Maslosoft\Addendum\Interfaces\AnnotatedInterface;
17
use Maslosoft\Mangan\Interfaces\ConditionDecoratorInterface;
18
use Maslosoft\Mangan\Interfaces\InternationalInterface;
19
use Maslosoft\Mangan\Meta\ManganMeta;
20
use Maslosoft\Mangan\Transformers\CriteriaArray;
21
22
/**
23
 * This class is used to decorate and sanitize conditions.
24
 * This should not be used directly. This is internal component of Criteria.
25
 *
26
 * @internal Criteria sub component
27
 * @author Piotr Maselkowski <pmaselkowski at gmail.com>
28
 */
29
class ConditionDecorator implements ConditionDecoratorInterface
30
{
31
32
	/**
33
	 * Model instance
34
	 * @var AnnotatedInterface
35
	 */
36
	private $model = null;
37
38
	/**
39
	 * Metadata
40
	 * @var ManganMeta
41
	 */
42
	private $meta = null;
43
44 111
	public function __construct(AnnotatedInterface $model = null)
45
	{
46 111
		if (!$model || !$model instanceof AnnotatedInterface)
47
		{
48 102
			return;
49
		}
50
		// Clone is to prevent possible required constructor params issues
51 109
		$this->model = clone $model;
52 109
		$this->meta = ManganMeta::create($this->model);
53
54
		/**
55
		 * NOTE: This is a workaround for:
56
		 * https://github.com/Maslosoft/Mangan/issues/82
57
		 * Condition decorator possibly fails on non-first language decoration of I18N field. #82
58
		 *
59
		 * TODO Should not depend on I18N here.
60
		 */
61 109
		if($this->model instanceof InternationalInterface)
62
		{
63 50
			$this->model->setLanguages([$this->model->getLang()]);
64
		}
65 109
	}
66
67
	/**
68
	 * @return AnnotatedInterface
69
	 */
70 6
	public function getModel()
71
	{
72 6
		return $this->model;
73
	}
74
75 103
	public function decorate($field, $value = null)
76
	{
77
		// 1. Do not decorate if empty model or dot notation
78
		// 2. Ignore non existing fields
79 103
		if (!$this->model || strstr($field, '.') || $this->meta->$field === false)
80
		{
81
			return [
82 81
				$field => $value
83
			];
84
		}
85
86 91
		$this->model->$field = $value;
87 91
		$data = CriteriaArray::fromModel($this->model, [$field]);
88
89 91
		return $this->_flatten($field, $this->model->$field, $data[$field]);
90
	}
91
92 91
	private function _flatten($field, $srcValue, $data)
93
	{
94 91
		$value = $data;
95 91
		while (is_array($value))
96
		{
97 9
			if(empty($value))
98
			{
99 1
				break;
100
			}
101
			// Flat value traverse
102 8
			foreach ($value as $key => $val)
103
			{
104 8
				if ($srcValue === $val)
105
				{
106 7
					$value = $value[$key];
107 7
					$field = "$field.$key";
108 8
					break 2;
109
				}
110
			}
111
112
			// Nested value
113 1
			$key = key($value);
114 1
			$value = $value[$key];
115 1
			$field = "$field.$key";
116 1
			if ($srcValue === $value)
117
			{
118
				break;
119
			}
120
		}
121
122
123
		return [
124 91
			$field => $value
125
		];
126
	}
127
128
}
129