Скрипт форума на PHP своими руками. Часть 8
В этой статье мы рассмотрим сервис Personal Messages (PM) для личного общения зарегистрированных пользователей форума. Функция getSendMsgForm() возвращает html формы для отправки личного сообщения:
<?php
// Функция возвращает html формы для отправки личного сообщения
function getSendMsgForm()
{
// Незарегистрированный пользователь не может отправлять личные сообщения
if ( !isset( $_SESSION['user'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
$html = '<h1>Личные сообщения</h1>'."\n";
$html = $html.getMessagesMenu();
$toUser = '';
if ( isset( $_GET['idUser'] ) ) {
$id = (int)$_GET['idUser'];
if ( $id > 0 ) {
$query = "SELECT name FROM ".TABLE_USERS." WHERE id_author=".$id;
$res = mysql_query( $query );
if ( $res ) {
if ( mysql_num_rows( $res ) > 0 ) $toUser = mysql_result( $res, 0, 0 );
}
}
}
$subject = '';
$message = '';
if ( isset( $_SESSION['viewMessage'] ) and !empty( $_SESSION['viewMessage']['message'] ) ) {
$view = file_get_contents( './templates/previewMessage.html' );
$view = str_replace( '{message}', print_page( $_SESSION['viewMessage']['message'] ), $view );
$html = $html.$view."\n";
$toUser = htmlspecialchars( $_SESSION['viewMessage']['toUser'] );
$subject = htmlspecialchars( $_SESSION['viewMessage']['subject'] );
$message = htmlspecialchars( $_SESSION['viewMessage']['message'] );
unset( $_SESSION['viewMessage'] );
}
$action = $_SERVER['PHP_SELF'].'?action=sendMessage';
// Если при заполнении формы были допущены ошибки
if ( isset( $_SESSION['sendMessageForm'] ) ) {
$info = file_get_contents( './templates/infoMessage.html' );
$info = str_replace( '{infoMessage}', $_SESSION['sendMessageForm']['error'], $info );
$html = $html.$info."\n";
$toUser = htmlspecialchars( $_SESSION['sendMessageForm']['toUser'] );
$subject = htmlspecialchars( $_SESSION['sendMessageForm']['subject'] );
$message = htmlspecialchars( $_SESSION['sendMessageForm']['message'] );
unset( $_SESSION['sendMessageForm'] );
}
$tpl = file_get_contents( './templates/sendMessageForm.html' );
$tpl = str_replace( '{action}', $action, $tpl );
$tpl = str_replace( '{toUser}', $toUser, $tpl );
$tpl = str_replace( '{subject}', $subject, $tpl );
$tpl = str_replace( '{message}', $message, $tpl );
$html = $html.$tpl;
return $html;
}
?>
Обработчик формы — функция sendMessage() :
<?php
// Отправка личного сообщения (добавляем новую запись в таблицу БД TABLE_MESSAGES)
function sendMessage()
{
// Незарегистрированный пользователь не может отправлять личные сообщения
if ( !isset( $_SESSION['user'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
// Если не переданы данные формы - функция вызвана по ошибке
if ( !isset( $_POST['toUser'] ) or
!isset( $_POST['subject'] ) or
!isset( $_POST['message'] ) )
{
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
$msgLen = strlen( $_POST['message'] );
// Обрезаем переменные до длины, указанной в параметре maxlength тега input
$toUser = substr( $_POST['toUser'], 0, 30 );
$subject = substr( $_POST['subject'], 0, 60 );
$message = substr( $_POST['message'], 0, MAX_MESSAGE_LENGTH );
// Обрезаем лишние пробелы
$toUser = trim( $toUser );
$subject = trim( $subject );
$message = trim( $message );
// Если пользователь хочет посмотреть на сообщение перед отправкой
if ( isset( $_POST['viewMessage'] ) )
{
$_SESSION['viewMessage'] = array();
$_SESSION['viewMessage']['toUser'] = $toUser;
$_SESSION['viewMessage']['subject'] = $subject;
$_SESSION['viewMessage']['message'] = $message;
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=sendMsgForm' );
die();
}
// Проверяем, заполнены ли обязательные поля
$error = '';
if ( empty( $toUser ) ) $error = $error.'<li>не заполнено поле "Для пользователя"</li>'."\n";
if ( empty( $subject ) ) $error = $error.'<li>не заполнено поле "Заголовок сообщения"</li>'."\n";
if ( empty( $message ) ) $error = $error.'<li>не заполнено поле "Текст сообщения"</li>'."\n";
if ( $msgLen > MAX_MESSAGE_LENGTH )
$error = $error.'<li>длина сообщения больше '.MAX_MESSAGE_LENGTH.' символов</li>'."\n";
// Проверяем поля формы на недопустимые символы
if ( !empty( $toUser ) and !preg_match( "#^[- _0-9a-zа-я]+$#i", $toUser ) )
$error = $error.'<li>поле "Для пользователя" содержит недопустимые символы</li>'."\n";
if ( !empty( $subject ) and !preg_match( "#^[-.;:,?!\/)(_\"\s0-9а-яa-z]+$#i", $subject ) )
$error = $error.'<li>поле "Заголовок сообщения" содержит недопустимые символы</li>'."\n";
// Проверяем, есть ли такой пользователь
if ( !empty( $toUser ) ) {
$to = preg_replace( "#[^- _0-9a-zа-я]#i", '', $toUser );
$query = "SELECT id_author FROM ".TABLE_USERS." WHERE name='".$to."' LIMIT 1";
$res = mysql_query( $query );
if ( !$res ) {
$msg = 'Произошла ошибка при отправке сообщения';
$err = 'Ошибка при выполнении запроса: <br/>'.
$query.'<br/>'.mysql_errno().': '.mysql_error().'<br/>'.
'(Файл '. __FILE__ .', строка '. __LINE__ .')';
return showErrorMessage( $msg, $err, true, 'action=sendMsgForm' );
}
if ( mysql_num_rows( $res ) == 0 )
$error = $error.'<li>пользователь с именем <strong>'.$to.'</strong> не зарегистрирован</li>'."\n";
if ( (mysql_num_rows( $res ) == 1 ) and (mysql_result( $res, 0, 0 ) == $_SESSION['user']['id_author']) )
$error = $error.'<li>нельзя послать сообщение самому себе</li>'."\n";
}
// Если были допущены ошибки при заполнении формы -
// перенаправляем посетителя для исправления ошибок
if ( !empty( $error ) )
{
$_SESSION['sendMessageForm'] = array();
$_SESSION['sendMessageForm']['error'] = '<p class="errorMsg">При заполнениии формы были допущены ошибки:</p>'.
"\n".'<ul class="errorMsg">'."\n".$error.'</ul>'."\n";
$_SESSION['sendMessageForm']['toUser'] = $toUser;
$_SESSION['sendMessageForm']['subject'] = $subject;
$_SESSION['sendMessageForm']['message'] = $message;
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=sendMsgForm' );
die();
}
// Все поля заполнены правильно - "посылаем" сообщение
$to = mysql_result( $res, 0, 0 );
$from = $_SESSION['user']['id_author'];
$query = "INSERT INTO ".TABLE_MESSAGES."
VALUES
(
NULL,
".$to.",
".$from.",
NOW(),
'".mysql_real_escape_string( $subject )."',
'".mysql_real_escape_string( $message )."',
0,
0
)";
$res = mysql_query( $query );
if ( !$res ) {
$msg = 'Произошла ошибка при отправке сообщения';
$err = 'Ошибка при выполнении запроса: <br/>'.
$query.'<br/>'.mysql_errno().': '.mysql_error().'<br/>'.
'(Файл '. __FILE__ .', строка '. __LINE__ .')';
return showErrorMessage( $msg, $err, true, 'action=showOutBox' );
}
return showInfoMessage( 'Ваше сообщение успешно отправлено', 'action=showOutBox' );
}
?>
Функция getInMsgBox() возвращает список личных сообщений в папке "Входящие":
<?php
// Папка личных сообщений (входящие)
function getInMsgBox()
{
if ( !isset( $_SESSION['user'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
$html = '<h1>Личные сообщения (входящие)</h1>'."\n";
$html = $html.getMessagesMenu();
$html = $html.'<table class="showTable">'."\n";
$html = $html.'<tr>'."\n";
$html = $html.'<th width="2%"> </th>'."\n";
$html = $html.'<th width="15%">Отправитель</th>'."\n";
$html = $html.'<th width="63%">Тема сообщения</th>'."\n";
$html = $html.'<th width="15%">Дата</th>'."\n";
$html = $html.'<th width="5%">Удл.</th>'."\n";
$html = $html.'</tr>'."\n";
// Запрос на выборку входящих сообщений
// id_rmv - это поле указывает на то, что это сообщение уже удалил
// один из пользователей. Т.е. сначала id_rmv=0, после того, как
// сообщение удалил один из пользователей, id_rmv=id_user. И только после
// того, как сообщение удалит второй пользователь, мы можем удалить
// запись в таблице БД TABLE_MESSAGES
$query = "SELECT a.id_msg, a.subject, a.from_user, a.sendtime, a.viewed, b.name
FROM ".TABLE_MESSAGES." a INNER JOIN ".TABLE_USERS." b
ON a.from_user=b.id_author
WHERE a.to_user=".$_SESSION['user']['id_author']."
AND id_rmv<>".$_SESSION['user']['id_author']."
ORDER BY sendtime DESC";
$res = mysql_query( $query );
while ( $msg = mysql_fetch_row( $res ) ) {
$html = $html.'<tr>'."\n";
// Если сообщение еще не прочитано
if ( $msg[4] == 0 )
$html = $html.'<td align="center" valign="middle"><img src="./images/folder_new.gif" width="19"
height="18" alt="" /></td>';
else
$html = $html.'<td align="center" valign="middle"><img src="./images/folder.gif" width="19"
height="18" alt="" /></td>';
$html = $html.'<td>'.$msg[5].'</td>'."\n";
$html = $html.'<td><a href="'.$_SERVER['PHP_SELF'].'?action=showMsg&idMsg='.
$msg[0].'">'.$msg[1].'</a></td>'."\n";
$html = $html.'<td>'.$msg[3].'</td>'."\n";
$html = $html.'<td align="center"><a href="'.$_SERVER['PHP_SELF'].
'?action=deleteMsg&idMsg='.$msg[0].'"><img src="./images/icon_delete.gif"
alt="Удалить" title="Удалить" border="0" /></a></td>'."\n";
$html = $html.'</tr>'."\n";
}
if ( mysql_num_rows( $res ) == 0 ) {
$html = $html.'<tr>'."\n";
$html = $html.'<td colspan="4">В этой папке нет сообщений</td>'."\n";
$html = $html.'</tr>'."\n";
}
$html = $html.'</table>'."\n";
return $html;
}
?>
Функция getOutMsgBox() возвращает список личных сообщений в папке "Исходящие":
<?php
// Папка личных сообщений (исходящие)
function getOutMsgBox()
{
if ( !isset( $_SESSION['user'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
$html = '<h1>Личные сообщения (исходящие)</h1>'."\n";
$html = $html.getMessagesMenu();
$html = $html.'<table class="showTable">'."\n";
$html = $html.'<tr>'."\n";
$html = $html.'<th width="15%">Получатель</th>'."\n";
$html = $html.'<th width="65%">Тема сообщения</th>'."\n";
$html = $html.'<th width="15%">Дата</th>'."\n";
$html = $html.'<th width="5%">Удл.</th>'."\n";
$html = $html.'</tr>'."\n";
// Запрос на выборку исходящих сообщений
// id_rmv - это поле указывает на то, что это сообщение уже удалил
// один из пользователей. Т.е. сначала id_rmv=0, после того, как
// сообщение удалил один из пользователей, id_rmv=id_user. И только после
// того, как сообщение удалит второй пользователь, мы можем удалить
// запись в таблице БД TABLE_MESSAGES
$query = "SELECT a.id_msg, a.subject, a.to_user, a.sendtime, b.name
FROM ".TABLE_MESSAGES." a INNER JOIN ".TABLE_USERS." b
ON a.to_user=b.id_author
WHERE a.from_user=".$_SESSION['user']['id_author']."
AND id_rmv<>".$_SESSION['user']['id_author']."
ORDER BY sendtime DESC";
$res = mysql_query( $query );
while ( $msg = mysql_fetch_row( $res ) ) {
$html = $html.'<tr>'."\n";
$html = $html.'<td>'.$msg[4].'</td>'."\n";
$html = $html.'<td><a href="'.$_SERVER['PHP_SELF'].'?action=showMsg&idMsg='.
$msg[0].'">'.$msg[1].'</a></td>'."\n";
$html = $html.'<td>'.$msg[3].'</td>'."\n";
$html = $html.'<td align="center"><a href="'.$_SERVER['PHP_SELF'].
'?action=deleteMsg&idMsg='.$msg[0].'"><img src="./images/icon_delete.gif"
alt="Удалить" title="Удалить" border="0" /></a></td>'."\n";
$html = $html.'</tr>'."\n";
}
if ( mysql_num_rows( $res ) == 0 ) {
$html = $html.'<tr>'."\n";
$html = $html.'<td colspan="4">В этой папке нет сообщений</td>'."\n";
$html = $html.'</tr>'."\n";
}
$html = $html.'</table>'."\n";
return $html;
}
?>
Вспомогательная функция getMessagesMenu() возвращает html меню для раздела "Личные сообщения":
<?php
function getMessagesMenu()
{
$html = '<table width="100%">'."\n";
$html = $html.'<tr valign="middle">'."\n";
$html = $html.'<td><img src="./images/msg_inbox.gif" alt="Входящие" title="Входящие" /></td>'."\n";
$html = $html.'<td><a class="header" href="'.$_SERVER['PHP_SELF'].
'?action=showInBox">Входящие</a> </td>'."\n";
$html = $html.'<td><img src="./images/msg_outbox.gif" alt="Исходящие" title="Исходящие" /></td>'."\n";
$html = $html.'<td><a class="header" href="'.$_SERVER['PHP_SELF'].
'?action=showOutBox">Исходящие</a></td>'."\n";
$html = $html.'<td align="right" width="90%"><a href="'.$_SERVER['PHP_SELF'].
'?action=sendMsgForm"><img
src="./images/msg_newpost.gif" alt="Новое сообщение"
title="Новое сообщение" /></a></td>'."\n";
$html = $html.'</tr>'."\n";
$html = $html.'</table>'."\n";
return $html;
}
?>
Для удаления личного сообщения надо вызвать функцию deleteMessage() :
<?php
// Функция удаляет личное сообщение; ID сообщения передается методом GET
function deleteMessage()
{
if ( !isset( $_SESSION['user'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
if ( !isset( $_GET['idMsg'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
$idMsg = (int)$_GET['idMsg'];
if ( $idMsg < 1 ) {
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
// Далее мы должны выяснить, удаляется входящее или исходящее
// сообщение. Это нужно, чтобы сделать редирект на нужный ящик.
// В этом запросе дополнительное условие нужно для того, чтобы
// пользователь не смог удалить чужое сообщение, просто указав
// ID сообщения в адресной строке браузера
$query = "SELECT to_user, id_rmv
FROM ".TABLE_MESSAGES."
WHERE id_msg=".$idMsg." AND
(to_user=".$_SESSION['user']['id_author']." OR from_user=".$_SESSION['user']['id_author'].")";
$res = mysql_query( $query );
if ( mysql_num_rows( $res ) == 0 ) {
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=showInBox' );
die();
}
list ( $toUser, $id_rmv ) = mysql_fetch_row( $res );
if ( $toUser == $_SESSION['user']['id_author'] )
$redirect = 'action=showInBox';
else
$redirect = 'action=showOutBox';
// id_rmv - это поле указывает на то, что это сообщение уже удалил
// один из пользователей. Т.е. сначала id_rmv=0, после того, как
// сообщение удалил один из пользователей, id_rmv=id_user. И только после
// того, как сообщение удалит второй пользователь, мы можем удалить
// запись в таблице БД TABLE_MESSAGES
if ( $id_rmv == 0 )
$query = "UPDATE ".TABLE_MESSAGES." SET id_rmv=".$_SESSION['user']['id_author']." WHERE id_msg=".$idMsg;
else
$query = "DELETE FROM ".TABLE_MESSAGES." WHERE id_msg=".$idMsg;
$res = mysql_query( $query );
if ( !$res ) {
$msg = 'Произошла ошибка при удалении сообщения';
$err = 'Ошибка при выполнении запроса: <br/>'.
$query.'<br/>'.mysql_errno().': '.mysql_error().'<br/>'.
'(Файл '. __FILE__ .', строка '. __LINE__ .')';
return showErrorMessage( $msg, $err, true, $redirect );
}
return showInfoMessage( 'Сообщение успешно удалено', $redirect );
}
?>
Функция getMessage() возвращает личное сообщение для просмотра пользователем:
<?php
// Функция возвращает личное сообщение для просмотра пользователем
function getMessage()
{
if ( !isset( $_SESSION['user'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
if ( !isset( $_GET['idMsg'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
$idMsg = (int)$_GET['idMsg'];
if ( $idMsg < 1 ) {
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=showInBox' );
die();
}
// Получаем из БД информацию о сообщении.
// В этом запросе дополнительное условие нужно для того, чтобы
// пользователь не смог просмотреть чужое сообщение, просто указав
// ID сообщения в адресной строке браузера
$query = "SELECT a.to_user, a.from_user, a.subject, a.sendtime, a.message, a.viewed,
b.name AS to_user_name, c.name AS from_user_name
FROM ".TABLE_MESSAGES." a INNER JOIN ".TABLE_USERS." b
ON a.to_user=b.id_author
INNER JOIN ".TABLE_USERS." c
ON a.from_user=c.id_author
WHERE id_msg=".$idMsg."
AND (a.to_user=".$_SESSION['user']['id_author']." OR a.from_user=".$_SESSION['user']['id_author'].")
AND a.id_rmv<>".$_SESSION['user']['id_author'];
$res = mysql_query( $query );
if ( !$res ) {
$msg = 'Произошла ошибка при получении сообщения';
$err = 'Ошибка при выполнении запроса: <br/>'.
$query.'<br/>'.mysql_errno().': '.mysql_error().'<br/>'.
'(Файл '. __FILE__ .', строка '. __LINE__ .')';
return showErrorMessage( $msg, $err, true, 'action=showInBox' );
}
if ( mysql_num_rows( $res ) == 0 ) {
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=showInBox' );
die();
}
// Далее мы должны выяснить, запрашивается входящее или исходящее
// сообщение? Это нужно, чтобы правильно указать "Отправитель"
// или "Получатель" и вывести заголовок страницы: "Входящие"
// или "Исходящие"
$message = mysql_fetch_array( $res );
if ( $message['to_user'] == $_SESSION['user']['id_author'] ) {
$redirect = 'action=showInBox';
$inBox = true;
} else {
$redirect = 'action=showOutBox';
$inBox = false;
}
// Формируем заголовок страницы
if ( $inBox ) // Папка "Входящие"
$html = '<h1>Личные сообщения (входящие)</h1>'."\n";
else // Папка "Исходящие"
$html = '<h1>Личные сообщения (исходящие)</h1>'."\n";
$html = $html.getMessagesMenu();
$html = $html.'<table class="showTable">'."\n";
$html = $html.'<tr>'."\n";
$html = $html.'<th colspan="2">Сообщение</th>'."\n";
$html = $html.'</tr>'."\n";
$html = $html.'<tr>'."\n";
if ( $inBox ) {
$html = $html.'<td width="15%">Отправитель</td>'."\n";
$html = $html.'<td width="85%">'.$message['from_user_name'].'</td>'."\n";
} else {
$html = $html.'<td width="15%">Получатель</td>'."\n";
$html = $html.'<td width="85%">'.$message['to_user_name'].'</td>'."\n";
}
$html = $html.'</tr>'."\n";
$html = $html.'<tr>'."\n";
if ( $inBox )
$html = $html.'<td>Отправлено</td>'."\n";
else
$html = $html.'<td>Получено</td>'."\n";
$html = $html.'<td>'.$message['sendtime'].'</td>'."\n";
$html = $html.'<tr>'."\n";
$html = $html.'</tr>'."\n";
$html = $html.'<td>Тема</td>'."\n";
$html = $html.'<td>'.$message['subject'].'</td>'."\n";
$html = $html.'<tr>'."\n";
$html = $html.'</tr>'."\n";
$html = $html.'<td>Сообщение</td>'."\n";
$html = $html.'<td>'.print_page( $message['message'] ).'</td>'."\n";
$html = $html.'</tr>'."\n";
$html = $html.'</table>'."\n";
// Помечаем сообщение, как прочитанное
if ( $inBox and $message['viewed'] != 1 ) {
$query = "UPDATE ".TABLE_MESSAGES." SET viewed=1 WHERE id_msg=".$idMsg;
mysql_query( $query );
}
return $html;
}
?>
Продолжение следует...
|