Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

SnowCMS[TPL, PDO, Prepared Statements]

Status
Not open for further replies.
Junior Spellweaver
Joined
May 5, 2012
Messages
110
Reaction score
10
Hi Ragezone,

First I'd like to apologise for stopping the other SnowCMS development but now I'd like to finish it. I'm opening a new development because it's quite different now...

This time i'm going to use PDO with prepared statements, plus there will be no globals. This time I think I really have enough experience to really finish it and have progress.

I will create my own style and there is a template system so you guys can create one yourself easily too.

Well enough of this, let's show off.
Screens:
KevinZuiker - SnowCMS[TPL, PDO, Prepared Statements] - RaGEZONE Forums


KevinZuiker - SnowCMS[TPL, PDO, Prepared Statements] - RaGEZONE Forums


KevinZuiker - SnowCMS[TPL, PDO, Prepared Statements] - RaGEZONE Forums



And some snippets:
Template:
PHP:
<?php
class TPL {
	private static $file, $dir, $variable, $content;
	
	public static function SetDirectory($dir) {
		self::$dir = $dir;
	}
	
	public static function SetFile($file) {
		self::$file = $file;
		
		if(trim($file) == '') {
			$file = 'index';
		}
		
		$file1 = 'data/TPL/' . self::$dir . '/' . $file . '.php';
		$error = 'data/TPL/' . self::$dir . '/error.php';
		 
		if(is_file($file1)) {
			self::$content = file_get_contents($file1);	
		}
		else {
			self::$content = file_get_contents($error);
		}
	}
	
	public static function GetHandler() {
		if(self::$file == '') {
			self::$file = 'index';
		}
		
		$handler = 'data/handlers/'.self::$file.'.php';
		
		if(is_file($handler)) {
			include $handler;
		}
		
		include('data/handlers/main.php');
	}

	public static function SetVariable($key, $value) {
		self::$variable['{'.$key.'}'] = $value;
	}
	
	public static function InitializeVariables() {
		return str_ireplace(array_keys(self::$variable), array_values(self::$variable), self::$content);
	}
	
	public static function Start()	{
		return self::InitializeVariables(self::$content);
	}
}
?>

User class:
PHP:
<?php
class users {	
	
	public static function CheckAccount($name, $pass) {
		$Check = DB::$connect->prepare("SELECT  count(*) FROM users WHERE username = :name AND password = :pass");
		$Check->Execute(array(
			':name' => $name,
			':pass' => Core::Hash($pass)
		));
		$Row = $Check->Fetch();
		return $Row['Count(*)'];
	}
			
	public static function AddUser($name, $pass, $mail) {
		$add = DB::$connect->prepare("INSERT INTO users(username, password, mail, motto) VALUES(:name, :pass, :mail, :motto)");
		return $add->execute(array(
			':name' => $name,
			':pass' => Core::Hash($pass),
			':mail' => $mail,
			':motto' => Config::$motto
		));
	}
	
	public static function ValidMail($mail) {
		return (preg_match("/^[a-zA-Z0-9_\.-]+@([a-zA-Z0-9]+([\-]+[a-zA-Z0-9]+)*\.)+[a-z]{2,7}$/i", $mail) && strlen($mail) >= 3 && strlen($mail) <= 64);
	}
	
	public static function CheckPass($pass) {
		return (strlen($pass) > 3 && strlen($pass) < 10);
	}
	
	public static function GetUser($user) {
		$getuser = DB::$connect->prepare("SELECT count(*) FROM users WHERE username = ?");
		$getuser->execute(array($user));
		$row = $getuser->fetch();
		return $row['count(*)'];
	}
}
?>

Bootstrap:
PHP:
<?php
session_start();

require('core.php');

Core::loadclasses();

DB::connect();

$file = trim($_SERVER['REQUEST_URI'], '/');

TPL::SetDirectory(Config::$style);

TPL::SetFile($file);

TPL::GetHandler();

echo TPL::Start();
?>

If you feel like posting any tips or criticisms, please do.

I hope you guys like this development and will follow it.
 
Last edited:
Junior Spellweaver
Joined
May 5, 2012
Messages
110
Reaction score
10
Simple update:
Made a GetHandler function because using this:
PHP:
		if(trim($file) == '') {
			$file = 'index';
		}
		
		if($file == 'index' || $file == 'register' && isset($_SESSION['user'])) {
			$file = 'me';
		}
		
		if($file != 'index' && $file != 'register' && !isset($_SESSION['user'])) {
			$file = 'index';
		}
		
		if($file == 'logout') {
			session_destroy();
			Core::Load('index');
		}

PHP:
			if($this->CheckFilledIn($username, $password, $password2, $mail)) {
				return '<div id="error">Vul asjeblieft alle velden in!</div><br>';
			}
			
			if($this->GetUser($username)) {
				return '<div id="error">Je naam is al in gebruik!</div><br>';
			}
			
			if($password != $password2) {
				return '<div id="error">Je wachtwoorden komen niet overheen!</div><br>';
			}
			
			if(!$this->CheckPass($password)) {
				return '<div id="error">Je wachtwoord moet tussen 4 en 10 tekens zijn!</div>';
			}
			
			else {
				$this->AddUser($username, $password, $mail);
				$_SESSION['user'] = $username;
				core::Load('me');
			}
