Completed
Push — master ( 64eab5...f30352 )
by Fran
02:01
created

NOSQLQuery::composeFilter()   B

Complexity

Conditions 9
Paths 9

Size

Total Lines 39
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 31
dl 0
loc 39
rs 8.0555
c 0
b 0
f 0
cc 9
nc 9
nop 2
1
<?php
2
namespace NOSQL\Models;
3
4
use MongoDB\BSON\ObjectId;
5
use MongoDB\Database;
6
use NOSQL\Services\Base\NOSQLBase;
7
use NOSQL\Dto\Model\ResultsetDto;
8
use NOSQL\Models\base\NOSQLParserTrait;
9
use PSFS\base\config\Config;
10
use PSFS\base\exception\ApiException;
11
use PSFS\base\types\Api;
12
13
final class NOSQLQuery {
14
    /**
15
     * @param $pk
16
     * @param Database|null $con
17
     * @return mixed
18
     * @throws ApiException
19
     */
20
    public static function findPk($modelName, $pk, Database $con = null) {
21
        $model = new $modelName();
22
        $con = NOSQLParserTrait::initConnection($model, $con);
23
        $collection = $con->selectCollection($model->getSchema()->name);
24
        $result = $collection->findOne(['_id' => new ObjectId($pk)]);
25
        if(null !== $result) {
26
            $model->feed($result->getArrayCopy());
27
        } else {
28
            throw new ApiException(t('Document not found'), 404);
29
        }
30
        return $model;
31
    }
32
33
    /**
34
     * @param string $modelName
35
     * @param array $criteria
36
     * @param Database|null $con
37
     * @return ResultsetDto
38
     * @throws \NOSQL\Exceptions\NOSQLValidationException
39
     * @throws \PSFS\base\exception\GeneratorException
40
     */
41
    public static function find($modelName, array $criteria, Database $con = null) {
42
        /** @var NOSQLActiveRecord $model */
43
        $model = new $modelName();
44
        $con = NOSQLParserTrait::initConnection($model, $con);
45
        $collection = $con->selectCollection($model->getSchema()->name);
46
        $resultSet = new ResultsetDto(false);
47
        // TODO create Query model for it
48
        $filters = self::parseCriteria($criteria, $model);
49
        $resultSet->count = $collection->countDocuments($filters);
50
        $nosqlOptions = [
51
            'limit' => (integer)(array_key_exists(Api::API_LIMIT_FIELD, $criteria) ? $criteria[Api::API_LIMIT_FIELD] : Config::getParam('pagination.limit', 50)),
52
        ];
53
        $results = $collection->find($filters, $nosqlOptions);
54
        /** @var  $result */
55
        $items = $results->toArray();
56
        foreach($items as $item) {
57
            $model->feed($item->getArrayCopy(), true);
58
            $resultSet->items[] = $model->getDtoCopy(true);
59
        }
60
        return $resultSet;
61
    }
62
63
    /**
64
     * @param array $criteria
65
     * @param NOSQLActiveRecord $model
66
     * @return array
67
     */
68
    private static function parseCriteria(array $criteria, NOSQLActiveRecord $model)
69
    {
70
        $filters = [];
71
        foreach ($model->getSchema()->properties as $property) {
72
            if (array_key_exists($property->name, $criteria)) {
73
                $filterValue = self::composeFilter($criteria, $property);
74
                $filters[$property->name] = $filterValue;
75
            }
76
        }
77
        return $filters;
78
    }
79
80
    /**
81
     * @param array $criteria
82
     * @param \NOSQL\Dto\PropertyDto $property
83
     * @return array|bool|float|int|mixed
84
     */
85
    private static function composeFilter(array $criteria, \NOSQL\Dto\PropertyDto $property)
86
    {
87
        $filterValue = $criteria[$property->name];
88
        if (is_array($filterValue)) {
89
            $filterValue = [
90
                '$in' => $filterValue,
91
            ];
92
        } elseif (in_array($property->type, [
93
            NOSQLBase::NOSQL_TYPE_BOOLEAN,
94
            NOSQLBase::NOSQL_TYPE_INTEGER,
95
            NOSQLBase::NOSQL_TYPE_DOUBLE,
96
            NOSQLBase::NOSQL_TYPE_LONG])) {
97
            if ($property->type === NOSQLBase::NOSQL_TYPE_BOOLEAN) {
98
                switch ($filterValue) {
99
                    case '1':
100
                    case 1:
101
                    case 'true':
102
                    case true:
103
                        $filterValue = true;
104
                        break;
105
                    default:
106
                        $filterValue = false;
107
                        break;
108
                }
109
            } elseif (NOSQLBase::NOSQL_TYPE_INTEGER === $property->type) {
110
                $filterValue = (integer)$filterValue;
111
            } else {
112
                $filterValue = (float)$filterValue;
113
            }
114
            $filterValue = [
115
                '$eq' => $filterValue,
116
            ];
117
        } else {
118
            $filterValue = [
119
                '$regex' => $filterValue,
120
                '$options' => 'i',
121
            ];
122
        }
123
        return $filterValue;
124
    }
125
}