Test Failed
Push — master ( 817d84...d52e3d )
by Raffael
05:44
created

Elasticsearch::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 0
cts 7
cp 0
rs 10
c 0
b 0
f 0
cc 1
crap 2
nc 1
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * balloon
7
 *
8
 * @copyright   Copryright (c) 2012-2019 gyselroth GmbH (https://gyselroth.com)
9
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
10
 */
11
12
namespace Balloon\App\Elasticsearch;
13
14
use Balloon\Filesystem;
15
use Balloon\Filesystem\Node\NodeInterface;
16
use Balloon\Server;
17
use Balloon\Server\User;
18
use Elasticsearch\Client;
19
use Generator;
20
use Psr\Log\LoggerInterface;
21
22
class Elasticsearch
23
{
24
    /**
25
     * ES client.
26
     *
27
     * @var Client
28
     */
29
    protected $client;
30
31
    /**
32
     * User.
33
     *
34
     * @var User
35
     */
36
    protected $user;
37
38
    /**
39
     * Filesystem.
40
     *
41
     * @var Filesystem
42
     */
43
    protected $fs;
44
45
    /**
46
     * Logger.
47
     *
48
     * @var LoggerInterface
49
     */
50
    protected $logger;
51
52
    /**
53
     * Constructor.
54
     */
55
    public function __construct(Server $server, Client $client, LoggerInterface $logger)
56
    {
57
        $this->client = $client;
58
        $this->logger = $logger;
59
        $this->user = $server->getIdentity();
60
        $this->fs = $server->getFilesystem();
61
    }
62
63
    /**
64
     * Search.
65
     */
66
    public function search(array $query, int $deleted = NodeInterface::DELETED_INCLUDE, ?int $skip = null, ?int $limit = null, ?int &$total = null): Generator
67
    {
68
        unset($query['body']['query']['bool']['must']);
69
        $result = $this->executeQuery($query, $skip, $limit);
70
71
        $this->logger->debug('elasticsearch query executed with ['.$result['hits']['total'].'] hits', [
72
            'category' => get_class($this),
73
            'params' => [
74
                'took' => $result['took'],
75
                'timed_out' => $result['timed_out'],
76
                '_shards' => $result['_shards'],
77
                'max_score' => $result['hits']['max_score'],
78
                'hits' => $result['hits']['total'],
79
            ],
80
        ]);
81
82
        $total = $result['hits']['total'];
83
84
        $nodes = [];
85
        foreach ($result['hits']['hits'] as $node) {
86
            if ('nodes' === $node['_index']) {
87
                $nodes[$node['_id']] = $node;
88
            } elseif ('blobs' === $node['_index']) {
89
                if (isset($node['_source']['metadata']['ref'])) {
90
                    foreach ($node['_source']['metadata']['ref'] as $blob) {
91
                        $nodes[$blob['id']] = $blob;
92
                    }
93
                }
94
95
                if (isset($node['_source']['metadata']['share_ref'])) {
96
                    foreach ($node['_source']['metadata']['share_ref'] as $blob) {
97
                        $nodes[$blob['id']] = $blob;
98
                    }
99
                }
100
            }
101
        }
102
103
        return $this->fs->findNodesById(array_keys($nodes), null, $deleted);
104
    }
105
106
    /**
107
     * Search.
108
     *
109
     * @param int $skip
110
     * @param int $limit
111
     */
112
    protected function executeQuery(array $query, ?int $skip = null, ?int $limit = null): array
113
    {
114
        $shares = $this->user->getShares();
115
        $bool = $query['body']['query'];
116
117
        $filter1 = [];
118
        $filter1['bool']['should'][]['term']['owner'] = (string) $this->user->getId();
119
        $filter1['bool']['should'][]['term']['metadata.ref.owner'] = (string) $this->user->getId();
120
121
        $share_filter = [
122
            'bool' => [
123
                'should' => [],
124
            ],
125
        ];
126
127
        foreach ($shares as $share) {
128
            $share = (string) $share;
129
            $share_filter['bool']['should'][]['term']['metadata.share_ref.share'] = $share;
130
            $share_filter['bool']['should'][]['term']['shared'] = $share;
131
            $share_filter['bool']['minimum_should_match'] = 1;
132
        }
133
134
        if (count($share_filter['bool']['should']) >= 1) {
135
            $rights_filter = [];
136
            $rights_filter['bool']['should'][] = $share_filter;
137
            $rights_filter['bool']['should'][] = $filter1;
138
            $rights_filter['bool']['minimum_should_match'] = 1;
139
        } else {
140
            $rights_filter = $filter1;
141
        }
142
143
        $query['body']['query']['bool'] = [
144
            'must' => [
145
                $bool,
146
                $rights_filter,
147
            ],
148
        ];
149
150
        $query['_source'] = ['metadata.*', '_id', 'owner'];
151
        $query['from'] = $skip;
152
        $query['size'] = $limit;
153
154
        $this->logger->debug('prepared elasticsearch query', [
155
            'category' => get_class($this),
156
            'params' => $query,
157
        ]);
158
159
        $result = $this->client->search($query);
160
161
        if ($result === null || $result['_shards']['failed'] > 0) {
162
            throw new Exception\InvalidQuery('elasticsearch query failed');
163
        }
164
165
        return $result;
166
    }
167
}
168