Skip to content

Instantly share code, notes, and snippets.

@r8r
Last active April 23, 2016 08:20
Show Gist options
  • Save r8r/5fa3e7d0fc8d1fb93cad to your computer and use it in GitHub Desktop.
Save r8r/5fa3e7d0fc8d1fb93cad to your computer and use it in GitHub Desktop.
<table class="table">
<thead>
<tr>
<th>
Title
</th>
<th>
Author
</th>
<th>
Price
</th>
<th>
<span class="glyphicon glyphicon-shopping-cart" aria-hidden="true"></span>
</th>
</tr>
</thead>
<tbody>
<?php
foreach ($books as $book):
$inCart = ShoppingCart::contains($book->getId());
?>
<tr>
<td><strong>
<?php echo Util::escape($book->getTitle()); ?>
</strong>
</td>
<td>
<?php echo Util::escape($book->getAuthor()); ?>
</td>
<td>
<?php echo Util::escape($book->getPrice()); ?>
</td>
<td class="add-remove">
<?php if ($inCart): ?>
<form method="post" action="<?php echo Util::action('removeFromCart', array('bookId' => $book->getId())); ?>">
<input type="submit" role="button" class="btn btn-default btn-xs btn-info" value="-" />
</form>
<?php else: ?>
<form method="post" action="<?php echo Util::action('addToCart', array('bookId' => $book->getId())); ?>">
<input type="submit" role="button" class="btn btn-default btn-xs btn-success" value="+" />
</form>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
DROP DATABASE fh_scm4_bookshop;
CREATE DATABASE fh_scm4_bookshop;
USE fh_scm4_bookshop;
CREATE TABLE books (
id int(11) NOT NULL AUTO_INCREMENT,
categoryId int(11) NOT NULL,
title varchar(255) NOT NULL,
author varchar(255) NOT NULL,
isbn varchar(255) NOT NULL,
price decimal(10,2) NOT NULL,
PRIMARY KEY (id),
KEY categoryId (categoryId)
) ENGINE=InnoDB AUTO_INCREMENT=1 CHARSET=utf8;;
CREATE TABLE categories (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=1 CHARSET=utf8;;
CREATE TABLE orderedbooks (
id int(11) NOT NULL AUTO_INCREMENT,
orderId int(11) NOT NULL,
bookId int(11) NOT NULL,
PRIMARY KEY (id),
KEY orderId (orderId),
KEY bookId (bookId)
) ENGINE=InnoDB AUTO_INCREMENT=1 CHARSET=utf8;;
CREATE TABLE orders (
id int(11) NOT NULL AUTO_INCREMENT,
userId int(11) NOT NULL,
creditCardNumber char(16) NOT NULL,
creditCardHolder varchar(255) NOT NULL,
PRIMARY KEY (id),
KEY userId (userId)
) ENGINE=InnoDB AUTO_INCREMENT=1 CHARSET=utf8;;
CREATE TABLE users (
id int(11) NOT NULL AUTO_INCREMENT,
userName varchar(255) NOT NULL,
passwordHash char(40) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY userName (userName)
) ENGINE=InnoDB AUTO_INCREMENT=1 CHARSET=utf8;;
ALTER TABLE books
ADD CONSTRAINT books_ibfk_1 FOREIGN KEY (categoryId) REFERENCES categories (id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE orderedbooks
ADD CONSTRAINT orderedbooks_ibfk_2 FOREIGN KEY (bookId) REFERENCES books (id) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT orderedBooks_ibfk_1 FOREIGN KEY (orderid) REFERENCES orders (id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE orders
ADD CONSTRAINT orders_ibfk_1 FOREIGN KEY (userId) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE;
INSERT INTO categories VALUES (1, 'Mobile & Wireless Computing');
INSERT INTO categories VALUES (2, 'Functional Programming');
INSERT INTO categories VALUES (3, 'C / C++');
INSERT INTO categories VALUES (4, '<< New Publications >>');
INSERT INTO books VALUES (1, 1, 'Hello, Android: Introducing Google''s Mobile Development Platform', 'Ed Burnette', '9781934356562', 19.97);
INSERT INTO books VALUES (2, 1, 'Android Wireless Application Development', 'Shane Conder, Lauren Darcey', '0321743016', 31.22);
INSERT INTO books VALUES (5, 1, 'Professional Flash Mobile Development', 'Richard Wagner', '0470620072', 19.90);
INSERT INTO books VALUES (7, 1, 'Mobile Web Design For Dummies', 'Janine Warner, David LaFontaine', '9780470560969', 16.32);
INSERT INTO books VALUES (11, 2, 'Introduction to Functional Programming using Haskell', 'Richard Bird', '9780134843469', 74.75);
INSERT INTO books VALUES (12, 2, 'Scripting (Attacks) for Beginners - <script type="text/javascript">alert(''All your base are belong to us!'');</script>', 'John Doe', '1234567890', 9.99);
INSERT INTO books VALUES (14, 2, 'Expert F# (Expert''s Voice in .NET)', 'Antonio Cisternino, Adam Granicz, Don Syme', '9781590598504', 47.64);
INSERT INTO books VALUES (16, 3, 'C Programming Language (2nd Edition)', 'Brian W. Kernighan, Dennis M. Ritchie', '0131103628', 48.36);
INSERT INTO books VALUES (27, 3, 'C++ Primer Plus (5th Edition)', 'Stephan Prata', ' 9780672326974', 36.94);
INSERT INTO books VALUES (29, 3, 'The C++ Programming Language', 'Bjarne Stroustrup', '0201700735', 67.49);
INSERT INTO users VALUES (1, 'scm4', 'a8af855d47d091f0376664fe588207f334cdad22');
<div class="panel panel-default">
<div class="panel-heading">
Please provide your credit card details for payment:
</div>
<div class="panel-body">
<form class="form-horizontal" method="post" action="<?php echo Util::action('placeOrder'); ?>">
<div class="form-group">
<label for="nameOnCard" class="col-sm-4 control-label">Name on card:</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="nameOnCard" name="nameOnCard" placeholder="Your name please!" value="<?php echo htmlentities($nameOnCard); ?>">
</div>
</div>
<div class="form-group">
<label for="cardNumber" class="col-sm-4 control-label">Card Number:</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="cardNumber" name="cardNumber" placeholder="try '1234567891234567'" value="<?php echo htmlentities($cardNumber); ?>">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8">
<button type="submit" class="btn btn-default">Place Order</button>
</div>
</div>
</form>
</div>
</div>
<?php
/**
* Controller
*
* class handles POST requests and redirects
* the client after processing
* - demo of singleton pattern
*/
class Controller extends BaseObject {
// static strings used in views
const ACTION = 'action';
const METHOD_POST = 'POST';
const PAGE = 'page';
const CC_NAME = 'nameOnCard';
const CC_NUMBER = 'cardNumber';
const ACTION_ADD = 'addToCart';
const ACTION_REMOVE = 'removeFromCart';
const ACTION_ORDER = 'placeOrder';
const ACTION_LOGIN = 'login';
const USR_NAME = 'userName';
const USR_PASSWORD = 'password';
const ACTION_LOGOUT = 'logout';
private static $instance = false;
/**
*
* @return Controller
*/
public static function getInstance() {
if (!self::$instance) {
self::$instance = new Controller();
}
return self::$instance;
}
private function __construct() {
}
/**
*
* processes POST requests and redirects client depending on selected
* action
*
* @return bool
* @throws Exception
*/
public function invokePostAction() {
if ($_SERVER['REQUEST_METHOD'] != self::METHOD_POST) {
throw new Exception('Controller can only handle POST requests.');
return null;
} elseif (!isset($_REQUEST[self::ACTION])) {
throw new Exception('Action not specified.');
return null;
}
// now process the assigned action
$action = $_REQUEST[self::ACTION];
switch ($action) {
case self::ACTION_ADD :
ShoppingCart::add((int) $_REQUEST['bookId']);
Util::redirect();
break;
case self::ACTION_REMOVE :
ShoppingCart::remove((int) $_REQUEST['bookId']);
Util::redirect();
break;
case self::ACTION_ORDER :
$user = AuthenticationManager::getAuthenticatedUser();
// abort
if ($user == null) {
$this->forwardRequest(array('Not logged in.'));
break;
}
// else
if ($this->processCheckout($_POST[self::CC_NAME], $_POST[self::CC_NUMBER]))
break;
else
return null;
case self::ACTION_LOGIN :
//try to authenticate the given user
if (!AuthenticationManager::authenticate($_REQUEST[self::USR_NAME], $_REQUEST[self::USR_PASSWORD])) {
$this->forwardRequest(array('Invalid user name or password.'));
}
Util::redirect();
break;
case self::ACTION_LOGOUT :
//sign out current user
AuthenticationManager::signOut();
Util::redirect();
break;
default : throw new Exception('Unknown controller action: ' . $action);
}
}
/**
*
* @param string $nameOnCard
* @param integer $cardNumber
* @return bool
*/
protected function processCheckout($nameOnCard = null, $cardNumber = null) {
$errors = array();
$nameOnCard = trim($nameOnCard);
if ($nameOnCard == null || strlen($nameOnCard) == 0) {
$errors[] = 'Invalid name on card.';
}
if ($cardNumber == null || strlen($cardNumber) != 16 || !ctype_digit($cardNumber)) {
$errors[] = 'Invalid card number. Card number must be sixteen digits.';
}
if (count($errors) > 0) {
$this->forwardRequest($errors);
return false;
}
//check cart
if (ShoppingCart::size() == 0) {
$this->forwardRequest(array('No items in cart.'));
}
//try to place a new order
$user = AuthenticationManager::getAuthenticatedUser();
$orderId = DataManager::createOrder($user->getId(), ShoppingCart::getAll(), $nameOnCard, $cardNumber);
if (!$orderId) {
$this->forwardRequest(array('Could not create order.'));
}
//clear shopping card and redirect to success page
ShoppingCart::clear();
Util::redirect('index.php?view=success&orderId=' . rawurlencode($orderId));
return true;
}
/**
*
* @param array $errors : optional assign it to
* @param string $target : url for redirect of the request
*/
protected function forwardRequest(array $errors = null, $target = null) {
//check for given target and try to fall back to previous page if needed
if ($target == null) {
if (!isset($_REQUEST[self::PAGE])) {
throw new Exception('Missing target for forward.');
}
$target = $_REQUEST[self::PAGE];
}
//forward request to target
// optional - add errors to redirect and process them in view
if (count($errors) > 0)
$target .= '&errors=' . urlencode(serialize($errors));
header('location: ' . $target);
exit();
}
}
<?php
// mock data
$__categories = array(1 => new Category(1, "Mobile & Wireless Computing"),
2 => new Category(2, "Functional Programming"),
3 => new Category(3, "C / C++"),
4 => new Category(4, "<< New Publications >>"));
$__books = array(1 => new Book(1, 1, "Hello, Android:\nIntroducing Google's Mobile Development Platform", "Ed Burnette", 19.97),
2 => new Book(2, 1, "Android Wireless Application Development", "Shane Conder, Lauren Darcey", 31.22),
5 => new Book(5, 1, "Professional Flash Mobile Development", "Richard Wagner", 19.90),
7 => new Book(7, 1, "Mobile Web Design For Dummies", "Janine Warner, David LaFontaine", 16.32),
11 => new Book(11, 2, "Introduction to Functional Programming using Haskell", "Richard Bird", 74.75),
//book with bad title to show scripting attack - add for scripting attack demo only
12 => new Book(12, 2, "Scripting (Attacks) for Beginners - <script type=\"text/javascript\">alert('All your base are belong to us!');</script>", "John Doe", 9.99),
14 => new Book(14, 2, "Expert F# (Expert's Voice in .NET)", "Antonio Cisternino, Adam Granicz, Don Syme", 47.64),
16 => new Book(16, 3, "C Programming Language\n(2nd Edition)", "Brian W. Kernighan, Dennis M. Ritchie", 48.36),
27 => new Book(27, 3, "C++ Primer Plus\n(5th Edition)", "Stephan Prata", 36.94),
29 => new Book(29, 3, "The C++ Programming Language", "Bjarne Stroustrup", 67.49));
$__users = array(1 => new User(1, "scm4", "a8af855d47d091f0376664fe588207f334cdad22")); //USER = scm4; PASSWORD = scm4
<?php
/**
* DataManager
* Mysqli Version
*
*
* @package
* @subpackage
* @author John Doe <jd@fbi.gov>
*/
class DataManager {
/**
* connect to the database
*
* note: alternatively put those in parameter list or as class variables
*
* @return connection resource
*/
private static function getConnection() {
$con = new mysqli('localhost', 'root', 'root', 'fh_scm4_bookshop');
if (mysqli_connect_errno()) {
die('Unable to connect to database.');
}
return $con;
}
/**
* place query
*
* @return mixed
*/
private static function query($connection, $query) {
$res = $connection->query($query);
if (!$res) {
die("Error in query \"" . $query . "\": " . $connection->error);
}
return $res;
}
/**
* get the key of the last inserted item
*
* @return integer
*/
private static function lastInsertId($connection) {
return mysqli_insert_id($connection);
}
/**
* retrieve an object from the database result set
*
* @param object $cursor result set
* @return object
*/
private static function fetchObject($cursor) {
return $cursor->fetch_object();
}
/**
* remove the result set
*
* @param object $cursor result set
* @return null
*/
private static function close($cursor) {
$cursor->close();
}
/**
* close the database connection
*
* @param object $cursor resource of current database connection
* @return null
*/
private static function closeConnection($connection) {
$connection->close();
}
/**
* get the categories
*
* @return array of Category-items
*/
public static function getCategories() {
$categories = array();
$con = self::getConnection();
$res = self::query($con, "
SELECT id, name
FROM categories;
");
while ($cat = self::fetchObject($res)) {
$categories[] = new Category($cat->id, $cat->name);
}
self::close($res);
self::closeConnection($con);
return $categories;
}
/**
* get the books per category
*
* @param integer $categoryId numeric id of the category
* @return array of Book-items
*/
public static function getBooksForCategory($categoryId) {
$books = array();
$con = self::getConnection();
$categoryId = intval($categoryId); /* !!! */
$res = self::query($con, "
SELECT id, categoryId, title, author, price
FROM books
WHERE categoryId = " . $categoryId . ";
");
while ($book = self::fetchObject($res)) {
$books[] = new Book($book->id, $book->categoryId, $book->title, $book->author, $book->price);
}
self::close($res);
self::closeConnection($con);
return $books;
}
/**
* get the books per search term
*
* note: search via LIKE
*
* @param string $term search term: book title string match
* @return array of Book-items
*/
public static function getBooksForSearchCriteria($term) {
$books = array();
$con = self::getConnection();
$term = $con->real_escape_string($term); /* !!! */
$res = self::query($con, "
SELECT id, categoryId, title, author, price
FROM books
WHERE title LIKE '%" . $term . "%';
");
while ($book = self::fetchObject($res)) {
$books[] = new Book($book->id, $book->categoryId, $book->title, $book->author, $book->price);
}
self::close($res);
self::closeConnection($con);
return $books;
}
/**
* get the books per search term – paginated set only
*
* @param string $term search term: book title string match
* @param integer $offset start at the nth item
* @param integer $numPerPage number of items per page
* @return array of Book-items
*/
public static function getBooksForSearchCriteriaWithPaging($term, $offset, $numPerPage) {
$con = self::getConnection();
//query total count
$term = $con->real_escape_string($term); /* !!! */
$res = self::query($con, "
SELECT COUNT(*) AS cnt
FROM books
WHERE title LIKE '%" . $term . "%';
");
$totalCount = self::fetchObject($res)->cnt;
self::close($res);
//query books to return
$books = array();
$offset = intval($offset); /* !!! */
$numPerPage = intval($numPerPage); /* !!! */
$res = self::query($con, "
SELECT id, categoryId, title, author, price
FROM books
WHERE title LIKE '%" . $term . "%'
LIMIT " . $offset . ", " . $numPerPage . ";
");
while ($book = self::fetchObject($res)) {
$books[] = new Book($book->id, $book->categoryId, $book->title, $book->author, $book->price);
}
self::close($res);
self::closeConnection($con);
return new PagingResult($books, $offset, $totalCount);
}
/**
* get the User item by id
*
* @param integer $userId uid of that user
* @return User | false
*/
public static function getUserForId($userId) {
$user = null;
$con = self::getConnection();
$userId = intval($userId); /* !!! */
$res = self::query($con, "
SELECT id, userName, passwordHash
FROM users
WHERE id = " . $userId . ";
");
if ($u = self::fetchObject($res)) {
$user = new User($u->id, $u->userName, $u->passwordHash);
}
self::close($res);
self::closeConnection($con);
return $user;
}
/**
* get the User item by name
*
* @param string $userName name of that user - must be exact match
* @return User | false
*/
public static function getUserForUserName($userName) {
$user = null;
$con = self::getConnection();
$userName = $con->real_escape_string($userName); /* !!! */
$res = self::query($con, "
SELECT id, userName, passwordHash
FROM users
WHERE userName = '" . $userName . "';
");
if ($u = self::fetchObject($res)) {
$user = new User($u->id, $u->userName, $u->passwordHash);
}
self::close($res);
self::closeConnection($con);
return $user;
}
/**
* place to order with the shopping cart items
*
* note: wrapped in a transaction
*
* @param integer $userId id of the ordering user
* @param array $bookIds integers of book ids
* @param string $nameOnCard cc name
* @param string $cardNumber cc number
* @return integer
*/
public static function createOrder($userId, $bookIds, $nameOnCard, $cardNumber) {
$con = self::getConnection();
self::query($con, 'BEGIN;');
$userId = intval($userId); /* !!! */
$nameOnCard = $con->real_escape_string($nameOnCard); /* !!! */
$cardNumber = $con->real_escape_string($cardNumber); /* !!! */
self::query($con, "
INSERT INTO orders (
userId
, creditCardNumber
, creditCardHolder
) VALUES (
" . $userId . "
, '" . $cardNumber . "'
, '" . $nameOnCard . "'
);
");
$orderId = self::lastInsertId($con);
$orderId = intval($orderId); /* !!! */
foreach ($bookIds as $bookId) {
$bookId = intval($bookId); /* !!! */
self::query($con, "
INSERT INTO orderedbooks (
orderId,
bookId
) VALUES (
" . $orderId . "
, " . $bookId . ");
");
}
self::query($con, 'COMMIT;');
self::closeConnection($con);
return $orderId;
}
}
<?php
/**
* DataManager
* PDO Version
*
*
* @package
* @subpackage
* @author John Doe <jd@fbi.gov>
*/
class DataManager {
private static $__connection;
/**
* connect to the database
*
* note: alternatively put those in parameter list or as class variables
*
* @return connection resource
*/
private static function getConnection() {
if (!isset(self::$__connection)) {
self::$__connection = new PDO('mysql:host=localhost;dbname=fh_scm4_bookshop;charset=utf8', 'root', 'root');
}
return self::$__connection;
}
/**
* place query
*
* note: using prepared statements
* see the filtering in bindValue()
*
* @return mixed
*/
private static function query($connection, $query, $parameters = array()) {
$statement = $connection->prepare($query);
$i = 1;
foreach ($parameters as $param) {
if (is_int($param)) {
$statement->bindValue($i, $param, PDO::PARAM_INT);
}
if (is_string($param)) {
$statement->bindValue($i, $param, PDO::PARAM_STR);
}
$i++;
}
$statement->execute();
return $statement;
}
/**
* get the key of the last inserted item
*
* @return integer
*/
private static function lastInsertId($connection) {
return $connection->lastInsertId();
}
/**
* retrieve an object from the database result set
*
* @param object $cursor result set
* @return object
*/
private static function fetchObject($cursor) {
return $cursor->fetchObject();
}
/**
* remove the result set
*
* @param object $cursor result set
* @return null
*/
private static function close($cursor) {
$cursor->closeCursor();
}
/**
* close the database connection
*
* note: not needed
*
* @param object $cursor resource of current database connection
* @return null
*/
private static function closeConnection($connection) {
}
/**
* get the categories
*
* @return array of Category-items
*/
public static function getCategories() {
$categories = array();
$con = self::getConnection();
$res = self::query($con, "
SELECT id, name
FROM categories;
");
while ($cat = self::fetchObject($res)) {
$categories[] = new Category($cat->id, $cat->name);
}
self::close($res);
self::closeConnection($con);
return $categories;
}
/**
* get the books per category
*
* note: see how prepared statements replace "?" with array element values
*
* @param integer $categoryId numeric id of the category
* @return array of Book-items
*/
public static function getBooksForCategory($categoryId) {
$books = array();
$con = self::getConnection();
$res = self::query($con, "
SELECT id, categoryId, title, author, price
FROM books
WHERE categoryId = ?;
", array($categoryId));
while ($book = self::fetchObject($res)) {
$books[] = new Book($book->id, $book->categoryId, $book->title, $book->author, $book->price);
}
self::close($res);
self::closeConnection($con);
return $books;
}
/**
* get the books per search term
*
* note: search via LIKE
*
* @param string $term search term: book title string match
* @return array of Book-items
*/
public static function getBooksForSearchCriteria($term) {
$books = array();
$con = self::getConnection();
$res = self::query($con, "
SELECT id, categoryId, title, author, price
FROM books
WHERE title LIKE ?;
", array("%" . $term . "%"));
while ($book = self::fetchObject($res)) {
$books[] = new Book($book->id, $book->categoryId, $book->title, $book->author, $book->price);
}
self::close($res);
self::closeConnection($con);
return $books;
}
/**
* get the books per search term – paginated set only
*
* @param string $term search term: book title string match
* @param integer $offset start at the nth item
* @param integer $numPerPage number of items per page
* @return array of Book-items
*/
public static function getBooksForSearchCriteriaWithPaging($term, $offset, $numPerPage) {
$con = self::getConnection();
//query total count
$res = self::query($con, "
SELECT COUNT(*) AS cnt
FROM books
WHERE title LIKE ?;
", array("%" . $term . "%"));
$totalCount = self::fetchObject($res)->cnt;
self::close($res);
//query books to return
$books = array();
$res = self::query($con, "
SELECT id, categoryId, title, author, price
FROM books
WHERE title
LIKE ? LIMIT ?, ?;
", array("%" . $term . "%", intval($offset), intval($numPerPage)));
while ($book = self::fetchObject($res)) {
$books[] = new Book($book->id, $book->categoryId, $book->title, $book->author, $book->price);
}
self::close($res);
self::closeConnection($con);
return new PagingResult($books, $offset, $totalCount);
}
/**
* get the User item by id
*
* @param integer $userId uid of that user
* @return User | false
*/
public static function getUserForId($userId) {
$user = null;
$con = self::getConnection();
$res = self::query($con, "
SELECT id, userName, passwordHash
FROM users
WHERE id = ?;
", array($userId));
if ($u = self::fetchObject($res)) {
$user = new User($u->id, $u->userName, $u->passwordHash);
}
self::close($res);
self::closeConnection($con);
return $user;
}
/**
* get the User item by name
*
* @param string $userName name of that user - must be exact match
* @return User | false
*/
public static function getUserForUserName($userName) {
$user = null;
$con = self::getConnection();
$res = self::query($con, "
SELECT id, userName, passwordHash
FROM users
WHERE userName = ?;
", array($userName));
if ($u = self::fetchObject($res)) {
$user = new User($u->id, $u->userName, $u->passwordHash);
}
self::close($res);
self::closeConnection($con);
return $user;
}
/**
* place to order with the shopping cart items
*
* note: wrapped in a transaction
*
* @param integer $userId id of the ordering user
* @param array $bookIds integers of book ids
* @param string $nameOnCard cc name
* @param string $cardNumber cc number
* @return integer
*/
public static function createOrder($userId, $bookIds, $nameOnCard, $cardNumber) {
$con = self::getConnection();
self::query($con, 'BEGIN;');
self::query($con, "
INSERT INTO orders (
userId
, creditCardNumber
, creditCardHolder
) VALUES (
?
, ?
, ?
);
", array($userId, $cardNumber, $nameOnCard));
$orderId = self::lastInsertId($con);
foreach ($bookIds as $bookId) {
self::query($con, "
INSERT INTO orderedbooks (
orderId
, bookId
) VALUES (
?
, ?
);", array($orderId, $bookId));
}
self::query($con, 'COMMIT;');
self::closeConnection($con);
return $orderId;
}
}
<?php require_once('views/partials/header.php'); ?>
<div class="page-header">
<h2>Welcome</h2>
</div>
<p>Welcome to the SCM4 book shop!</p>
<?php require_once('views/partials/footer.php'); ?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta charset="utf-8">
<title>SCM4 Book Shop</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="assets/bootstrap/css/bootstrap-theme.min.css" rel="stylesheet">
<link href="assets/main.css" rel="stylesheet">
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">SCM 4 Bookshop (V 2.0)</a>
</div>
<div class="navbar-collapse collapse" id="bs-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="index.php">Home</a></li>
<li><a href="index.php?view=list">List</a></li>
<li><a href="index.php?view=search">Search</a></li>
<li><a href="index.php?view=checkout">Checkout</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<div class="container">
<?php
$user = AuthenticationManager::getAuthenticatedUser();
$cartSize = ShoppingCart::size();
if (isset($_GET["errors"])) {
$errors = unserialize(urldecode($_GET["errors"]));
}
// /needed for shopping cart
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta charset="utf-8">
<title>SCM4 Book Shop</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="assets/bootstrap/css/bootstrap-theme.min.css" rel="stylesheet">
<link href="assets/main.css" rel="stylesheet">
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">SCM 4 Bookshop (V 2.0)</a>
</div>
<div class="navbar-collapse collapse" id="bs-navbar-collapse-1">
<ul class="nav navbar-nav">
<li <?php if ($view === 'welcome') { ?>class="active"<?php } ?>><a href="index.php">Home</a></li>
<li <?php if ($view === 'list') { ?>class="active"<?php } ?>><a href="index.php?view=list">List</a></li>
<li <?php if ($view === 'search') { ?>class="active"<?php } ?>><a href="index.php?view=search">Search</a></li>
<li <?php if ($view === 'checkout') { ?>class="active"<?php } ?>><a href="index.php?view=checkout">Checkout</a></li>
</ul>
<ul class="nav navbar-nav navbar-right login">
<li>
<a href="index.php?view=checkout">
<span class="badge"><?php echo Util::escape($cartSize); ?></span> <span class="glyphicon glyphicon-shopping-cart" aria-hidden="true"></span></a>
</li>
<li class="dropdown">
<?php if ($user == null): ?>
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
Not logged in!
<b class="caret"></b>
</a>
<ul class="dropdown-menu" role="menu">
<li>
<a href="index.php?view=login">Login now</a>
</li>
</ul>
<?php else: ?>
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
Logged in as <span class="badge"><?php echo Util::escape($user->getUserName()); ?></span>
<b class="caret"></b>
</a>
</a>
<ul class="dropdown-menu" role="menu">
<li class="centered">
<form method="post" action="<?php echo Util::action('logout'); ?>">
<input class="btn btn-xs" role="button" type="submit" value="Logout" />
</form>
</li>
</ul>
<?php endif; ?>
</li>
</ul> <!-- /. login -->
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<div class="container">
<?php
require_once('inc/bootstrap.inc.php');
$view = isset($_REQUEST['view']) ? $_REQUEST['view'] : 'welcome';
$postAction = isset($_REQUEST['action']) ? $_REQUEST['action'] : null;
/* if we have a form post, invoke the controller */
if ($postAction != null)
Controller::getInstance()->invokePostAction();
/**
* no post action - switch the views via GET parameter
**/
if (file_exists(__DIR__ .'/views/' . $view .'.php'))
require_once('views/' . $view .'.php');
<?php
$categories = DataManager::getCategories();
$categoryId = isset($_REQUEST['categoryId']) ? (int) $_REQUEST['categoryId'] : null;
$books = (isset($categoryId) && ($categoryId > 0)) ? DataManager::getBooksForCategory($categoryId) : null;
require('views/partials/header.php');
?>
<div class="page-header">
<h2>List of books by category</h2>
</div>
<ul class="nav nav-tabs">
<?php foreach ($categories as $cat) : ?>
<li role="presentation"
<?php if ($cat->getId() === $categoryId) { ?>class="active" <?php } ?>>
<a href="<?php echo $_SERVER['PHP_SELF'] ?>?view=list&categoryId=<?php echo urlencode($cat->getId()); ?>"><?php echo Util::escape($cat->getName()); ?></a></span>
<?php endforeach; ?>
</ul>
<br />
<?php if (isset($books)) : ?>
<?php
if (sizeof($books) > 0) :
require('views/partials/booklist.php');
else :
?>
<div class="alert alert-warning" role="alert">No books in this category.</div>
<?php endif; ?>
<?php else : ?>
<div class="alert alert-info" role="alert">Please select a category.</div>
<?php endif; ?>
<?php
require('views/partials/footer.php');
?>
<?php
//as soon as shopping cart is referenced the session context is created
SessionContext::create();
/**
* ShoppingCart
*
*
* @package
* @subpackage
* @author John Doe <jd@fbi.gov>
*/
class ShoppingCart extends BaseObject {
/**
* add an item to the shopping cart
*
* @param integer $bookId book id
* @return null
*/
public static function add($bookId) {
}
/**
* remove an item from the shopping cart
*
* @param integer $bookId book id
* @return null
*/
public static function remove($bookId) {
}
/**
* empty the shopping cart
*
* @return null
*/
public static function clear() {
}
/**
* check if an item is in the shopping cart
*
* @param integer $bookId book id
* @return boolean
*/
public static function contains($bookId) {
}
/**
* get number of shopping cart items
*
* @return integer
*/
public static function size() {
}
/**
* get the shopping cart contents
*
* @return ShoppingCart object | empty array
*/
public static function getAll() {
}
/**
* add an item to the shopping cart
*
* @return ShoppingCart object | empty array
*/
private static function getCart() {
}
/**
* make shopping cart persistent
*
* @return null
*/
private static function storeCart(array $cart) {
}
}
<?php
$orderId = isset($_REQUEST['orderId']) ? $_REQUEST['orderId'] : null;
require_once('views/partials/header.php');
?>
<div class="page-header">
<h2>Success!</h2>
</div>
<p>Thank you for your purchase.</p>
<?php if ($orderId != null) : ?>
<p>Your order number is <?php echo Util::escape($orderId); ?>.</p>
<?php endif; ?>
<?php /* TODO order Summary */ ?>
<?php
require_once('views/partials/footer.php');
?>
<?php
class Util extends BaseObject {
/**
* bereinigt den output
*
* @param string $string der string
* @return string
*/
public static function escape($string) {
return nl2br(htmlentities($string));
}
/**
* redirect mit optionaler url - HINWEIS - redirection attack möglich!
*
* @param string $string uri optional
* @return null
*/
public static function redirect($page = null) {
if ($page == null) {
$page = isset($_REQUEST['page']) ?
$_REQUEST['page'] :
$_SERVER['REQUEST_URI'];
}
header("Location: $page");
}
/**
* GET parameter "page" adds current page to action so that a redirect
* back to this page is possible after successful execution of POST action
* if "page" has been set before then just keep the current value (to avoid
* problem with "growing URLs" when a POST form is rendered "a second time"
* e.g. during a forward after an unsuccessful POS action)
*
* Be sure to check for invalid / insecure page redirects!!
*
* @param string $action uri optional
* @param string $params array key/value pairs
* @return null
*/
public static function action($action, $params = null) {
$page = isset($_REQUEST['page']) ?
$_REQUEST['page'] :
$_SERVER['REQUEST_URI'];
$res = 'index.php?action=' . rawurlencode($action) . '&page=' . rawurlencode($page);
if (is_array($params)) {
foreach ($params as $name => $value) {
$res .= '&' . rawurlencode($name) . '=' . rawurlencode($value);
}
}
return $res;
}
}
<?php require_once('views/partials/header.php'); ?>
<div class="page-header">
<h2>Welcome</h2>
</div>
<p>Welcome to the SCM4 book shop!</p>
<?php require_once('views/partials/footer.php'); ?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment