Completed
Push — master ( 6a5328...43881d )
by Mehmet
02:51
created

MongoDB::multiGet()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 24
Code Lines 18

Duplication

Lines 8
Ratio 33.33 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 8
loc 24
ccs 0
cts 21
cp 0
rs 8.6845
cc 4
eloc 18
nc 6
nop 2
crap 20
1
<?php
2
3
namespace Soupmix;
4
/*
5
MongoDB Adapter
6
*/
7
8
class MongoDB implements Base
9
{
10
    protected $conn = null;
11
12
    private $dbName = null;
13
14
    private $database = null;
15
16 2
    public function __construct($config, \MongoDB\Client $client)
17
    {
18 2
        $this->dbName = $config['db_name'];
19 2
        $this->conn = $client;
20 2
        $this->database = $this->conn->{$this->dbName};
21 2
    }
22
23
    public function getConnection()
24
    {
25
        return $this->conn;
26
    }
27
28
    public function create($collection, $fields)
29
    {
30
        return $this->database->createCollection($collection);
31
    }
32
33
    public function drop($collection)
34
    {
35
        return $this->database->dropCollection($collection);
36
    }
37
38
    public function truncate($collection)
39
    {
40
        $this->database->dropCollection($collection);
41
        return $this->database->createCollection($collection);
42
    }
43
44
    public function createIndexes($collection, $indexes)
45
    {
46
        $collection = $this->database->selectCollection($collection);
47
        return $collection->createIndexes($indexes);
48
    }
49
50 2
    public function insert($collection, $values)
51
    {
52 2
        $collection = $this->database->selectCollection($collection);
53 2
        $result = $collection->insertOne($values);
54 2
        $docId = $result->getInsertedId();
55 2
        if (is_object($docId)) {
56 2
            return (string) $docId;
57
        }
58
        return null;
59
        
60
    }
61
62 1
    public function get($collection, $docId)
63
    {
64 1
        $collection = $this->database->selectCollection($collection);
65 1
        if (gettype($docId) == "array") {
66
            return $this->multiGet($collection, $docId);
67
        }
68 1
        return $this->singleGet($collection, $docId);
69
    }
70
71 1
    private function singleGet($collection, $docId)
72
    {
73
        $options = [
74 1
            'typeMap' => ['root' => 'array', 'document' => 'array'],
75 1
        ];
76 1
        $filter = ['_id' => new \MongoDB\BSON\ObjectID($docId)];
77 1
        $result = $collection->findOne($filter, $options);
78 1
        if ($result!==null) {
79 1
            $result['id'] = (string) $result['_id'];
80 1
            unset($result['_id']);
81 1
        }
82 1
        return $result;
83
    }
84
85
    private function multiGet($collection, $docIds)
86
    {
87
        $options = [
88
            'typeMap' => ['root' => 'array', 'document' => 'array'],
89
        ];
90
        $idList = [];
91
        foreach ($docIds as $itemId) {
92
            $idList[]=['_id'=>new \MongoDB\BSON\ObjectID($itemId)];
93
        }
94
        $filter = ['$or'=>$idList];
95
        $cursor = $collection->find($filter, $options);
96
        $iterator = new \IteratorIterator($cursor);
97
        $iterator->rewind();
98
        $results=[];
99 View Code Duplication
        while ($doc = $iterator->current()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
100
            if (isset($doc['_id'])) {
101
                $doc['id'] = (string) $doc['_id'];
102
                unset($doc['_id']);
103
            }
104
            $results[$doc['id']] = $doc;
105
            $iterator->next();
106
        }
107
        return $results;
108
    }
109
110
    public function update($collection, $filters, $values)
111
    {
112
        $collection = $this->database->selectCollection($collection);
113 View Code Duplication
        if (isset($filters['id'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
114
            $filters['_id'] = new \MongoDB\BSON\ObjectID($filters['id']);
115
            unset($filters['id']);
116
        }
117
        $query_filters = [];
118
        if ($filters != null) {
119
            $query_filters = ['$and' => self::buildFilter($filters)];
120
        }
121
        $values_set = ['$set' => $values];
122
        try{
123
            $result = $collection->updateMany($query_filters, $values_set);
124
125
        } catch (\Exception $e){
126
            throw new \Exception($e->getMessage());
127
        }
128
129
130
        return $result->getModifiedCount();
131
    }
132
133 2
    public function delete($collection, $filter)
134
    {
135 2
        $collection = $this->database->selectCollection($collection);
136 2
        $filter = self::buildFilter($filter)[0];
137
138 2
        if (isset($filter['id'])) {
139 2
            $filter['_id'] = new \MongoDB\BSON\ObjectID($filter['id']);
140 2
            unset($filter['id']);
141 2
        }
142 2
        $result = $collection->deleteMany($filter);
143
144 2
        return $result->getDeletedCount();
145
    }
146
147 1
    public function find($collection, $filters, $fields = null, $sort = null, $start = 0, $limit = 25)
148
    {
149 1
        $collection = $this->database->selectCollection($collection);
150 1 View Code Duplication
        if (isset($filters['id'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
151
            $filters['_id'] = new \MongoDB\BSON\ObjectID($filters['id']);
152
            unset($filters['id']);
153
        }
154 1
        $query_filters = [];
155 1
        if ($filters != null) {
156 1
            $query_filters = ['$and' => self::buildFilter($filters)];
157 1
        }
158 1
        $count = $collection->count($query_filters);
159 1
        if ($count > 0) {
160 1
            $results = [];
161
            $options = [
162 1
                'limit' => (int) $limit,
163 1
                'skip' => (int) $start,
164 1
                'typeMap' => ['root' => 'array', 'document' => 'array'],
165 1
            ];
166 1
            if ($fields!==null) {
167
                $projection = [];
168
                foreach ($fields as $field) {
169
                    if ($field=='id') {
170
                        $field = '_id';
171
                    }
172
                    $projection[$field] = true;
173
                }
174
                $options['projection'] = $projection;
175
            }
176 1
            if ($sort!==null) {
177
                foreach ($sort as $sort_key => $sort_dir) {
178
                    $sort[$sort_key] = ($sort_dir=='desc') ? -1 : 1;
179
                    if ($sort_key=='id') {
180
                        $sort['_id'] = $sort[$sort_key];
181
                        unset($sort['id']);
182
                    }
183
                }
184
                $options['sort'] = $sort;
185
            }
186
187 1
            $cursor = $collection->find($query_filters, $options);
188 1
            $iterator = new \IteratorIterator($cursor);
189 1
            $iterator->rewind();
190 1 View Code Duplication
            while ($doc = $iterator->current()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
191 1
                if (isset($doc['_id'])) {
192 1
                    $doc['id'] = (string) $doc['_id'];
193 1
                    unset($doc['_id']);
194 1
                }
195 1
                $results[] = $doc;
196 1
                $iterator->next();
197 1
            }
198 1
            return ['total' => $count, 'data' => $results];
199
        }
200
        return ['total' => 0, 'data' => null];
201
    }
202
203
    public function query($collection)
204
    {
205
        return new MongoDBQueryBuilder($collection, $this);
206
    }
207
208 2
    public static function buildFilter($filter)
209
    {
210 2
        $filters = [];
211 2
        foreach ($filter as $key => $value) {
212
            
213 2
            if (strpos($key, '__')!==false) {
214 1
                $filters[] = self::buildFilterForKeys($key, $value);
215
                //$filters = self::mergeFilters($filters, $tmpFilters);
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
216 2
            } elseif (strpos($key, '__') === false && is_array($value)) {
217 1
                $filters[]['$or'] = self::buildFilterForOr($value);
218 1
            } else {
219 2
                $filters[][$key] = $value;
220
            }
221 2
        }
222 2
        return $filters;
223
    }
224
225 1
    public static function buildFilterForOr($orValues)
226
    {
227 1
        $filters = [];
228 1
        foreach ($orValues as $filter) {
229 1
            $subKey = array_keys($filter)[0];
230 1
            $subValue = $filter[$subKey];
231 1
            if (strpos($subKey, '__')!==false) {
232 1
                $filters[] = self::buildFilterForKeys($subKey, $subValue);
233
               // $filters = self::mergeFilters($filters, $tmpFilters);
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
234 1
            } else {
235
                $filters[][$subKey] = $subValue;
236
            }
237 1
        }
238 1
        return $filters;
239
    }
240
241
    private static function mergeFilters ($filters, $tmpFilters){
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
242
243
        foreach ($tmpFilters as $fKey => $fVals) {
244
            if (isset($filters[$fKey])) {
245
                foreach ($fVals as $fVal) {
246
                    $filters[$fKey][] = $fVal;
247
                }
248
            } else {
249
                $filters[$fKey] = $fVals;
250
            }
251
        }
252
        return $filters;
253
    }
254
255 1
    private static function buildFilterForKeys($key, $value)
256
    {
257 1
        preg_match('/__(.*?)$/i', $key, $matches);
258 1
        $operator = $matches[1];
259
        switch ($operator) {
260 1
            case '!in':
261
                $operator = 'nin';
262
                break;
263 1
            case 'not':
264 1
                $operator = 'ne';
265
                break;
266 1
            case 'wildcard':
267
                $operator = 'regex';
268
                $value = str_replace(array('?'), array('.'), $value);
269
                break;
270 1
            case 'prefix':
271
                $operator = 'regex';
272
                $value = $value.'*';
273
                break;
274
        }
275 1
        $key = str_replace($matches[0], '', $key);
276 1
        $filters= [$key => ['$'.$operator => $value]];
277 1
        return $filters;
278
    }
279
280
}
281