| only for RuBoard - do not distribute or recompile |
There are five things we want our users to be able to do after they have logged in:
Look at the lists available for subscription
Subscribe and unsubscribe from lists
Change the way their accounts are set up
Change their passwords
Log out
You can see most of these options in Figure 28.6. We will now look at the implementation of each of these options.
We will implement a number of options for viewing available lists and list details. In Figure 28.6, you can see two of these options: Show My Lists, which will retrieve the lists this user is subscribed to, and Show Other Lists, which will retrieve the lists the user is not subscribed to.
If you look back at Figure 28.4, you will see that we have another option, Show All Lists, which will retrieve all the available mailing lists on the system. For the system to be truly scalable, we should add paging functionality (to display, say, 10 results per page). We have not done this here for brevity.
These three menu options activate the show-my-lists, show-other-lists, and show-all-lists actions, respectively. As you have probably realized, all these actions work quite similarly. The code for these three actions is as follows:
case 'show-all-lists':
{
display_items("All Lists", get_all_lists(), 'information',
'show-archive','');
break;
}
case 'show-other-lists':
{
display_items("Unsubscribed Lists",
get_unsubscribed_lists(get_email()), 'information',
'show-archive', 'subscribe');
break;
}
case '':
case 'show-my-lists':
{
display_items("Subscribed Lists", get_subscribed_lists(get_email()),
'information', 'show-archive', 'unsubscribe');
break;
}
As you can see, all these actions call the display_items() function from the output_fns.php library, but they each call it with different parameters. They all also use the get_email() function we mentioned earlier to get the appropriate email address for this user.
To see what this function does, look at Figure 28.7.

This is the Show Other Lists page.
Let's look at the code for the display_items() function. It is shown in Listing 28.6.
function display_items($title, $list, $action1='', $action2='', $action3='')
{
global $table_width;
echo "<table width = $table_width cellspacing = 0 cellpadding = 0
border = 0>";
// count number of actions
$actions = (($action1!='') + ($action2!='') + ($action3!=''));
echo "<tr>
<th colspan = ". (1+$actions) ." bgcolor='#5B69A6'> $title </th>
</tr>";
// count number of items
$items = sizeof($list);
if($items == 0)
echo "<tr>
<td colspan = ".(1+$actions)."align = center>No Items to Display</td>
</tr>";
else
{
// print each row
for($i = 0; $items; $i++)
{
if($i%2) // background colors alternate
$bgcolor = "'#ffffff'";
else
$bgcolor = "'#ccccff'";
echo "<tr
<td bgcolor = $bgcolor
width = ". ($table_width - ($actions*149)) .">";
echo $list[$i][1];
if($list[$i][2])
echo " - ".$list[$i][2];
echo "</td>";
// create buttons for up to three actions per line
for($j = 1; $j<=3; $j++)
{
$var = 'action'.$j;
if($$var)
{
echo "<td bgcolor = $bgcolor width = 149>";
// view/preview buttons are a special case as they link to a file
if($$var == 'preview-html'||$$var == 'view-html'||
$$var == 'preview-text'||$$var == 'view-text')
display_preview_button($list[$i][3], $list[$i][0], $$var);
else
display_button( $$var, "&id=" . $list[$i][0] );
echo "</td>";
}
}
echo "</tr>\ n";
}
echo "</table>";
}
}
This function will output a table of items, with each item having up to three associated action buttons. The function expects five parameters, which are, in order:
$title is the title that appears at the top of the table—in the case shown in Figure 28.7, we are passing in the title Unsubscribed Lists, as shown in the previously discussed code snippet for the action "Show Other Lists".
$list is an array of items to display in each row of the table. In this case, it is an array of the lists the user is not currently subscribed to. We are building this array (in this case) in the function get_unsubscribed_lists(), which we'll discuss in a minute. This is a multidimensional array, with each row in the array containing up to four pieces of data about each row. In order, again:
$list[n][0] should contain the item id, which will usually be a row number. This gives the action buttons the id of the row they are to operate upon. In our case, we will use ids from the database—more on this in a minute.
$list[n][1] should contain the item name. This will be the text displayed for a particular item. For example, in the case shown in Figure 28.7, the item name in the first row of the table is PHP Tipsheet.
$list[n][2] and $list[n][3] are optional. We use these to convey that there is more information. They correspond to the more information text and the more information id, respectively. We will look at an example using these two parameters when we come to the View Mail action in the "Implementing Administrative Functions" section.
We could, as an alternative, have used keywords as indices to the array.
The third, fourth, and fifth parameters to the function are used to pass in three actions that will be displayed on buttons corresponding to each item. In Figure 28.7, these are the three action buttons shown as Information, Show Archive, and Subscribe.
We got these three buttons for the Show All Lists page by passing in the action names, information, show-archive, and subscribe. By using the display_button() function, these actions have been turned into buttons with those words on them, and the appropriate action assigned to them.
Each of the Show actions calls the display_items() function in a different way, as you can see by looking back at their actions. As well as having different titles and action buttons, each of the three uses a different function to build the array of items to display. Show All Lists uses the function get_all_lists(), Show Other Lists uses the function get_unsubscribed_ lists(), and Show My Lists uses the function get_subscribed_lists(). All these functions work in a similar fashion. They are all from the mlm_fns.php function library.
We'll look at get_unsubscribed_lists() because that's the example we've followed so far. The code for the get_unsubscribed_lists() function is shown in Listing 28.7.
function get_unsubscribed_lists($email)
{
$list = array();
$query = "select lists.listid, listname, email from lists left join sub_lists
on lists.listid = sub_lists.listid
and email='$email'where email is NULL order by listname";
if(db_connect())
{
$result = mysql_query($query);
if(!$result)
echo "<p>Unable to get list from database.";
$num = mysql_numrows($result);
for($i = 0; $i<$num; $i++)
{
array_push($list, array(mysql_result($result, $i, 0),
mysql_result($result, $i, 1)));
}
}
return $list;
}
As you can see, this function requires an email address passed into it. This should be the email address of the subscriber that we are working with. The get_subscribed_lists() function also requires an email address as a parameter, but the get_all_lists() function does not for obvious reasons.
Given a subscriber's email address, we connect to the database and fetch all the lists the subscriber is not subscribed to. As usual for this kind of query in MySQL, we use a LEFT JOIN to find unmatched items.
We loop through the result and build the array row by row using the array_push() built-in function.
Now that we know how this list is produced, let's look at the action buttons associated with these displays.
The Information button shown in Figure 28.7 triggers the 'information' action, which is as follows:
case 'information':
{
display_information($id);
break;
}
To see what the display_information() function does, look at Figure 28.8.

