Completed
Branch 1707_add_explain_command (4124c6)
by Alessandro
02:34
created

ExplainQueryService::getDeleteArgs()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 0
cts 9
cp 0
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Facile\MongoDbBundle\Services;
4
5
use Facile\MongoDbBundle\Models\Query;
6
use MongoDB\Driver\Command;
7
use MongoDB\Driver\Cursor;
8
9
class ExplainQueryService
10
{
11
    const VERBOSITY_QUERY_PLANNER = 'queryPlanner';
12
    const VERBOSITY_EXECUTION_STATS = 'executionStats';
13
    const VERBOSITY_ALL_PLAN_EXECUTION = 'allPlansExecution';
14
15
    public static $acceptedMethods= [
16
        'count',
17
        'distinct',
18
        'find',
19
        'findOne',
20
        'findOneAndUpdate',
21
        'findOneAndDelete',
22
        'deleteOne',
23
        'deleteMany',
24
        'aggregate',
25
    ];
26
27
    /** @var ClientRegistry */
28
    private $clientRegistry;
29
30
    /**
31
     * Constructs a explain command.
32
     *
33
     * Supported options:
34
     * verbosity : queryPlanner | executionStats Mode | allPlansExecution (default)
35
     * The explain command provides information on the execution of the following commands:
36
     * count, distinct, group, find, findAndModify, delete, and update.
37
     *
38
     * @param ClientRegistry $clientRegistry
39
     */
40
    public function __construct(ClientRegistry $clientRegistry)
41
    {
42
43
        $this->clientRegistry = $clientRegistry;
44
    }
45
46
    /**
47
     * Execute the operation.
48
     *
49
     * @param Query  $query
50
     * @param string $verbosity
51
     *
52
     * @return Cursor
53
     */
54
    public function execute(Query $query, string $verbosity = self::VERBOSITY_ALL_PLAN_EXECUTION): Cursor
55
    {
56
        if (!in_array($query->getMethod(), self::$acceptedMethods)) {
57
            throw new \InvalidArgumentException(
58
                'Cannot explain the method \''.$query->getMethod().'\'. Allowed methods: '. implode(', ',self::$acceptedMethods)
59
            );
60
        };
61
62
        $manager = $this->clientRegistry->getClient($query->getClient())->getManager();
63
64
        return $manager
65
            ->executeCommand($query->getDatabase(), $this->createCommand($query, $verbosity));
66
    }
67
68
    /**
69
     * Create the explain command.
70
     *
71
     * @param Query  $query
72
     * @param string $verbosity
73
     *
74
     * @return Command
75
     */
76
    private function createCommand(Query $query, string $verbosity)
77
    {
78
        $args = [
79
            $query->getMethod() => $query->getCollection(),
80
        ];
81
        switch($query->getMethod()) {
82
            case 'count':
83
                $args +=  $this->getCountArgs($query);break;
0 ignored issues
show
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
84
            case 'find':
85
            case 'findOne':
86
            case 'findOneAndUpdate':
87
            case 'findOneAndDelete':
88
                $args =  $this->getFindArgs($query);break;
0 ignored issues
show
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
89
            case 'distinct':
90
                $args +=  $this->getDistinctArgs($query);break;
0 ignored issues
show
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
91
            case 'deleteOne':
92
            case 'deleteMany':
93
                $args =  $this->getDeleteArgs($query);break;
0 ignored issues
show
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
94
            case 'aggregate':
95
                return new Command([
96
                    'aggregate' => $query->getCollection(),
97
                    'pipeline' => $query->getData(),
98
                    'explain' => true,
99
                ]);
100
        }
101
102
        $cmd = [
103
            'explain' => $args,
104
            'verbosity' => $verbosity,
105
        ];
106
107
        return new Command($cmd);
108
    }
109
110
    private function getCountArgs(Query $query)
111
    {
112
        $args = [
113
            'query' => $query->getFilters(),
114
        ];
115
116 View Code Duplication
        foreach (['limit', 'hint', 'skip'] as $supportedOption) {
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...
117
            $args += (isset($query->getOptions()[$supportedOption]) ? [$supportedOption => $query->getOptions()[$supportedOption]] : []);
118
        }
119
120
        return $args;
121
    }
122
123
    private function getFindArgs(Query $query)
124
    {
125
        $args = [
126
            'find' => $query->getCollection(),
127
            'filter' => $query->getFilters(),
128
        ];
129
130 View Code Duplication
        foreach (['sort', 'projection', 'hint', 'skip', 'limit'] as $supportedOption) {
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...
131
            $args += (isset($query->getOptions()[$supportedOption]) ? [$supportedOption => $query->getOptions()[$supportedOption]] : []);
132
        }
133
134
        return $args;
135
    }
136
137
    private function getDistinctArgs(Query $query)
138
    {
139
        return [
140
            'key' => $query->getData()['fieldName'],
141
            'query' => $query->getFilters(),
142
        ];
143
    }
144
145
    private function getDeleteArgs(Query $query)
146
    {
147
        return [
148
            'delete' => $query->getCollection(),
149
            'deletes' => [
150
                ['q' => $query->getFilters(), 'limit' => $query->getOptions()['limit'] ?? 0,]
151
            ]
152
        ];
153
    }
154
}
155