Skip to content

Commit d498890

Browse files
author
Merijn
committed
more php8 standard code; created login & register page template; fixed register & login process; include database bootstrap export; fixed css/js includes; added automatic css/js includes w/ same name as controller
1 parent 161f4c0 commit d498890

File tree

17 files changed

+249
-68
lines changed

17 files changed

+249
-68
lines changed

index.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
<?php
2+
declare(strict_types=1);
3+
24
define('DOCROOT', str_replace('/public', '', getcwd()));
3-
define('NOCACHE', (isset($_GET['nocache']) || isset($_GET['NOCACHE']) ? TRUE : FALSE));
4-
define('CLEARCACHE', (isset($_GET['clearcache']) || isset($_GET['CLEARCACHE']) ? TRUE : FALSE));
5+
define('NOCACHE', isset($_GET['nocache']) || isset($_GET['NOCACHE']));
6+
define('CLEARCACHE', isset($_GET['clearcache']) || isset($_GET['CLEARCACHE']));
57

6-
$url = (!empty($_GET['url']) ? $_GET['url'] : '');
8+
$url = filter_input(INPUT_GET, 'url') ?? '';
79

8-
require_once(DOCROOT . '/lib/bootstrap.php');
10+
require_once(DOCROOT . '/lib/bootstrap.php');

lib/shared.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ function redirectNotFound(string $requestUri, ?string $httpReferrer): void
8989
base64_encode($requestUri),
9090
base64_encode($httpReferrer)
9191
));
92-
return;
92+
exit();
9393
}
9494

9595
define('TIMER_START', microtime(true));
9696
setReporting();
97-
callHook($url, $routing, $default);
97+
callHook($url ?? '', $routing ?? [], $default ?? []);