The function displays some general information about a particular mailing list, as well as listing the number of subscribers and the number of newsletters that have been sent out to that list and are available in the archive (more on that in a minute).
The code for this function is shown in Listing 28.8.
function display_information($listid)
{
if(!$listid)
return false;
$info = load_list_info($listid);
if($info)
{
echo "<h2>".pretty($info[listname])."</h2>";
echo '<p>'.pretty($info[blurb]);
echo '<p>Number of subscribers:'. $info[subscribers];
echo '<p>Number of messages in archive:'. $info[archive];
}
}
The display_information() function uses two other functions to help it achieve its Web task: the load_list_info() function and the pretty() function. The load_list_info() function actually retrieves the data from the database. The pretty() function simply formats the data from the database by stripping out slashes, turning newlines into HTML line breaks, and so on.
Let's look briefly at the load_list_info() function. This function is in the mlm_fns.php function library. The code for it is shown in Listing 28.9.
function load_list_info($listid)
{
if(!$listid)
return false;
if(!db_connect())
return false;
$query = "select listname, blurb from lists where listid = $listid";
$result = mysql_query($query);
if(!$result)
{
echo "Cannot retrieve this list";
return false;
}
$info = mysql_fetch_array($result);
$query = "select count(*) from sub_lists where listid = $listid";
$result = mysql_query($query);
if($result)
{
$info['subscribers'] = mysql_result($result, 0, 0);
}
$query = "select count(*) from mail where listid = $listid
and status = 'SENT'";
$result = mysql_query($query);
if($result)
{
$info['archive'] = mysql_result($result, 0, 0);
}
return $info;
}
This function runs three database queries to collect the name and blurb for a list from the lists table; the number of subscribers from the sub_lists table; and the number of newsletters sent from the mail table.
In addition to viewing the list blurb, users can look at all the mail that has been sent to a mailing list by clicking on the Show Archive button. This activates the show-archive action, which triggers the following code:
case 'show-archive':
{
display_items("Archive For ".get_list_name($id),
get_archive($id), 'view-html', 'view-text', '');
break;
}
Again, this function uses the display_items() function to list out the various items of mail that have been sent to the list. These items are retrieved using the get_archive() function from mlm_fns.php. This function is shown in Listing 28.10.
function get_archive($listid)
{
//returns an array of the archived mail for this list
//array has rows like (mailid, subject)
$list = array();
$listname = get_list_name($listid);
$query = "select mailid, subject, listid from mail
where listid = $listid and status = 'SENT'order by sent";
if(db_connect())
{
$result = mysql_query($query);
if(!$result)
{
echo "<p>Unable to get list from database - $query.";
return false;
}
$num = mysql_numrows($result);
for($i = 0; $i<$num; $i++)
{
$row = array(mysql_result($result, $i, 0),
mysql_result($result, $i, 1), $listname, $listid);
array_push($list, $row);
}
}
return $list;
}
Again, this function gets the required information—in this case, the details of mail that has been sent—from the database and builds an array suitable for passing to the display_items() function.
On the list of mailing lists shown in Figure 28.7, each list has a button that enables users to subscribe to it. Similarly, if users use the Show My Lists option to see the lists to which they are already subscribed, they will see an Unsubscribe button next to each list.
These buttons activate the subscribe and unsubscribe actions, which trigger the following two pieces of code, respectively:
case 'subscribe':
{
subscribe(get_email(), $id);
display_items("Subscribed Lists", get_subscribed_lists(get_email()),
'information', 'show-archive', 'unsubscribe');
break;
}
case 'unsubscribe' :
{
unsubscribe(get_email(), $id);
display_items("Subscribed Lists", get_subscribed_lists(get_email()),
'information', 'show-archive', 'unsubscribe');
break;
}
In each case, we call a function (subscribe() or unsubscribe()) and then redisplay a list of mailing lists the user is now subscribed to using the display_items() function again.
The subscribe() and unsubscribe() functions are shown in Listing 28.11.
function subscribe($email, $listid)
{
if(!$email||!$listid||!list_exists($listid)||!subscriber_exists($email))
return false;
//if already subscribed exit
if(subscribed($email, $listid))
return false;
if(!db_connect())
return false;
$query = "insert into sub_lists values ('$email', $listid)";
$result = mysql_query($query);
return $result;
}
function unsubscribe($email, $listid)
{
if(!$email||!$listid)
return false;
if(!db_connect())
return false;
$query = "delete from sub_lists where email = '$email'and listid = $listid";
$result = mysql_query($query);
return $result;
}
The subscribe() function adds a row to the sub_lists table corresponding to the subscription; the unsubscribe() function deletes this row.
The Account Settings button, when clicked, activates the account-settings action. The code for this action is as follows:
case 'account-settings':
{
display_account_form($normal_user, $admin_user, get_email(),
get_real_name(get_email()), get_mimetype(get_email()));
break;
}
As you can see, we are reusing the display_account_form() function that we used to create the account in the first place. However, this time we are passing in the user's current details, which will be displayed in the form for easy editing. When the user clicks on the submit button in this form, the store-account action is activated as discussed previously.
Clicking on the Change Password button activates the change-password action, which triggers the following code:
case 'change-password' :
{
display_password_form();
break;
}
The display_password_form() function (from the output_fns.php library) simply displays a form for the user to change his password. This form is shown in Figure 28.9.

