Completed
Push — master ( 6ac675...8a72f8 )
by Peter
07:00
created

UniqueValidator   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 92
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 90%

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 7
lcom 1
cbo 11
dl 0
loc 92
ccs 18
cts 20
cp 0.9
rs 10
c 2
b 0
f 1

1 Method

Rating   Name   Duplication   Size   Complexity  
C isValid() 0 39 7
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 http://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
	 * TODO Not implemented
62
	 *
63
	 * @see attributeName
64
	 * @since 1.0.8
65
	 */
66
	public $className;
67
68
	/**
69
	 * @var string the ActiveRecord class attribute name that should be
70
	 * used to look for the attribute value being validated. Defaults to null,
71
	 * meaning using the name of the attribute being validated.
72
	 *
73
	 * @see className
74
	 * @since 1.0.8
75
	 */
76
	public $attributeName;
77
78
	/**
79
	 * @var array additional query criteria. This will be combined with the condition
80
	 * that checks if the attribute value exists in the corresponding table column.
81
	 * This array will be used to instantiate a {@link Criteria} object.
82
	 * @since 1.0.8
83
	 */
84
	public $criteria = [];
85
86
	/**
87
	 * @Label('{attribute} "{value}" has already been taken')
88
	 * @var string
89
	 */
90
	public $msgTaken = '';
91
92
	/**
93
	 * Validates the attribute of the object.
94
	 * If there is any error, the error message is added to the object.
95
	 * @param AnnotatedInterface $model the object being validated
96
	 * @param string $attribute the attribute being validated
97
	 */
98 3
	public function isValid(AnnotatedInterface $model, $attribute)
99
	{
100 3
		$value = $model->$attribute;
101 3
		if ($this->allowEmpty && empty($value))
102
		{
103
			return true;
104
		}
105
106 3
		$className = empty($this->className) ? get_class($model) : $this->className;
107
108 3
		$compareModel = new $className;
109
110 3
		$criteria = (new Criteria)->decorateWith($compareModel);
111 3
		$criteria->addCond($attribute, '==', $value);
112
113 3
		if ($this->criteria !== [])
114
		{
115
			$criteria->mergeWith($this->criteria);
116
		}
117 3
		ScenarioManager::setScenario($compareModel, ValidatorInterface::ScenarioValidate);
118 3
		$finder = new Finder($compareModel);
119
120 3
		$found = $finder->find($criteria);
121
122
		// Not found entirely
123 3
		if (null === $found)
124
		{
125 1
			return true;
126
		}
127
128
		// Same pk
129 2
		if (PkManager::compare($found, $model))
130
		{
131 2
			return true;
132
		}
133 2
		$label = ManganMeta::create($model)->field($attribute)->label;
134 2
		$this->addError('msgTaken', ['{attribute}' => $label, '{value}' => $value]);
135 2
		return false;
136
	}
137
138
}
139