Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]

   1  <?php
   2  /*
   3   * Copyright 2014 Google Inc.
   4   *
   5   * Licensed under the Apache License, Version 2.0 (the "License");
   6   * you may not use this file except in compliance with the License.
   7   * You may obtain a copy of the License at
   8   *
   9   *     http://www.apache.org/licenses/LICENSE-2.0
  10   *
  11   * Unless required by applicable law or agreed to in writing, software
  12   * distributed under the License is distributed on an "AS IS" BASIS,
  13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14   * See the License for the specific language governing permissions and
  15   * limitations under the License.
  16   */
  17  
  18  if (!class_exists('Google_Client')) {
  19    require_once dirname(__FILE__) . '/../autoload.php';
  20  }
  21  
  22  /**
  23   * File logging class based on the PSR-3 standard.
  24   *
  25   * This logger writes to a PHP stream resource.
  26   */
  27  #[AllowDynamicProperties]
  28  class Google_Logger_File extends Google_Logger_Abstract
  29  {
  30    /**
  31     * @var string|resource $file Where logs are written
  32     */
  33    private $file;
  34    /**
  35     * @var integer $mode The mode to use if the log file needs to be created
  36     */
  37    private $mode = 0640;
  38    /**
  39     * @var boolean $lock If a lock should be attempted before writing to the log
  40     */
  41    private $lock = false;
  42  
  43    /**
  44     * @var integer $trappedErrorNumber Trapped error number
  45     */
  46    private $trappedErrorNumber;
  47    /**
  48     * @var string $trappedErrorString Trapped error string
  49     */
  50    private $trappedErrorString;
  51  
  52    /**
  53     * {@inheritdoc}
  54     */
  55    public function __construct(Google_Client $client)
  56    {
  57      parent::__construct($client);
  58  
  59      $file = $client->getClassConfig('Google_Logger_File', 'file');
  60      if (!is_string($file) && !is_resource($file)) {
  61        throw new Google_Logger_Exception(
  62            'File logger requires a filename or a valid file pointer'
  63        );
  64      }
  65  
  66      $mode = $client->getClassConfig('Google_Logger_File', 'mode');
  67      if (!$mode) {
  68        $this->mode = $mode;
  69      }
  70  
  71      $this->lock = (bool) $client->getClassConfig('Google_Logger_File', 'lock');
  72      $this->file = $file;
  73    }
  74  
  75    /**
  76     * {@inheritdoc}
  77     */
  78    protected function write($message)
  79    {
  80      if (is_string($this->file)) {
  81        $this->open();
  82      } elseif (!is_resource($this->file)) {
  83        throw new Google_Logger_Exception('File pointer is no longer available');
  84      }
  85  
  86      if ($this->lock) {
  87        flock($this->file, LOCK_EX);
  88      }
  89  
  90      fwrite($this->file, (string) $message);
  91  
  92      if ($this->lock) {
  93        flock($this->file, LOCK_UN);
  94      }
  95    }
  96  
  97    /**
  98     * Opens the log for writing.
  99     *
 100     * @return resource
 101     */
 102    private function open()
 103    {
 104      // Used for trapping `fopen()` errors.
 105      $this->trappedErrorNumber = null;
 106      $this->trappedErrorString = null;
 107  
 108      $old = set_error_handler(array($this, 'trapError'));
 109  
 110      $needsChmod = !file_exists($this->file);
 111      $fh = fopen($this->file, 'a');
 112  
 113      restore_error_handler();
 114  
 115      // Handles trapped `fopen()` errors.
 116      if ($this->trappedErrorNumber) {
 117        throw new Google_Logger_Exception(
 118            sprintf(
 119                "Logger Error: '%s'",
 120                $this->trappedErrorString
 121            ),
 122            $this->trappedErrorNumber
 123        );
 124      }
 125  
 126      if ($needsChmod) {
 127        @chmod($this->file, $this->mode & ~umask());
 128      }
 129  
 130      return $this->file = $fh;
 131    }
 132  
 133    /**
 134     * Closes the log stream resource.
 135     */
 136    private function close()
 137    {
 138      if (is_resource($this->file)) {
 139        fclose($this->file);
 140      }
 141    }
 142  
 143    /**
 144     * Traps `fopen()` errors.
 145     *
 146     * @param integer $errno The error number
 147     * @param string $errstr The error string
 148     */
 149    private function trapError($errno, $errstr)
 150    {
 151      $this->trappedErrorNumber = $errno;
 152      $this->trappedErrorString = $errstr;
 153    }
 154  
 155    public function __destruct()
 156    {
 157      $this->close();
 158    }
 159  }