Passed
Pull Request — master (#72)
by
unknown
01:53
created

RestObject::skipUniqueFieldsValidation()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
cc 2
eloc 4
nc 2
nop 2
crap 2
1
<?php
2
namespace Fathomminds\Rest\Database\Clusterpoint;
3
4
use Fathomminds\Rest\Exceptions\RestException;
5
use Fathomminds\Rest\Objects\RestObject as CoreRestObject;
6
7
class RestObject extends CoreRestObject
8
{
9
    protected $primaryKey = '_id';
10
    protected $databaseClass = Database::class;
11
12 3
    public function find($client = null)
13
    {
14 3
        if ($client === null) {
15 1
            $client = $this->getClient();
16
        }
17 3
        return (new Finder($client))
18 3
            ->database($this->getDatabaseName())
19 3
            ->from($this->getResourceName());
20
    }
21
22 8
    public function validateUniqueFields()
23
    {
24 8
        $uniqueFields = $this->getUniqueFields();
25 8
        if ($this->skipUniqueFieldsValidation($uniqueFields, $this->isModification())) {
26 2
            return;
27
        }
28 6
        $query = $this->getUniqueFieldQuery($uniqueFields);
29 6
        $res = $query->get();
30 6
        if ((int)$res->hits() > 0) {
31 2
            $results = json_decode($res->rawResponse())->results;
32 2
            $message = $results[0]->{$this->primaryKey} === $this->getPrimaryKeyValue() ?
33 2
                'Primary key collision' : 'Unique constraint violation';
34 2
            throw new RestException(
35 2
                $message,
36 2
                ['resourceName' => $this->resourceName, 'confilct' => $results[0]]
37
            );
38
        }
39 4
    }
40
41 8
    private function skipUniqueFieldsValidation($uniqueFields, $isModification)
42
    {
43 8
        if ($isModification) {
44 3
            return $this->skipUniqueFieldsValidationModification($uniqueFields);
45
        }
46 5
        return $this->skipUniqueFieldsValidationCreation($uniqueFields);
47
    }
48
49 3
    private function skipUniqueFieldsValidationModification($uniqueFields)
50
    {
51 3
        $filteredUniqueKeys = array_diff($uniqueFields, [$this->primaryKey]);
52 3
        if (count($filteredUniqueKeys) > 0) {
53 2
            return false;
54
        }
55 1
        return true;
56
    }
57
58 5
    private function skipUniqueFieldsValidationCreation($uniqueFields)
59
    {
60 5
        $onlyOneUF = count($uniqueFields) === 1;
61 5
        $PKinUniqueFields = in_array($this->primaryKey, $uniqueFields);
62 5
        $PKnotSet = !property_exists($this->resource(), $this->primaryKey);
63 5
        if ($onlyOneUF && $PKinUniqueFields && $PKnotSet) {
64 1
            return true;
65
        }
66 4
        return false;
67
    }
68
69 6
    private function getUniqueFieldQuery($uniqueFields)
70
    {
71 6
        $query = $this->getClient()->database($this->getDatabaseName() . '.' . $this->resourceName);
72 6
        if ($this->isModification()) {
73 2
            $uniqueFields = array_diff($uniqueFields, [$this->primaryKey]);
74 2
            $query->where($this->primaryKey, '!=', $this->getPrimaryKeyValue(), false);
75
        }
76
        // @codeCoverageIgnoreStart
77
        $query->where(function($query) use ($uniqueFields) {
78
            foreach ($uniqueFields as $fieldName) {
79
                list($propertyExists, $propertyValue) = $this->getProperty($fieldName);
80
                if ($propertyExists) {
81
                    $this->validateUniqueFieldDataType($fieldName, $propertyValue);
82
                    $query->orWhere($fieldName, '==', $propertyValue, false);
83
                }
84
            }
85
        });
86
        // @codeCoverageIgnoreEnd
87 6
        return $query->limit(1);
88
    }
89
90 1
    private function getProperty($fieldNameDotted, $resource = null)
91
    {
92 1
        if ($resource === null) {
93 1
            $resource = $this->resource;
94
        }
95 1
        $fieldNameArr = explode('.', $fieldNameDotted);
96 1
        $fieldName = array_shift($fieldNameArr);
97 1
        if (!property_exists($resource, $fieldName)) {
98
            return [
99 1
                false,
100
                null
101
            ];
102
        }
103 1
        if (count($fieldNameArr) === 0) {
104
            return [
105 1
                true,
106 1
                $resource->{$fieldName}
107
            ];
108
        }
109 1
        return $this->getProperty(implode('.', $fieldNameArr), $resource->{$fieldName});
110
    }
111
112 1
    private function validateUniqueFieldDataType($fieldName, $propertyValue)
113
    {
114 1
        $dataType = gettype($propertyValue);
115 1
        if (in_array($dataType, $this->validUniqueFieldTypes)) {
116 1
            return;
117
        }
118 1
        throw new RestException(
119 1
            'Data type is invalid for unique field',
120
            [
121 1
                'resourceName' => $this->resourceName,
122 1
                'fieldName' => $fieldName,
123 1
                'data' => $propertyValue,
124 1
                'dataType' => $dataType,
125 1
                'validDataTypes' => $this->validUniqueFieldTypes
126
            ]
127
        );
128
    }
129
130 8
    private function isModification()
131
    {
132 8
        if ($this->updateMode() || $this->replaceMode()) {
133 3
            return true;
134
        }
135 5
        return false;
136
    }
137
138 1
    public function query()
139
    {
140 1
        $query = $this->getClient()->database($this->getDatabaseName() . '.' . $this->resourceName);
141 1
        return $query;
142
    }
143
}
144