Commits

JanKanis committed a8c6779

check if all form fields exist in the spreadsheet

Comments (0)

Files changed (1)

aanmeldscript-functions.php

 <http://bitbucket.org/JanKanis>, (C) 2010-2011. Beschikbaar gesteld zonder 
 beperkingen voor elk gebruik aan de Outreach Utrecht en Youth for Christ, of 
 openbaar te maken onder de GPL versie 3 of elke latere versie. 
+
+
+code layout: 
+Class AanmeldScript contains all data specific to the form. Everything is set up in its constructor. It has two instances of Sheet, one for the aanmeldingen sheet and one for the projecten sheet. The sheet data is available in AanmeldScript attributes aanmeldingendata and projectendata. The other public methods are 'plekvrij' which returns if there's space left in the specified project, and 'insertAanmelding', which inserts (after some checks) a new registration into the aanmeldingen spreadsheet. The other (private) methods deal with consistency and error checking. 
+Class Sheet represents a reference to a google spreadsheet. It does not itself store the spreadsheet data, but that is available through the 'getData' method. 'insertRow' inserts a row into the sheet. 
+
+Below that are a bunch of functions. Some important ones:
+'do_request' wraps a remote call and retries it a few times if it fails. RequestMultiException is the associated exception if the request keeps failing. 
+'filterfields', 'index', and 'plekvrij' are basic functions that are used to munge arrays with spreadsheet or configuration data into the right form. 
+'parsecsv' parses a string with csv data into an array. 
+I use 'parseparams' to simulate optional and named arguments to functions. 
+'checkpoint' can be used to profile the script's time and memory usage. 
+'log_error' logs an error to the error mail address, and optionally displays it in the page output. 
+'warn_sheetbeheerder' sends an error message to the mail addres of the registration manager, and optionally displays it.
+'debugprint' formats and prints an error message to the outputstream. 
+
 */
 
 define('SCRIPT_VERSION', '2.0.2');
 	public $projecten, $aanmeldingen;
 	public $projectendata, $aanmeldingendata;
 
-	function __construct($account, $password, $sheetnames=array()) {
-		extract(parseparams($sheetnames, array(), array('aanmeldingen', 'projecten')));
+	private $errors;
+	private $aanmeldingcolumns;
+
+	function __construct($account, $password, $extra=array()) {
+		extract(parseparams($extra, array(), array('aanmeldingen', 'projecten')));
 
 		//checkpoint('preconnect');
 		$service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
 			$this->checkprojecten($projectencsv);
 			$projectendata = index(filterfield(filterfield($projectencsv, 'naam'), 'code'), 'code');
 	
-			$this->aanmeldingendata = $this->aanmeldingen->getData();
+			$this->aanmeldingendata = $this->aanmeldingen->getData(array('headerref'=>&$this->aanmeldingcolumns));
 			$this->checkaanmeldingen($projectendata);
 	
 			$this->projectendata = plekvrij($projectendata, $this->aanmeldingendata);
 	}
 
 	function insertAanmelding($row) {
+		$missing = array_values(array_diff(array_keys($row), $this->aanmeldingcolumns));
+		if(count($missing) > 0) {
+			$warnmsg = "De volgende kolom(men) missen in het aanmeldingen spreadsheet in Google Docs:\n";
+			foreach($missing as $col) {
+				$warnmsg .= " - '$col'\n"; }
+			$warnmsg .= "\nDeze aanmelding is mogelijk niet volledig opgeslagen:\n";
+			foreach($row as $key => $val) {
+				$warnmsg .= "  $key: $val\n"; }
+			warn_sheetbeheerder($warnmsg);
+		}
 		return $this->aanmeldingen->insertrow($row);
 	}
 
 		$this->key = end(@explode('/', $sheet->getId()));
 	}
 
-	function getData() {
+	function getData($extra=array()) {
+		$pp = parseparams($extra, array('headerref'=>Null));
+
 		// Reading spreadsheet data using ListQuery only reads until it 
 		// encounters a blank row. The Google list API doesn't provide any way
 		// around this apparently. Using CellQuery is a possibility, but uses 
 		//$response = $this->spreadsheetService->performHttpRequest('GET', $url);
 		$response = do_request(array($this->spreadsheetService, 'performHttpRequest'), array('GET', $url), "export {$this->sheetname} as csv");
 		//checkpoint('got content');
-		return parsecsv($response->getBody());
+		return parsecsv($response->getBody(), array('headerref'=>&$pp['headerref']));
 	}
 
 	function insertrow($row) {
-		// The third parameter (worksheet ID) is optional
+		// The third parameter to insertRow (the worksheet ID) is optional
 		return do_request(array($this->spreadsheetService, 'insertRow'), array($row, $this->key), "insert row into {$this->sheetname}");
 	} 
 
 // the same as that. We also skip empty lines, use a header row, and hack 
 // around crappy php escape character behaviour. 
 function parsecsv($input, $extra=array()) {
-	extract(parseparams($extra, array('haveheader'=>True)));
+	$pp = parseparams($extra, array('haveheader'=>True, 'headerref'=>Null));
+	extract($pp);
+	$header = &$pp['headerref'];
 
 	// WTF
 	// php fgetcsv recognizes \-escapes, while google doesn't use them. This 
 $required is a list of keyword arguments that are required, so they don't need to be present in $defaults. 
 */
 function parseparams($params, $defaults, $required=array()) {
-	$knownparams = array_keys($defaults) + $required;
+	$knownparams = array_merge(array_keys($defaults), $required); 
 	foreach(array_keys($params) as $p) {
 		if(!in_array($p, $knownparams)) {
 			throw new Exception("Undefined extra argument '$p' in ".var_export_str($params)."!"); }
 // niet een fout in de php code zit). 
 function warn_sheetbeheerder($msg) {
 	global $aanmeldemail;
-	mail($aanmeldemail, "Foutmelding van het outreach aanmeldscript op {$_SERVER['SERVER_NAME']}", $msg);
+	if(!mail($aanmeldemail, "Waarschuwing van het outreach aanmeldsysteem op {$_SERVER['SERVER_NAME']}", 
+			$msg, "From: website@{$_SERVER['SERVER_NAME']}\r\n")) {
+		log_error("Mail naar \$aanmeldemail ($aanmeldemail) versturen mislukt:\n\n".$msg); }
 	if(DEBUG) debugprint($msg);
 }