qa-event-logger.php 6.58 KB
Newer Older
Scott committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
<?php
/*
	Question2Answer by Gideon Greenspan and contributors
	http://www.question2answer.org/

	File: qa-plugin/event-logger/qa-event-logger.php
	Description: Event module class for event logger plugin


	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	More about this license: http://www.question2answer.org/license.php
*/

Scott committed
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
class qa_event_logger
{
	public function init_queries($table_list)
	{
		if (qa_opt('event_logger_to_database')) {
			$tablename=qa_db_add_table_prefix('eventlog');

			if (!in_array($tablename, $table_list)) {
				require_once QA_INCLUDE_DIR.'app/users.php';
				require_once QA_INCLUDE_DIR.'db/maxima.php';

				return 'CREATE TABLE ^eventlog ('.
					'datetime DATETIME NOT NULL,'.
					'ipaddress VARCHAR (15) CHARACTER SET ascii,'.
					'userid '.qa_get_mysql_user_column_type().','.
					'handle VARCHAR('.QA_DB_MAX_HANDLE_LENGTH.'),'.
					'cookieid BIGINT UNSIGNED,'.
					'event VARCHAR (20) CHARACTER SET ascii NOT NULL,'.
					'params VARCHAR (800) NOT NULL,'.
					'KEY datetime (datetime),'.
					'KEY ipaddress (ipaddress),'.
					'KEY userid (userid),'.
					'KEY event (event)'.
				') ENGINE=MyISAM DEFAULT CHARSET=utf8';
Scott committed
47 48
			}
		}
49 50

		return array();
Scott committed
51
	}
Scott committed
52 53


Scott committed
54 55
	public function admin_form(&$qa_content)
	{
Scott committed
56

Scott committed
57
	//	Process form input
Scott committed
58

Scott committed
59
		$saved=false;
Scott committed
60

Scott committed
61 62 63 64 65
		if (qa_clicked('event_logger_save_button')) {
			qa_opt('event_logger_to_database', (int)qa_post_text('event_logger_to_database_field'));
			qa_opt('event_logger_to_files', qa_post_text('event_logger_to_files_field'));
			qa_opt('event_logger_directory', qa_post_text('event_logger_directory_field'));
			qa_opt('event_logger_hide_header', !qa_post_text('event_logger_hide_header_field'));
Scott committed
66

Scott committed
67 68
			$saved=true;
		}
Scott committed
69

Scott committed
70
	//	Check the validity of the currently entered directory (if any)
Scott committed
71

Scott committed
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
		$directory=qa_opt('event_logger_directory');

		$note=null;
		$error=null;

		if (!strlen($directory))
			$note='Please specify a directory that is writable by the web server.';
		elseif (!file_exists($directory))
			$error='This directory cannot be found. Please enter the full path.';
		elseif (!is_dir($directory))
			$error='This is a file. Please enter the full path of a directory.';
		elseif (!is_writable($directory))
			$error='This directory is not writable by the web server. Please choose a different directory, use chown/chmod to change permissions, or contact your web hosting company for assistance.';

	//	Create the form for display
Scott committed
87

Scott committed
88 89 90 91 92 93 94 95 96 97 98 99 100 101
		qa_set_display_rules($qa_content, array(
			'event_logger_directory_display' => 'event_logger_to_files_field',
			'event_logger_hide_header_display' => 'event_logger_to_files_field',
		));

		return array(
			'ok' => ($saved && !isset($error)) ? 'Event log settings saved' : null,

			'fields' => array(
				array(
					'label' => 'Log events to <code>'.QA_MYSQL_TABLE_PREFIX.'eventlog</code> database table',
					'tags' => 'name="event_logger_to_database_field"',
					'value' => qa_opt('event_logger_to_database'),
					'type' => 'checkbox',
Scott committed
102 103
				),

Scott committed
104 105 106 107 108
				array(
					'label' => 'Log events to daily log files',
					'tags' => 'name="event_logger_to_files_field" id="event_logger_to_files_field"',
					'value' => qa_opt('event_logger_to_files'),
					'type' => 'checkbox',
Scott committed
109 110
				),

Scott committed
111 112 113 114 115 116 117 118
				array(
					'id' => 'event_logger_directory_display',
					'label' => 'Directory for log files - enter full path:',
					'value' => qa_html($directory),
					'tags' => 'name="event_logger_directory_field"',
					'note' => $note,
					'error' => qa_html($error),
				),
Scott committed
119

Scott committed
120 121 122 123 124 125 126 127
				array(
					'id' => 'event_logger_hide_header_display',
					'label' => 'Include header lines at top of each log file',
					'type' => 'checkbox',
					'tags' => 'name="event_logger_hide_header_field"',
					'value' => !qa_opt('event_logger_hide_header'),
				),
			),
Scott committed
128

Scott committed
129 130 131 132 133 134 135 136
			'buttons' => array(
				array(
					'label' => 'Save Changes',
					'tags' => 'name="event_logger_save_button"',
				),
			),
		);
	}
Scott committed
137 138


Scott committed
139 140 141 142 143 144 145 146
	public function value_to_text($value)
	{
		if (is_array($value))
			$text='array('.count($value).')';
		elseif (strlen($value)>40)
			$text=substr($value, 0, 38).'...';
		else
			$text=$value;
Scott committed
147

Scott committed
148 149
		return strtr($text, "\t\n\r", '   ');
	}
Scott committed
150 151


Scott committed
152 153 154 155
	public function process_event($event, $userid, $handle, $cookieid, $params)
	{
		if (qa_opt('event_logger_to_database')) {
			$paramstring='';
Scott committed
156

Scott committed
157 158
			foreach ($params as $key => $value)
				$paramstring.=(strlen($paramstring) ? "\t" : '').$key.'='.$this->value_to_text($value);
Scott committed
159

Scott committed
160 161 162 163 164 165
			qa_db_query_sub(
				'INSERT INTO ^eventlog (datetime, ipaddress, userid, handle, cookieid, event, params) '.
				'VALUES (NOW(), $, $, $, #, $, $)',
				qa_remote_ip_address(), $userid, $handle, $cookieid, $event, $paramstring
			);
		}
Scott committed
166

Scott committed
167
		if (qa_opt('event_logger_to_files')) {
Scott committed
168

Scott committed
169
		//	Substitute some placeholders if certain information is missing
Scott committed
170

Scott committed
171 172
			if (!strlen($userid))
				$userid='no_userid';
Scott committed
173

Scott committed
174 175
			if (!strlen($handle))
				$handle='no_handle';
Scott committed
176

Scott committed
177 178
			if (!strlen($cookieid))
				$cookieid='no_cookieid';
Scott committed
179

Scott committed
180 181 182
			$ip=qa_remote_ip_address();
			if (!strlen($ip))
				$ip='no_ipaddress';
Scott committed
183

Scott committed
184
		//	Build the log file line to be written
Scott committed
185

Scott committed
186 187 188 189 190 191 192 193 194
			$fixedfields=array(
				'Date' => date('Y\-m\-d'),
				'Time' => date('H\:i\:s'),
				'IPaddress' => $ip,
				'UserID' => $userid,
				'Username' => $handle,
				'CookieID' => $cookieid,
				'Event' => $event,
			);
Scott committed
195

Scott committed
196
			$fields=$fixedfields;
Scott committed
197

Scott committed
198 199
			foreach ($params as $key => $value)
				$fields['param_'.$key]=$key.'='.$this->value_to_text($value);
Scott committed
200

Scott committed
201
			$string=implode("\t", $fields);
Scott committed
202

Scott committed
203
		//	Build the full path and file name
Scott committed
204

Scott committed
205
			$directory=qa_opt('event_logger_directory');
Scott committed
206

Scott committed
207 208
			if (substr($directory, -1)!='/')
				$directory.='/';
Scott committed
209

Scott committed
210
			$filename=$directory.'q2a-log-'.date('Y\-m\-d').'.txt';
Scott committed
211

Scott committed
212
		//	Open, lock, write, unlock, close (to prevent interference between multiple writes)
Scott committed
213

Scott committed
214
			$exists=file_exists($filename);
Scott committed
215

Scott committed
216 217 218 219 220 221 222 223 224 225 226
			$file=@fopen($filename, 'a');

			if (is_resource($file)) {
				if (flock($file, LOCK_EX)) {
					if ( (!$exists) && (filesize($filename)===0) && !qa_opt('event_logger_hide_header') )
						$string="Question2Answer ".QA_VERSION." log file generated by Event Logger plugin.\n".
							"This file is formatted as tab-delimited text with UTF-8 encoding.\n\n".
							implode("\t", array_keys($fixedfields))."\textras...\n\n".$string;

					fwrite($file, $string."\n");
					flock($file, LOCK_UN);
Scott committed
227
				}
Scott committed
228 229

				fclose($file);
Scott committed
230 231 232
			}
		}
	}
Scott committed
233
}