1 <?php 2 3 // This file is part of Moodle - http://moodle.org/ 4 // 5 // Moodle is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // Moodle is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 17 18 /** 19 * @package moodlecore 20 * @subpackage backup-logger 21 * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 /** 26 * Base abstract class for all the loggers to be used in backup/restore 27 * 28 * Any message passed will be processed by all the loggers in the defined chain 29 * (note some implementations may be not strictly "loggers" but classes performing 30 * other sort of tasks (avoiding browser/php timeouts, painters...). One simple 1-way 31 * basic chain of commands/responsibility pattern. 32 * 33 * TODO: Finish phpdocs 34 */ 35 abstract class base_logger implements checksumable { 36 37 protected $level; // minimum level of logging this logger must handle (valid level from @backup class) 38 protected $showdate; // flag to decide if the logger must output the date (true) or no (false) 39 protected $showlevel; // flag to decide if the logger must output the level (true) or no (false) 40 protected $next; // next logger in the chain 41 42 public function __construct($level, $showdate = false, $showlevel = false) { 43 // TODO: check level is correct 44 $this->level = $level; 45 $this->showdate = $showdate; 46 $this->showlevel = $showlevel; 47 $this->next = null; 48 } 49 50 public final function set_next($next) { 51 // TODO: Check is a base logger 52 53 // TODO: Check next hasn't been set already 54 55 // TODO: Avoid circular dependencies 56 if ($this->is_circular_reference($next)) { 57 $a = new stdclass(); 58 $a->alreadyinchain = get_class($this); 59 $a->main = get_class($next); 60 throw new base_logger_exception('logger_circular_reference', $a); 61 } 62 63 $this->next = $next; 64 } 65 66 public function get_next() { 67 return $this->next; 68 } 69 70 public function get_level() { 71 return $this->level; 72 } 73 74 /** 75 * Destroy (nullify) the chain of loggers references, also closing resources when needed. 76 * 77 * @since Moodle 3.1 78 */ 79 public final function destroy() { 80 // Recursively destroy the chain. 81 if ($this->next !== null) { 82 $this->next->destroy(); 83 $this->next = null; 84 } 85 // And close every logger. 86 $this->close(); 87 } 88 89 /** 90 * Close any resource the logger may have open. 91 * 92 * @since Moodle 3.1 93 */ 94 public function close() { 95 // Nothing to do by default. Only loggers using resources (files, own connections...) need to override this. 96 } 97 98 // checksumable interface methods 99 100 public function calculate_checksum() { 101 // Checksum is a simple md5 hash of classname, level and 102 // on each specialised logger, its own atrributes 103 // Not following the chain at all. 104 return md5(get_class($this) . '-' . $this->level); 105 } 106 107 public function is_checksum_correct($checksum) { 108 return $this->calculate_checksum() === $checksum; 109 } 110 111 // Protected API starts here 112 113 abstract protected function action($message, $level, $options = null); // To implement 114 115 public final function process($message, $level, $options = null) { 116 $result = true; 117 if ($this->level != backup::LOG_NONE && $this->level >= $level 118 && !(defined('BEHAT_TEST') && BEHAT_TEST)) { // Perform action conditionally. 119 $result = $this->action($message, $level, $options); 120 } 121 if ($result === false) { // Something was wrong, stop the chain 122 return $result; 123 } 124 if ($this->next !== null) { // The chain continues being processed 125 $result = $this->next->process($message, $level, $options); 126 } 127 return $result; 128 } 129 130 protected function is_circular_reference($obj) { 131 // Get object all nexts recursively and check if $this is already there 132 $nexts = $obj->get_nexts(); 133 if (array_key_exists($this->calculate_checksum(), $nexts) || $obj == $this) { 134 return true; 135 } 136 return false; 137 } 138 139 protected function get_nexts() { 140 $nexts = array(); 141 if ($this->next !== null) { 142 $nexts[$this->next->calculate_checksum()] = $this->next->calculate_checksum(); 143 $nexts = array_merge($nexts, $this->next->get_nexts()); 144 } 145 return $nexts; 146 } 147 148 protected function get_datestr() { 149 return userdate(time(), '%c'); 150 } 151 152 protected function get_levelstr($level) { 153 $result = 'undefined'; 154 switch ($level) { 155 case backup::LOG_ERROR: 156 $result = 'error'; 157 break; 158 case backup::LOG_WARNING: 159 $result = 'warn'; 160 break; 161 case backup::LOG_INFO: 162 $result = 'info'; 163 break; 164 case backup::LOG_DEBUG: 165 $result = 'debug'; 166 break; 167 } 168 return $result; 169 } 170 171 protected function get_prefix($level, $options) { 172 $prefix = ''; 173 if ($this->showdate) { 174 $prefix .= '[' . $this->get_datestr() . '] '; 175 } 176 if ($this->showlevel) { 177 $prefix .= '[' . $this->get_levelstr($level) . '] '; 178 } 179 return $prefix; 180 } 181 } 182 183 /* 184 * Exception class used by all the @base_logger stuff 185 */ 186 class base_logger_exception extends backup_exception { 187 188 public function __construct($errorcode, $a=NULL, $debuginfo=null) { 189 parent::__construct($errorcode, $a, $debuginfo); 190 } 191 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body