The Full Monty!


16/10/04
 

The Full Monty!

Putting it all together - with a few minor tweaks here and there - gives this...
 
<?php

//----------------------------------------------------------------

function CreateExpiryDataFile($ExpiryDataFile) {

  // open ExpiryData file ("r+" for read/write)
  $ExpiryData_fp = fopen($ExpiryDataFile, "r+");

  // lock ExpiryData file ("2" for exclusive writing lock)
  $lock = flock($ExpiryData_fp, 2);

  // continue when lock is obtained
  if ( $lock) {

    // truncate to empty the file
    ftruncate($ExpiryData_fp, 0);

    // write contents to create a properly formatted file
    fwrite($ExpiryData_fp, "<?xml version=\"1.0\"?>");
    fwrite($ExpiryData_fp, "\n");
    fwrite($ExpiryData_fp, "<?xml-stylesheet");
    fwrite($ExpiryData_fp, " href=\"ExpiryData.css\"");
    fwrite($ExpiryData_fp, " type=\"text/css\"?>");
    fwrite($ExpiryData_fp, "\n");
    fwrite($ExpiryData_fp, "<expiredpages>");
    fwrite($ExpiryData_fp, "\n\n");
    fwrite($ExpiryData_fp, "<date>");
    fwrite($ExpiryData_fp, date("Y-m-d"));
    fwrite($ExpiryData_fp, "</date>");
    fwrite($ExpiryData_fp, "\n\n");
    fwrite($ExpiryData_fp, "</expiredpages>");

  }

  // unlock and close reminders file ("3" is for unlock)
  $lock = flock($ExpiryData_fp, 3);
  fclose($ExpiryData_fp);

}

//----------------------------------------------------------------

function GetTodayYYMMDD() {

// Get today's date in dd/mm/yy format
$today = date("d/m/y");
// Convert to yymmdd format - e.g. 24/08/02 becomes 020824
// *** End-of-century bug - will fail in the year 2100! ***
$today_day = substr($today,-8,2);
$today_month = substr($today,-5,2);
$today_year = substr($today,-2,2);
$today_yymmdd = $today_year.$today_month.$today_day;

return($today_yymmdd);

}

//----------------------------------------------------------------

function ConvertExpiryDateToYYMMDD($theDate) {

  // prepare to convert expiry date to yymmdd format
  // handle dd/mm/yy dates including single digits for dd, mm, yy
  // - e.g. 06/06/03, 6/6/03, 06/6/03, 6/06/03, 06/06/3 etc.
  $position_of_first_slash = strpos($theDate, "/");
  $expiry_day = substr($theDate, 0, $position_of_first_slash);
  $expiry_mm_yy = substr($theDate, $position_of_first_slash + 1, 
                                                strlen($theDate));
  $position_of_second_slash = strpos($expiry_mm_yy, "/");
  $expiry_month = substr($expiry_mm_yy, 0, $position_of_second_slash);
  $expiry_year = substr($expiry_mm_yy, $position_of_second_slash + 1, 
                                                strlen($theDate));
  // if any of dd, mm or yy are single digits then add a leading zero
  if ( strlen($expiry_day) == 1 ) { 
    $expiry_day = "0".$expiry_day; 
  }
  if ( strlen($expiry_month) == 1 ) {
    $expiry_month = "0".$expiry_month; 
  }
  if ( strlen($expiry_year) == 1 ) {
    $expiry_year = "0".$expiry_year; 
  }
  // now able to convert expiry date to yymmdd format
  $expiry_yymmdd = $expiry_year.$expiry_month.$expiry_day;

  return($expiry_yymmdd);

}

//----------------------------------------------------------------

function AppendExpiryDataToFile($theURL, $theOwner, $theExpiryDate, 
$theMessage, $theFile) {

  // if (theURL is a valid LSBU www address) then
  if ((substr($theURL, 0, 23) == "http://myweb.lsbu.ac.uk")) {
  
    // open and lock the expiry data file
    $theFile_fp = fopen($theFile, "r+");
    $lock = flock($theFile_fp, 2);

    // continue when lock is obtained
    if ($lock) {

      // read expired page data file
      $db = readDatabase($theFile);

      // rewind and read date on the 5th line of the file
      fseek($theFile_fp, 0);
      $i = 1;
      while ($i < 6):
        $line = fgets($theFile_fp);
        $i = $i + 1;
      endwhile;
      $theDate = substr($line, 6, 10);

    } 

    // unlock and close reminders file
    $lock = flock($theFile_fp, 3);
    fclose($theFile_fp);

    $found = FALSE;
    // Pop each ExpiredPage object and see if the URL matches
    while (($poppedExpiredPage = (array_pop($db))) && (!$found)):
      if ($poppedExpiredPage->url == $theURL) {
        $found = TRUE;
      }
    endwhile;
    
    // if there's no entry for the web page then append to file
    if ($found == FALSE) {

      // go to end of file, back two lines (i.e. 15 places)
      fseek($theFile_fp, -15, SEEK_END);

      // now append...
      fwrite($theFile_fp, "<expiredPage>\n");
      fwrite($theFile_fp, "  <url>");
      fwrite($theFile_fp, $theURL);
      fwrite($theFile_fp, "</url>\n");
      fwrite($theFile_fp, "  <owner>");
      fwrite($theFile_fp, $theOwner);
      fwrite($theFile_fp, "</owner>\n");
      fwrite($theFile_fp, "  <expired>");
      fwrite($theFile_fp, $theExpiryDate);
      fwrite($theFile_fp, "</expired>\n");
      fwrite($theFile_fp, "  <message>");
      fwrite($theFile_fp, $theMessage);
      fwrite($theFile_fp, "</message>\n");
      fwrite($theFile_fp, "</expiredPage>\n\n");
      fwrite($theFile_fp, "</expiredPages>");
    }
  }

  return $theDate;

}

