<file_sep><?php

function validate($title, $content) {
	if (!(
		isset($title) &&
		isset($content) &&
		strlen($title) > 0 &&
		strlen($content) > 0
	))
	{
		return 'Title AND content required!';
	}
}

?>
<file_sep><?php

$title = 'Logging In';
$from = $_GET['from'];

include '../../views/blog/login.php';

?>
<file_sep>CREATE TABLE test.posts (
	id INT PRIMARY KEY AUTO_INCREMENT,
	title VARCHAR(255),
	content TEXT,
	created_at DATETIME
);

CREATE TABLE test.comments (
	id INT PRIMARY KEY AUTO_INCREMENT,
	post_id INT,
	author VARCHAR(255),
	comment TEXT,
	comment_date DATETIME
);

CREATE TABLE test.members (
	id INT PRIMARY KEY AUTO_INCREMENT,
	nickname VARCHAR(255),
	password VARCHAR(255),
	email VARCHAR(255),
	joined_at DATE
);
<file_sep>Read [php_tutorial/README.md](../README.md) first!

Following exercise 1 (page 110)
-------------------------------

Steps:
- Go on http://localhost/php_tutorial/ex1/secret.php (the correct password is "<PASSWORD>")
<file_sep>Your nickname doesn't match the given password.<br/>
<a href="login.php?from=<?php echo $from; ?>">Try again</a>

<file_sep><!DOCTYPE html>
<html>
	<head>
		<title>My awesome blog!</title>
		<meta charset="utf8" />
		<link rel="stylesheet" href="../../views/blog/style.css" type="text/css" />
	</head>
	
	<body>
		<h1>My awesome blog!</h1>
		<a href="index.php">Back to posts list</a>
		
		<div class="news">
			<h3>
				<?php echo $post['title']; ?>
				<em> on (french fashion display) <?php echo $post['created_at']; ?></em>
			</h3>
			<p><?php echo $post['content']; ?></p>
		</div>
		
		<h2>Comments</h2>
		
		<form method="post" action="comments_post.php">
			<fieldset>
				<legend>Add a comment</legend>
				
				<p>
					<label for="author">Author:</label>
					<br/>
					<input type="text" id="author" name="author" />
				</p>
				<p>
					<label for="comment">Comment:</label>
					<br/>
					<textarea id="comment" name="comment"></textarea>
				</p>
				
				<input type="hidden" name="post_id" value="<?php echo $post_id; ?>" />
				
				<input type="submit" value="Send" />
			</fieldset>
		</form>
		
		<?php
		
		if (count($comments) > 0)
		{
			foreach($comments as $comment) {
				
		?>
				<p>
					<strong><?php echo $comment['author']; ?></strong>
					on (french fashion display) <?php echo $comment['comment_date_french_fashion']; ?>
				</p>
				<p><?php echo $comment['comment']; ?></p>
		<?php
			
			}
		} else {
			echo '<p><em>No comments for this post</em></p>';
		}
		
		?>
	</body>
</html>

<file_sep><!DOCTYPE httml>
<html>
	<head>
		<title><?php echo $title; ?></title>
		<meta charset="utf8" />
	</head>
	
	<body>
		<h1><?php echo $title; ?></h1>
		
		<form method="post" action="signup_post.php">
			<label for="nickname">Nickname:</label>
			<br/>
			<input type="text" id="nickname" name="nickname" />
			<br/>
			<label for="pwd">Password:</label>
			<br/>
			<input type="<PASSWORD>" id="pwd" name="pwd" />
			<br/>
			<label for="pwd_again">Type again your password:</label>
			<br/>
			<input type="<PASSWORD>" id="pwd_again" name="pwd_<PASSWORD>" />
			<br/>
			<label for="email">Email:</label>
			<br/>
			<input type="text" id="email" name="email" />
			<br/>
			
			<input type="submit" value="Sign up" />
		</form>
	</body>
</html>

