Storing User Data in Cookies

Một phần của tài liệu Professional PHP Programming phần 8 pptx (Trang 24 - 34)

Phorum uses several cookies to store users' information and preferences. This is handy because it allows us to personalize our pages for each user.

New Messages

The first thing Phorum uses cookies for is determining whether to display a label on each message indicating that it is a new message. Two cookies are involved here. The first is a cookie that holds the ID of the latest message the user has read in this forum. The following code is used to set this cookie:

SetCookie("phorum-new-$TableName", $id, time() + 31536000);

The variable $TableName is used in the cookie to allow for storing settings for each forum. This variable contains just what we would imagine – the name of the table in the database where the data for this forum is stored.

The second is a session cookie – that is a cookie that dies when that browser is closed, that keeps up with which messages are read during that visit to the forum. The IDs of the messages that the user has read during that session are placed in an array. That array is then passed through the serialize() function which prepares the variable to be stored without losing its structure or type. That value is then passed into the SetCookie() call:

$haveread[$id] = 1;

SetCookie("phorum-haveread-$TableName", serialize($haveread), 0);

It should be noted here that to read the values in the $haveread array, the cookie must be passed through the unserialize() function:

$haveread_cookie = "phorum-haveread-$TableName";

$haveread = unserialize($$haveread_cookie);

By using these two cookies together, Phorum allows users to see messages which have arrived since the last time they visited the forum.

User Information

The next cookies store the name and email address which a user enters when posting a message. The next time that user goes to post a message, the correct name and email address are already loaded in the browser. These cookies are persistent, by default expiring after one year:

$name cookie = "phorum name $TableName";

$email cookie = "phorum email $TableName";

