Скрипт форума на PHP своими руками. Часть 9


Прислал: Евгений Токмаков [ 03.07.2008 @ 12:59 ]
Раздел:: [ Статьи по PHP ]


Кроме того, что пользователи могут обмениваться личными сообщениями, они могут еще написать письмо через форум. Функция getSendMailForm() возвращает html формы для отправки письма через форум:

<?php
// Функция возвращает html формы для отправки письма через форум
function getSendMailForm()
{
  
// Если письмо пытается отправить незарегистрированный пользователь
  
if ( !isset( $_SESSION['user'] ) ) {
    
header'Location: '.$_SERVER['PHP_SELF'] );
    die();  
  }
  
  
$html '';
  
  
$toUser '';
  if ( isset( 
$_GET['idUser'] ) ) {
    
$id = (int)$_GET['idUser'];
    if ( 
$id ) {
      
$query "SELECT name FROM ".TABLE_USERS." WHERE id_author=".$id;
      
$res mysql_query$query );
      if ( 
$res ) {
        if ( 
mysql_num_rows$res ) > $toUser mysql_result$res0);
      }
    }
  }
  
$subject '';
  
$message '';
  
  
$action $_SERVER['PHP_SELF'].'?action=sendMail';
  
// Если при заполнении формы были допущены ошибки
  
if ( isset( $_SESSION['sendMailForm'] ) ) {
    
$info file_get_contents'./templates/infoMessage.html' );
    
$info str_replace'{infoMessage}'$_SESSION['sendMailForm']['error'], $info );
    
$html $html.$info."\n";
    
$toUser  htmlspecialchars$_SESSION['sendMailForm']['toUser'] );
    
$subject htmlspecialchars$_SESSION['sendMailForm']['subject'] );
    
$message htmlspecialchars$_SESSION['sendMailForm']['message'] );
    unset( 
$_SESSION['sendMailForm'] );
  }
  
  
$tpl file_get_contents'templates/sendMailForm.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;
}
?>

Обработчик формы - функция sendMail():

<?php
// Отправка письма пользователю сайта
function sendMail()
{
  
// Если не переданы данные формы - функция вызвана по ошибке
  
if ( !isset( $_POST['toUser'] ) or
       !isset( 
$_POST['subject'] ) or
       !isset( 
$_POST['message'] ) )
  {
    
header'Location: '.$_SERVER['PHP_SELF'] );
    die();
  }
  
// Если письмо пытается отправить незарегистрированный пользователь
  
if ( !isset( $_SESSION['user'] ) ) {
    
header'Location: '.$_SERVER['PHP_SELF'] );
    die();  
  }

  
// Обрезаем переменные до длины, указанной в параметре maxlength тега input
  
$toUser  substr$_POST['toUser'], 030 );
  
$subject substr$_POST['subject'], 060 );
  
$message substr$_POST['message'], 0MAX_MAILBODY_LENGTH );
  
// Обрезаем лишние пробелы
  
$toUser  trim$toUser );
  
$subject trim$subject );
  
$message trim$message );
  
  
// Проверяем, заполнены ли обязательные поля
  
$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 ( !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, name, email FROM ".TABLE_USERS." WHERE name='".$to."' LIMIT 1";
    
$res mysql_query$query );
    if ( !
$res ) {
      
$msg 'Произошла ошибка при отправке письма';
      
$err 'Ошибка при выполнении запроса: <br/>'.
             
$query.'<br/>'.mysql_errno().':&nbsp;'.mysql_error().'<br/>'.
             
'(Файл '__FILE__ .', строка '__LINE__ .')';
      return 
showErrorMessage$msg$errtrue'' );
    }
    if ( 
mysql_num_rows$res ) == 
      
$error $error.'<li>пользователь с именем <strong>'.$to.'</strong> не зарегистрирован</li>'."\n";
  }
  
// Если были допущены ошибки при заполнении формы - 
  // перенаправляем посетителя для исправления ошибок
  
if ( !empty( $error ) )
  {
    
$_SESSION['sendMailForm'] = array();
    
$_SESSION['sendMailForm']['error'] = '<p class="errorMsg">При заполнениии формы были допущены ошибки:</p>'.
    
"\n".'<ul class="errorMsg">'."\n".$error.'</ul>'."\n";
    
$_SESSION['sendMailForm']['toUser'] = $toUser;
    
$_SESSION['sendMailForm']['subject'] = $subject;
    
$_SESSION['sendMailForm']['message'] = $message;
    
header'Location: '.$_SERVER['PHP_SELF'].'?action=sendMailForm' );
    die();
  }
  
$toUser mysql_fetch_array$res );
  
$fromUser $_SESSION['user']['name'];

  
$message 'ОТ: '.$fromUser."\n".'ТЕМА: '.$subject."\n\n".$message;
    
  
// формируем заголовки письма
  
