Completed
Push — master ( 9990f6...68e6db )
by Nicolas
01:47
created

Client::setLogger()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Elastica;
4
5
use Elastica\Bulk\Action;
6
use Elastica\Exception\ConnectionException;
7
use Elastica\Exception\InvalidException;
8
use Elastica\Script\AbstractScript;
9
use Elasticsearch\Endpoints\AbstractEndpoint;
10
use Elasticsearch\Endpoints\Indices\ForceMerge;
11
use Elasticsearch\Endpoints\Indices\Refresh;
12
use Elasticsearch\Endpoints\Update;
13
use Psr\Log\LoggerInterface;
14
use Psr\Log\NullLogger;
15
16
/**
17
 * Client to connect the the elasticsearch server.
18
 *
19
 * @author Nicolas Ruflin <[email protected]>
20
 */
21
class Client
22
{
23
    /**
24
     * @var ClientConfiguration
25
     */
26
    protected $_config;
27
28
    /**
29
     * @var callback
30
     */
31
    protected $_callback;
32
33
    /**
34
     * @var Connection\ConnectionPool
35
     */
36
    protected $_connectionPool;
37
38
    /**
39
     * @var \Elastica\Request|null
40
     */
41
    protected $_lastRequest;
42
43
    /**
44
     * @var \Elastica\Response|null
45
     */
46
    protected $_lastResponse;
47
48
    /**
49
     * @var LoggerInterface
50
     */
51
    protected $_logger;
52
53
    /**
54
     * @var string
55
     */
56
    protected $_version;
57
58
    /**
59
     * Creates a new Elastica client.
60
     *
61
     * @param array|string    $config   OPTIONAL Additional config or DSN of options
62
     * @param callback|null   $callback OPTIONAL Callback function which can be used to be notified about errors (for example connection down)
63
     * @param LoggerInterface $logger
64
     *
65
     * @throws \Elastica\Exception\InvalidException
66
     */
67
    public function __construct($config = [], callable $callback = null, LoggerInterface $logger = null)
68
    {
69
        if (\is_string($config)) {
70
            $configuration = ClientConfiguration::fromDsn($config);
71
        } elseif (\is_array($config)) {
72
            $configuration = ClientConfiguration::fromArray($config);
73
        } else {
74
            throw new InvalidException('Config parameter must be an array or a string.');
75
        }
76
77
        $this->_config = $configuration;
0 ignored issues
show
Documentation Bug introduced by
It seems like $configuration of type object<self> is incompatible with the declared type object<Elastica\ClientConfiguration> of property $_config.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
78
        $this->_callback = $callback;
79
        $this->_logger = $logger ?: new NullLogger();
80
81
        $this->_initConnections();
82
    }
83
84
    /**
85
     * Get current version.
86
     *
87
     * @return string
88
     */
89
    public function getVersion()
90
    {
91
        if ($this->_version) {
92
            return $this->_version;
93
        }
94
95
        $data = $this->request('/')->getData();
96
97
        return $this->_version = $data['version']['number'];
98
    }
99
100
    /**
101
     * Inits the client connections.
102
     */
103
    protected function _initConnections()
104
    {
105
        $connections = [];
106
107
        foreach ($this->getConfig('connections') as $connection) {
0 ignored issues
show
Bug introduced by
The expression $this->getConfig('connections') of type array|string is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
108
            $connections[] = Connection::create($this->_prepareConnectionParams($connection));
109
        }
110
111
        if ($this->_config->has('servers')) {
112
            $servers = $this->_config->get('servers');
113
            foreach ($servers as $server) {
114
                $connections[] = Connection::create($this->_prepareConnectionParams($server));
115
            }
116
        }
117
118
        // If no connections set, create default connection
119
        if (empty($connections)) {
120
            $connections[] = Connection::create($this->_prepareConnectionParams($this->getConfig()));
0 ignored issues
show
Bug introduced by
It seems like $this->getConfig() targeting Elastica\Client::getConfig() can also be of type string; however, Elastica\Client::_prepareConnectionParams() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
121
        }
122
123
        if (!$this->_config->has('connectionStrategy')) {
124
            if (true === $this->getConfig('roundRobin')) {
125
                $this->setConfigValue('connectionStrategy', 'RoundRobin');
126
            } else {
127
                $this->setConfigValue('connectionStrategy', 'Simple');
128
            }
129
        }
130
131
        $strategy = Connection\Strategy\StrategyFactory::create($this->getConfig('connectionStrategy'));
132
133
        $this->_connectionPool = new Connection\ConnectionPool($connections, $strategy, $this->_callback);
134
    }
135
136
    /**
137
     * Creates a Connection params array from a Client or server config array.
138
     *
139
     * @param array $config
140
     *
141
     * @return array
142
     */
143
    protected function _prepareConnectionParams(array $config)
144
    {
145
        $params = [];
146
        $params['config'] = [];
147
        foreach ($config as $key => $value) {
148
            if (\in_array($key, ['bigintConversion', 'curl', 'headers', 'url'])) {
149
                $params['config'][$key] = $value;
150
            } else {
151
                $params[$key] = $value;
152
            }
153
        }
154
155
        return $params;
156
    }
157
158
    /**
159
     * Sets specific config values (updates and keeps default values).
160
     *
161
     * @param array $config Params
162
     *
163
     * @return $this
164
     */
165
    public function setConfig(array $config)
166
    {
167
        foreach ($config as $key => $value) {
168
            $this->_config->set($key, $value);
169
        }
170
171
        return $this;
172
    }
173
174
    /**
175
     * Returns a specific config key or the whole
176
     * config array if not set.
177
     *
178
     * @param string $key Config key
179
     *
180
     * @throws \Elastica\Exception\InvalidException
181
     *
182
     * @return array|string Config value
183
     */
184
    public function getConfig($key = '')
185
    {
186
        return $this->_config->get($key);
187
    }
188
189
    /**
190
     * Sets / overwrites a specific config value.
191
     *
192
     * @param string $key   Key to set
193
     * @param mixed  $value Value
194
     *
195
     * @return $this
196
     */
197
    public function setConfigValue($key, $value)
198
    {
199
        return $this->setConfig([$key => $value]);
200
    }
201
202
    /**
203
     * @param array|string $keys    config key or path of config keys
204
     * @param mixed        $default default value will be returned if key was not found
205
     *
206
     * @return mixed
207
     */
208
    public function getConfigValue($keys, $default = null)
209
    {
210
        $value = $this->_config->getAll();
211
        foreach ((array) $keys as $key) {
212
            if (isset($value[$key])) {
213
                $value = $value[$key];
214
            } else {
215
                return $default;
216
            }
217
        }
218
219
        return $value;
220
    }
221
222
    /**
223
     * Returns the index for the given connection.
224
     *
225
     * @param string $name Index name to create connection to
226
     *
227
     * @return \Elastica\Index Index for the given name
228
     */
229
    public function getIndex($name)
230
    {
231
        return new Index($this, $name);
232
    }
233
234
    /**
235
     * Adds a HTTP Header.
236
     *
237
     * @param string $header      The HTTP Header
238
     * @param string $headerValue The HTTP Header Value
239
     *
240
     * @throws \Elastica\Exception\InvalidException If $header or $headerValue is not a string
241
     *
242
     * @return $this
243
     */
244
    public function addHeader($header, $headerValue)
245
    {
246
        if (\is_string($header) && \is_string($headerValue)) {
247
            if ($this->_config->has('headers')) {
248
                $headers = $this->_config->get('headers');
249
            } else {
250
                $headers = [];
251
            }
252
            $headers[$header] = $headerValue;
253
            $this->_config->set('headers', $headers);
254
        } else {
255
            throw new InvalidException('Header must be a string');
256
        }
257
258
        return $this;
259
    }
260
261
    /**
262
     * Remove a HTTP Header.
263
     *
264
     * @param string $header The HTTP Header to remove
265
     *
266
     * @throws \Elastica\Exception\InvalidException If $header is not a string
267
     *
268
     * @return $this
269
     */
270
    public function removeHeader($header)
271
    {
272
        if (\is_string($header)) {
273
            if ($this->_config->has('headers')) {
274
                $headers = $this->_config->get('headers');
275
                unset($headers[$header]);
276
                $this->_config->set('headers', $headers);
277
            }
278
        } else {
279
            throw new InvalidException('Header must be a string');
280
        }
281
282
        return $this;
283
    }
284
285
    /**
286
     * Uses _bulk to send documents to the server.
287
     *
288
     * Array of \Elastica\Document as input. Index and type has to be
289
     * set inside the document, because for bulk settings documents,
290
     * documents can belong to any type and index
291
     *
292
     * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
293
     *
294
     * @param array|\Elastica\Document[] $docs          Array of Elastica\Document
295
     * @param array                      $requestParams
296
     *
297
     * @throws \Elastica\Exception\InvalidException If docs is empty
298
     *
299
     * @return \Elastica\Bulk\ResponseSet Response object
300
     */
301 View Code Duplication
    public function updateDocuments(array $docs, array $requestParams = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
302
    {
303
        if (empty($docs)) {
304
            throw new InvalidException('Array has to consist of at least one element');
305
        }
306
307
        $bulk = new Bulk($this);
308
309
        $bulk->addDocuments($docs, Action::OP_TYPE_UPDATE);
310
        foreach ($requestParams as $key => $value) {
311
            $bulk->setRequestParam($key, $value);
312
        }
313
314
        return $bulk->send();
315
    }
316
317
    /**
318
     * Uses _bulk to send documents to the server.
319
     *
320
     * Array of \Elastica\Document as input. Index and type has to be
321
     * set inside the document, because for bulk settings documents,
322
     * documents can belong to any type and index
323
     *
324
     * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
325
     *
326
     * @param array|\Elastica\Document[] $docs          Array of Elastica\Document
327
     * @param array                      $requestParams
328
     *
329
     * @throws \Elastica\Exception\InvalidException If docs is empty
330
     *
331
     * @return \Elastica\Bulk\ResponseSet Response object
332
     */
333 View Code Duplication
    public function addDocuments(array $docs, array $requestParams = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
334
    {
335
        if (empty($docs)) {
336
            throw new InvalidException('Array has to consist of at least one element');
337
        }
338
339
        $bulk = new Bulk($this);
340
341
        $bulk->addDocuments($docs);
342
343
        foreach ($requestParams as $key => $value) {
344
            $bulk->setRequestParam($key, $value);
345
        }
346
347
        return $bulk->send();
348
    }
349
350
    /**
351
     * Update document, using update script. Requires elasticsearch >= 0.19.0.
352
     *
353
     * @param int|string                                               $id      document id
354
     * @param array|\Elastica\Script\AbstractScript|\Elastica\Document $data    raw data for request body
355
     * @param string                                                   $index   index to update
356
     * @param string                                                   $type    type of index to update
357
     * @param array                                                    $options array of query params to use for query. For possible options check es api
358
     *
359
     * @return \Elastica\Response
360
     *
361
     * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html
362
     */
363
    public function updateDocument($id, $data, $index, $type, array $options = [])
364
    {
365
        $endpoint = new Update();
366
        $endpoint->setID($id);
367
        $endpoint->setIndex($index);
368
        $endpoint->setType($type);
0 ignored issues
show
Deprecated Code introduced by
The method Elasticsearch\Endpoints\...ractEndpoint::setType() has been deprecated.

This method has been deprecated.

Loading history...
369
370
        if ($data instanceof AbstractScript) {
371
            $requestData = $data->toArray();
372
        } elseif ($data instanceof Document) {
373
            $requestData = ['doc' => $data->getData()];
374
375
            if ($data->getDocAsUpsert()) {
376
                $requestData['doc_as_upsert'] = true;
377
            }
378
379
            $docOptions = $data->getOptions(
380
                [
381
                    'version',
382
                    'version_type',
383
                    'routing',
384
                    'percolate',
385
                    'parent',
386
                    'retry_on_conflict',
387
                    'consistency',
388
                    'replication',
389
                    'refresh',
390
                    'timeout',
391
                ]
392
            );
393
            $options += $docOptions;
394
        } else {
395
            $requestData = $data;
396
        }
397
398
        //If an upsert document exists
399
        if ($data instanceof AbstractScript || $data instanceof Document) {
400
            if ($data->hasUpsert()) {
401
                $requestData['upsert'] = $data->getUpsert()->getData();
402
            }
403
        }
404
405
        $endpoint->setBody($requestData);
406
        $endpoint->setParams($options);
407
408
        $response = $this->requestEndpoint($endpoint);
409
410
        if ($response->isOk()
411
            && $data instanceof Document
412
            && ($data->isAutoPopulate() || $this->getConfigValue(['document', 'autoPopulate'], false))
413
        ) {
414
            $responseData = $response->getData();
415
            if (isset($responseData['_version'])) {
416
                $data->setVersion($responseData['_version']);
417
            }
418
        }
419
420
        return $response;
421
    }
422
423
    /**
424
     * Bulk deletes documents.
425
     *
426
     * @param array|\Elastica\Document[] $docs
427
     * @param array                      $requestParams
428
     *
429
     * @throws \Elastica\Exception\InvalidException
430
     *
431
     * @return \Elastica\Bulk\ResponseSet
432
     */
433 View Code Duplication
    public function deleteDocuments(array $docs, array $requestParams = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
434
    {
435
        if (empty($docs)) {
436
            throw new InvalidException('Array has to consist of at least one element');
437
        }
438
439
        $bulk = new Bulk($this);
440
        $bulk->addDocuments($docs, Action::OP_TYPE_DELETE);
441
442
        foreach ($requestParams as $key => $value) {
443
            $bulk->setRequestParam($key, $value);
444
        }
445
446
        return $bulk->send();
447
    }
448
449
    /**
450
     * Returns the status object for all indices.
451
     *
452
     * @return \Elastica\Status Status object
453
     */
454
    public function getStatus()
455
    {
456
        return new Status($this);
457
    }
458
459
    /**
460
     * Returns the current cluster.
461
     *
462
     * @return \Elastica\Cluster Cluster object
463
     */
464
    public function getCluster()
465
    {
466
        return new Cluster($this);
467
    }
468
469
    /**
470
     * Establishes the client connections.
471
     */
472
    public function connect()
473
    {
474
        return $this->_initConnections();
475
    }
476
477
    /**
478
     * @param \Elastica\Connection $connection
479
     *
480
     * @return $this
481
     */
482
    public function addConnection(Connection $connection)
483
    {
484
        $this->_connectionPool->addConnection($connection);
485
486
        return $this;
487
    }
488
489
    /**
490
     * Determines whether a valid connection is available for use.
491
     *
492
     * @return bool
493
     */
494
    public function hasConnection()
495
    {
496
        return $this->_connectionPool->hasConnection();
497
    }
498
499
    /**
500
     * @throws \Elastica\Exception\ClientException
501
     *
502
     * @return \Elastica\Connection
503
     */
504
    public function getConnection()
505
    {
506
        return $this->_connectionPool->getConnection();
507
    }
508
509
    /**
510
     * @return \Elastica\Connection[]
511
     */
512
    public function getConnections()
513
    {
514
        return $this->_connectionPool->getConnections();
515
    }
516
517
    /**
518
     * @return \Elastica\Connection\Strategy\StrategyInterface
519
     */
520
    public function getConnectionStrategy()
521
    {
522
        return $this->_connectionPool->getStrategy();
523
    }
524
525
    /**
526
     * @param array|\Elastica\Connection[] $connections
527
     *
528
     * @return $this
529
     */
530
    public function setConnections(array $connections)
531
    {
532
        $this->_connectionPool->setConnections($connections);
533
534
        return $this;
535
    }
536
537
    /**
538
     * Deletes documents with the given ids, index, type from the index.
539
     *
540
     * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
541
     *
542
     * @param array                  $ids     Document ids
543
     * @param string|\Elastica\Index $index   Index name
544
     * @param string|\Elastica\Type  $type    Type of documents
545
     * @param string|bool            $routing Optional routing key for all ids
546
     *
547
     * @throws \Elastica\Exception\InvalidException
548
     *
549
     * @return \Elastica\Bulk\ResponseSet Response  object
550
     */
551
    public function deleteIds(array $ids, $index, $type, $routing = false)
552
    {
553
        if (empty($ids)) {
554
            throw new InvalidException('Array has to consist of at least one id');
555
        }
556
557
        $bulk = new Bulk($this);
558
        $bulk->setIndex($index);
559
        $bulk->setType($type);
560
561
        foreach ($ids as $id) {
562
            $action = new Action(Action::OP_TYPE_DELETE);
563
            $action->setId($id);
564
565
            if (!empty($routing)) {
566
                $action->setRouting($routing);
0 ignored issues
show
Bug introduced by
It seems like $routing defined by parameter $routing on line 551 can also be of type boolean; however, Elastica\Bulk\Action::setRouting() does only seem to accept string|integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
567
            }
568
569
            $bulk->addAction($action);
570
        }
571
572
        return $bulk->send();
573
    }
574
575
    /**
576
     * Bulk operation.
577
     *
578
     * Every entry in the params array has to exactly on array
579
     * of the bulk operation. An example param array would be:
580
     *
581
     * array(
582
     *         array('index' => array('_index' => 'test', '_type' => 'user', '_id' => '1')),
583
     *         array('user' => array('name' => 'hans')),
584
     *         array('delete' => array('_index' => 'test', '_type' => 'user', '_id' => '2'))
585
     * );
586
     *
587
     * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
588
     *
589
     * @param array $params Parameter array
590
     *
591
     * @throws \Elastica\Exception\ResponseException
592
     * @throws \Elastica\Exception\InvalidException
593
     *
594
     * @return \Elastica\Bulk\ResponseSet Response object
595
     */
596
    public function bulk(array $params)
597
    {
598
        if (empty($params)) {
599
            throw new InvalidException('Array has to consist of at least one param');
600
        }
601
602
        $bulk = new Bulk($this);
603
604
        $bulk->addRawData($params);
605
606
        return $bulk->send();
607
    }
608
609
    /**
610
     * Makes calls to the elasticsearch server based on this index.
611
     *
612
     * It's possible to make any REST query directly over this method
613
     *
614
     * @param string       $path        Path to call
615
     * @param string       $method      Rest method to use (GET, POST, DELETE, PUT)
616
     * @param array|string $data        OPTIONAL Arguments as array or pre-encoded string
617
     * @param array        $query       OPTIONAL Query params
618
     * @param string       $contentType Content-Type sent with this request
619
     *
620
     * @throws Exception\ConnectionException|Exception\ClientException
621
     *
622
     * @return Response Response object
623
     */
624
    public function request($path, $method = Request::GET, $data = [], array $query = [], $contentType = Request::DEFAULT_CONTENT_TYPE)
625
    {
626
        $connection = $this->getConnection();
627
        $request = $this->_lastRequest = new Request($path, $method, $data, $query, $connection, $contentType);
0 ignored issues
show
Bug introduced by
It seems like $data defined by parameter $data on line 624 can also be of type string; however, Elastica\Request::__construct() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
628
        $this->_lastResponse = null;
629
630
        try {
631
            $response = $this->_lastResponse = $request->send();
632
        } catch (ConnectionException $e) {
633
            $this->_connectionPool->onFail($connection, $e, $this);
634
            $this->_logger->error('Elastica Request Failure', [
635
                'exception' => $e,
636
                'request' => $e->getRequest()->toArray(),
637
                'retry' => $this->hasConnection(),
638
            ]);
639
640
            // In case there is no valid connection left, throw exception which caused the disabling of the connection.
641
            if (!$this->hasConnection()) {
642
                throw $e;
643
            }
644
645
            return $this->request($path, $method, $data, $query);
646
        }
647
648
        $this->_logger->debug('Elastica Request', [
649
            'request' => $request,
650
            'response' => $this->_lastResponse ? $this->_lastResponse->getData() : null,
651
            'responseStatus' => $this->_lastResponse ? $this->_lastResponse->getStatus() : null,
652
        ]);
653
654
        return $response;
655
    }
656
657
    /**
658
     * Makes calls to the elasticsearch server with usage official client Endpoint.
659
     *
660
     * @param AbstractEndpoint $endpoint
661
     *
662
     * @return Response
663
     */
664
    public function requestEndpoint(AbstractEndpoint $endpoint)
665
    {
666
        return $this->request(
667
            \ltrim($endpoint->getURI(), '/'),
668
            $endpoint->getMethod(),
669
            null === $endpoint->getBody() ? [] : $endpoint->getBody(),
670
            $endpoint->getParams()
671
        );
672
    }
673
674
    /**
675
     * Force merges all search indices.
676
     *
677
     * @param array $args OPTIONAL Optional arguments
678
     *
679
     * @return \Elastica\Response Response object
680
     *
681
     * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html
682
     */
683
    public function forcemergeAll($args = [])
684
    {
685
        $endpoint = new ForceMerge();
686
        $endpoint->setParams($args);
687
688
        return $this->requestEndpoint($endpoint);
689
    }
690
691
    /**
692
     * Refreshes all search indices.
693
     *
694
     * @return \Elastica\Response Response object
695
     *
696
     * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html
697
     */
698
    public function refreshAll()
699
    {
700
        return $this->requestEndpoint(new Refresh());
701
    }
702
703
    /**
704
     * @return Request|null
705
     */
706
    public function getLastRequest()
707
    {
708
        return $this->_lastRequest;
709
    }
710
711
    /**
712
     * @return Response|null
713
     */
714
    public function getLastResponse()
715
    {
716
        return $this->_lastResponse;
717
    }
718
719
    /**
720
     * Replace the existing logger.
721
     *
722
     * @param LoggerInterface $logger
723
     *
724
     * @return $this
725
     */
726
    public function setLogger(LoggerInterface $logger)
727
    {
728
        $this->_logger = $logger;
729
730
        return $this;
731
    }
732
}
733