Passed
Pull Request — develop (#79)
by
unknown
01:47
created

RestObject::skipUniqueFieldsValidationCreation()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 17
ccs 12
cts 12
cp 1
rs 8.2222
cc 7
eloc 12
nc 12
nop 1
crap 7
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 10
    public function validateUniqueFields()
23
    {
24 10
        $uniqueFields = $this->getUniqueFields();
25 10
        if ($this->skipUniqueFieldsValidation($uniqueFields, $this->isModification())) {
26 2
            return;
27
        }
28 8
        $query = $this->getUniqueFieldQuery($uniqueFields);
29 8
        $res = $query->get();
30 8
        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 6
    }
40
41 10
    private function skipUniqueFieldsValidation($uniqueFields, $isModification)
42
    {
43 10
        if ($isModification) {
44 3
            return $this->skipUniqueFieldsValidationModification($uniqueFields);
45
        }
46 7
        return $this->skipUniqueFieldsValidationCreation($uniqueFields);
47
    }
48
49 3
    private function skipUniqueFieldsValidationModification($uniqueFields)
50
    {
51 3
        $resource = $this->resource();
52 3
        $filteredUniqueFields = array_diff($uniqueFields, [$this->primaryKey]);
53 3
        foreach ($filteredUniqueFields as $uniqueField) {
54 2
            $UFisSet = (property_exists($resource, $uniqueField) && $resource->{$uniqueField} !== null);
55 2
            if ($UFisSet) {
56 2
                return false;
57
            }
58
        }
59 1
        return true;
60
    }
61
62 7
    private function skipUniqueFieldsValidationCreation($uniqueFields)
63
    {
64 7
        $resource = $this->resource();
65 7
        $PKisInUniqueFields = in_array($this->primaryKey, $uniqueFields);
66 7
        $PKisSet = (property_exists($resource, $this->primaryKey) && $resource->{$this->primaryKey} !== null);
67 7
        if ($PKisInUniqueFields && $PKisSet) {
68 5
            return false;
69
        }
70 2
        $filteredUniqueFields = array_diff($uniqueFields, [$this->primaryKey]);
71 2
        foreach ($filteredUniqueFields as $uniqueField) {
72 1
            $UFisSet = (property_exists($resource, $uniqueField) && $resource->{$uniqueField} !== null);
73 1
            if ($UFisSet) {
74 1
                return false;
75
            }
76
        }
77 1
        return true;
78
    }
79
80 8
    private function getUniqueFieldQuery($uniqueFields)
81
    {
82 8
        $query = $this->getClient()->database($this->getDatabaseName() . '.' . $this->resourceName);
83 8
        if ($this->isModification()) {
84 2
            $uniqueFields = array_diff($uniqueFields, [$this->primaryKey]);
85 2
            $query->where($this->primaryKey, '!=', $this->getPrimaryKeyValue(), false);
86
        }
87
        // @codeCoverageIgnoreStart
88
        $query->where(function($query) use ($uniqueFields) {
89
            foreach ($uniqueFields as $fieldName) {
90
                list($propertyExists, $propertyValue) = $this->getProperty($fieldName);
91
                if ($propertyExists && $propertyValue !== null) {
92
                    $this->validateUniqueFieldDataType($fieldName, $propertyValue);
93
                    $query->orWhere($fieldName, '==', $propertyValue, false);
94
                }
95
            }
96
        });
97
        // @codeCoverageIgnoreEnd
98 8
        return $query->limit(1);
99
    }
100
101 1
    private function getProperty($fieldNameDotted, $resource = null)
102
    {
103 1
        if ($resource === null) {
104 1
            $resource = $this->resource;
105
        }
106 1
        $fieldNameArr = explode('.', $fieldNameDotted);
107 1
        $fieldName = array_shift($fieldNameArr);
108 1
        if (!property_exists($resource, $fieldName)) {
109
            return [
110 1
                false,
111
                null
112
            ];
113
        }
114 1
        if (count($fieldNameArr) === 0) {
115
            return [
116 1
                true,
117 1
                $resource->{$fieldName}
118
            ];
119
        }
120 1
        return $this->getProperty(implode('.', $fieldNameArr), $resource->{$fieldName});
121
    }
122
123 1
    private function validateUniqueFieldDataType($fieldName, $propertyValue)
124
    {
125 1
        $dataType = gettype($propertyValue);
126 1
        if (in_array($dataType, $this->validUniqueFieldTypes)) {
127 1
            return;
128
        }
129 1
        throw new RestException(
130 1
            'Data type is invalid for unique field',
131
            [
132 1
                'resourceName' => $this->resourceName,
133 1
                'fieldName' => $fieldName,
134 1
                'data' => $propertyValue,
135 1
                'dataType' => $dataType,
136 1
                'validDataTypes' => $this->validUniqueFieldTypes
137
            ]
138
        );
139
    }
140
141 10
    private function isModification()
142
    {
143 10
        if ($this->updateMode() || $this->replaceMode()) {
144 3
            return true;
145
        }
146 7
        return false;
147
    }
148
149 1
    public function query()
150
    {
151 1
        $query = $this->getClient()->database($this->getDatabaseName() . '.' . $this->resourceName);
152 1
        return $query;
153
    }
154
}
155