$headers "From: ".$_SERVER['SERVER_NAME']." <".ADMIN_EMAIL.">\n";
  
$headers $headers."Content-type: text/plain; charset=\"windows-1251\"\n";
  
$headers $headers."Return-path: <".ADMIN_EMAIL.">\n";
  
$subject 'Письмо с форума '.$_SERVER['SERVER_NAME'].' от '.$fromUser;
  
$subject '=?koi8-r?B?'.base64_encode(convert_cyr_string($subject"w","k")).'?=';
  if ( 
mail$toUser['email'], $subject$message$headers ) )
    return 
showInfoMessage'Ваше письмо успешно отправлено''' );
  else
    return 
showInfoMessage'Произошла ошибка при отправке письма''' );
}
?>

Перед тем как рассматривать систему администрирования форума, давайте бросим взгляд на несколько вспомогательных функций. Функция print_page() отвечает за обработку BB-кодов:

<?php
// Функция обработки bbCode
function print_page($message)
{
  
// Разрезаем слишком длинные слова
    
$message preg_replace_callback(
              
"|([a-zа-я\d!]{35,})|i",
              
"split_text",
              
$message);
        
  
// Тэги - [code], [php]
  
preg_match_all"#\[php\](.+)\[\/php\]#isU"$message$matches );
  
$cnt count$matches[0] );
  for ( 
$i 0$i $cnt$i++ ) {
    
$phpBlocks[] = '<div class="codePHP">'.highlight_string$matches[1][$i], true ).'</div>';
    
$uniqidPHP '[php_'.uniqid('').']';
    
$uniqidsPHP[] = $uniqidPHP;
    
$message str_replace$matches[0][$i], $uniqidPHP$message ); 
  }

  
$spaces = array( ' '"\t" );
  
$entities = array( '&nbsp;''&nbsp;&nbsp;&nbsp;&nbsp;' );
  
  
preg_match_all"#\[code\](.+)\[\/code\]#isU"$message$matches );
  
$cnt count$matches[0] );

  for ( 
$i 0$i $cnt$i++ ) {
    
$codeBlocks[] = '<div class="code">'.nl2brstr_replace$spaces$entitieshtmlspecialchars$matches[1][$i] ) ) ).'</div>';
    
$uniqidCode '[code_'.uniqid('').']';
    
$uniqidsCode[] = $uniqidCode;
    
$message str_replace$matches[0][$i], $uniqidCode$message ); 
  }
  
  
$message htmlspecialchars$message );
  
$message preg_replace("#\[b\](.+)\[\/b\]#isU"'<b>\\1</b>'$message);
  
$message preg_replace("#\[i\](.+)\[\/i\]#isU"'<i>\\1</i>'$message);
  
$message preg_replace("#\[u\](.+)\[\/u\]#isU"'<u>\\1</u>'$message);
  
$message preg_replace("#\[quote\](.+)\[\/quote\]#isU",'<div class="quoteHead">Цитата</div><div class="quoteContent">\\1</div>',$message);
  
$message preg_replace("#\[quote=&quot;([- 0-9a-zа-яА-Я]{1,30})&quot;\](.+)\[\/quote\]#isU"'<div class="quoteHead">\\1 пишет:</div><div class="quoteContent">\\2</div>'$message);
  
$message preg_replace("#\[url\][\s]*([\S]+)[\s]*\[\/url\]#isU",'<a href="\\1" target="_blank">\\1</a>',$message);
  
$message preg_replace("#\[url[\s]*=[\s]*([\S]+)[\s]*\][\s]*([^\[]*)\[/url\]#isU",
                             
'<a href="\\1" target="_blank">\\2</a>',
                             
$message);
  
$message preg_replace("#\[img\][\s]*([\S]+)[\s]*\[\/img\]#isU",'<img src="\\1" alt="" />',$message);
  
$message preg_replace("#\[color=red\](.+)\[\/color\]#isU",'<span style="color:#FF0000">\\1</span>',$message);
  
$message preg_replace("#\[color=green\](.+)\[\/color\]#isU",'<span style="color:#008000">\\1</span>',$message);
  
$message preg_replace("#\[color=blue\](.+)\[\/color\]#isU",'<span style="color:#0000FF">\\1</span>',$message);
  
$message preg_replace_callback("#\[list\]\s*((?:\[\*\].+)+)\[\/list\]#siU",'getUnorderedList',$message);
  
$message preg_replace_callback("#\[list=([a|1])\]\s*((?:\[\*\].+)+)\[\/list\]#siU"'getOrderedList',$message);
  
  
$message nl2br$message);
  
  if ( isset( 
$uniqidCode ) ) $message str_replace$uniqidsCode$codeBlocks$message );
  if ( isset( 
$uniqidPHP ) ) $message str_replace$uniqidsPHP$phpBlocks$message );
  
  return 