<file_sep><!DOCTYPE html>
<html>
	<head>
		<title><?php echo $title; ?></title>
		<meta charset="utf8" />
	</head>
	
	<body>
		<h1><?php echo $title; ?></h1>
		
		<form method="post" action="login_post.php">
			<input type="hidden" name="from" value="<?php echo $from; ?>" />
			
			<label for="nickname">Nickname:</label>
			<br/>
			<input type="text" id="nickname" name="nickname" />
			<br/>
			<label for="pwd">Password:</label>
			<br/>
			<input type="password" id="pwd" name="pwd" />
			<br/>
			<label for="stay_connected">Stay connected?</label>
			<br/>
			<input type="checkbox" id="stay_connected" name="stay_connected" />
			<br/>
			<input type="submit" value="Log in" />
		</form>
	</body>
</html>

<file_sep><?php

try
{
	$db = new PDO(
		'mysql:host=localhost;dbname=test',
		'root',
		'',
		array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
	);
}
catch (Exception $e)
{
	die('ERROR: ' . $e->getMessage());
}

?>
<file_sep><?php

$title = 'Signing Up';

include '../../views/blog/signup.php';

?>

<file_sep><?php echo $msg; ?><br/>
<a href="signup.php">Try again!</a>

<file_sep><?php

$pwd = <PASSWORD>;

if (isset($_POST['pwd']))
{
	$pwd = $_POST['pwd'];
}

if (!isset($pwd) && htmlspecialchars($pwd) != '<PASSWORD>')
{
?>

<!DOCTYPE html>
<html>
	<head>
		<title>Restricted access - PHP Tutorial</title>
	</head>
	
	<body>
		<form method="POST" action="secret.php">
			<label for="pwd">Please, enter password:</label>
			<br/>
			<input type="password" id="pwd" name="pwd"/>
			<br/>
			<input type="submit"/>
		</form>
	</body>
</html>

<?php
}
elseif (isset($pwd) && $pwd != '<PASSWORD>')
{
	echo 'Wrong password, try again! <br/>'.
		'<a href="secret.php">Enter password</a>';
}
else
{
	echo 'Welcome to this restricted area. <br/>' .
	'The secret message is: CONGRATULATIONS!';
}

?>

<file_sep>Welcome <strong><?php echo $nickname; ?>!</strong><br/>
<a href="index.php">Go to our Home Page</a>

<file_sep><?php

include '../../models/db.php';

$post_id = $_GET['post_id'];

function get_post($post_id)
{
	global $db;
	
	$get_post = $db->prepare(
		"SELECT title, content, DATE_FORMAT(created_at, '%d/%m/%Y at %Hh%imin%ss') AS created_at " .
		"FROM posts " .
		"WHERE id = :post_id"
	);
	$get_post->execute(array(
		'post_id' => $post_id
	));
	
	$post = $get_post->fetch();
	
	$get_post->closeCursor();
	
	return $post;
}

function get_comments_from_post($post_id)
{
	global $db;
	
	$get_comments_from_post = $db->prepare(
		"SELECT author, comment, DATE_FORMAT(comment_date, '%d/%m/%Y at %Hh%imin%ss') AS comment_date_french_fashion " .
		"FROM comments " .
		"WHERE post_id = :post_id " .
		"ORDER BY comment_date"
	);
	$get_comments_from_post->execute(array(
		'post_id' => $post_id
	));
	
	$comments = $get_comments_from_post->fetchAll();
	
	$get_comments_from_post->closeCursor();
	
	return $comments;
}

?>
<file_sep><?php

$title = 'Admin - Add post';
$form_action = 'add_post.php';

include 'edit_form.php';

?>