When a user clicks on the Change Password button at the bottom of this form, the store-change-password action will be activated. The code for this is as follows:
case 'store-change-password' :
{
if(change_password(get_email(), $old_passwd,
$new_passwd, $new_passwd2))
{
echo "<p>OK: Password changed.<br><br><br><br><br><br>";
}
else
{
echo "<p>Sorry, your password could not be changed.";
display_password_form();
}
break;
}
As you can see, this code tries to change the password using the change_password() function and reports success or failure to the user. The change_password() function can be found in the user_auth_fns.php function library. The code for this function is shown in Listing 28.12.
function change_password($email, $old_password, $new_password,
$new_password_conf)
// change password for email/old_password to new_password
// return true or false
{
// if the old password is right
// change their password to new_password and return true
// else return false
if (login($email, $old_password))
{
if($new_password==$new_password_conf)
{
if (!($conn = db_connect()))
return false;
$query = "update subscribers
set password = password('$new_password')
where email = '$email'";
$result = mysql_query($query);
return $result;
}
else
echo "<p> Your passwords do not match.";
}
else
echo "<p> Your old password is incorrect.";
return false; // old password was wrong
}
This function is similar to other password setting and changing functions we have looked at. It compares the two new passwords entered by the user to make sure they are the same, and if they are, tries to update the user's password in the database.
When a user clicks on the Log Out button, it triggers the log-out action. The code executed by this action in the main script is actually in the preprocessing section of the script, as follows:
if($action == 'log-out')
{
session_destroy();
unset($action);
unset($normal_user);
unset($admin_user);
}
This snippet of code disposes of the session variables and destroys the session. Notice that it also unsets the $action variable—this means that we enter the main case statement without an action, triggering the following code:
case '':
{
if(!check_logged_in())
display_login_form($action);
break;
}
This will allow another user to log in, or allow the user to log in as someone else.
| only for RuBoard - do not distribute or recompile |