$message;
}

function 
split_text($matches
{
  return 
wordwrap($matches[1], 35' ',1);
}

function 
getUnorderedList$matches )
{
  
$list '<ul>';
  
$tmp trim$matches[1] );
  
$tmp substr$tmp);
  
$tmpArray explode'
  • '$tmp );   
      
    $elements '';
      foreach ( 
    $tmpArray as $value ) {
        
    $elements $elements.'<li>'.trim($value).'</li>';
      }
      
    $list $list.$elements;
      
    $list $list.'</ul>';
      return 
    $list;
    }

    function 
    getOrderedList$matches )
    {
      if ( 
    $matches[1] == '1' )
        
    $list '<ol type="1">';
      else
        
    $list '<ol type="a">';
      
    $tmp trim$matches[2] );
      
    $tmp substr$tmp);
      
    $tmpArray explode'
  • '$tmp );
     
      
    $elements '';
      foreach ( 
    $tmpArray as $value ) {
        
    $elements $elements.'<li>'.trim($value).'</li>';
      }
      
    $list $list.$elements;
      
    $list $list.'</ol>';
      return 
    $list;
    }
    ?>
  • Функция getStat() отвечает за вывод статистики форума: общее количество оставленных сообщений, число зарегистрированных пользователей и т.п.

    <?php
    // Статистика форума
    function getStat()
    {
      
    $html '<table class="showTable">'."\n";
      
    $html $html.'<tr><th>Статистика</th></tr>'."\n";
      
    $html $html.'<tr>'."\n";
      
    $html $html.'<td>'."\n";
      
    $html $html.'<div class="details">'."\n";
      
    $query 'SELECT COUNT(*) FROM '.TABLE_POSTS;
      
    $res mysql_query$query );
      if ( !
    $res ) return '';
      
    $html $html.'Наши пользователи оставили сообщений: '.mysql_result$res0).'<br/>'."\n";
      
    $query 'SELECT COUNT(*) FROM '.TABLE_USERS;
      
    $res mysql_query$query );
      if ( !
    $res ) return '';
      
    $html $html.'Всего зарегистрированных пользователей: '.mysql_result$res0).'<br/>'."\n";
      
    $query 'SELECT id_author, name FROM '.TABLE_USERS.' ORDER BY id_author DESC LIMIT 1';
      
    $res mysql_query$query );
      if ( !
    $res ) return '';
      list( 
    $id_user$name ) = mysql_fetch_array$res );
      
    $html $html.'Последний зарегистрированный пользователь: '.
              
    '<a href="'.$_SERVER['PHP_SELF'].'?action=showUserInfo&idUser='.
              
    $id_user.'">'.$name.'</a><br/>'."\n";
      
    // Пользователи on-line
      
    if ( isset( $_SESSION['usersOnLine'] ) ) {
        
    $cnt count$_SESSION['usersOnLine'] );
        
    $onLine '';
        if ( 
    $cnt ) {
          
    $onLine $onLine.'Сейчас на форуме: ';
          foreach ( 
    $_SESSION['usersOnLine'] as $id => $name ) {
            
    $onLine $onLine.'<a href="'.$_SERVER['PHP_SELF'].
                      
    '?action=showUserInfo&idUser='.$id.'">'.$name.'</a>, ';    
          }
          
    $onLine substr$onLine0, (strlen$onLine )-2) );
        }
        
    $html $html.$onLine."\n";
      }
      
    $html $html.'</div>'."\n";
      
    $html $html.'</td>'."\n";
      
    $html $html.'</tr>'."\n";
      
    $html $html.'</table>'."\n";
      
      return 
    $html;
    }

    // Функция помещает в массив $_SESSION['usersOnLine'] список зарегистрированных 
    // пользователей, которые в настоящий момент просматривают форум
    function getUsersOnLine()
    {
      
    $query "SELECT id_author, name 
                FROM "
    .TABLE_USERS.
                WHERE UNIX_TIMESTAMP(last_visit)>"
    .( time() - 60 TIME_ON_LINE )."
                ORDER BY status DESC"
    ;
      
    $res mysql_query$query );
      if ( 
    $res ) {
        if ( isset( 
    $_SESSION['usersOnLine'] ) ) unset( $_SESSION['usersOnLine'] );
        
    $cnt mysql_num_rows$res );
        if ( 
    $cnt ) {
          for ( 
    $i 0$on mysql_fetch_array$res ); $i++ ) {
            
    $_SESSION['usersOnLine'][$on['id_author']] = $on['name'];
          }
        }
      }
      return;
    }
    ?>

    Продолжение следует...