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 MongoDB\BSON\UTCDateTime; 16use MongoDB\Driver\BulkWrite; 17use MongoDB\Driver\Manager; 18use MongoDB\Driver\WriteConcern; 19use Traversable; 20 21/** 22 * MongoDB log writer. 23 */ 24class MongoDB extends AbstractWriter 25{ 26 /** 27 * @var Manager 28 */ 29 protected $manager; 30 31 /** 32 * @var string 33 */ 34 protected $database; 35 36 /** 37 * @var WriteConcern 38 */ 39 protected $writeConcern; 40 41 /** 42 * Constructor 43 * 44 * @param Manager|array|Traversable $manager 45 * @param string $database 46 * @param string $collection 47 * @param WriteConcern|array|Traversable $writeConcern 48 * @throws Exception\InvalidArgumentException 49 */ 50 public function __construct($manager, $database = null, $collection = null, $writeConcern = null) 51 { 52 if (! extension_loaded('mongodb')) { 53 throw new Exception\ExtensionNotLoadedException('Missing ext/mongodb'); 54 } 55 56 if ($manager instanceof Traversable) { 57 // Configuration may be multi-dimensional due to save options 58 $manager = ArrayUtils::iteratorToArray($manager); 59 } 60 61 if (is_array($manager)) { 62 parent::__construct($manager); 63 $writeConcern = isset($manager['write_concern']) ? $manager['write_concern'] : new WriteConcern(1); 64 $collection = isset($manager['collection']) ? $manager['collection'] : null; 65 $database = isset($manager['database']) ? $manager['database'] : null; 66 $manager = isset($manager['manager']) ? $manager['manager'] : null; 67 } 68 69 if (null === $database) { 70 throw new Exception\InvalidArgumentException('The database parameter cannot be empty'); 71 } 72 73 if (null !== $collection) { 74 $database = sprintf('%s.%s', $database, $collection); 75 } 76 77 if (! $manager instanceof Manager) { 78 throw new Exception\InvalidArgumentException(sprintf( 79 'Parameter of type %s is invalid; must be MongoDB\Driver\Manager', 80 (is_object($manager) ? get_class($manager) : gettype($manager)) 81 )); 82 } 83 84 if ($writeConcern instanceof Traversable) { 85 $writeConcern = iterator_to_array($writeConcern); 86 } 87 88 if (is_array($writeConcern)) { 89 $wstring = isset($writeConcern['wstring']) ? $writeConcern['wstring'] : 1; 90 $wtimeout = isset($writeConcern['wtimeout']) ? $writeConcern['wtimeout'] : 0; 91 $journal = isset($writeConcern['journal']) ? $writeConcern['journal'] : false; 92 $writeConcern = new WriteConcern($wstring, $wtimeout, $journal); 93 } 94 95 $this->manager = $manager; 96 $this->database = $database; 97 $this->writeConcern = $writeConcern; 98 } 99 100 /** 101 * This writer does not support formatting. 102 * 103 * @param string|FormatterInterface $formatter 104 * @param array|null $options (unused) 105 * @return WriterInterface 106 */ 107 public function setFormatter($formatter, array $options = null) 108 { 109 return $this; 110 } 111 112 /** 113 * Write a message to the log. 114 * 115 * @param array $event Event data 116 * @return void 117 * @throws Exception\RuntimeException 118 */ 119 protected function doWrite(array $event) 120 { 121 if (null === $this->manager) { 122 throw new Exception\RuntimeException('MongoDB\Driver\Manager must be defined'); 123 } 124 125 if (isset($event['timestamp']) && $event['timestamp'] instanceof DateTimeInterface) { 126 $millis = (int) floor((float) $event['timestamp']->format('U.u') * 1000); 127 $event['timestamp'] = new UTCDateTime($millis); 128 } 129 130 $bulkWrite = new BulkWrite(); 131 $bulkWrite->insert($event); 132 133 $this->manager->executeBulkWrite($this->database, $bulkWrite, $this->writeConcern); 134 } 135} 136