Completed
Push — master ( 31b733...8aa96a )
by Mehmet
03:17
created

MongoDB::create()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 2
rs 10
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, $debug = false)
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
        if($debug){
159
            return ['filters'=>$query_filters, 'start'=>$start, 'limit'=>$limit];
160
        }
161 1
        $count = $collection->count($query_filters);
162
163 1
        if($debug){
164
            return ['filters'=>$query_filters, 'start'=>$start, 'limit'=>$limit,'sort'=>$sort];
165
        }
166 1
        if ($count > 0) {
167 1
            $results = [];
168
            $options = [
169 1
                'limit' => (int) $limit,
170 1
                'skip' => (int) $start,
171 1
                'typeMap' => ['root' => 'array', 'document' => 'array'],
172 1
            ];
173 1
            if ($fields!==null) {
174
                $projection = [];
175
                foreach ($fields as $field) {
176
                    if ($field=='id') {
177
                        $field = '_id';
178
                    }
179
                    $projection[$field] = true;
180
                }
181
                $options['projection'] = $projection;
182
            }
183 1
            if ($sort!==null) {
184
                foreach ($sort as $sort_key => $sort_dir) {
185
                    $sort[$sort_key] = ($sort_dir=='desc') ? -1 : 1;
186
                    if ($sort_key=='id') {
187
                        $sort['_id'] = $sort[$sort_key];
188
                        unset($sort['id']);
189
                    }
190
                }
191
                $options['sort'] = $sort;
192
            }
193
194 1
            $cursor = $collection->find($query_filters, $options);
195 1
            $iterator = new \IteratorIterator($cursor);
196 1
            $iterator->rewind();
197 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...
198 1
                if (isset($doc['_id'])) {
199 1
                    $doc['id'] = (string) $doc['_id'];
200 1
                    unset($doc['_id']);
201 1
                }
202 1
                $results[] = $doc;
203 1
                $iterator->next();
204 1
            }
205 1
            return ['total' => $count, 'data' => $results];
206
        }
207
        return ['total' => 0, 'data' => null];
208
    }
209
210
    public function query($collection)
211
    {
212
        return new MongoDBQueryBuilder($collection);
213
    }
214
215 2
    public static function buildFilter($filter)
216
    {
217 2
        $filters = [];
218 2
        foreach ($filter as $key => $value) {
219
            
220 2
            if (strpos($key, '__')!==false) {
221 1
                $filters[] = self::buildFilterForKeys($key, $value);
222
                //$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...
223 2
            } elseif (strpos($key, '__') === false && is_array($value)) {
224 1
                $filters[]['$or'] = self::buildFilterForOr($value);
225 1
            } else {
226 2
                $filters[][$key] = $value;
227
            }
228 2
        }
229 2
        return $filters;
230 1
    }
231
232 1
    public static function buildFilterForOr($orValues)
233
    {
234 1
        $filters = [];
235 1
        foreach ($orValues as $filter) {
236 1
            $subKey = array_keys($filter)[0];
237 1
            $subValue = $filter[$subKey];
238 1
            if (strpos($subKey, '__')!==false) {
239 1
                $filters[] = self::buildFilterForKeys($subKey, $subValue);
240
               // $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...
241 1
            } else {
242
                $filters[][$subKey] = $subValue;
243
            }
244 1
        }
245 1
        return $filters;
246
    }
247
248
    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...
249
250
        foreach ($tmpFilters as $fKey => $fVals) {
251
            if (isset($filters[$fKey])) {
252
                foreach ($fVals as $fVal) {
253
                    $filters[$fKey][] = $fVal;
254
                }
255
            } else {
256
                $filters[$fKey] = $fVals;
257
            }
258
        }
259
        return $filters;
260
    }
261
262 2
    private static function buildFilterForKeys($key, $value)
263
    {
264 2
        preg_match('/__(.*?)$/i', $key, $matches);
265 1
        $operator = $matches[1];
266
        switch ($operator) {
267 1
            case '!in':
268
                $operator = 'nin';
269
                break;
270 1
            case 'not':
271
                $operator = 'ne';
272
                break;
273 1
            case 'wildcard':
274
                $operator = 'regex';
275
                $value = str_replace(array('?'), array('.'), $value);
276
                break;
277 1
            case 'prefix':
278
                $operator = 'regex';
279
                $value = $value.'*';
280
                break;
281
        }
282 1
        $key = str_replace($matches[0], '', $key);
283 1
        $filters= [$key => ['$'.$operator => $value]];
284 1
        return $filters;
285
    }
286
287
}
288