Passed
Push — master ( 8a3ec8...8d1c9e )
by Mehmet
03:27
created

MongoDB::singleGet()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 13
rs 9.4285
cc 2
eloc 9
nc 2
nop 2
1
<?php
2
3
namespace Soupmix;
4
/*
5
MongoDB Adapter
6
*/
7
Use MongoDB as MongoDBLib;
8
9
class MongoDB implements Base
10
{
11
    public $conn = null;
12
13
    private $dbName = null;
14
15
    public $db = null;
16
17
    public function __construct($config)
18
    {
19
        $this->dbName = $config['db_name'];
20
        $this->connect($config);
21
    }
22
23
    public function connect($config)
24
    {
25
        $this->conn = new MongoDBLib\Client($config['connection_string'], $config['options']);
26
        $this->db = $this->conn->{$this->dbName};
27
    }
28
29
    public function create($collection, $config)
30
    {
31
        return $this->db->createCollection($collection);
32
    }
33
34
    public function drop($collection, $config)
35
    {
36
        return $this->db->dropCollection($collection);
37
    }
38
39
    public function truncate($collection, $config)
40
    {
41
        $this->db->dropCollection($collection);
42
43
        return $this->db->createCollection($collection);
44
    }
45
46
    public function createIndexes($collection, $indexes)
47
    {
48
        $collection = $this->db->selectCollection($collection);
49
50
        return $collection->createIndexes($indexes);
51
    }
52
53
    public function insert($collection, $values)
54
    {
55
        $collection = $this->db->selectCollection($collection);
56
        $result = $collection->insertOne($values);
57
        $docId = $result->getInsertedId();
58
        if (is_object($docId)) {
59
            return (string) $docId;
60
        }
61
        return null;
62
        
63
    }
64
65
    public function get($collection, $docId)
66
    {
67
        $collection = $this->db->selectCollection($collection);
68
        if (gettype($docId) == "array") {
69
            return $this->multiGet($collection, $docId);
70
        } else {
71
            return $this->singleGet($collection, $docId);
72
        }
73
    }
74
75
    private function singleGet($collection, $docId)
76
    {
77
        $options = [
78
            'typeMap' => ['root' => 'array', 'document' => 'array'],
79
        ];
80
        $filter = ['_id' => new MongoDBLib\BSON\ObjectID($docId)];
81
        $result = $collection->findOne($filter, $options);
82
        if ($result!==null) {
83
            $result['id'] = (string) $result['_id'];
84
            unset($result['_id']);
85
        }
86
        return $result;
87
    }
88
89
    private function multiGet($collection, $docIds)
90
    {
91
        $options = [
92
            'typeMap' => ['root' => 'array', 'document' => 'array'],
93
        ];
94
        $idList = [];
95
        foreach ($docIds as $itemId) {
96
            $idList[]=['_id'=>new MongoDBLib\BSON\ObjectID($itemId)];
97
        }
98
        $filter = ['$or'=>$idList];
99
        $cursor = $collection->find($filter, $options);
100
        $iterator = new \IteratorIterator($cursor);
101
        $iterator->rewind();
102
        $results=[];
103 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...
104
            if (isset($doc['_id'])) {
105
                $doc['id'] = (string) $doc['_id'];
106
                unset($doc['_id']);
107
            }
108
            $results[$doc['id']] = $doc;
109
            $iterator->next();
110
        }
111
        return $results;
112
    }
113
114
    public function update($collection, $filters, $values)
115
    {
116
        $collection = $this->db->selectCollection($collection);
117 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...
118
            $filters['_id'] = new MongoDBLib\BSON\ObjectID($filters['id']);
119
            unset($filters['id']);
120
        }
121
        $query_filters = [];
122
        if ($filters != null) {
123
            $query_filters = ['$and' => self::buildFilter($filters)];
124
        }
125
        $values_set = ['$set' => $values];
