1: <?php
2:
3: /**
4: * Jyxo PHP Library
5: *
6: * LICENSE
7: *
8: * This source file is subject to the new BSD license that is bundled
9: * with this package in the file license.txt.
10: * It is also available through the world-wide-web at this URL:
11: * https://github.com/jyxo/php/blob/master/license.txt
12: */
13:
14: /**
15: * Class for sending error emails (can be used in register_shutdown_function, etc.)
16: *
17: * @category Jyxo
18: * @package Jyxo_ErrorHandling
19: * @copyright Copyright (c) 2005-2011 Jyxo, s.r.o.
20: * @license https://github.com/jyxo/php/blob/master/license.txt
21: * @author Jakub Tománek
22: */
23: class Jyxo_ErrorMail
24: {
25: /**
26: * Minimal interval between sending two mails; to prevent from mailserver flooding.
27: *
28: * @var integer
29: */
30: const SEND_INTERVAL = 600;
31:
32: /**
33: * Path to the file with last sending timestamp.
34: *
35: * @var string
36: */
37: private $timerFile;
38:
39: /**
40: * Additional headers.
41: *
42: * @var array
43: */
44: private $headers = array();
45:
46: /**
47: * Mail recipients.
48: *
49: * @var array
50: */
51: private $email = array();
52:
53: /**
54: * Constructor.
55: *
56: * @param string $timerFile Path to the file with last sending timestamp
57: * @param string|array $recipients Recipient(s)
58: * @param string $sender Mail sender
59: */
60: public function __construct($timerFile, $recipients, $sender)
61: {
62: $this->timerFile = $timerFile;
63: $this->email = (array) $recipients;
64: $this->headers[] = 'From: ' . $sender;
65: }
66:
67: /**
68: * Sends the error email.
69: *
70: * @param Exception $e Caught exception
71: * @param boolean $forceTimer Ignore timer (Always send)
72: */
73: public function send(Exception $e, $forceTimer = false)
74: {
75: if ($forceTimer || $this->timerOutdated()) {
76: $this->mail($this->createMail($e));
77: file_put_contents($this->timerFile, time());
78: }
79: }
80:
81: /**
82: * Checks if we can send another email right now.
83: *
84: * @return boolean
85: */
86: private function timerOutdated()
87: {
88: $send = true;
89: if (is_file($this->timerFile)) {
90: $contents = file_get_contents($this->timerFile);
91: $next = $contents + self::SEND_INTERVAL;
92: if ($next > time()) {
93: // Next timestamp is in the future
94: $send = false;
95: }
96: }
97: return $send;
98: }
99:
100: /**
101: * Creates an error email from an exception.
102: *
103: * @param Exception $e Caught exception
104: * @return array
105: */
106: private function createMail(Exception $e)
107: {
108: $subject = get_class($e);
109: if (!empty($_SERVER['SERVER_NAME'])) {
110: $subject .= ': ' . $_SERVER['SERVER_NAME'];
111: }
112:
113: $data = array(
114: 'Exception' => '[' . $e->getCode() . '] ' . $e->getMessage(),
115: 'File' => $e->getFile() . '@' . $e->getLine(),
116: 'Trace' => $e->getTraceAsString(),
117: 'GET' => count($_GET) ? print_r($_GET, true) : null,
118: 'POST' => count($_POST) ? print_r($_POST, true) : null,
119: 'SERVER' => print_r($_SERVER, true)
120: );
121: // Remove empty GET and POST definitions
122: $data = array_filter($data);
123:
124: $message = '';
125: foreach ($data as $key => $val) {
126: $message .= $key . "\n" . str_repeat('-', strlen($key)) . "\n";
127: $message .= $val . "\n\n";
128: }
129:
130: return array($subject, $message);
131: }
132:
133: /**
134: * Actually sends an email.
135: *
136: * @param array $data Array(subject, body)
137: */
138: private function mail(array $data)
139: {
140: list($subject, $message) = $data;
141: @mail(implode(', ', $this->email), $subject, $message, implode("\r\n", $this->headers));
142: }
143: }
144: