Completed
Push — master ( c8f19a...ddbfd2 )
by Peter
72:09 queued 69:12
created

UniqueValidator::isValid()   C

Complexity

Conditions 7
Paths 13

Size

Total Lines 39
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 7.0031

Importance

Changes 0
Metric Value
dl 0
loc 39
ccs 24
cts 25
cp 0.96
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 20
nc 13
nop 2
crap 7.0031
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\Validators\BuiltIn;
15
16
use Maslosoft\Addendum\Interfaces\AnnotatedInterface;
17
use Maslosoft\Mangan\Criteria;
18
use Maslosoft\Mangan\Finder;
19
use Maslosoft\Mangan\Helpers\PkManager;
20
use Maslosoft\Mangan\Interfaces\Validators\ValidatorInterface;
21
use Maslosoft\Mangan\Meta\ManganMeta;
22
use Maslosoft\Mangan\ScenarioManager;
23
use Maslosoft\Mangan\Validators\Traits\AllowEmpty;
24
use Maslosoft\Mangan\Validators\Traits\Messages;
25
use Maslosoft\Mangan\Validators\Traits\OnScenario;
26
use Maslosoft\Mangan\Validators\Traits\Safe;
27
use Maslosoft\Mangan\Validators\Traits\SkipOnError;
28
29
/**
30
 * UniqueValidator class file.
31
 *
32
 * @author Ianaré Sévi
33
 * @author Florian Fackler <[email protected]>
34
 * @link http://mintao.com
35
 * @copyright Copyright (c) 2008-2010 Yii Software LLC
36
 * @license New BSD license
37
 */
38
39
/**
40
 * UniqueValidator validates that the attribute value is unique in the corresponding database table.
41
 *
42
 * @author Florian Fackler <[email protected]>
43
 * @version $Id$
44
 * @package system.validators
45
 * @since 1.0
46
 */
47
class UniqueValidator implements ValidatorInterface
48
{
49
50
	use AllowEmpty,
51
	  SkipOnError,
52
	  Messages,
53
	  OnScenario,
54
	  Safe;
55
56
	/**
57
	 * @var string the document class name that should be used to
58
	 * look for the attribute value being validated. Defaults to null, meaning using
59
	 * the class of the object currently being validated.
60
	 *
61
	 * @see attributeName
62
	 * @since 1.0.8
63
	 */
64
	public $className;
65
66
	/**
67
	 * @var string the ActiveRecord class attribute name that should be
68
	 * used to look for the attribute value being validated. Defaults to null,
69
	 * meaning using the name of the attribute being validated.
70
	 *
71
	 * @see className
72
	 * @since 1.0.8
73
	 */
74
	public $attributeName;
75
76
	/**
77
	 * @var array additional query criteria. This will be combined with the condition
78
	 * that checks if the attribute value exists in the corresponding table column.
79
	 * This array will be used to instantiate a {@link Criteria} object.
80
	 * @since 1.0.8
81
	 */
82
	public $criteria = [];
83
84
	/**
85
	 * @Label('{attribute} "{value}" has already been taken')
86
	 * @var string
87
	 */
88
	public $msgTaken = '';
89
90
	/**
91
	 * Validates the attribute of the object.
92
	 * If there is any error, the error message is added to the object.
93
	 * @param AnnotatedInterface $model the object being validated
94
	 * @param string $attribute the attribute being validated
95
	 */
96 4
	public function isValid(AnnotatedInterface $model, $attribute)
97
	{
98 4
		$value = $model->$attribute;
99 4
		if ($this->allowEmpty && empty($value))
100 4
		{
101
			return true;
102
		}
103
104 4
		$className = empty($this->className) ? get_class($model) : $this->className;
105
106 4
		$compareModel = new $className;
107
108 4
		$criteria = (new Criteria)->decorateWith($compareModel);
109 4
		$criteria->addCond($attribute, '==', $value);
110
111 4
		if ($this->criteria !== [])
112 4
		{
113 1
			$criteria->mergeWith($this->criteria);
114 1
		}
115 4
		ScenarioManager::setScenario($compareModel, ValidatorInterface::ScenarioValidate);
116 4
		$finder = new Finder($compareModel);
117
118 4
		$found = $finder->find($criteria);
119
120
		// Not found entirely
121 4
		if (null === $found)
122 4
		{
123 2
			return true;
124
		}
125
126
		// Same pk
127 3
		if (PkManager::compare($found, $model))
128 3
		{
129 2
			return true;
130
		}
131 3
		$label = ManganMeta::create($model)->field($attribute)->label;
132 3
		$this->addError('msgTaken', ['{attribute}' => $label, '{value}' => $value]);
133 3
		return false;
134
	}
135
136
}
137