126
        try{
127
            $result = $collection->updateMany($query_filters, $values_set);
128
129
        } catch (\Exception $e){
130
            throw new \Exception($e->getMessage());
131
        }
132
133
134
        return $result->getModifiedCount();
135
    }
136
137
    public function delete($collection, $filter)
138
    {
139
        $collection = $this->db->selectCollection($collection);
140
        $filter = self::buildFilter($filter)[0];
141
142
        if (isset($filter['id'])) {
143
            $filter['_id'] = new MongoDBLib\BSON\ObjectID($filter['id']);
144
            unset($filter['id']);
145
        }
146
        $result = $collection->deleteMany($filter);
147
148
        return $result->getDeletedCount();
149
    }
150
151
    public function find($collection, $filters, $fields = null, $sort = null, $start = 0, $limit = 25, $debug = false)
152
    {
153
        $collection = $this->db->selectCollection($collection);
154 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...
155
            $filters['_id'] = new MongoDBLib\BSON\ObjectID($filters['id']);
156
            unset($filters['id']);
157
        }
158
        $query_filters = [];
159
        if ($filters != null) {
160
            $query_filters = ['$and' => self::buildFilter($filters)];
161
        }
162
        $count = $collection->count($query_filters);
163
        if ($count > 0) {
164
            $results = [];
165
            $options = [
166
                'limit' => (int) $limit,
167
                'skip' => (int) $start,
168
                'typeMap' => ['root' => 'array', 'document' => 'array'],
169
            ];
170
            if ($fields!==null) {
171
                $projection = [];
172
                foreach ($fields as $field) {
173
                    if ($field=='id') {
174
                        $field = '_id';
175
                    }
176
                    $projection[$field] = true;
177
                }
178
                $options['projection'] = $projection;
179
            }
180
            if ($sort!==null) {
181
                foreach ($sort as $sort_key => $sort_dir) {
182
                    $sort[$sort_key] = ($sort_dir=='desc') ? -1 : 1;
183
                    if ($sort_key=='id') {
184
                        $sort['_id'] = $sort[$sort_key];
185
                        unset($sort['id']);
186
                    }
187
                }
188
                $options['sort'] = $sort;
189
            }
190
            $cursor = $collection->find($query_filters, $options);
191
            $iterator = new \IteratorIterator($cursor);
192
            $iterator->rewind();
193 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...
194
                if (isset($doc['_id'])) {
195
                    $doc['id'] = (string) $doc['_id'];
196
                    unset($doc['_id']);
197
                }
198
                $results[] = $doc;
199
                $iterator->next();
200
            }
201
            return ['total' => $count, 'data' => $results];
202
        }
203
        return ['total' => 0, 'data' => null];
204
    }
205
206
    public function query($query)
207
    {
208
        // reserved
209
    }
210
211
    public static function buildFilter($filter)
212
    {
213
        $filters = [];
214
        foreach ($filter as $key => $value) {
215
            if (strpos($key, '__')!==false) {
216
                preg_match('/__(.*?)$/i', $key, $matches);
217
                $operator = $matches[1];
218
                switch ($operator) {
219
                    case '!in':
220
                        $operator = 'nin';
221
                        break;
222
                    case 'not':
223
                        $operator = 'ne';
224
                        break;
225
                    case 'wildcard':
226
                        $operator = 'regex';
227
                        $value = str_replace(array('?'), array('.'), $value);
228
                        break;
229
                    case 'prefix':
230
                        $operator = 'regex';
231
                        $value = $value.'*';
232
                        break;
233
                }
234
                $key = str_replace($matches[0], '', $key);
235
                $filters[] = [$key => ['$'.$operator => $value]];
236
            } elseif (strpos($key, '__')===false && is_array($value)) {
237
                $filters[]['$or'] = self::buildFilter($value);
238
            } else {
239
                $filters[][$key] = $value;
240
            }
241
        }
242
243
        return $filters;
244
    }
245
}
246