In classes is pretty lame...
And I don't want to call this in every file:
PHP:
$TPL->SetVariables('registererror', (isset($_POST['r-username']) ? $user->Register($_POST['r-username'], $_POST['r-password'], $_POST['r-password2'], $_POST['r-mail']) : ''));
$TPL->SetVariables('loginerror', (isset($_POST['username']) ? $user->Login($_POST['username'], $_POST['password']) : ''));
$TPL->SetVariables('username', (isset($_SESSION['user']) ? $_SESSION['user'] : ''));

Well that's it, plus I made a little edit in the /me :p

KevinZuiker - SnowCMS[TPL, PDO, Prepared Statements] - RaGEZONE Forums

I hope you guys like it. :p
 
Joined
Aug 10, 2011
Messages
7,399
Reaction score
3,307
Why you call it this:

Code:
public function GetDirectory($dir) {
        $this->dir = $dir;
    }

Get is usually used to return something and Set to set a value to a variable.

Also why do you have all the variables public? You can directly set a value to that variable so the method 'GetDirectory' is not needed. (Unless you make your variables private which makes more sense.)
 
Junior Spellweaver
Joined
May 5, 2012
Messages
110
Reaction score
10
Updated and cleaned up the classes.
Check first post to see the changes.
 
Last edited:
Junior Spellweaver
Joined
May 5, 2012
Messages
110
Reaction score
10
I use the normal habbo news container so you can simply use the news images of habbo. I know it looks a bit like normal habbo now, but I still think it's nice :p.
This is how it looks with the news container:
KevinZuiker - SnowCMS[TPL, PDO, Prepared Statements] - RaGEZONE Forums

KevinZuiker - SnowCMS[TPL, PDO, Prepared Statements] - RaGEZONE Forums


I will code the article system now.
 
Newbie Spellweaver
Joined
Nov 29, 2011
Messages
57
Reaction score
8
Hmm I quite like the layout of the index and the register that you've chosen, although the login and register buttons on the index look slightly out of alignment, just a simple thing though. I feel as if the me page is lacking something, maybe it's the content boxes I'm frequently used to haha.

Best of luck with your project!
 
I don't even know
Loyal Member
Joined
Apr 7, 2010
Messages
1,699
Reaction score
420
If you keep everything static, then don't bother using OO approach.

Thats the power of object orientated programming.

Actually, why bother using initialized objects when you're not making multiple instances of them. It kind of defeats the purpose of these objects if you're only using one, so you can save yourself some memory and reference-copying by just keeping them static. And the OO approach can still be used to organise functions into static classes, I've seen multiple great CMS'es using this approach.
 
Junior Spellweaver
Joined
May 5, 2012
Messages
110
Reaction score
10
Update:
News container & Articles are working now.

Snippets:

Article:
PHP:
<?php 

$GetTitles = DB::$connect->Prepare("SELECT * FROM cms_news ORDER BY id DESC LIMIT 15");
$GetTitles->Execute();

$titles = Array();

if(!isset($_GET['id'])) {
	$_GET['id'] = '0';
}

while($News = $GetTitles->Fetch()) {
	if($News['id'] == $_GET['id']) {
		$News['title'] = '<b>'.$News['title'].'</b>';
		TPL::SetVariable('title', $News['title']);
	}
	else {
		$News['title'] = '<a href="article?id='.$News['id'].'">'.$News['title'].'</a>';
	}
	$titles[] = $News['title'];
}



$titles = implode('<br>', $titles);

$GetArticle = DB::$connect->Prepare("SELECT * FROM cms_news WHERE id = :id");
$GetArticle->Execute(array(
	':id' => $_GET['id']
));
$Article = $GetArticle->Fetch();


TPL::SetVariable('Titles', $titles);
TPL::SetVariable('Article', $Article['longstory']);
?>

News:
PHP:
<?php
$getnews = DB::$connect->Prepare('SELECT * FROM cms_news ORDER BY id DESC LIMIT 3');
$getnews->execute();

$i = 0;

while($row = $getnews->fetch()) {
	$i++;
	TPL::SetVariable('title-'.$i, $row['title']);
	TPL::SetVariable('shortstory-'.$i, $row['shortstory']);
	TPL::SetVariable('image-'.$i, $row['image']);
	TPL::SetVariable('id-'.$i, $row['id']);
}
?>

I'll post a screen later this day or tomorrow, I have a design, but I have to change the design a bit first.

I'm going to make a housekeeping now.
 
Last edited:
Banned
Banned
Joined
Feb 9, 2007
Messages
1,313
Reaction score
177
The news page doesn't even look nice, and you should really work on your PDO to be honest.
 
I don't even know
Loyal Member
Joined
Apr 7, 2010
Messages
1,699
Reaction score
420
The news page doesn't even look nice
CSS can always be changed later, and this is his first time creating CSS himself, there's always room for improvement later

