<<

. 92
( 132 .)



>>

Early on, the script calls the start_page() function, like this:

print start_page(˜Project Management Example™);

That function, defined in an imported file, does the work of generating opening
HTML. The argument is inserted as the HTML TITLE element.
With that done, the application proceeds to determine if the user accessing the
page is an administrator:

if (!session_user()->is_admin())

If so, then the status of all current projects is displayed; if the current user is not
an administrator, then only the projects to which that user is assigned are displayed.
To query the database, the application makes use of a function called dbh(),
which is contained in base.class.php (imported everywhere). The dbh() function
establishes the link to the database and enables queries to be run against it:

function dbh()
{
static $dbh = NULL;
if ($dbh === NULL)
{
Chapter 17: Project Management 549

$dbh = db_connect($this->appname);
if ($dbh === NULL)
{
user_error(˜Received NULL db connection™,
E_USER_ERROR);
return FALSE;
}
$dbh->setFetchMode(DB_FETCHMODE_ASSOC);
}
return $dbh;

With dbh() invoked, the index page can send a query to it:

$rows = session_user()->dbh()->getAll($query, $bind);

The index page gets a set of rows back. Those rows, looped through, form the
bulk of what™s on the index page. Here is the looping logic:

foreach ($rows as $row)
{
extract($row, EXTR_OVERWRITE|EXTR_PREFIX_ALL, ˜p™);
$tlinks = array();
$tlinks[] = anchor_tag(
˜tasks/cal.php?project_id=™.$p_project_id
, ˜Calendar™
);
$tlinks[] = anchor_tag(
˜tasks/list.php?project_id=™.$p_project_id
, ˜Task List™
);
$query = ˜select t.*, u.user as owner
from tasks t left join users u on t.owner_id = u.user_id
where t.project_id = ?
and t.status_id <> ?
and (t.due_dt >= curdate() - interval 3 day
and t.due_dt <= curdate() + interval 3 day)
˜;
$bind = array($p_project_id,$cancelled_id);
$events = session_user()->dbh()->getAll($query,$bind);
$elist = array();
if (count($events) > 0)
{
$elinks = array();
$today = strtotime(date(˜Y-m-d™,strtotime(˜today™)));
foreach ($events as $e)
550 Part IV: Not So Simple Applications

{
extract($e, EXTR_OVERWRITE|EXTR_PREFIX_ALL, ˜e™);
session_user()->format_dt($e_due_dt);
$e_task_tag = anchor_tag(
˜tasks/view_task.php?task_id=™.$e_task_id
, $e_task
);
$its_yours = FALSE;
if ($e_owner_id == session_user()->user_id)
{
$e_owner = ˜You™;
$its_yours = TRUE;
}
if ($e_status_id == $done_id)
{
$e_text = “$e_owner finished $e_task_tag on
$e_due_dt”;
}
elseif ($e_status_id == $slipped_id)
{
$e_text = “$e_owner slipped $e_task_tag to
$e_due_dt”;
}
else
{
$e_due_ts = strtotime($e_due_dt);
$on_time = ($today <= $e_due_ts);
if ($its_yours)
{
$due_word = $on_time ? ˜are™ : ˜were™;
}
else
{
$due_word = $on_time ? ˜is™ : ˜was™;
}
$e_text = “$e_owner $due_word supposed to finish
$e_task_tag on $e_due_dt”;
}
$elinks[] = $e_text;
}
$tlinks[] = ˜<b>Alerts:</b>™.ul_list($elinks);
}

$links[] = anchor_tag(
˜project.php?project_id=™.$p_project_id
Chapter 17: Project Management 551

, $p_project
)
. ul_list($tlinks)
;
}

Some of the most interesting calls there are the ones to cal.php and list.php. These
files contain functions that generate information about the due date and about the
task list associated with the project at hand, respectively. They handle some of the
bothersome aspects of PHP dates.
It™s worth noting, as well, how the project management application deals with
projects. Consider the following, for example:

$links[] = anchor_tag(
˜project.php?project_id=™.$p_project_id
, $p_project
)
. ul_list($tlinks)
;

The call to project.php guarantees that the call to the database is made ” the
details of the project the user is interested in are retrieved and populated into a
local object, which can then be manipulated. Here is that code:

$fetch_ok = TRUE;
if ($submit == ˜Save™)
{
if (empty($p->owner_id))
{
print paragraph(array(
˜style™ => ˜color:red™
, ˜values™ => ˜Error: No owner is associated with this
project™
));
$fetch_ok = FALSE;
}
else
{
$p->write_to_db();
}
}
if ($fetch_ok)
{
$p->fetch_from_db();
}
552 Part IV: Not So Simple Applications

else
{
$p->owner()->fetch_from_db();
$p->status();
}


Uploading a file
The project management application provides its users with the ability to upload
files to the files table of the database, which makes those files accessible to others
with the proper access. It™s interesting to see how the application goes about
uploading a file from the user™s local file system and encoding it into the database.
Upload duties are the domain of savefile.php, which capitalizes upon PHP™s abil-
ity to work with a traditional computer file system and also its ability to interact
with the contents of a relational database.
The code first sets out to determine whether the file already exists in the data-
base. If it does not, the application proceeds to create a File object, complete with
a file name, a MIME type, and the contents of the uploaded file itself:

$f = new File;
$f->build($_POST);
$uf = $_FILES[˜projectfile™];
$f->description = $uf[˜name™];
$f->mimetype = $uf[˜type™];

if (file_exists($uf[˜tmp_name™])) {
$f->file = gzdeflate(
file_get_contents($uf[˜tmp_name™]), 9
);
}
else
{
error_log(“could not find {$uf[˜tmp_name™]}”);
}

$f->write_to_db();

Where does the File object come from, anyway? It™s defined in projects/classes/
file.class.php and describes the mapping between its properties and the fields in the
files database. Early in the File class definition, the fields are established in an
array:

array(˜file_id™,™project_id™,™task_id™,™description™,™public™,™owner
_id™,™upload_dt™,™first_upload_dt™,™fullpath™,™mimetype™,™file™);
Chapter 17: Project Management 553


Displaying the contents of a file
Our project management application needs to be able to display the files it™s man-
aging, which it does with the contents of displayfile.php, in which a named file is
retrieved from the database:

$f = new File;
$f->build($_REQUEST);
$f->fetch_from_db();
if ($f->file)
{
$f->display();
}
elseif ($f->fullpath)
{
virtual($f->fullpath);
}
else
{
print “<li>Duh, like what do I do now?\n”;
}
unset($f);

That code segment, in turn, calls the display() function in the File class,
defined in file.class.php. This function is a simple one:

function display()
{
header(˜Content-type: ˜.$this->mimetype);
echo gzinflate($this->file);
}

display() simply undoes the gzdeflate() function invoked at storage time
and decompresses it after storage.



Summary
In this chapter we designed and built an application that manages projects, files,
users, deadlines, and notes by storing everything in a database and presenting a
coherent, useful user interface.
This exercise enabled you to explore the way PHP manages sessions persistently
and to see how it goes about stuffing files from a file system into a database. You also
got a further look at object orientation in PHP and ended up with both a library of
reusable functions and a simple project management application.
Part V
Appendixes
APPENDIX A
What™s on the CD-ROM
APPENDIX B
HTML Forms
APPENDIX C
Brief Guide to MySQL/PHP Installation
and Configuration
APPENDIX D
MySQL Utilities
APPENDIX E
MySQL User Administration
APPENDIX F

<<

. 92
( 132 .)



>>