Commits

JanKanis committed 3273d1c

add a lot of error checking for the spreadsheet data; v2.0.1

Comments (0)

Files changed (3)

 
 .. _Google spreadsheet: http://www.google.com/google-d-s/spreadsheets/
 
+
 Installatie
 -----------
 
 __ https://accounts.google.com/b/0/SmsAuthConfig
 __ https://accounts.google.com/b/0/IssuedAuthSubTokens
 
+
+Problemen
+---------
+
+Als er problemen zijn met het aanmeldscript, probeer dan eerst ``DEBUG`` op ``True`` te zetten in ``aanmeldscript-config.php``, dan worden gevonden fouten weergegeven. Als dat geen oplossing biedt, neem dan contact met mij op. 

aanmeldscript-functions.php

 openbaar te maken onder de GPL versie 3 of elke latere versie. 
 */
 
-define('SCRIPT_VERSION', '2.0; revision 7b83231a5e72');
+define('SCRIPT_VERSION', '2.0.1');
 
 require_once 'aanmeldscript-config.php';
 
 
 //checkpoint('prestartup');
 
-if(!isset($ERROR_LOG_EMAIL)) {
-	die('Error: $ERROR_LOG_EMAIL is not defined. Define $ERROR_LOG_EMAIL in aanmeldscript-config.php to the email addresses to send error messages to');
+if(!isset($ERROR_LOG_EMAIL) or count($ERROR_LOG_EMAIL)<1) {
+	die('Error: $ERROR_LOG_EMAIL is not set. Set $ERROR_LOG_EMAIL in aanmeldscript-config.php to the email addresses to send error messages to');
 }
 
 require_once 'Zend/Gdata/Spreadsheets.php';
 //checkpoint('loaded Zend');
 
 
+///////////////////////////////
+// Policy and Driver section //
+///////////////////////////////
+
 class AanmeldScript {
 
 	private $spreadsheetService, $spreadsheetFeed;
 		//checkpoint('connected');
 		$this->spreadsheetFeed = do_request(array($this->spreadsheetService, 'getSpreadsheetFeed'), array());
 		//checkpoint('got sheets feed');
-		$this->aanmeldingen = new Sheet($this->spreadsheetService, $this->spreadsheetFeed, trim($aanmeldingen));
-		$this->projecten = new Sheet($this->spreadsheetService, $this->spreadsheetFeed, trim($projecten));
+		$this->aanmeldingen = new Sheet($this->spreadsheetService, $this->findsheet($this->spreadsheetFeed, trim($aanmeldingen)));
+		$this->projecten = new Sheet($this->spreadsheetService, $this->findsheet($this->spreadsheetFeed, trim($projecten)));
 		//checkpoint('got sheets');
-		$this->aanmeldingendata = $this->aanmeldingen->getData();
-		$this->projectendata = plekvrij(
-				index(filterfield($this->projecten->getData(), 'code'), 'code'), 
-				$this->aanmeldingendata
-			);
+		
+		$this->errors = array();
+			$projectencsv = $this->projecten->getData();
+			$this->checkprojecten($projectencsv);
+			$projectendata = index(filterfield(filterfield($projectencsv, 'naam'), 'code'), 'code');
+	
+			$this->aanmeldingendata = $this->aanmeldingen->getData();
+			$this->checkaanmeldingen($projectendata);
+	
+			$this->projectendata = plekvrij($projectendata, $this->aanmeldingendata);
+
+		if(count($this->errors) > 0) {
+			warn_sheetbeheerder("Fouten gevonden in spreadsheets:\n".implode("\n", $this->errors)); }
 	}
 
 	function plekvrij($project) {
 	function insertAanmelding($row) {
 		return $this->aanmeldingen->insertrow($row);
 	}
+
+
+	private function findsheet($spreadsheetFeed, $name) {
+		$name = trim($name);
+		$found = 0;
+		foreach($spreadsheetFeed as $sheet) {
+			if(trim($sheet->getTitle()) == $name) {
+				$found++;
+				break;
+			}
+		}
+		if($found < 1) {
+			throw new Exception("Spreadsheet met titel '$name' niet gevonden in Google Docs"); }
+		elseif($found > 1) {
+			throw new Exception("Meerdere spreadsheets met titel '$name' gevonden in Google Docs, zorg dat er maar één spreadsheet met die naam is"); }
+		return $sheet;
+	}
+
+	private function checkprojecten($projectencsv) {
+		foreach(array_count_values(array_map(fn('$x["code"]'), $projectencsv)) as $code => $count) {
+			if($count > 1) {
+				$this->errors[] = "Projectcode ".var_export_str($code)." wordt voor meerdere projecten gebruikt"; }
+		}
+
+		foreach($projectencsv as $project) {
+			$code = $project['code'];
+			$maxdeelnemers = $project['max deelnemers'];
+			if(!($code === htmlspecialchars($code) && ($maxdeelnemers === '' || $maxdeelnemers === (string) (int) $maxdeelnemers))) {
+				throw new Exception("niet toegestane tekens in Projecten configuratie: ".var_export_str($arr));
+			}
+		}
+		return True;
+	}
+
+	private function checkaanmeldingen($projecten) {
+		foreach($this->aanmeldingendata as $aanmelding) {
+			if($aanmelding['ingedeeld'] && !isset($projecten[$aanmelding['ingedeeld']])) {
+				$this->errors[] = "Er is iemand aangemeld voor een onbekend project ".var_export_str($aanmelding['ingedeeld']); }
+		}
+		return True;
+	}
+
 }
 
+//
+// End of Policy and Driver section //
+//
+
+
 /* Note: It is not the responsibility of Sheet to maintain a local cache of the sheet data. Sheet only contains the keys necessary to get at the remote spreadsheet representation. 
 */
 class Sheet {
 
-	private $spreadsheetService, $spreadsheetFeed, $sheetname;
+	private $spreadsheetService, $sheet, $sheetname;
 	private $key;
 	// not used: private $sheet; 
 	
-	function __construct($spreadsheetService, $spreadsheetFeed, $sheetname) {
+	function __construct($spreadsheetService, $sheet) {
 
 		$this->spreadsheetService = $spreadsheetService;
-		$this->spreadsheetFeed = $spreadsheetFeed;
-		$this->sheetname = $sheetname;
-
-		foreach($this->spreadsheetFeed as $sheet) {
-			if(trim($sheet->getTitle()) == $sheetname) {
-				$found = True;
-				break;
-			}
-		}
-		if(!$found) {
-			throw new Exception("Spreadsheet met titel '$name' niet gevonden in Google Docs"); }
 		$this->sheet = $sheet;
-
+		$this->sheetname = trim($sheet->getTitle());
 		//The @ to suppress an E_STRICT warning of "Only variables should be passed by reference"
 		$this->key = end(@explode('/', $sheet->getId()));
 	}
 		}
 	}
 	if($tries > 1) {
-		log_error("Web request $name had to be retried:\n".requestLogStrval($rqdata)); }
+		log_error("Web request '$name' had to be retried:\n".requestLogStrval($rqdata)); }
 	//checkpoint("do_request '$name'");
 	//debugprint(sprintf("request '$name' took $tries trie(s) in %.3F seconds", $time));
 	return $res;
 }
 
 
