respondWithAccessDenied(); } $dbFileName = preg_replace("/[^A-Za-z0-9]/", '', $_SERVER['PHP_AUTH_USER']) . '.db'; if(!file_exists($dbFileName)) { $this->respondWithAccessDenied(); } $this->db = new DB($dbFileName); if($this->db == null) { $this->respondWithAccessDenied(); } $pass = $this->db->getConfigValueByKey('PASSWORD'); if($_SERVER['PHP_AUTH_PW'] !== $pass) { $this->respondWithAccessDenied(); } } public function getDBHandle() { return $this->db; } private function respondWithAccessDenied() { header('HTTP/1.0 401 Unauthorized'); header('WWW-Authenticate: Basic realm="Flashy"'); echo 'You are not authorized to access this site. Please log in.'; exit; } } class Card { public $id, $boxID, $classID, $front, $back; public function __construct($id, $boxID, $classID, $front, $back) { $this->id=$id; $this->boxID=$boxID; $this->classID=$classID; $this->front=$front; $this->back=$back; } public static function createFromDBRow($row) { return new Card($row['id'], $row['box_id'], $row['class_id'], $row['front'], $row['back']); } } class DB { private $db; public function __construct($dbFileName) { try { $this->db = new PDO('sqlite:' . $dbFileName); $this->db->query("PRAGMA foreign_keys = ON"); } catch(PDOException $e) { $this->db = null; } } public function __destruct() { $db = null; } public function databaseIsOpen() { if($this->db != null) return true; else return false; } public function getClasses() { return $this->db->query("SELECT * FROM classes"); } public function getBoxes() { return $this->db->query("SELECT * FROM boxes"); } public function getConfigValueByKey($key) { $query = $this->db->prepare("SELECT value FROM config where key=?"); $query->execute([$key]); return $query->fetchColumn(); } public function getBoxNameByBoxID($boxID) { $query = $this->db->prepare("SELECT name FROM boxes WHERE id=? LIMIT 1"); $query->execute([$boxID]); return $query->fetchColumn(); } public function getNewBoxIDOnCorrectByBoxID($boxID) { $query = $this->db->prepare("SELECT class_id_on_correct FROM boxes WHERE id=? LIMIT 1"); $query->execute([$boxID]); return $query->fetchColumn(); } public function getNewBoxIDOnIncorrectByBoxID($boxID) { $query = $this->db->prepare("SELECT class_id_on_incorrect FROM boxes WHERE id=? LIMIT 1"); $query->execute([$boxID]); return $query->fetchColumn(); } public function getClassNameByClassID($classID) { $query = $this->db->prepare("SELECT name FROM classes WHERE id=? LIMIT 1"); $query->execute([$classID]); return $query->fetchColumn(); } public function getNumBoxes() { return $this->db->query("SELECT COUNT(*) FROM boxes")->fetchColumn(); } public function getFirstCardByBoxID($boxID) { $query = $this->db->prepare("SELECT * FROM cards WHERE box_id=? LIMIT 1"); $query->execute([$boxID]); $res = $query->fetchAll(); if (count($res) > 0) { $row = $res[0]; return Card::createFromDBRow($row); } else { return null; } } public function getCardByCardID($card_id) { $res = $this->db->query("SELECT * FROM cards WHERE id = '" . $card_id . "' LIMIT 1")->fetchAll(); if (count($res) > 0) { $row = $res[0]; return Card::createFromDBRow($row); } else { return null; } } public function getNumCardsByBoxID($boxID) { return $this->db->query("SELECT COUNT(*) FROM cards where box_id='" . $boxID . "'")->fetchColumn(); } public function getNumCards() { return $this->db->query("SELECT COUNT(*) FROM cards")->fetchColumn(); } public function updateCard($card) { $origCard = $this->getCardByCardID($card->id); if($origCard->boxID != $card->boxID) { $this->db->prepare("UPDATE cards SET box_id=? WHERE id=?")->execute([$card->boxID, $card->id]); } if($origCard->classID != $card->classID) { $this->db->prepare("UPDATE cards SET class_id=? WHERE id=?")->execute([$card->classID, $card->id]); } if($origCard->front != $card->front) { $this->db->prepare("UPDATE cards SET front=? WHERE id=?")->execute([$card->id]); } if($origCard->back != $card->back) { $this->db->prepare("UPDATE cards SET back=? WHERE id=?")->execute([$card->back, $card->id]); } } public function createCard($card) { if($card->classID != null && $card->front != null && $card->back != null) { $this->db->prepare("INSERT INTO cards (box_id,class_id,front,back) VALUES(?,?,?,?)") ->execute([$card->boxID, $card->classID, $card->front, $card->back]); } } public function deleteCard($cardID) { if($cardID != null) { $this->db->prepare("DELETE FROM cards WHERE id=?")->execute([$cardID]); } } public function getRandomCardByBoxID($boxID) {} public function getAllCardsByBoxID($boxID) {} } class App { private $db, $selectedCard, $selectedBoxID, $testInput, $message, $checkCase = true; public function __construct($db) { if($db == null) { echo 'App cannot start without an active database. Good bye!'; exit; } $this->db = $db; $this->handleAllInput(); $this->selectCardIfBoxSelected(); $this->runTestIfUserInput(); $this->renderTest(); $this->renderBoxes(); $this->renderEditor(); } private function renderTest() { echo '
' . "\n"; echo '
' . $this->message . "
\n"; echo '
'.($this->selectedCard == null ? '' : $this->selectedCard->front.' | '.$this->db->getClassNameByClassID($this->selectedCard->classID))."
\n"; echo '
' . "\n"; echo 'testInput == null ? '' : ' value="' . $this->testInput . '"') .($this->selectedCard == null ? '' : ' autofocus') .'>'."\n"; echo '' . "\n"; echo ''."\n"; echo '
' . "\n"; echo 'Case sensitive' . "\n"; echo "
\n"; } private function selectCardIfBoxSelected() { // Select random card from selected box since none is selected yet: if($this->selectedBoxID != null && $this->selectedCard == null) { $this->selectNewCard(); /* if($this->selectedCard != null) { // Give the user some info... $this->message = $this->selectedCard->front.' | '.$this->db->getClassNameByClassID($this->selectedCard->classID); } */ } } private function runTestIfUserInput() { // Do some evaluation... if(isset($this->selectedCard) && $this->testInput != null) { // Copy values to be mangled :) $a = $this->selectedCard->back; $b = $this->testInput; // Normalize Umlauts $umlauts = array( "ä"=>"ae", "Ä"=>"Ae", "ö"=>"oe", "Ö"=>"Oe", "ü"=>"ue", "Ü"=>"Ue", "ß"=>"ss", "ẞ"=>"Ss" ); $a = str_replace(array_keys($umlauts), array_values($umlauts), $a); $b = str_replace(array_keys($umlauts), array_values($umlauts), $b); // Case insensitive... if(!$this->checkCase) { $a = strtolower($a); $b = strtolower($b); } //Answer correct: if($a == $b) { if($this->selectedCard->back == $this->testInput) { $this->message = 'Correct'; } else { $this->message = 'Correct spelling but wrong upper/lower case'; } /* if($this->selectedCard->boxID >= 0 && $this->selectedCard->boxID < 3) { $this->selectedCard->boxID = 4; } else if($this->selectedCard->boxID >= 3 && $this->selectedCard->boxID < $this->db->getNumBoxes()-1) { $this->selectedCard->boxID += 1; } */ $this->selectedCard->boxID = $this->db->getNewBoxIDOnCorrectByBoxID($this->selectedCard->boxID); } //Answer wrong: else { $this->message = 'Wrong - Correct answer:
'.$this->selectedCard->back; /* if($this->selectedCard->boxID > 0 && $this->selectedCard->boxID <= 3) { $this->selectedCard->boxID -= 1; } else if($this->selectedCard->boxID > 3 && $this->selectedCard->boxID < $this->db->getNumBoxes()) { $this->selectedCard->boxID = 2; } */ $this->selectedCard->boxID = $this->db->getNewBoxIDOnIncorrectByBoxID($this->selectedCard->boxID); } // Flush box_id update to database $this->db->updateCard($this->selectedCard); // Clear the input field $this->testInput = ''; // select the next card for the new round $this->selectNewCard(); } } private function renderBoxes() { echo '
'."\n"; echo "\n"; echo "
\n"; } private function renderEditor() { echo '
' . "\n"; echo '
' . "\n"; echo '
' . "\n"; echo '
' . "\n"; echo '\n"; echo '
' . "\n"; echo '
' . "\n"; echo '
' . "\n"; echo ''."\n"; echo '
' . "\n"; echo "
\n"; } private function handleAllInput() { if (isset($_REQUEST['box_id']) && $_REQUEST['box_id'] >= 0 && $_REQUEST['box_id'] < $this->db->getNumBoxes()) { $this->selectedBoxID = $_REQUEST['box_id']; } if (isset($_REQUEST['card_id']) && $_REQUEST['card_id'] >= 0) { $this->selectedCard = $this->db->getCardByCardID($_REQUEST['card_id']); } if (isset($_REQUEST['check_case']) && $_REQUEST['check_case'] == 1) { $this->checkCase = true; } else $this->checkCase = false; if (isset($_REQUEST['test_input']) && $_REQUEST['test_input'] != '') { $this->testInput = trim($_REQUEST['test_input']); } // Create a new Card in the database if (isset($_REQUEST['action_create']) && isset($_REQUEST['class_id']) && $_REQUEST['class_id'] != null && isset($_REQUEST['card_front']) && $_REQUEST['card_front'] != null && isset($_REQUEST['card_back']) && $_REQUEST['card_back'] != null) { $card = new Card(null, (int)$this->db->getConfigValueByKey('NEW_CARD_BOX_ID'), $_REQUEST['class_id'], trim($_REQUEST['card_front']), trim($_REQUEST['card_back'])); $this->db->createCard($card); } // Modify an existing card in the database else if (isset($_REQUEST['action_replace']) && isset($_REQUEST['class_id']) && $_REQUEST['class_id'] != null && isset($_REQUEST['card_front']) && $_REQUEST['card_front'] != null && isset($_REQUEST['card_back']) && $_REQUEST['card_back'] != null && $this->selectedCard != null) { $card = new Card($this->selectedCard->id, $this->selectedCard->boxID, $_REQUEST['class_id'], trim($_REQUEST['card_front']), trim($_REQUEST['card_back'])); $this->db->updateCard($card); // Reload the updated card $this->selectedCard = $this->db->getCardByCardID($card->id); } // Delete a card from the database else if (isset($_REQUEST['action_delete']) && $this->selectedCard != null) { $this->db->deleteCard($this->selectedCard->id); // Make sure the deleted card is no longer selected $this->selectedCard = null; } } private function selectNewCard() { $this->selectedCard = $this->db->getFirstCardByBoxID($this->selectedBoxID); } private function addGetParameter($parameterName, $parameterValue) { $_GET[$parameterName] = $parameterValue; } private function createGetParameterString() { $tmp = '?'; foreach($_GET as $key => $value) { $tmp = $tmp . $key . '=' . $value . '&'; } return trim($tmp, '&');//substr($tmp, 0, -1); } //Add a temporary extra key/value pair to string private function createExtendedGetParameterString($key, $value) { $this->deleteGetParameter($key); $existingParams = $this->createGetParameterString(); return $existingParams == '?' ? '?'.$key.'='.$value : $existingParams.'&'.$key.'='.$value; } private function deleteGetParameter($key) { unset($_GET[$key]); } } $auth = new Auth(); new App($auth->getDBHandle()); ?>