if((!IsSet($$name cookie)) || ($$name cookie != $author)) {

SetCookie("phorum name $TableName", $author, time() + 31536000);

// 365 days = 31536000 seconds }

if((!IsSet($$email cookie)) || ($$email cookie != $email)) {

SetCookie("phorum email $TableName", $email, time() + 31536000);

}

The $author and $email variables are set in the form which users fill out when they post a message.

Before setting the cookie, Phorum checks that the cookie is not already set to the value supplied by the user.

The last cookie Phorum uses is one that stores a user setting for Phorum. The default view of a message list in Phorum is to show all messages in a conversation. That means that each message list will contain the original message in the conversation and all subsequent replies. Users can select any one of these to read from that list. However, to allow users to scan through the various conversations more quickly, there is an option to collapse the conversation tree views so that only the original message is shown. Users may do this by selecting one of two links (situated at the top and bottom of the message list). Once the Collapse option has been selected, a cookie is set on the user's machine to save this setting. From that point, on the user will see the collapsed view when visiting the site. Here is the code for setting this value:

$phcollapse="phorum-collapse-$TableName";

if (IsSet($collapse)) { $$phcollapse=$collapse;

SetCookie("phorum-collapse-$TableName", $collapse, time() + 31536000);

} elseif (!isset($$phcollapse)) { $$phcollapse=$Collapsed;

}

The variable $collapase is passed in the URL specified in the link the user clicks to activate the collapsed view. Phorum checks that this variable is set and if so sets the cookie as well as

$$phcollapse which is used later as the switch for using the collapsed view. If $collapse is not set, $$phcollapse is set to $Collapsed which holds the default setting for this forum.

To summarize the cookies used in the Phorum application:

Cookie Description

phorum-new-$TableName The ID of the latest message read by the user

phorum-haveread-$TableName An array of the IDs of the messages read by the user in the current session

phorum_name_$TableName The user's name phorum_email_$TableName The user's email address

phorum-collapse-$TableName Whether the conversation trees are to be collapsed

The Heart of it All: forums.inf

This file controls all the settings for Phorum. As we said earlier, this file is generated on the fly. All of the default settings, as well as the unique settings for each forum, are contained in this file. There is one value that is passed around all pages in Phorum with the exception of the forum list page: the parameter

$num. The value of this determines which forum is displayed on the other pages. The code in

forums.inf assigns values from the array containing information for the forums to variables for use in the other files. This is to ease both the writing and reading of code in the rest of the script. A typical forums.inf file might look like this:

<?php

// DO NOT EDIT THIS FILE. USE ADMIN.PHP3

// initialize database $dbName = 'name';

$dbUser = 'user';

$dbPass = 'pass';

$dbServer = '';

$DB = new db();

$DB->open($dbName, $dbServer, $dbUser, $dbPass);

$q = new query($DB); //dummy query for generic operations

// master information $Password = 'webman';

$nDisplay = '20';

$default email = 'phorum-dev@phorum.org';

$UseCookies = '1';

$sortforums = '1';

$forum url = 'http://dev.phorum.org/phorum3/';

$ext = 'php3';

$forum page = 'index';

$list page = 'list';

$search page = 'search';

$read page = 'read';

$post page = 'post';

$violation page = 'violation';

$down page = 'down';

$default lang = 'english.lang';

$default_table_width = '100%';

$default table header color = '#000080';

$default table header font color = '#FFFFFF';

$default table body color 1 = '#FFFFCC';

$default table body font color 1 = '#000000';

$default table body color 2 = '#CC0000';

$default table body font color 2 = '#000000';

$default nav color = '#FFFFFF';

$default nav font color = '#0000FF';

// forum information

// Phorum Admin forum $forums['2']['id'] = 2;

$forums['2']['active'] = 1;

$forums['2']['name'] = 'Phorum Admin';

$forums['2']['table'] = 'dev Xfh8Uit admin';

$forums['2']['mod'] = 'phorum-dev@phorum.org';

$forums['2']['mod pass'] = 'webman';

$forums['2']['email mod'] = '1';

$forums['2']['description'] = 'This forum is for Phorum Administrators.';

$forums['2']['multi level'] = '1';

$forums['2']['collapse'] = '1';

$forums['2']['staff host'] = '';

$forums['2']['lang'] = 'english.lang';

$forums['2']['html'] = '1';

$forums['2']['table width'] = '100%';

$forums['2']['table header color'] = '#000080';

$forums['2']['table header font color'] = '#FFFFFF';

$forums['2']['table body color 1'] = '#FFFFCC';

$forums['2']['table body font color 1'] = '#000000';

$forums['2']['table body color 2'] = '#0000CC';

$forums['2']['table body font color 2'] = '#000000';

$forums['2']['nav color'] = '#FFFFFF';

$forums['2']['nav font color'] = '#0000FF';

// Phorum Features and Bugs forum $forums['1']['id'] = 1;

$forums['1']['active'] = 1;

$forums['1']['name'] = 'Phorum Features and Bugs';

$forums['1']['table'] = 'dev Xfh8Uit phorum';

$forums['1']['mod'] = 'phorum-dev@phorum.org';

$forums['1']['mod pass'] = 'webman';

$forums['1']['email mod'] = '1';

$forums['1']['description'] = 'This forum is for discussing Phorum.';

$forums['1']['multi level'] = '1';

$forums['1']['collapse'] = '1';

$forums['1']['staff host'] = '';

$forums['1']['lang'] = 'english.lang';

$forums['1']['html'] = '1';

$forums['1']['table width'] = '100%';

$forums['1']['table header color'] = '#000080';

$forums['1']['table header font color'] = '#FFFFFF';

$forums['1']['table body color 1'] = '#FFFFCC';

$forums['1']['table_body_font_color_1'] = '#000000';

$forums['1']['table body color 2'] = '#0000CC';

$forums['1']['table body font color 2'] = '#000000';

$forums['1']['nav color'] = '#FFFFFF';

$forums['1']['nav font color'] = '#0000FF';

if (is array($forums) && $num>0) { $ForumName = $forums["$num"]["name"];

$TableName = $forums["$num"]["table"];

$BodiesTable = $TableName." bodies";

$Mod = $forums["$num"]["mod"];

$ModPass = $forums["$num"]["mod pass"];

$EmailModerator = $forums["$num"]["email mod"];

$Description = $forums["$num"]["description"];

$MultiLevel = $forums["$num"]["multi level"];

$Collapsed = $forums["$num"]["collapse"];

$StaffHost = $forums["$num"]["staff host"];

$ForumLang = $forums["$num"]["lang"];

$AllowHtml = $forums["$num"]["html"];

$TableWidth = $forums["$num"]["table width"];

$TableHeaderColor = $forums["$num"]["table header color"];

$TableHeaderFontColor = $forums["$num"]["table header font color"];

$TableBodyColor1 = $forums["$num"]["table body color 1"];

$TableBodyFontColor1 = $forums["$num"]["table body font color 1"];

$TableBodyColor2 = $forums["$num"]["table body color 2"];

$TableBodyFontColor2 = $forums["$num"]["table body font color 2"];

$NavColor = $forums["$num"]["nav color"];

$NavFontColor = $forums["$num"]["nav font color"];

}

if ($ForumLang != "") {

include "./" . $forums["$num"]["lang"];

} else{

include "./" . $default lang;

}

?>

Listing Forums

The first page a user will see is a list of the available forums. This is achieved by looping through an array that is created in the forums.inf file, the file generated by the forum administration section.

Each forum is listed with a description, the total number of messages in the forum and the date of the most recent post in the forum. A user can select a forum by clicking on its name, and so be taken to the list page. The main section of this page consists of an HTML table containing all the forum names. First we print the table header:

<TABLE WIDTH="<?php echo $default table width; ?>" CELLSPACING="0"

CELLPADDING="2" BORDER="0">

<TR>

<TD WIDTH="100%" COLSPAN=2

<?php echo bgcolor($default table header color); ?>>

<FONT COLOR="<?PHP echo $default table header font color; ?>">

&nbsp;

<?php echo $lAvailableForums;?>

</FONT>

</TD>

</TR>

First we set a variable $empty with the value true. We will check this variable later to give a message if there are no active forums. Next, we check to see whether the $forums array exists. If so, we loop through each available forum:

<?php

$empty=true;

if (is array($forums)) { $forum=current($forums);

while(is array($forum)){

if ($forum["active"]==true) {

We set the variable $empty to false, since we have found an active forum, $name to the name of the current forum and $num to its ID. Then we query the database to check the number of messages in the forum:

$empty=false;

$name=$forum["name"];

$num=$forum["id"];

$sSQL="SELECT count(*) AS posts FROM $forum[table]";

$q->query($DB, $sSQL);

if ($q->numrows()) {

$num posts=$q->field("posts", 0);

} else {

$num posts='0';

}

Then we check for the date of the latest message:

$sSQL="SELECT max(datestamp) AS max date FROM $forum[table]";

$q->query($DB, $sSQL);

$last post date=$q->field("max date", 0);

if($last post date==0){

$last post date=date format("0000-00-00");

} else {

$last post date=date format($last post date);

}

Now we can print out the table row with the forum details. Each forum name is contained in an <A> link which will take the user to the list page (list.php3) with the query string ?num=forum_id added to the end of the URL:

echo "<TR BGCOLOR=\"$default table body color 1\">

<TD WIDTH=\"60%\">";

echo "<FONT SIZE=4 COLOR=\"$default table body font color 1\">";

echo "<DL><DT><B>&nbsp;

<A HREF=\"$list page.$ext?num=$num$GetVars\">

$name</A></B></TD>";

echo "<TD WIDTH=\"40%\"><FONT SIZE=-1

COLOR=\"$default table body font color 1\">

&nbsp;&nbsp;$lNumPosts:

<B>$num posts</B>&nbsp;&nbsp;&nbsp;&nbsp;

$lLastPostDate: <B>$last post date</B></FONT></TD></TR>";

echo "<TR BGCOLOR=\"$default table body color 1\">

<TD COLSPAN=2>";

echo "<DD><FONT SIZE=-1

COLOR=\"$default table body font color 1\">";

echo $forum["description"];

echo "</FONT></DL></TD></TR><P>\n";

}

When we've printed the row, we move to the next forum. If $empty is still set to true when this loop has finished, no active forums were found, so we print a message to that effect:

$forum=next($forums);

} }

if ($empty) {

echo $lNoActiveForums;

} ?>

</FONT></TD></TR></TABLE>

Listing Messages

As we stated earlier, using a SQL database allows Phorum to manipulate the messages quickly. The list page is a good example of that. Several queries are used to set up the display of the messages.

The first query retrieves a list of threads that will be shown on the front page. This is done by selecting the threads in a descending order and limiting the query to the number set by the administrator. The default is 20. The query used here is:

SELECT thread FROM $TableName WHERE thread > $cutoff_thread ORDER BY thread DESC LIMIT 20

$TableName is the variable that holds the table name for this forum; $cutoff_thread is the thread number of the last message on the previous page. If this is the front page, a query will have been run before this one to retrieve the maximum thread in the table.

The high and low thread values from this list are then retrieved from the results and placed in the variables $max and $min. Individual threads cannot be selected in the query as we are looking for threads which cover a given number of messages. Also, by limiting the number of rows returned, we would risk failing to return all the messages in the last thread. This is the reason for the next query. We feed the maximum and minimum thread numbers into the following query:

SELECT id,parent,thread,subject,author,datestamp FROM $TableName WHERE thread<=$max AND thread>=$min

ORDER BY thread DESC, id asc

This returns the fields that we will use for displaying the messages. Depending on what type of display

the administrator has set up, two different code modules will be used to display the messages. If the messages are to be displayed in two-tiered format, threads.inc is included. However, if they are to be shown in a multi-tiered format, multi-threads.inc is included. Both do the same thing – they cycle through the messages and output the HTML to display the messages. The only difference is that the multi-tiered format requires some preprocessing to order the threads correctly.

But first we perform the cookie handling, checking for the last message read by the user and checking the user's preference for a collapsed or non-collapsed view:

<?PHP

$cutoff = 800; // See the faq.

$phcollapse="phorum-collapse-$TableName";

$new cookie="phorum-new-$TableName";

$haveread cookie="phorum-haveread-$TableName";

if ($UseCookies) {

if (IsSet($$new cookie)) { $old message=$$new cookie;

} else {

$old message="0";

}

if (IsSet($$haveread cookie)) {

$haveread=unserialize(urldecode($$haveread cookie));

} else {

$haveread[0]=$old message;

}

if (IsSet($collapse)) { $$phcollapse=$collapse;

SetCookie("phorum-collapse-$TableName",$collapse,time()+ 31536000);

} elseif (!isset($$phcollapse)) { $$phcollapse=$Collapsed;

}

if (!IsSet($$haveread cookie)) {

SetCookie("phorum-haveread-$TableName", urlencode(serialize($haveread)), 0);

} else {

$$haveread cookie="";

}

} else {

if (IsSet($collapse)) { $$phcollapse=$collapse;

} else {

$$phcollapse=$Collapsed;

} }

Next, we check whether the database is PostgreSQL, and if so, we know we need to avoid using a LIMIT clause in our SQL queries:

if ($DB->type=="postgresql") { $limit="";

$q->query($DB, "set QUERY LIMIT TO '$nDisplay'");

} else {

$limit=" LIMIT $nDisplay";

}

Now we build the database queries which we looked at above. The query will depend on whether we are on the front page (in which case we will first need to get the maximum thread in the table), and whether the user has selected collapsed view (if not, we also need to get the count field from the database):

if ($thread==0 || $action==0) {

$sSQL = "SELECT max(thread) AS thread FROM $TableName";

$q->query($DB, $sSQL);

if ($q->numrows()>1) {

$maxthread=$q->field("thread", 0);

} else {

$maxthread=0;

}

$cutoff thread=$maxthread-$cutoff;

if ($$phcollapse==0) {

$sSQL = "SELECT thread FROM $TableName WHERE thread > $cutoff thread ORDER BY thread desc" . $limit;

} else {

$sSQL = "SELECT thread, count(*) AS tcount, max(datestamp) AS latest, max(id) AS maxid FROM $TableName WHERE thread > $cutoff thread GROUP BY thread ORDER BY thread DESC" . $limit;

echo "<!--$sSQL-->\n";

} } else {

if ($action==1) {

$cutoff thread=$thread+$cutoff;

$sSQL = "SELECT thread FROM $TableName WHERE thread < $cutoff thread AND thread > $thread ORDER BY thread" . $limit;

$q=new query($DB, $sSQL);

if ($rows=$q->numrows()) {

$thread = $q->field("thread",$rows-1);

}

$thread=$thread+1;

}

$cutoff thread=$thread-$cutoff;

if ($$phcollapse==0) {

$sSQL = "SELECT thread FROM $TableName WHERE thread < $thread AND thread > $cutoff thread ORDER BY thread DESC" . $limit;

} else {

$sSQL = "SELECT thread, count(*) AS tcount, max(datestamp) AS latest, max(id) AS maxid FROM $TableName WHERE thread < $thread AND thread > $cutoff thread GROUP BY thread ORDER BY thread DESC" . $limit;

echo "<!--$sSQL-->\n";

} }

$thread list = new query($DB, $sSQL);

if ($DB->type=="postgresql") {

$q->query($DB, "SET QUERY LIMIT TO '0'");

}

$rows = $thread list->numrows();

if($rows==0 && $action!=0){

Header("Location: $list page.$ext?num=$num$GetVars");

exit();

}

if ($$phcollapse==0) {

$sSQL = "SELECT id,parent,thread,subject,author,datestamp FROM $TableName WHERE thread<=$max AND thread>=$min ORDER BY thread DESC, id ASC";

} else {

$sSQL = "SELECT id,parent,thread,subject,author,datestamp FROM $TableName WHERE thread<=$max AND thread>=$min AND thread=id ORDER BY thread DESC";

}

echo "<!--$sSQL-->\n";

$msg_list = new query($DB, $sSQL);

Next we build the <A> tag which the user can use to select a collapsed or non-collapsed view, and use this when we build the navigation bar links (at the top and bottom of the table):

if ($$phcollapse==0) {

$collapse link = "<A HREF=\"$list page.$ext?num=$num&collapse=1$GetVars\">

<FONT COLOR='$NavFontColor'>" . $lCollapseThreads . "</FONT></A>";

} else {

$collapse link = "<A HREF=\"$list page.$ext?num=$num&collapse=0$GetVars\">

<FONT COLOR='$NavFontColor'>" . $lViewThreads . "</FONT></A>";

}

if (count($forums)>1) {

$nav = "<DIV CLASS=nav><FONT COLOR='$NavFontColor'>&nbsp;

<A HREF=\"$forum page.$ext?$GetVars\">

<FONT COLOR='$NavFontColor'>" . $lForumList . "</FONT></A>&nbsp;&nbsp;|&nbsp;&nbsp;

<A HREF=\"$list page.$ext?num=$num$GetVars\">

<FONT COLOR='$NavFontColor'>" . $lGoToTop . "</FONT></A>&nbsp;&nbsp;|&nbsp;&nbsp;

<A HREF=\"$post page.$ext?num=$num$GetVars\">

<FONT COLOR='$NavFontColor'>" . $lStartTopic .

"</FONT></A>&nbsp;&nbsp;|&nbsp;&nbsp;$collapse link&nbsp;

&nbsp;|&nbsp;&nbsp;<A HREF=\"$search page.$ext?num=$num$GetVars\">

<FONT COLOR='$NavFontColor'>" . $lSearch . "</FONT></A>&nbsp;</FONT></DIV>";

} else {

$nav = "<DIV CLASS=nav><FONT COLOR='$NavFontColor'>&nbsp;

<A HREF=\"$list page.$ext?num=$num$GetVars\">

<FONT COLOR='$NavFontColor'>" . $lGoToTop . "</FONT></A>&nbsp;&nbsp;|&nbsp;&nbsp;

<A HREF=\"$post page.$ext?num=$num$GetVars\">

<FONT COLOR='$NavFontColor'>" . $lStartTopic .

"</FONT></A>&nbsp;&nbsp;|&nbsp;&nbsp;$collapse_link&nbsp;&nbsp;|

Một phần của tài liệu Professional PHP Programming phần 8 pptx (Trang 24 - 34)

Tải bản đầy đủ (PDF)

(86 trang)