mvc.sql

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
-- phpMyAdmin SQL Dump
2+
-- version 5.2.0
3+
-- https://www.phpmyadmin.net/
4+
--
5+
-- Host: 127.0.0.1
6+
-- Generation Time: Sep 27, 2022 at 02:55 PM
7+
-- Server version: 10.4.24-MariaDB
8+
-- PHP Version: 8.0.19
9+
10+
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
11+
START TRANSACTION;
12+
SET time_zone = "+00:00";
13+
14+
15+
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
16+
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
17+
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
18+
/*!40101 SET NAMES utf8mb4 */;
19+
20+
--
21+
-- Database: `mvc`
22+
--
23+
24+
-- --------------------------------------------------------
25+
26+
--
27+
-- Table structure for table `user`
28+
--
29+
30+
CREATE TABLE `user` (
31+
`id` int(11) NOT NULL,
32+
`username` varchar(64) NOT NULL,
33+
`email` varchar(128) DEFAULT NULL,
34+
`passwordhash` varchar(128) NOT NULL,
35+
`enabled` tinyint(1) NOT NULL DEFAULT 1,
36+
`roles` text DEFAULT NULL,
37+
`registered_date` datetime NOT NULL,
38+
`last_login` datetime DEFAULT NULL
39+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
40+
41+
--
42+
-- Indexes for table `user`
43+
--
44+
ALTER TABLE `user`
45+
ADD PRIMARY KEY (`id`),
46+
ADD UNIQUE KEY `username` (`username`);
47+
48+
--
49+
-- AUTO_INCREMENT for dumped tables
50+
--
51+
52+
--
53+
-- AUTO_INCREMENT for table `user`
54+
--
55+
ALTER TABLE `user`
56+
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
57+
COMMIT;
58+
59+
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
60+
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
61+
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

public/css/login.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/* place custom css for Login controller pages here */

public/css/mvc.css

Whitespace-only changes.

public/js/mvc.js

Whitespace-only changes.

src/Controller/Login.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77

88
class Login extends Controller {
99

10-
public function index() {
11-
12-
if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') === 'POST')
13-
{
10+
public function index()
11+
{
12+
if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') === 'POST') {
1413
$username = filter_input(INPUT_POST, 'username');
1514
$password = filter_input(INPUT_POST, 'password');
1615

src/Controller/Register.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,21 @@ public function index() {
1313
if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') === 'POST') {
1414
try {
1515
$username = filter_input(INPUT_POST, 'username');
16+
$email = filter_input(INPUT_POST, 'email');
1617
$password = filter_input(INPUT_POST, 'password');
1718
$passwordVerify = filter_input(INPUT_POST, 'passwordVerify');
1819
$admin = filter_input(INPUT_POST, 'admin');
1920

20-
if ($this->model->validate($username, $password, $passwordVerify)) {
21-
if ($this->model->registerAndLogin($username, $password, $admin)) {
21+
if ($this->model->validate($username, $email, $password, $passwordVerify)) {
22+
if ($this->model->registerAndLogin($username, $email, $password, $admin)) {
2223

2324
$this->setDelayedInfo('Registration successful.');
2425
$this->redirect('/');
2526
} else {
2627
$this->setError('Registration failed.');
2728
$this->set('post', [
2829
'username' => $username,
30+
'email' => $email,
2931
'password' => $password,
3032
'passwordVerify' => $passwordVerify,
3133
]);
@@ -35,6 +37,7 @@ public function index() {
3537
$this->setError($e->getMessage());
3638
$this->set('post', [
3739
'username' => $username,
40+
'email' => $email,
3841
'password' => $password,
3942
'passwordVerify' => $passwordVerify,
4043
]);

src/Lib/Controller.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public function setDelayedMessage($sType, $sMessage): void
123123
}
124124

125125
//wrapper call for including css
126-
public function includeCss($content): void
126+
public function includeCss(string $content): void
127127
{
128128
$this->_template->includeExternal('css', $content);
129129
}

src/Lib/Template.php

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<?php
2+
declare(strict_types=1);
3+
24
namespace MVC\Lib;
35

46
use Twig\Loader\FilesystemLoader;
@@ -12,23 +14,24 @@ class Template {
1214

1315
protected $twig;
1416

15-
protected $variables = array();
16-
private $includes = array('css' => array(), 'js' => array());
17+
protected $variables = [];
18+
private $includes = ['css' => [], 'js' => []];
1719

18-
public function __construct($controller, $action) {
20+
public function __construct($controller, $action)
21+
{
1922
$this->_controller = $controller;
2023
$this->_action = $action;
2124

2225
$twig_loader = new FilesystemLoader(DOCROOT . '/view');
2326
$this->twig = new Environment($twig_loader, [
24-
'cache' => (defined('ENV') && ENV == 'prod' ? DOCROOT . '/cache' : FALSE),
27+
'cache' => (defined('ENV') && ENV == 'prod' ? DOCROOT . '/cache' : false),
2528
'debug' => !(defined('ENV') && ENV == 'prod'),
2629
]);
2730
$this->twig->addExtension(new DebugExtension());
2831
}
2932

30-
public function set($name, $value = FALSE) {
31-
33+
public function set($name, $value = false)
34+
{
3235
if (is_array($name)) {
3336
foreach ($name as $key => $value) {
3437
$this->variables[$key] = $value;
@@ -38,12 +41,12 @@ public function set($name, $value = FALSE) {
3841
}
3942
}
4043

41-
public function get($name) {
42-
44+
public function get($name)
45+
{
4346
if (!empty($this->variables[$name])) {
4447
return $this->variables[$name];
4548
} else {
46-
return FALSE;
49+
return false;
4750
}
4851
}
4952

@@ -52,13 +55,15 @@ public function get($name) {
5255
* @param string $type either 'css' or 'js'
5356
* @param string $content either a filename (relative path to /public), an url (js only) or inline content
5457
*/
55-
public function includeExternal($type, $content) {
58+
public function includeExternal(string $type, string $content)
59+
{
5660
$this->includes[$type][] = $content;
5761
}
5862

5963
//called in template
60-
private function getCss() {
61-
$return = array();
64+
private function getCss(): string
65+
{
66+
$return = [];
6267
foreach ($this->includes['css'] as $content) {
6368
if (is_file(DOCROOT . '/public' . $content)) {
6469
//content is a file, create <link> tag
@@ -72,8 +77,9 @@ private function getCss() {
7277
}
7378

7479
//called in template
75-
private function getJs() {
76-
$return = array();
80+
private function getJs(): string
81+
{
82+
$return = [];
7783
foreach ($this->includes['js'] as $content) {
7884
if (is_file(DOCROOT . '/public' . $content)) {
7985
//content is a local file, create <script src="./.."> tag
@@ -90,21 +96,32 @@ private function getJs() {
9096
}
9197

9298
//render the page
93-
public function fetch() {
94-
99+
public function fetch(): string
100+
{
95101
if (!is_file(DOCROOT . '/view/' . $this->_controller . '/' . $this->_action . '.twig')) {
102+
die('view not found: ' . DOCROOT . "/view/{$this->_controller}/{$this->_action}.twig");
96103
Controller::redirect(sprintf('/errorpage/error500/%s/%s',
97104
base64_encode(sprintf('/%s/%s', $this->_controller, $this->_action)),
98105
base64_encode($_SERVER['HTTP_REFERER'] ?? '')
99106
));
100107
}
101108

109+
//auto-include css and js for this controller
110+
if (is_file(DOCROOT . '/public/css/' . $this->_controller . '.css')) {
111+
$this->includeExternal('css', '/css/' . $this->_controller . '.css');
112+
}
113+
if (is_file(DOCROOT . '/public/js/' . $this->_controller . '.js')) {
114+
$this->includeExternal('js', '/js/' . $this->_controller . '.js');
115+
}
116+
117+
$this->variables['included_css'] = $this->getCss();
118+
$this->variables['included_js'] = $this->getJs();
102119
return $this->twig->render($this->_controller . '/' . $this->_action . '.twig', $this->variables);
103120
}
104121

105122
//display the page
106-
public function render() {
107-
123+
public function render(): void
124+
{
108125
echo $this->fetch();
109126
}
110127
}

src/Model/Login.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,11 @@ public function login(string $username, string $password) {
1818
FROM user
1919
WHERE username = :username
2020
AND enabled = 1
21-
AND locked = 0
22-
AND expired = 0
23-
AND credentials_expired = 0
2421
LIMIT 1',
2522
[':username' => $username]
2623
);
2724

28-
if ($user && password_verify($password, $user['password'])) {
25+
if ($user && password_verify($password, $user['passwordhash'])) {
2926

3027
$this->sql->fquery('
3128
UPDATE user

src/Model/Register.php

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33

44
namespace MVC\Model;
55

6-
use MVC\Lib\Model;
76
use Exception;
7+
use MVC\Lib\Model;
88

99
class Register extends Model {
1010

11-
public function validate(string $username, string $password, string $passwordVerify) {
11+
public function validate(string $username, string $email, string $password, string $passwordVerify) {
1212

13-
if ($this->userExists($username) && !$_SESSION['user']['username'] == $username) {
14-
throw new Exception('This email address is already taken.');
13+
if ($this->userExists($username, $email) && isset($_SESSION['user']) && $_SESSION['user']['username'] !== $username) {
14+
throw new Exception('This username or email address is already taken.');
1515

16-
} elseif (!validEmailSyntax($username)) {
16+
} elseif (!$this->validateEmailSyntax($email)) {
1717
throw new Exception('Email adress is invalid.');
1818

1919
} elseif (empty($password) || empty($passwordVerify)) {
@@ -26,21 +26,31 @@ public function validate(string $username, string $password, string $passwordVer
2626
return true;
2727
}
2828

29-
private function userExists($sUsername) {
29+
private function validateEmailSyntax($email): bool
30+
{
31+
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
32+
}
3033

31-
return $this->sql->fetch_single('
34+
private function userExists(string $username, string $email): bool
35+
{
36+
$result = $this->sql->fetch_single('
3237
SELECT *
3338
FROM user
3439
WHERE username = :username
35-
OR email = :username
40+
OR email = :email
3641
LIMIT 1',
37-
[':username' => $sUsername]
42+
[
43+
':username' => $username,
44+
':email' => $email
45+
]
3846
);
39-
}
4047

41-
public function registerAndLogin(string $username, string $password, string $admin) {
48+
return is_countable($result) && count($result) > 0;
49+
}
4250

43-
$userId = $this->register($username, $password, !empty($admin));
51+
public function registerAndLogin(string $username, string $email, string $password, ?string $admin): bool
52+
{
53+
$userId = $this->register($username, $email, $password, !empty($admin));
4454

4555
if ($userId) {
4656
return $this->login($username, $password);
@@ -49,27 +59,22 @@ public function registerAndLogin(string $username, string $password, string $adm
4959
return false;
5060
}
5161

52-
private function register(string $username, string $password, $bAdmin = false)
62+
private function register(string $username, string $email, string $password, bool $isAdmin = false)
5363
{
54-
$sUsername = $username;
55-
$sPassword = $password;
56-
57-
$sHash = password_hash($sPassword, PASSWORD_BCRYPT, ['cost' => 12]);
64+
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
5865

5966
$roles = ['ROLE_USER'];
60-
if ($bAdmin) {
67+
if ($isAdmin) {
6168
$roles[] = 'ROLE_SUPER_ADMIN';
6269
}
6370

6471
return $this->sql->fquery('
65-
INSERT INTO user
66-
(username, email, enabled, salt, password, locked, expired, roles, credentials_expired)
67-
VALUES
68-
(:username, :email, 1, "", :password, 0, 0, :roles, 0)',
72+
INSERT INTO user (username, email, passwordHash, enabled, roles, registered_date)
73+
VALUES (:username, :email, :password, 1, :roles, NOW())',
6974
[
70-
':username' => $sUsername,
71-
':email' => $sUsername,
72-
':password' => $sHash,
75+
':username' => $username,
76+
':email' => $email,
77+
':password' => $hash,
7378
':roles' => serialize($roles),
7479
]
7580
);

0 commit comments

Comments
 (0)