Completed
Push — master ( febdbe...957a77 )
by Fran
03:33
created

NOSQLActiveRecord::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
c 0
b 0
f 0
rs 10
cc 1
nc 1
nop 0
1
<?php
2
namespace NOSQL\Models;
3
4
use MongoDB\BSON\ObjectId;
5
use MongoDB\Database;
6
use NOSQL\Dto\Model\NOSQLModelDto;
7
use NOSQL\Exceptions\NOSQLValidationException;
8
use NOSQL\Models\base\NOSQLModelTrait;
9
use NOSQL\Models\base\NOSQLParserTrait;
10
use NOSQL\Services\ParserService;
11
use PSFS\base\Logger;
12
use PSFS\base\types\traits\SingletonTrait;
13
14
/**
15
 * Class NOSQLActiveRecord
16
 * @package NOSQL\Models
17
 */
18
abstract class NOSQLActiveRecord {
19
    use NOSQLModelTrait;
20
    use NOSQLParserTrait;
21
    use SingletonTrait;
22
23
    /**
24
     * NOSQLActiveRecord constructor.
25
     * @throws \NOSQL\Exceptions\NOSQLParserException
26
     * @throws \PSFS\base\exception\GeneratorException
27
     */
28
    public function __construct()
29
    {
30
        $this->hydrate();
31
    }
32
33
    /**
34
     * @return array
35
     */
36
    public function toArray() {
37
        return $this->dto->toArray();
38
    }
39
40
    /**
41
     * @param bool $cleanPk
42
     * @return \NOSQL\Dto\Model\NOSQLModelDto
43
     */
44
    public function getDtoCopy($cleanPk = false) {
45
        $copy = clone $this->dto;
46
        if($cleanPk) {
47
            $this->dto->resetPk();
48
        }
49
        return $copy;
50
    }
51
52
    private function prepareData() {
53
        $this->dto->validate(true);
54
    }
55
56
    /**
57
     * @param Database|null $con
58
     * @return bool
59
     */
60
    public function save(Database $con = null) {
61
        $saved = false;
62
        if(null === $con) {
63
            $con = ParserService::getInstance()->createConnection($this->getDomain());
64
        }
65
        $collection = $con->selectCollection($this->getSchema()->name);
66
        try {
67
            $isInsert = $isUpdate = false;
68
            $this->prepareData();
69
            $this->dto->setLastUpdate();
70
            if($this->isNew()) {
71
                $this->preInsert($con);
72
                $isInsert = true;
73
            } elseif ($this->isModified()) {
74
                $this->preUpdate($con);
75
                $isUpdate = true;
76
            }
77
            $result = $collection->insertOne($this->toArray());
78
            if($result->getInsertedCount() > 0) {
79
                $id = $result->getInsertedId();
80
                $this->dto->setPk($id->jsonSerialize()['$oid']);
81
                if($isInsert) {
82
                    $this->postInsert($con);
83
                } elseif($isUpdate) {
84
                    $this->postUpdate($con);
85
                }
86
                $saved = true;
87
                $this->countAction();
88
            }
89
        } catch(\Exception $exception) {
90
            if($exception instanceof NOSQLValidationException) {
91
                throw $exception;
92
            } else {
93
                Logger::log($exception->getMessage(), LOG_CRIT, $this->toArray());
94
            }
95
        }
96
        return $saved;
97
    }
98
99
    /**
100
     * @param Database|null $con
101
     * @return bool
102
     */
103
    public function update(Database $con = null) {
104
        $updated = false;
105
        if(null === $con) {
106
            $con = ParserService::getInstance()->createConnection($this->getDomain());
107
        }
108
        $collection = $con->selectCollection($this->getSchema()->name);
109
        try {
110
            $this->prepareData();
111
            $this->dto->setLastUpdate();
112
            $this->preUpdate($con);
113
            $data = $this->toArray();
114
            unset($data['_id']);
115
            $collection->findOneAndReplace(['_id' => new ObjectId($this->dto->getPk())], $data);
116
            $this->postUpdate($con);
117
            $updated = true;
118
            $this->countAction();
119
        } catch(\Exception $exception) {
120
            if($exception instanceof NOSQLValidationException) {
121
                throw $exception;
122
            } else {
123
                Logger::log($exception->getMessage(), LOG_CRIT, $this->toArray());
124
            }
125
        }
126
        return $updated;
127
    }
128
129
    /**
130
     * @param array $data
131
     * @param Database|null $con
132
     * @return int
133
     */
134
    public function bulkInsert(array $data, Database $con = null) {
135
        $inserts = 0;
136
        if(null === $con) {
137
            $con = ParserService::getInstance()->createConnection($this->getDomain());
138
        }
139
        $collection = $con->selectCollection($this->getSchema()->name);
140
        try {
141
            $dtos = $this->prepareInsertDtos($data, $con);
142
            $result = $collection->insertMany($data);
143
            $ids = $result->getInsertedIds();
144
            $inserts = $this->parseInsertedDtos($con, $ids, $dtos);
145
            $this->setActionCount($inserts);
146
        } catch(\Exception $exception) {
147
            Logger::log($exception->getMessage(), LOG_CRIT, $this->toArray());
148
        }
149
        return $inserts;
150
    }
151
152
    /**
153
     * @param Database|null $con
154
     * @return bool
155
     */
156
    public function delete(Database $con = null) {
157
        $deleted = false;
158
        if(null === $con) {
159
            $con = ParserService::getInstance()->createConnection($this->getDomain());
160
        }
161
        $collection = $con->selectCollection($this->getSchema()->name);
162
        try {
163
            $this->preDelete($con);
164
            $collection->deleteOne(['_id' => new ObjectId($this->dto->getPk())]);
165
            $this->postDelete($con);
166
            $deleted = true;
167
            $this->dto = null;
168
            $this->countAction();
169
        } catch(\Exception $exception) {
170
            Logger::log($exception->getMessage(), LOG_CRIT, $this->toArray());
171
        }
172
        return $deleted;
173
    }
174
175
    /**
176
     * @param array $data
177
     * @param Database $con
178
     * @return array
179
     * @throws \NOSQL\Exceptions\NOSQLValidationException
180
     */
181
    private function prepareInsertDtos(array $data, Database $con)
182
    {
183
        $dtos = [];
184
        /** @var NOSQLModelDto $dto */
185
        foreach ($data as $insertData) {
186
            $dto = $this->getDtoCopy(true);
187
            $dto->fromArray($insertData);
188
            $dto->setLastUpdate();
189
            $dtos[] = $dto;
190
            self::invokeHook($this, $dto, 'preInsert', $con);
191
            self::invokeHook($this, $dto, 'preSave', $con);
192
        }
193
        unset($dto);
194
        return $dtos;
195
    }
196
197
    /**
198
     * @param Database $con
199
     * @param ObjectId[] $ids
200
     * @param NOSQLModelDto[] $dtos
201
     * @return int
202
     * @throws \NOSQL\Exceptions\NOSQLValidationException
203
     */
204
    private function parseInsertedDtos(Database $con, $ids, $dtos)
205
    {
206
        $inserts = 0;
207
        foreach ($ids as $index => $insertedId) {
208
            $id = $insertedId->jsonSerialize();
0 ignored issues
show
Bug introduced by
The method jsonSerialize() does not exist on MongoDB\BSON\ObjectId. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

208
            /** @scrutinizer ignore-call */ 
209
            $id = $insertedId->jsonSerialize();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
209
            $dtos[$index]->setPk($id['$oid']);
210
            self::invokeHook($this, $dtos[$index], 'postInsert', $con);
211
            self::invokeHook($this, $dtos[$index], 'postSave', $con);
212
            $inserts++;
213
        }
214
        return $inserts;
215
    }
216
}