+// Aan te roepen als er een fout in de spreadsheets wordt gevonden (en er dus 
+// 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(DEBUG) debugprint($msg);
+}
+
+// Aan te roepen bij een fout in de PHP code
 function log_error($e, $servervars=True) {
 	global $ERROR_LOG_EMAIL;
 	$mail = "Foutmelding!\n\n".

aanmeldscript.php

 set_error_handler('error_handler');
 
 
+date_default_timezone_set($timezone);
 $velden = index(parsecsv($csvvelden), 'code');
 $janee = index(parsecsv($janeevragen), 'code');
 $fields = array_merge(array_keys($velden), array_keys($janee), array('opmerkingen'));
 $aanmelding = Null;
 $displayform = True;
 
+// Returns True or throws an exception
+function checkconfig() {
+	global $velden, $janee;
+	foreach(array($velden, $janee) as $arr) {
+		foreach($arr as $elem) {
+			if($elem['code'] !== htmlspecialchars($elem['code'])) {
+				log_error("niet toegestane tekens in een configuratie item: ".var_export_sr($arr));
+				throw new Exception("Er staan niet toegestane tekens in de configuratie: ".var_export_str($elem).
+					"\nDe websitebeheerder is op de hoogte gesteld.\n");
+			}
+		}
+	}
+	return True;
+}
+
 // return array('displayform'=>bool, 'fout'=>string?)
 function init() {
 	global $username, $password, $velden, $janee, $displayform, $min_aantal_projecten, $app, $aanmeldingensheet, $projectensheet;
+
 	try {
+		checkconfig($velden, $janee);
 		$app = new AanmeldScript($username, $password, array(
 					'aanmeldingen' => $aanmeldingensheet, 'projecten' => $projectensheet));
 	} catch(Exception $e) {
 		return array('fout'=>$e->getMessage(), 'displayform'=>False);
 	}
 
-	$checkcode = '$x["code"] == htmlspecialchars($x["code"])';
-	$check = array(
-			fn($checkcode.' && ($x["max deelnemers"] === "" || $x["max deelnemers"] == (string) (int) $x["max deelnemers"])') => $app->projectendata,
-			fn($checkcode) => $velden,
-			fn($checkcode) => $janee) ;
-	foreach($check as $func => $arr) {
-		foreach($arr as $elem) {
-			if(!$func($elem)) {
-				log_error("niet toegestane tekens in een configuratie item: ".var_export_sr($arr));
-				$fout = "Er staan niet toegestane tekens in de configuratie: ".var_export_str($elem).
-					"<br><br>De websitebeheerder is op de hoogte gesteld.\n";
-				return array('fout'=>$fout, 'displayform'=>False);
-			}
-		}
-	}
 	return array('fout'=>Null, 'displayform'=>True);
 }
 
 flush();
 
 extract(init()); // extracts $fout, $displayform
+if(!is_null($fout)): ?>
+<div class="fout"><p>
+	Aanmelding MISLUKT!<br>
+	Foutmelding:
+	</p>
+	<pre><?php echo $fout; ?></pre>
+	<p>De websitebeheerder is op de hoogte gesteld</p>
+</div>
+<?php else:
+
 
 $succes = False;
 if(isset($_POST['aanmelden'])) {
 		generate_opmerkingen($aanmelding); ?>
 	<p><input type=submit name=aanmelden value=Aanmelden onclick="scrollToTop()"></p>
 </form>
-<?php endif; ?>
+<?php endif; 
+
+endif; /*end init() error check*/
+?>
 
 </div>
 <!-- hide the 'loading' message -->