<file_sep>Following a (french) PHP [tutorial](14668-concevez-votre-site-web-avec-php-et-mysql.pdf) from [Open Classrooms](http://www.openclassrooms.com)

Tools:
- XAMPP 5.6.8-0 (Apache 2.4.12, PHP 5.6.8, MySQL 5.6.24, phpMyAdmin 4.4.3)

Steps:
- Start Apache from XAMPP's panel
- Synchronize this folder (php_tutorial) in XAMPP's htdocs folder
- Follow one of the following link: [ex1](ex1) [ex2](ex2) [ex3](ex3) [ex4](ex4)
<file_sep><?php

session_start();

$_SESSION = array();

session_destroy();

setcookie('member_nickname', null);
setcookie('member_pwd', null);

header('Location: index.php');

?>

<file_sep><?php

include '../../models/db.php';

function insert_post($title, $content)
{
	global $db;
	
	$insert_post = $db->prepare(
		'INSERT INTO posts(title, content, created_at) ' .
		'VALUES(:title, :content, NOW())'
	);
	$insert_post->execute(array(
		'title' => $title,
		'content' => $content
	));
	$insert_post->closeCursor();
	
	return $db->lastInsertId();
}

?>
<file_sep><!DOCTYPE html>
<html>
	<head>
		<meta charset="utf8" />
		<title>Page not found</title>
	</head>
	
	<body>
		<h1>Page not found</h1>
		<p>We are sorry, but we can't find the page you are looking for.</p>
		<p>
			You should check the URL you entered or return to our
			<a href="<?php echo $SERVER['DOCUMENT_ROOT'] . '/php_tutorial/ex4/'; ?>index.php">Home Page</a>
		</p>
	</body>
</html>

<file_sep><?php

$page_number = -1;

if (isset($_GET['page']))
{
	$page_number = (int) $_GET['page'];
}

if ($page_number < 1)
{
	$page_number = 1; // Display first page by default
}

$offset = ($page_number - 1) * 10;

try
{
	$db = new PDO(
		'mysql:host=localhost;dbname=test;',
		'root',
		'',
		array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
	);
}
catch (Exception $e)
{
	die('ERROR: ' . $e->getMessage());
}

//TODO(find a way to use an integer in prepared statement)
$response = $db->query('SELECT nickname, message FROM chat ORDER BY id DESC LIMIT ' . $offset . ', 10');

$nickname = '';

if (isset($_COOKIE['nickname']))
{
	$nickname = $_COOKIE['nickname'];
}

?>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf8" />
		<title>Chat</title>
	</head>
	
	<body>
		<form action="chat_post.php" method="post">
			Nickname:
			<br/>
			<input type="text" name="nickname" value="<?php echo $nickname; ?>" />
			<br/>
			Message:
			<br/>
			<textarea name="message"/></textarea>
			<br/>
			<input type="submit" value="Send" />
		</form>
		
		<p><a href="chat.php">Refresh</a></p>
		
		<?php while ($data = $response->fetch()) { ?>
			<p>
				<strong><?php echo htmlspecialchars($data['nickname']); ?>:</strong>
				<?php echo htmlspecialchars($data['message']); ?>
			</p>
		<?php } ?>
	</body>
</html>

<?php

$response->closeCursor();

?>

<file_sep><!DOCTYPE html>
<html>
	<head>
		<title><?php echo $title; ?></title>
		<meta charset="utf8" />
		<link rel="stylesheet" type="text/css" href="../style.css" />
	</head>
	
	<body>
		<h1><?php echo $title; ?></h1>
		<a href="../../controllers/blog/index.php">Back to Home Page</a>
		<br/>
		<a href="add.php">Add a new post</a>
		
		<ul class="no-decoration">
			<?php foreach ($posts as $post) { ?>
				<li>
					<!--TODO(how to put "return false;" in a function?)-->
					<form method="get" action="delete.php" onsubmit="confirmDeletion(this); return false;">
						<input type="hidden" name="post_id" value="<?php echo $post['id']; ?>" />
						<input type="submit" value="Delete" />
						<a href="edit.php?post_id=<?php echo $post['id']; ?>">
							<?php echo $post['title']; ?>
						</a>
					</form>
				</li>
			<?php } ?>
		</ul>
	</body>
	<script>
	
	function confirmDeletion(thisParam) {
		if(confirm('Are you sure?'))
			thisParam.submit();
	}
	
	</script>
</html>

<file_sep><!DOCTYPE html>
<html>
	<head>
		<title><?php echo $title; ?></title>
		<meta charset="utf8" />
	</head>
	
	<body>
		<h1><?php echo $title; ?></h1>
		
		<form method="post" action="<?php echo $form_action; ?>">
			<input type="hidden" name="post_id" value="<?php echo $post_id; ?>" />
			Title:
			<br/>
			<input type="text" name="title" value="<?php echo $post['title']; ?>" size="50" />
			<br/>
			Content:
			<br/>
			<textarea name="content" rows="5" cols="100"><?php echo $post['content']; ?></textarea>
			<br/>
			<input type="button" value="Cancel" onclick="goToAdminHomePage()" />
			<input type="submit" value="Save" />
		</form>
	</body>
	
	<script>
	
	function goToAdminHomePage() {
		location.href = '.';
	}
	
	</script>
</html>

<file_sep><?php

include '../../models/blog/comments.php';

$post_id = $_GET['post_id'];

if (isset($post_id))
{
	$post_id = intval($post_id);
	
	$post = get_post($post_id);
	
	if (empty($post))
	{
		include '../../views/404.php';
		exit;
	}
	
	$post['title'] = htmlspecialchars($post['title']);
	$post['content'] = nl2br(htmlspecialchars($post['content']));
	
	$comments = get_comments_from_post($post_id);
	
	foreach($comments as $key => $comment)
	{
		$comments[$key]['author'] = htmlspecialchars($comment['author']);
		$comments[$key]['comment'] = nl2br(htmlspecialchars($comment['comment']));
	}
	
	include '../../views/blog/comments.php';
}

?>
<file_sep><?php

include '../models/add_post.php';
include 'edit_validation.php';

$title = $_POST['title'];
$content = $_POST['content'];

if ($error_msg = validate($title, $content))
{
	include '../views/add_post_error.php';
	exit;
}
else
{
	if ($post_id = insert_post($title, $content))
		header('Location: ../../controllers/blog/comments.php?post_id=' . $post_id);
}

include '../../views/404.php'; // If no posts have been inserted, display error page

?>

<file_sep><?php echo $error_msg; ?>
<a href="edit.php?post_id=<?php echo $post_id; ?>">Try again</a>

<file_sep><?php

include '../../models/db.php';

function get_post($post_id)
{
	global $db;
	
	$get_post = $db->prepare('SELECT * FROM posts WHERE id = :post_id');
	$get_post->execute(array(
		'post_id' => $post_id
	));
	
	$post = $get_post->fetch();
	
	$get_post->closeCursor();
	
	return $post;
}

?>
<file_sep><?php

$pwd = $_POST['pwd'];

if (isset($pwd))
{
	if ($pwd == '<PASSWORD>')
	{
		echo 'Welcome to this restricted area. <br/>' .
		'The secret message is: CONGRATULATIONS!';
	}
	else
	{
		echo 'Wrong password, try again! <br/>'.
		'<a href="secret.php">Enter password</a>';
	}
}
else
{
	echo 'Password required';
}

?>

<file_sep><?php

include '../../models/blog/index.php';

function display_pagination() {
	global $page, $nb_pages;
	
	echo '<p>Page';
	
	for ($i = 1; $i <= $nb_pages; $i++)
	{
		if ($i !== $page)
			echo ' <a href="index.php?page=' . $i . '">' . $i . '</a>';
		else
			echo ' ' . $i;
	}
	
	echo '</p>';
}

session_start();

$member_nickname = '';
$member_pwd = '';
$connected_member_nickname = '';

if (isset($_COOKIE['member_nickname']))
{
	$member_nickname = $_COOKIE['member_nickname'];
}
if (isset($_COOKIE['member_pwd']))
{
	$member_pwd = $_COOKIE['member_pwd'];
}
if (isset($_SESSION['connected_member_nickname']))
{
	$connected_member_nickname = $_SESSION['connected_member_nickname'];
}

if (
	!$connected_member_nickname &&
	$member_nickname &&
	$member_pwd
)
{
	if (check_cookies($member_nickname, $member_pwd))
	{
		$connected_member_nickname = $_SESSION['connected_member_nickname'] = $member_nickname;
	};
}

define('NB_POSTS_PER_PAGE', 5);

$page = 0;

if (isset($_GET['page']))
{
	$page = (int) $_GET['page'];
}

if ($page === 0)
	$page++;

// Get the number of posts
$nb_posts = get_nb_posts();

// Get the number of pages
$remainder = $nb_posts % NB_POSTS_PER_PAGE;
$nb_pages = intval($nb_posts / NB_POSTS_PER_PAGE) + ($remainder > 0 ? 1 : 0);//TODO(use ceil() instead?)

$offset = ($page - 1) * NB_POSTS_PER_PAGE;

$posts = get_posts($offset);//TODO(add NB_POSTS_PER_PAGE as a parameter)

foreach($posts as $key => $post)
{
	$posts[$key]['title'] = htmlspecialchars($post['title']);
	$posts[$key]['content'] = nl2br(htmlspecialchars($post['content']));
}

include '../../views/blog/index.php';

?>
<file_sep><?php

include '../../models/db.php';

function get_pwd($nickname)
{
	global $db;
	
	$get_pwd = $db->prepare(
		'SELECT password ' .
		'FROM members ' .
		'WHERE nickname = :nickname'
	);
	$get_pwd->execute(array(
		'nickname' => $nickname
	));
	
	$hashed_pwd = $get_pwd->fetch();
	
	$get_pwd->closeCursor();
	
	return $hashed_pwd['password'];
}

?>
<file_sep>Read [README.md](README.md) first!

Steps:
- Start MySQL from XAMPP's panel
- Go on http://localhost/phpmyadmin/
- Create test database from [db.sql](db.sql) file
- Follow one of the following link: [ex3](ex3) [ex4](ex4)
<file_sep><?php

include '../../models/db.php';

function list_posts()
{
	global $db;
	
	$list_posts = $db->query('SELECT * FROM posts');
	
	$posts = $list_posts->fetchAll();
	
	$list_posts->closeCursor();
	
	return $posts;
}

?>
<file_sep><?php

include '../../models/blog/signup_post.php';

$nickname = $_POST['nickname'];
$pwd = $_POST['pwd'];
$pwd_again = $_POST['pwd_again'];
$email = $_POST['email'];

function display_error($msg)
{
	include '../../views/blog/signup_post_error.php';
	exit;
}

if (
	isset($nickname) &&
	isset($pwd) &&
	isset($pwd_again) &&
	isset($email)
)
{
	if (strlen($nickname) === 0)
	{
		display_error('Nickname required.');
	}
	if (strlen($pwd) === 0)
	{
		display_error('Password required.');
	}
	
	if (count_identical_nicknames($nickname) > 0)
	{
		display_error(
			'Another member is already using the nickname ' .
			'<strong>' . $nickname . '</strong>. Please choose another one.'
		);
	}
	
	if ($pwd !== $pwd_again)
	{
		display_error('The two passwords are not identical.');
	}
	
	//TODO(replace by official email format specification)
	if (!preg_match('#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,}$#i', $email))
	{
		display_error('Email format is invalid.');
	}
	
	//TODO(what if password_hash() returns FALSE?)
	if (insert_member($nickname, password_hash($pwd, PASSWORD_DEFAULT), $email) === 1)
	{
		include '../../views/blog/signup_post_success.php';
	}
	else
	{
		display_error(
			"We haven't been able to register you. " .
			"We are sorry for the inconvenience."
		);
	}
}
else
{
	header('Location: signup.php');
}

?>

<file_sep>Read [php_tutorial/README_ex3_ex4.md](../README_ex3_ex4.md) first!

Following exercise 2 (page 166)
-------------------------------

Steps:
- Create chat table from [db.sql](db.sql) file
- Go on http://localhost/php_tutorial/ex3/chat.php
<file_sep>CREATE TABLE test.chat (
	id INT PRIMARY KEY AUTO_INCREMENT,
	nickname VARCHAR(255),
	message VARCHAR(255)
);
<file_sep>Read [php_tutorial/README.md](../README.md) first!

Following exercise 1, going further (page 113)
----------------------------------------------

Steps:
- Go on http://localhost/php_tutorial/ex2/secret.php (the correct password is "<PASSWORD>")
<file_sep><?php

include '../models/edit_post.php';
include 'edit_validation.php';

$title = $_POST['title'];
$content = $_POST['content'];
$post_id = (int) $_POST['post_id'];

if ($error_msg = validate($title, $content))
{
	include '../views/edit_post_error.php';
	exit;
}
else
{
	if (update_post($title, $content, $post_id) === 1)
		header('Location: ../../controllers/blog/comments.php?post_id=' . $post_id);
}

//TODO(should not display a "not found" error when there are no changes)
include '../../views/404.php'; // If no posts have been updated, display error page

?>

<file_sep><?php

include '../../models/db.php';

function update_post($title, $content, $post_id)
{
	global $db;
	
	$update_post = $db->prepare(
		'UPDATE posts ' .
		'SET title = :title, content = :content ' .
		'WHERE id = :post_id'
	);
	$update_post->execute(array(
		'title' => $title,
		'content' => $content,
		'post_id' => $post_id
	));
	
	$nb_updated_posts = $update_post->rowCount();
	
	$update_post->closeCursor();
	
	return $nb_updated_posts;
}

?>
<file_sep><?php

if (!isset($post))
{
	$post = array('title' => '', 'content' => '');
}

$post['title'] = htmlspecialchars($post['title']);
$post['content'] = htmlspecialchars($post['content']);

include '../views/edit_form.php';

?>
<file_sep><?php

include '../../models/db.php';

function count_identical_nicknames($nickname)
{
	global $db;
	
	//TODO(check unique constraint instead)
	$count_identical_nicknames = $db->prepare(
		'SELECT COUNT(*) AS nb_identical_nicknames ' .
		'FROM members ' .
		'WHERE nickname = :nickname'
	);
	$count_identical_nicknames->execute(array(
		'nickname' => $nickname
	));
	
	$nb_identical_nicknames = $count_identical_nicknames->fetch();
	
	$count_identical_nicknames->closeCursor();
	
	return $nb_identical_nicknames['nb_identical_nicknames'];
}

function insert_member($nickname, $hashed_pwd, $email)
{
	global $db;
	
	$insert_member = $db->prepare(
		'INSERT INTO members(nickname, password, email, joined_at) '.
		'VALUES(:nickname, :password, :email, NOW())'
	);
	$insert_member->execute(array(
		'nickname' => $nickname,
		'password' => $<PASSWORD>,
		'email' => $email
	));
	
	$nb_inserted_members = $insert_member->rowCount();
	
	$insert_member->closeCursor();
	
	return $nb_inserted_members;
}

?>
<file_sep><?php echo $error_msg; ?>

<a href="../controllers/add.php">Try again</a>

<file_sep><?php

include '../../models/db.php';

function check_cookies($member_nickname, $member_pwd) {
	global $db;
	
	$check_cookies = $db->prepare(
		'SELECT nickname ' .
		'FROM members ' .
		'WHERE nickname = :nickname AND password = :<PASSWORD>'
	);
	$check_cookies->execute(array(
		'nickname' => $member_nickname,
		'password' => $<PASSWORD>
	));
	
	$nickname = $check_cookies->fetch();
	
	$check_cookies->closeCursor();
	
	return $nickname['nickname'];
}

function get_nb_posts() {
	global $db;
	
	$get_nb_posts = $db->query('SELECT COUNT(*) AS nb_posts FROM posts');
	
	$nb_posts = $get_nb_posts->fetch();
	
	$get_nb_posts->closeCursor();
	
	return $nb_posts['nb_posts'];
}

function get_posts($offset) {
	global $db;
	
	$get_posts = $db->prepare("" .
		"SELECT title, id, content, DATE_FORMAT(created_at, '%d/%m/%Y at %Hh%imin%ss') AS created_at_french_fashion " .
		"FROM posts " .
		"ORDER BY created_at DESC " .
		"LIMIT :offset, 5"
	);
	$get_posts->bindParam(':offset', $offset, PDO::PARAM_INT);
	$get_posts->execute();
	
	$posts = $get_posts->fetchAll();
	
	$get_posts->closeCursor();
	
	return $posts;
}

?>
<file_sep><?php

include '../../models/db.php';

function remove_comments_from_post($post_id)
{
	global $db;
	
	//TODO(add constraint on foreign key)
	$remove_comments_from_post = $db->prepare('DELETE FROM comments WHERE post_id = :post_id');
	$remove_comments_from_post->execute(array(
		'post_id' => $post_id
	));
	$remove_comments_from_post->closeCursor();
}

function remove_post($post_id)
{
	global $db;
	
	$remove_post = $db->prepare('DELETE FROM posts WHERE id = :post_id');
	$remove_post->execute(array(
		'post_id' => $post_id
	));
	
	$nb_deleted_posts = $remove_post->rowCount();
	
	$remove_post->closeCursor();
	
	return $nb_deleted_posts;
}

?>
<file_sep><?php

include '../models/edit.php';

$post_id = $_GET['post_id'];

if (isset($post_id))
{
	$post_id = (int) $post_id;
	$post = get_post($post_id);
	
	if (empty($post))
	{
		include '../../views/404.php';
		exit;
	}
	
	$title = 'Admin - Edit post';
	$form_action = 'edit_post.php';
}
else
{
	header('Location: index.php');
}

include 'edit_form.php';

?>

<file_sep><?php

include '../../models/blog/login_post.php';

session_start();

$from = $_POST['from'];
$nickname = $_POST['nickname'];
$pwd = $_POST['pwd'];

$hashed_pwd = get_pwd($nickname);

if (password_verify($pwd, $hashed_pwd))
{
	if ($_POST['stay_connected'])
	{
		setcookie('member_nickname', $nickname, time() + 365 * 24 * 3600, null, null, null, true);
		setcookie('member_pwd', $hashed_pwd, time() + 365 * 24 * 3600, null, null, null, true);
	}
	
	$_SESSION['connected_member_nickname'] = $nickname;
	header('Location: ' . $from);
}
else
{
	include '../../views/blog/login_post_error.php';
}

?>

<file_sep><?php

include '../models/index.php';

$posts = list_posts();

foreach($posts as $key => $post)
{
	$posts[$key]['title'] = htmlspecialchars($post['title']);
}

$title = 'Admin - Posts list';

include '../views/index.php';

?>
<file_sep><!DOCTYPE html>
<html>
	<head>
		<title>My awesome blog!</title>
		<meta charset="utf8" />
		<link rel="stylesheet" href="../../views/blog/style.css" type="text/css" />
	</head>
	
	<body>
		<p>
			<?php if ($connected_member_nickname) { ?>
				Connected as <em><?php echo $connected_member_nickname; ?></em> | <a href="../../controllers/blog/logout.php">Log out</a>
			<?php } else { ?>
				<a href="../../controllers/blog/login.php?from=<?php echo $_SERVER['PHP_SELF']; ?>">Log in</a> | <a href="../../controllers/blog/signup.php">Sign up</a>
			<?php } ?>
			<a class="float-right" href="../../admin/controllers/index.php">Admin section</a>
		</p>
		
		<h1>My awesome blog!</h1>
		<?php display_pagination(); ?>
		
		<?php
		
		foreach ($posts as $post)
		{
		
		?>
			<div class="news">
				<h3>
					<?php echo $post['title']; ?>
					<em>on (french fashion display) <?php echo $post['created_at_french_fashion']; ?></em>
				</h3>
				<p>
					<?php echo $post['content']; ?>
					<br/>
					<a href="comments.php?post_id=<?php echo $post['id']; ?>"><em>Comments</em></a>
				</p>
			</div>
		<?php
		
		}
		
		display_pagination();
		
		?>
	</body>
</html>

<file_sep><?php

include '../../models/db.php';

function insert_comment($post_id, $author, $comment)
{
	global $db;
	
	$insert_comment = $db->prepare(
		'INSERT INTO comments(post_id, author, comment, comment_date)' .
		'VALUES(:post_id, :author, :comment, NOW())'
	);
	
	$insert_comment->execute(array(
		'post_id' => $post_id,
		'author' => $author,
		'comment' => $comment
	));
	
	$insert_comment->closeCursor();
}

?>
<file_sep><?php

include '../models/delete.php';

$post_id = $_GET['post_id'];

if (isset($post_id))
{
	$post_id = (int) $post_id;
	
	remove_comments_from_post($post_id);
	
	if (remove_post($post_id) === 1)
		header('Location: .');
}

include '../../views/404.php'; // If no posts have been deleted, display error page

?>

<file_sep><?php

include '../../models/blog/comments_post.php';

$author = $_POST['author'];
$comment = $_POST['comment'];
$post_id = (int) $_POST['post_id'];//TODO(check that the post_id exists in order to avoid orphan comments)

if (!(
	isset($author) &&
	isset($comment) &&
	strlen($author) > 0 &&
	strlen($comment) > 0
))
{
	include '../../views/blog/comments_post_error.php';
	exit;
}

insert_comment($post_id, $author, $comment);

header('Location: comments.php?post_id=' . $post_id);

?>
<file_sep><?php

try
{
	$db = new PDO(
		'mysql:host=localhost;dbname=test;',
		'root',
		'',
		array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
	);
}
catch (Exception $e)
{
	die('ERROR: ' . $e->getMessage());
}

$nickname = $_POST['nickname'];
$message = $_POST['message'];

if (isset($nickname) && isset($message))
{
	if (strlen($nickname) > 0 && strlen($message) > 0)
	{
		$query = $db->prepare(
			'INSERT INTO chat(nickname, message) VALUES(:nickname, :message)'
		);
		
		$query->execute(array(
			'nickname' => $nickname,
			'message' => $message
		));
		
		$query->closeCursor();
		
		// Retain user's nickname
		setcookie('nickname', $nickname, time() + 60, null, null, null, true);
	}
	else
	{
		echo '<p>You must provide a nickname AND a message!</p>';
		echo '<a href="chat.php">Back</a>';
		
		return; // Avoid header() call
	}
}

header('Location: chat.php');

?>

<file_sep>Read [php_tutorial/README_ex3_ex4.md](../README_ex3_ex4.md) first!

Following exercise 3 (page 186) and 4 (page 265)
------------------------------------------------

Steps:
- Create posts, comments and members tables from [db.sql](db.sql) file
- Edit the file at [admin/.htaccess](admin/.htaccess) according to your server configuration: look for the line starting by AuthUserFile and change the absolute path to .htpasswd file
- Use XAMPP's htpasswd utility (in /Applications/XAMPP/bin on Mac OS) to edit the file at [admin/.htpasswd](admin/.htpasswd) by issuing the following command: htpasswd -b admin/.htpasswd login password
- Go on http://localhost/php_tutorial/ex4/controllers/blog/ (admin section login is "login" and password is "<PASSWORD>")