and you should really work on your PDO to be honest.
What do you mean? He's just not using a framework.. in fact, that's faster than calling $pdo->query() in $pdoframework->query()
 
Junior Spellweaver
Joined
May 5, 2012
Messages
110
Reaction score
10
Update:
I designed the housekeeping, and you can create a news article (still need to add some function), here you can see the design:

KevinZuiker - SnowCMS[TPL, PDO, Prepared Statements] - RaGEZONE Forums

KevinZuiker - SnowCMS[TPL, PDO, Prepared Statements] - RaGEZONE Forums

KevinZuiker - SnowCMS[TPL, PDO, Prepared Statements] - RaGEZONE Forums
 
Junior Spellweaver
Joined
May 5, 2012
Messages
110
Reaction score
10
The background makes me want to throw my computer out of the window. It has so many colors and the background image is just repeating. Maybe you could design a better background rather than using a hotelview image?

Your proably right, I'll look for one. If anyone has a good one, you can post it :p

Edit:

I think this looks way better? :p
KevinZuiker - SnowCMS[TPL, PDO, Prepared Statements] - RaGEZONE Forums
 
Last edited:
Junior Spellweaver
Joined
May 5, 2012
Messages
110
Reaction score
10
Yes it does however I think it will be more rewarding if you create your own background so it suits your theme better and it makes it just a bit more personal. :):

I know but I'm not good at photoshopping :p



Update: Ban system works.

Updated the Login function:
PHP:
	public static function CheckAccount($name, $pass) {
		
		$Check = DB::$connect->prepare("SELECT  count(*) FROM users WHERE username = :name AND password = :pass");
		$Check->Execute(array(
			':name' => $name,
			':pass' => Core::Hash($pass)
		));
		
		$Row = $Check->fetch();
		
		if($Row['count(*)']) {
			$getban = DB::$connect->Prepare("SELECT value, reason, expire FROM bans WHERE value = ?");
			$getban->execute(array($name));
			$BanRow = $getban->Fetch();
		
			if($BanRow !== false) {
				if($BanRow['expire'] > time()) {
					$_SESSION['banned'] = $BanRow;
					return 1;
				}
			}
			
			elseif($BanRow === false) {
				$_SESSION['user'] = $name;
				Core::Load('me');
			}
		}
		
		else {
			return 2;
		}
			
		$DeleteBans = DB::$connect->Prepare('DELETE FROM bans WHERE expire < ?');
		$DeleteBans->Execute(array(time()));
	}

And this is how it looks in the handler file now:
PHP:
<?php
if(isset($_SESSION['user'])) {
	Core::Load('me');
}

if(isset($_POST['username'])) {
	$username = $_POST['username'];
	$password = $_POST['password'];
	
	$errors = Array(
		1 => 'Your banned until '.gmdate('d-m-Y h:i', $_SESSION['banned']['expire']).' | Reason: '.$_SESSION['banned']['reason'].'',
		2 => 'Your username/ password is not correct.'
	);
	
	$geterror = users::CheckAccount($username, $password);
	
	if($geterror == 1) {
		$error = $errors[1];
	}
	
	if($geterror == 2) {
		$error = $errors[2];
	}
}

TPL::SetVariable('loginerror', (isset($error) ? '<div id="error">'.$error.'</div>' : ''));

?>
 
Last edited:
I don't even know
Loyal Member
Joined
Apr 7, 2010
Messages
1,699
Reaction score
420
if($Row['count(*)']) -> if($Row['count(*)'] > 0) is far easier to read and less confusing.
Also, you should put " type = 'name' " in the ban query because you don't want the data from someone with the name 5.6.7.8 to get the reason for the ipban of someone with ip 5.6.7.8. Highly unlikely but still a design flaw.

$BanRow = $getban->Fetch();
if($BanRow !== false) {
} elseif($BanRow === false) {
}

Can be simplified to:
if($getban->Fetch()) {
} else {
}

Also when the ban is expired you're not redirecting the user to /me, your code blocks are kinda strangely ordered, they could be ordered far more efficient.

Put into code:

public static function CheckAccount($name, $pass) {

$Check = DB::$connect->prepare("SELECT count(*) FROM users WHERE username = :name AND password = :pass");
$Check->Execute(array(
':name' => $name,
':pass' => Core::Hash($pass)
));

$Row = $Check->fetch();

if($Row['count(*)'] > 0) {
$getban = DB::$connect->Prepare("SELECT value, reason, expire FROM bans WHERE value = ?");
$getban->execute(array($name));

if($getban->Fetch()) {
if($BanRow['expire'] > time()) {
$_SESSION['banned'] = $BanRow;
return 1;
}
else
{
$DeleteBans = DB::$connect->Prepare('DELETE FROM bans WHERE expire < ?');
$DeleteBans->Execute(array(time()));
}
}

$_SESSION['user'] = $name;
Core::Load('me');
}

return 2;
}

I assume Core::Load has exit in it btw, otherwise you need an extra return after Core::Load('me');
 
Status
Not open for further replies.
Back
Top