\d+)(?:\.\d+)?\s*(?[gkm])\s*$/i', strtolower(ini_get('memory_limit')), $matches) === 1) { $num = (int)$matches['num']; switch ($matches['unit'] ?? '') { case 'g': $num *= 1024; case 'm': $num *= 1024; case 'k': $num *= 1024; } // Use 10% of allowed memory or 100K, whichever is largest $this->chunkSize = min($this->chunkSize, max((int)($num / 10), 100 * 1024)); } if (is_resource($stream)) { $this->resource = $stream; stream_set_chunk_size($this->resource, $this->chunkSize); } elseif(is_string($stream)) { $stream = Path::canonicalize($stream); // This wouldn't be useful for validating a URI schema, but it's fine for what this needs preg_match('/^(?:(?[^:\s\/]+):)?(?\/*)/i', $stream, $matches); if (in_array($matches['scheme'], [ 'file', '' ])) { $slashCount = strlen($matches['slashes'] ?? ''); $relative = ($matches['scheme'] === 'file') ? ($slashCount === 0 || $slashCount === 2) : ($slashCount === 0); $stream = (($relative) ? getcwd() : '') . '/' . substr($stream, strlen($matches[0])); } $this->url = $stream; $this->urlScheme = $matches['scheme'] ?: 'file'; } else { $type = gettype($stream); $type = ($type === 'object') ? $stream::class : $stream; throw new \TypeError(sprintf("Expected type 'resource|string'. Found '%s'", $type)); } parent::__construct($levels, $options); } public function getStream() { return $this->resource ?? $this->url; } protected function invokeCallback(string $datetime, int $level, string $channel, string $message, array $context = []): void { if (!in_array($level, $this->levels)) { return; } // Do output formatting here. $output = trim(preg_replace_callback('/%([a-z_]+)%/', function($m) use ($datetime, $level, $channel, $message) { switch ($m[1]) { case 'channel': return $channel; case 'datetime': return $datetime; case 'level': return (string)$level; case 'level_name': return strtoupper(Level::from($level)->name); case 'message': return $message; default: return ''; } }, $this->_entryFormat)); // If output contains any newlines then add an additional newline to aid readability. if (str_contains($output, \PHP_EOL)) { $output .= \PHP_EOL; } $output .= \PHP_EOL; if ($this->resource === null) { if ($this->urlScheme === 'file') { Fs::mkdir(dirname($this->url)); } $fp = fopen($this->url, 'a'); stream_set_chunk_size($fp, $this->chunkSize); fwrite($fp, $output); fclose($fp); } else { fwrite($this->resource, $output); } } }