1<?php declare(strict_types=1); 2 3/* 4 * This file is part of the Monolog package. 5 * 6 * (c) Jordi Boggiano <j.boggiano@seld.be> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Monolog\Handler; 13 14use Monolog\Formatter\FormatterInterface; 15use Monolog\ResettableInterface; 16 17/** 18 * Forwards records to multiple handlers 19 * 20 * @author Lenar Lõhmus <lenar@city.ee> 21 * 22 * @phpstan-import-type Record from \Monolog\Logger 23 */ 24class GroupHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface 25{ 26 use ProcessableHandlerTrait; 27 28 /** @var HandlerInterface[] */ 29 protected $handlers; 30 /** @var bool */ 31 protected $bubble; 32 33 /** 34 * @param HandlerInterface[] $handlers Array of Handlers. 35 * @param bool $bubble Whether the messages that are handled can bubble up the stack or not 36 */ 37 public function __construct(array $handlers, bool $bubble = true) 38 { 39 foreach ($handlers as $handler) { 40 if (!$handler instanceof HandlerInterface) { 41 throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.'); 42 } 43 } 44 45 $this->handlers = $handlers; 46 $this->bubble = $bubble; 47 } 48 49 /** 50 * {@inheritDoc} 51 */ 52 public function isHandling(array $record): bool 53 { 54 foreach ($this->handlers as $handler) { 55 if ($handler->isHandling($record)) { 56 return true; 57 } 58 } 59 60 return false; 61 } 62 63 /** 64 * {@inheritDoc} 65 */ 66 public function handle(array $record): bool 67 { 68 if ($this->processors) { 69 /** @var Record $record */ 70 $record = $this->processRecord($record); 71 } 72 73 foreach ($this->handlers as $handler) { 74 $handler->handle($record); 75 } 76 77 return false === $this->bubble; 78 } 79 80 /** 81 * {@inheritDoc} 82 */ 83 public function handleBatch(array $records): void 84 { 85 if ($this->processors) { 86 $processed = []; 87 foreach ($records as $record) { 88 $processed[] = $this->processRecord($record); 89 } 90 /** @var Record[] $records */ 91 $records = $processed; 92 } 93 94 foreach ($this->handlers as $handler) { 95 $handler->handleBatch($records); 96 } 97 } 98 99 public function reset() 100 { 101 $this->resetProcessors(); 102 103 foreach ($this->handlers as $handler) { 104 if ($handler instanceof ResettableInterface) { 105 $handler->reset(); 106 } 107 } 108 } 109 110 public function close(): void 111 { 112 parent::close(); 113 114 foreach ($this->handlers as $handler) { 115 $handler->close(); 116 } 117 } 118 119 /** 120 * {@inheritDoc} 121 */ 122 public function setFormatter(FormatterInterface $formatter): HandlerInterface 123 { 124 foreach ($this->handlers as $handler) { 125 if ($handler instanceof FormattableHandlerInterface) { 126 $handler->setFormatter($formatter); 127 } 128 } 129 130 return $this; 131 } 132} 133