1<?php
2
3/**
4 * @see       https://github.com/laminas/laminas-log for the canonical source repository
5 * @copyright https://github.com/laminas/laminas-log/blob/master/COPYRIGHT.md
6 * @license   https://github.com/laminas/laminas-log/blob/master/LICENSE.md New BSD License
7 */
8
9namespace Laminas\Log\Writer;
10
11use DateTimeInterface;
12use Laminas\Log\Exception;
13use Laminas\Log\Formatter\FormatterInterface;
14use Laminas\Stdlib\ArrayUtils;
15use Mongo as MongoC;
16use MongoClient;
17use MongoCollection;
18use MongoDate;
19use Traversable;
20
21/**
22 * Mongo log writer.
23 */
24class Mongo extends AbstractWriter
25{
26    /**
27     * MongoCollection instance
28     *
29     * @var MongoCollection
30     */
31    protected $mongoCollection;
32
33    /**
34     * Options used for MongoCollection::save()
35     *
36     * @var array
37     */
38    protected $saveOptions;
39
40    /**
41     * Constructor
42     *
43     * @param MongoC|MongoClient|array|Traversable $mongo
44     * @param string $database
45     * @param string $collection
46     * @param array $saveOptions
47     * @throws Exception\InvalidArgumentException
48     * @throws Exception\ExtensionNotLoadedException
49     */
50    public function __construct($mongo, $database = null, $collection = null, array $saveOptions = [])
51    {
52        if (! extension_loaded('mongo')) {
53            throw new Exception\ExtensionNotLoadedException('Missing ext/mongo');
54        }
55
56        if ($mongo instanceof Traversable) {
57            // Configuration may be multi-dimensional due to save options
58            $mongo = ArrayUtils::iteratorToArray($mongo);
59        }
60        if (is_array($mongo)) {
61            parent::__construct($mongo);
62            $saveOptions = isset($mongo['save_options']) ? $mongo['save_options'] : [];
63            $collection  = isset($mongo['collection']) ? $mongo['collection'] : null;
64            $database    = isset($mongo['database']) ? $mongo['database'] : null;
65            $mongo       = isset($mongo['mongo']) ? $mongo['mongo'] : null;
66        }
67
68        if (null === $collection) {
69            throw new Exception\InvalidArgumentException('The collection parameter cannot be empty');
70        }
71
72        if (null === $database) {
73            throw new Exception\InvalidArgumentException('The database parameter cannot be empty');
74        }
75
76        if (! ($mongo instanceof MongoClient || $mongo instanceof MongoC)) {
77            throw new Exception\InvalidArgumentException(sprintf(
78                'Parameter of type %s is invalid; must be MongoClient or Mongo',
79                (is_object($mongo) ? get_class($mongo) : gettype($mongo))
80            ));
81        }
82
83        $this->mongoCollection = $mongo->selectCollection($database, $collection);
84        $this->saveOptions     = $saveOptions;
85    }
86
87    /**
88     * This writer does not support formatting.
89     *
90     * @param string|FormatterInterface $formatter
91     * @param array|null $options (unused)
92     * @return WriterInterface
93     */
94    public function setFormatter($formatter, array $options = null)
95    {
96        return $this;
97    }
98
99    /**
100     * Write a message to the log.
101     *
102     * @param array $event Event data
103     * @return void
104     * @throws Exception\RuntimeException
105     */
106    protected function doWrite(array $event)
107    {
108        if (null === $this->mongoCollection) {
109            throw new Exception\RuntimeException('MongoCollection must be defined');
110        }
111
112        if (isset($event['timestamp']) && $event['timestamp'] instanceof DateTimeInterface) {
113            $event['timestamp'] = new MongoDate($event['timestamp']->getTimestamp());
114        }
115
116        $this->mongoCollection->save($event, $this->saveOptions);
117    }
118}
119