ConditionDecorator::_flatten()   B
last analyzed

Complexity

Conditions 6
Paths 7

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 6.0087

Importance

Changes 0
Metric Value
dl 0
loc 35
ccs 15
cts 16
cp 0.9375
rs 8.7377
c 0
b 0
f 0
cc 6
nc 7
nop 3
crap 6.0087
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\Decorators\ConditionDecoratorTypeAwareInterface;
19
use Maslosoft\Mangan\Interfaces\Decorators\ConditionDecoratorTypeInterface;
20
use Maslosoft\Mangan\Interfaces\InternationalInterface;
21
use Maslosoft\Mangan\Meta\ManganMeta;
22
use Maslosoft\Mangan\Transformers\CriteriaArray;
23
24
/**
25
 * This class is used to decorate and sanitize conditions.
26
 * This should not be used directly. This is internal component of Criteria.
27
 *
28
 * @internal Criteria sub component
29
 * @author Piotr Maselkowski <pmaselkowski at gmail.com>
30
 */
31
class ConditionDecorator implements ConditionDecoratorInterface, ConditionDecoratorTypeInterface
32
{
33
34
	/**
35
	 * Model instance
36
	 * @var AnnotatedInterface
37
	 */
38
	private $model = null;
39
40
	/**
41
	 * Metadata
42
	 * @var ManganMeta
43
	 */
44
	private $meta = null;
45
46
	private $decoratorType = CriteriaArray::class;
47
48 151
	public function __construct(AnnotatedInterface $model = null)
49
	{
50 151
		if (!$model || !$model instanceof AnnotatedInterface)
51
		{
52 138
			return;
53
		}
54
		// Clone is to prevent possible required constructor params issues
55 146
		$this->model = clone $model;
56 146
		$this->meta = ManganMeta::create($this->model);
57
58
		/**
59
		 * NOTE: This is a workaround for:
60
		 * https://github.com/Maslosoft/Mangan/issues/82
61
		 * Condition decorator possibly fails on non-first language decoration of I18N field. #82
62
		 *
63
		 * TODO Should not depend on I18N here.
64
		 */
65 146
		if($this->model instanceof InternationalInterface)
66
		{
67 75
			$this->model->setLanguages([$this->model->getLang()]);
68
		}
69 146
	}
70
71
	/**
72
	 * @return AnnotatedInterface
73
	 */
74 8
	public function getModel()
75
	{
76 8
		return $this->model;
77
	}
78
79
	/**
80
	 * @param string $decoratorType
81
	 * @return string
82
	 */
83
	public function setDecoratorType($decoratorType = CriteriaArray::class)
84
	{
85
		$this->decoratorType = $decoratorType;
86
		return $this;
87
	}
88
89
90
91 143
	public function decorate($field, $value = null)
92
	{
93
		// 1. Do not decorate if empty model or dot notation
94
		// 2. Ignore non existing fields
95 143
		if (!$this->model || strstr($field, '.') || $this->meta->$field === false)
96
		{
97
			return [
98 112
				$field => $value
99
			];
100
		}
101
102 126
		$this->model->$field = $value;
103
104 126
		$dt = $this->decoratorType;
105
106 126
		$data = $dt::fromModel($this->model, [$field]);
107
108 126
		return $this->_flatten($field, $this->model->$field, $data[$field]);
109
	}
110
111 126
	private function _flatten($field, $srcValue, $data)
112
	{
113 126
		$value = $data;
114 126
		while (is_array($value))
115
		{
116 17
			if(empty($value))
117
			{
118 1
				break;
119
			}
120
			// Flat value traverse
121 16
			foreach ($value as $key => $val)
122
			{
123 16
				if ($srcValue === $val)
124
				{
125 14
					$value = $value[$key];
126 14
					$field = "$field.$key";
127 14
					break 2;
128
				}
129
			}
130
131
			// Nested value
132 2
			$key = key($value);
133 2
			$value = $value[$key];
134 2
			$field = "$field.$key";
135 2
			if ($srcValue === $value)
136
			{
137
				break;
138
			}
139
		}
140
141
142
		return [
143 126
			$field => $value
144
		];
145
	}
146
147
}
148