[795] | 1 | <?php |
---|
| 2 | /** |
---|
| 3 | * $Header: /repository/pear/Log/Log/win.php,v 1.21 2008/11/12 05:07:31 jon Exp $ |
---|
| 4 | * |
---|
| 5 | * @version $Revision: 1.21 $ |
---|
| 6 | * @package Log |
---|
| 7 | */ |
---|
| 8 | |
---|
| 9 | /** |
---|
| 10 | * The Log_win class is a concrete implementation of the Log abstract |
---|
| 11 | * class that logs messages to a separate browser window. |
---|
| 12 | * |
---|
| 13 | * The concept for this log handler is based on part by Craig Davis' article |
---|
| 14 | * entitled "JavaScript Power PHP Debugging: |
---|
| 15 | * |
---|
| 16 | * http://www.zend.com/zend/tut/tutorial-DebugLib.php |
---|
| 17 | * |
---|
| 18 | * @author Jon Parise <jon@php.net> |
---|
| 19 | * @since Log 1.7.0 |
---|
| 20 | * @package Log |
---|
| 21 | * |
---|
| 22 | * @example win.php Using the window handler. |
---|
| 23 | */ |
---|
| 24 | class Log_win extends Log |
---|
| 25 | { |
---|
| 26 | /** |
---|
| 27 | * The name of the output window. |
---|
| 28 | * @var string |
---|
| 29 | * @access private |
---|
| 30 | */ |
---|
| 31 | var $_name = 'LogWindow'; |
---|
| 32 | |
---|
| 33 | /** |
---|
| 34 | * The title of the output window. |
---|
| 35 | * @var string |
---|
| 36 | * @access private |
---|
| 37 | */ |
---|
| 38 | var $_title = 'Log Output Window'; |
---|
| 39 | |
---|
| 40 | /** |
---|
| 41 | * Mapping of log priorities to styles. |
---|
| 42 | * @var array |
---|
| 43 | * @access private |
---|
| 44 | */ |
---|
| 45 | var $_styles = array( |
---|
| 46 | PEAR_LOG_EMERG => 'color: red;', |
---|
| 47 | PEAR_LOG_ALERT => 'color: orange;', |
---|
| 48 | PEAR_LOG_CRIT => 'color: yellow;', |
---|
| 49 | PEAR_LOG_ERR => 'color: green;', |
---|
| 50 | PEAR_LOG_WARNING => 'color: blue;', |
---|
| 51 | PEAR_LOG_NOTICE => 'color: indigo;', |
---|
| 52 | PEAR_LOG_INFO => 'color: violet;', |
---|
| 53 | PEAR_LOG_DEBUG => 'color: black;' |
---|
| 54 | ); |
---|
| 55 | |
---|
| 56 | /** |
---|
| 57 | * String buffer that holds line that are pending output. |
---|
| 58 | * @var array |
---|
| 59 | * @access private |
---|
| 60 | */ |
---|
| 61 | var $_buffer = array(); |
---|
| 62 | |
---|
| 63 | /** |
---|
| 64 | * Constructs a new Log_win object. |
---|
| 65 | * |
---|
| 66 | * @param string $name Ignored. |
---|
| 67 | * @param string $ident The identity string. |
---|
| 68 | * @param array $conf The configuration array. |
---|
| 69 | * @param int $level Log messages up to and including this level. |
---|
| 70 | * @access public |
---|
| 71 | */ |
---|
| 72 | function Log_win($name, $ident = '', $conf = array(), |
---|
| 73 | $level = PEAR_LOG_DEBUG) |
---|
| 74 | { |
---|
| 75 | $this->_id = md5(microtime()); |
---|
| 76 | $this->_name = str_replace(' ', '_', $name); |
---|
| 77 | $this->_ident = $ident; |
---|
| 78 | $this->_mask = Log::UPTO($level); |
---|
| 79 | |
---|
| 80 | if (isset($conf['title'])) { |
---|
| 81 | $this->_title = $conf['title']; |
---|
| 82 | } |
---|
| 83 | if (isset($conf['styles']) && is_array($conf['styles'])) { |
---|
| 84 | $this->_styles = $conf['styles']; |
---|
| 85 | } |
---|
| 86 | if (isset($conf['colors']) && is_array($conf['colors'])) { |
---|
| 87 | foreach ($conf['colors'] as $level => $color) { |
---|
| 88 | $this->_styles[$level] .= "color: $color;"; |
---|
| 89 | } |
---|
| 90 | } |
---|
| 91 | |
---|
| 92 | register_shutdown_function(array(&$this, '_Log_win')); |
---|
| 93 | } |
---|
| 94 | |
---|
| 95 | /** |
---|
| 96 | * Destructor |
---|
| 97 | */ |
---|
| 98 | function _Log_win() |
---|
| 99 | { |
---|
| 100 | if ($this->_opened || (count($this->_buffer) > 0)) { |
---|
| 101 | $this->close(); |
---|
| 102 | } |
---|
| 103 | } |
---|
| 104 | |
---|
| 105 | /** |
---|
| 106 | * The first time open() is called, it will open a new browser window and |
---|
| 107 | * prepare it for output. |
---|
| 108 | * |
---|
| 109 | * This is implicitly called by log(), if necessary. |
---|
| 110 | * |
---|
| 111 | * @access public |
---|
| 112 | */ |
---|
| 113 | function open() |
---|
| 114 | { |
---|
| 115 | if (!$this->_opened) { |
---|
| 116 | $win = $this->_name; |
---|
| 117 | $styles = $this->_styles; |
---|
| 118 | |
---|
| 119 | if (!empty($this->_ident)) { |
---|
| 120 | $identHeader = "$win.document.writeln('<th>Ident</th>')"; |
---|
| 121 | } else { |
---|
| 122 | $identHeader = ''; |
---|
| 123 | } |
---|
| 124 | |
---|
| 125 | echo <<< EOT |
---|
| 126 | <script language="JavaScript"> |
---|
| 127 | $win = window.open('', '{$this->_name}', 'toolbar=no,scrollbars,width=600,height=400'); |
---|
| 128 | $win.document.writeln('<html>'); |
---|
| 129 | $win.document.writeln('<head>'); |
---|
| 130 | $win.document.writeln('<title>{$this->_title}</title>'); |
---|
| 131 | $win.document.writeln('<style type="text/css">'); |
---|
| 132 | $win.document.writeln('body { font-family: monospace; font-size: 8pt; }'); |
---|
| 133 | $win.document.writeln('td,th { font-size: 8pt; }'); |
---|
| 134 | $win.document.writeln('td,th { border-bottom: #999999 solid 1px; }'); |
---|
| 135 | $win.document.writeln('td,th { border-right: #999999 solid 1px; }'); |
---|
| 136 | $win.document.writeln('tr { text-align: left; vertical-align: top; }'); |
---|
| 137 | $win.document.writeln('td.l0 { $styles[0] }'); |
---|
| 138 | $win.document.writeln('td.l1 { $styles[1] }'); |
---|
| 139 | $win.document.writeln('td.l2 { $styles[2] }'); |
---|
| 140 | $win.document.writeln('td.l3 { $styles[3] }'); |
---|
| 141 | $win.document.writeln('td.l4 { $styles[4] }'); |
---|
| 142 | $win.document.writeln('td.l5 { $styles[5] }'); |
---|
| 143 | $win.document.writeln('td.l6 { $styles[6] }'); |
---|
| 144 | $win.document.writeln('td.l7 { $styles[7] }'); |
---|
| 145 | $win.document.writeln('</style>'); |
---|
| 146 | $win.document.writeln('</head>'); |
---|
| 147 | $win.document.writeln('<body>'); |
---|
| 148 | $win.document.writeln('<table border="0" cellpadding="2" cellspacing="0">'); |
---|
| 149 | $win.document.writeln('<tr><th>Time</th>'); |
---|
| 150 | $identHeader |
---|
| 151 | $win.document.writeln('<th>Priority</th><th width="100%">Message</th></tr>'); |
---|
| 152 | </script> |
---|
| 153 | EOT; |
---|
| 154 | $this->_opened = true; |
---|
| 155 | } |
---|
| 156 | |
---|
| 157 | return $this->_opened; |
---|
| 158 | } |
---|
| 159 | |
---|
| 160 | /** |
---|
| 161 | * Closes the output stream if it is open. If there are still pending |
---|
| 162 | * lines in the output buffer, the output window will be opened so that |
---|
| 163 | * the buffer can be drained. |
---|
| 164 | * |
---|
| 165 | * @access public |
---|
| 166 | */ |
---|
| 167 | function close() |
---|
| 168 | { |
---|
| 169 | /* |
---|
| 170 | * If there are still lines waiting to be written, open the output |
---|
| 171 | * window so that we can drain the buffer. |
---|
| 172 | */ |
---|
| 173 | if (!$this->_opened && (count($this->_buffer) > 0)) { |
---|
| 174 | $this->open(); |
---|
| 175 | } |
---|
| 176 | |
---|
| 177 | if ($this->_opened) { |
---|
| 178 | $this->_writeln('</table>'); |
---|
| 179 | $this->_writeln('</body></html>'); |
---|
| 180 | $this->_opened = false; |
---|
| 181 | } |
---|
| 182 | |
---|
| 183 | return ($this->_opened === false); |
---|
| 184 | } |
---|
| 185 | |
---|
| 186 | /** |
---|
| 187 | * Writes a single line of text to the output window. |
---|
| 188 | * |
---|
| 189 | * @param string $line The line of text to write. |
---|
| 190 | * |
---|
| 191 | * @access private |
---|
| 192 | */ |
---|
| 193 | function _writeln($line) |
---|
| 194 | { |
---|
| 195 | /* Add this line to our output buffer. */ |
---|
| 196 | $this->_buffer[] = $line; |
---|
| 197 | |
---|
| 198 | /* Buffer the output until this page's headers have been sent. */ |
---|
| 199 | if (!headers_sent()) { |
---|
| 200 | return; |
---|
| 201 | } |
---|
| 202 | |
---|
| 203 | /* If we haven't already opened the output window, do so now. */ |
---|
| 204 | if (!$this->_opened && !$this->open()) { |
---|
| 205 | return false; |
---|
| 206 | } |
---|
| 207 | |
---|
| 208 | /* Drain the buffer to the output window. */ |
---|
| 209 | $win = $this->_name; |
---|
| 210 | foreach ($this->_buffer as $line) { |
---|
| 211 | echo "<script language='JavaScript'>\n"; |
---|
| 212 | echo "$win.document.writeln('" . addslashes($line) . "');\n"; |
---|
| 213 | echo "self.focus();\n"; |
---|
| 214 | echo "</script>\n"; |
---|
| 215 | } |
---|
| 216 | |
---|
| 217 | /* Now that the buffer has been drained, clear it. */ |
---|
| 218 | $this->_buffer = array(); |
---|
| 219 | } |
---|
| 220 | |
---|
| 221 | /** |
---|
| 222 | * Logs $message to the output window. The message is also passed along |
---|
| 223 | * to any Log_observer instances that are observing this Log. |
---|
| 224 | * |
---|
| 225 | * @param mixed $message String or object containing the message to log. |
---|
| 226 | * @param string $priority The priority of the message. Valid |
---|
| 227 | * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT, |
---|
| 228 | * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING, |
---|
| 229 | * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG. |
---|
| 230 | * @return boolean True on success or false on failure. |
---|
| 231 | * @access public |
---|
| 232 | */ |
---|
| 233 | function log($message, $priority = null) |
---|
| 234 | { |
---|
| 235 | /* If a priority hasn't been specified, use the default value. */ |
---|
| 236 | if ($priority === null) { |
---|
| 237 | $priority = $this->_priority; |
---|
| 238 | } |
---|
| 239 | |
---|
| 240 | /* Abort early if the priority is above the maximum logging level. */ |
---|
| 241 | if (!$this->_isMasked($priority)) { |
---|
| 242 | return false; |
---|
| 243 | } |
---|
| 244 | |
---|
| 245 | /* Extract the string representation of the message. */ |
---|
| 246 | $message = $this->_extractMessage($message); |
---|
| 247 | $message = preg_replace('/\r\n|\n|\r/', '<br />', $message); |
---|
| 248 | |
---|
| 249 | list($usec, $sec) = explode(' ', microtime()); |
---|
| 250 | |
---|
| 251 | /* Build the output line that contains the log entry row. */ |
---|
| 252 | $line = '<tr>'; |
---|
| 253 | $line .= sprintf('<td>%s.%s</td>', |
---|
| 254 | strftime('%H:%M:%S', $sec), substr($usec, 2, 2)); |
---|
| 255 | if (!empty($this->_ident)) { |
---|
| 256 | $line .= '<td>' . $this->_ident . '</td>'; |
---|
| 257 | } |
---|
| 258 | $line .= '<td>' . ucfirst($this->priorityToString($priority)) . '</td>'; |
---|
| 259 | $line .= sprintf('<td class="l%d">%s</td>', $priority, $message); |
---|
| 260 | $line .= '</tr>'; |
---|
| 261 | |
---|
| 262 | $this->_writeln($line); |
---|
| 263 | |
---|
| 264 | $this->_announce(array('priority' => $priority, 'message' => $message)); |
---|
| 265 | |
---|
| 266 | return true; |
---|
| 267 | } |
---|
| 268 | |
---|
| 269 | } |
---|