//----------------------------------------------------------------

function EmailExpiryMessages($FileName) {

  // open and lock the expiry data file
  $theFile_fp = fopen($FileName, "r+");
  $lock = flock($theFile_fp, 2);

  // continue when lock is obtained
  if ($lock) {

    $db = readDatabase($FileName);

    // Pop each ExpiredPage object and send the email
    while ($poppedExpiredPage = (array_pop($db))):

      $pageURL = $poppedExpiredPage->url;
      $pageOwner = $poppedExpiredPage->owner;
      $pageExpiryDate = $poppedExpiredPage->expired;
      $pageMessage = $poppedExpiredPage->message;

// Prepare the email
$mail_message = "This is to remind you that this web page...
\n  $pageURL
\n...expired on $pageExpiryDate. Here is the reminder message (if any):
\n*** $pageMessage ***
\nYou will receive a reminder each day that this page is hit. 
Please update the page as necessary, and remember to specify a new 
expiry date."; 

    // Now [send the email] echo the email contents

echo "<html><head><title></title></head><body><pre>";
echo "\n\n  pageOwner = ";
echo $pageOwner;
echo "\n  pageURL = ";
echo $pageURL;
echo "\n  mail_message = ";
echo $mail_message;
echo "</pre></body></html>";

    endwhile;

  }  // unlock and close reminders file
  $lock = flock($theFile_fp, 3);
  fclose($theFile_fp);

}

//================================================================
// This section based on: http://jp2.php.net/xml_parse_into_struct
//----------------------------------------------------------------
class ExpiredPage {
  var $url;
  var $owner;
  var $expired;
  var $message;
  function ExpiredPage ($aa) {
    foreach ($aa as $k=>$v)
      $this->$k = $aa[$k];
  }
}
//----------------------------------------------------------------
function readDatabase($file) {
  // read the xml database of ExpiredPages
  $data = implode("",file($file));
  $parser = xml_parser_create();
  xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
  xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);
  xml_parse_into_struct($parser,$data,$values,$tags);
  xml_parser_free($parser);
  // loop through the structures
  foreach ($tags as $key=>$val) {
    if ($key == "expiredpage") {
      $molranges = $val;
      // each contiguous pair of array entries are the 
      // lower and upper range for each expiredpage definition
      for ($i=0; $i < count($molranges); $i+=2) {
        $offset = $molranges[$i] + 1;
        $len = $molranges[$i + 1] - $offset;
        $tdb[] = parseMol(array_slice($values, $offset, $len));
      }
    } else {
      continue;
    }
  }
  return $tdb;
}
//----------------------------------------------------------------
function parseMol($mvalues) {
  for ($i=0; $i < count($mvalues); $i++)
    $mol[$mvalues[$i]["tag"]] = $mvalues[$i]["value"];
  return new ExpiredPage($mol);
}
//================================================================


/*
// MAIN PROGRAM
*/

$file = "ExpiryData.xml";

// Parse query_string to get $owner, $expirydate and $message
parse_str($QUERY_STRING);

// Discover url of referring web page
$url = $GLOBALS["HTTP_REFERER"];

// Use ConvertExpiryDateToYYMMDD to re-format $expirydate
$expirydateYYMMDD = ConvertExpiryDateToYYMMDD($expirydate);

// Get today's date in dd/mm/yy format
$todayYYMMDD = GetTodayYYMMDD();

// If the referring page has expired then
if ($expirydateYYMMDD <= $todayYYMMDD) {

  // If the referring page is a valid LSBU myweb page then
  if ((substr($url, 0, 23) == "http://myweb.lsbu.ac.uk")) {

    // Append Expiry Data to ExpiryData.xml
    $filedate = AppendExpiryDataToFile($url, $owner, $expirydate,
                                                  $message, $file);

    // Re-format $filedate
    $filedateYYMMDD = ConvertExpiryDateToYYMMDD($expirydate);

    // If ((today is a Monday) but (ExpiryData file is pre-today)) then
    if ((date("D") == "Mon") && ($filedateYYMMDD <= $todayYYMMDD)) {

      // Email the expiry messages
      EmailExpiryMessages($file);

      // Copy ExpiryData.xml to ExpiryDataLastWeek.xml
      copy($file, "ExpiryDataLastWeek.xml");

      // Create a fresh (empty, formatted) ExpiryData.xml file
      CreateFreshExpiryDataFile($file);

    }
  }
}

?>

 
Notes:

  • I realise now that the <date> stored within the ExpiryData.xml file should be in the form "dd/mm/yy", rather than "yyyy-mm-dd", so that I can re-use the ConvertExpiryDateToYYMMDD function. In fact, I really ought to rename it to ConvertDateToYYMMDD.
     
 
 
 

<<contents ^top^