I hope you’re looking forward to a new lesson. For today I prepared few important changes. For the first – this is a new login and registration system for our script, the second – since today we are going to use database to keep information about members, photos, and for future comments. Now, you need to log in to be able to upload photos. Today I’ll publish all updated files of our script, in case if you want to investigate everything at your local computer – you always can download full package with sources.
Now you can check our demo and download the sources here:
[sociallocker]
[/sociallocker]
Step 1. SQL
To better understand how it works – let’s look at all the new database tables:
01 |
CREATE TABLE `pd_profiles` ( |
02 |
`id` int(10) unsigned NOT NULL auto_increment, |
03 |
`first_name` varchar(255) NOT NULL default '', |
04 |
`last_name` varchar(255) NOT NULL default '', |
05 |
`email` varchar(255) NOT NULL default '', |
06 |
`password` varchar(40) NOT NULL default '', |
07 |
`salt` varchar(10) NOT NULL default '', |
08 |
`status` enum('active','passive') NOT NULL default 'active', |
09 |
`role` tinyint(4) unsigned NOT NULL default '1', |
10 |
`date_reg` datetime NOT NULL default '0000-00-00 00:00:00', |
12 |
) ENGINE=MyISAM DEFAULT CHARSET=utf8; |
13 |
INSERT INTO `pd_profiles` (`first_name`, `last_name`, `email`, `password`, `salt`, `status`, `role`, `date_reg`) VALUES |
14 |
('test user first name', 'test user last name', '[email protected]', 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'testing', 'active', 1, NOW()), |
15 |
('moderator first name', 'moderator last name', '[email protected]', 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'testing', 'active', 2, NOW()), |
16 |
('admin first name', 'admin last name', '[email protected]', 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'testing', 'active', 3, NOW()), |
17 |
('test user 2 first name', 'test user 2 last name', '[email protected]', 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'testing', 'active', 1, NOW()); |
18 |
CREATE TABLE IF NOT EXISTS `pd_photos` ( |
19 |
`id` int(10) unsigned NOT NULL auto_increment, |
20 |
`title` varchar(255) default '', |
21 |
`filename` varchar(255) default '', |
22 |
`owner` int(11) NOT NULL, |
23 |
`when` int(11) NOT NULL default '0', |
24 |
`comments_count` int(11) NOT NULL default '0', |
26 |
) ENGINE=MyISAM DEFAULT CHARSET=utf8; |
27 |
INSERT INTO `pd_photos` (`title`, `filename`, `owner`, `when`) VALUES |
28 |
('Item #1', 'pic1.jpg', 1, UNIX_TIMESTAMP()), |
29 |
('Item #2', 'pic2.jpg', 2, UNIX_TIMESTAMP()+1), |
30 |
('Item #3', 'pic3.jpg', 3, UNIX_TIMESTAMP()+2), |
31 |
('Item #4', 'pic4.jpg', 4, UNIX_TIMESTAMP()+3); |
32 |
CREATE TABLE IF NOT EXISTS `pd_items_cmts` ( |
33 |
`c_id` int(11) NOT NULL AUTO_INCREMENT , |
34 |
`c_item_id` int(12) NOT NULL default '0', |
35 |
`c_ip` varchar(20) default NULL, |
36 |
`c_name` varchar(64) default '', |
37 |
`c_text` text NOT NULL , |
38 |
`c_when` int(11) NOT NULL default '0', |
40 |
KEY `c_item_id` (`c_item_id`) |
41 |
) ENGINE=MYISAM DEFAULT CHARSET=utf8; |
There are three tables, the first one (pd_profiles) keeps information about members, the second one (pd_photos) keep info about all photos, and the third one is for comments. Please pay attention, that all members have the same password: ‘password’. You have to use email and password to login into system.
Step 2. HTML
I made small corrections in our ‘index.html’ template file. As you know, we don’t have to display upload form for usual visitors, it is only for logged in members. But, we have to display login and join forms for visitors. Please look at updated html markup of our index page:
templates/index.html
04 |
< meta charset = "utf-8" /> |
05 |
< meta name = "author" content = "Script Tutorials" /> |
06 |
< title >How to create Pinterest-like script - step 3 | Script Tutorials</ title > |
08 |
< link href = "css/main.css" rel = "stylesheet" type = "text/css" /> |
09 |
< link href = "css/colorbox.css" rel = "stylesheet" type = "text/css" /> |
11 |
< script src = "js/jquery.min.js" ></ script > |
12 |
< script src = "js/jquery.colorbox-min.js" ></ script > |
13 |
< script src = "js/jquery.masonry.min.js" ></ script > |
14 |
< script src = "js/script.js" ></ script > |
18 |
< div class = "header_panel" > |
20 |
< a href = "#" class = "logo" ></ a > |
22 |
< form action = "" method = "get" class = "search" > |
23 |
< input autocomplete = "off" name = "q" size = "27" placeholder = "Search" type = "text" /> |
24 |
< input name = "search" type = "submit" /> |
29 |
< a href = "#" >About< span ></ span ></ a > |
31 |
< li >< a href = "#" >Help</ a ></ li > |
32 |
< li >< a href = "#" >Pin It Button</ a ></ li > |
33 |
< li >< a href = "#" target = "_blank" >For Businesses</ a ></ li > |
34 |
< li class = "div" >< a href = "#" >Careers</ a ></ li > |
35 |
< li >< a href = "#" >Team</ a ></ li > |
36 |
< li >< a href = "#" >Blog</ a ></ li > |
37 |
< li class = "div" >< a href = "#" >Terms of Service</ a ></ li > |
38 |
< li >< a href = "#" >Privacy Policy</ a ></ li > |
39 |
< li >< a href = "#" >Copyright</ a ></ li > |
40 |
< li >< a href = "#" >Trademark</ a ></ li > |
51 |
< div class = "main_container" > |
As you see – I added two new template keys: {menu_elements} – this keys will contain extra join and login forms for visitors, and Upload, Profile and Logout menu elements for logged-in members. Our new key {extra_data} contains join and login forms for visitors, and upload form for members. All these forms – pure CSS-driven forms.
Step 3. PHP
As you might imagine – all our php files were modified. Let’s start with main index file:
index.php
02 |
if (version_compare(phpversion(), '5.3.0' , '>=' ) == 1) |
03 |
error_reporting (E_ALL & ~E_NOTICE & ~E_DEPRECATED); |
05 |
error_reporting (E_ALL & ~E_NOTICE); |
06 |
require_once ( 'classes/CMySQL.php' ); |
07 |
require_once ( 'classes/CMembers.php' ); |
08 |
require_once ( 'classes/CPhotos.php' ); |
10 |
list ( $sLoginMenu , $sExtra ) = $GLOBALS [ 'CMembers' ]->getLoginData(); |
12 |
$sPhotos = $GLOBALS [ 'CPhotos' ]->getAllPhotos(); |
15 |
'{menu_elements}' => $sLoginMenu , |
16 |
'{extra_data}' => $sExtra , |
17 |
'{images_set}' => $sPhotos |
19 |
echo strtr ( file_get_contents ( 'templates/index.html' ), $aKeys ); |
As you see – it is much smaller now. But in the same time you can see that I added three new classes: CMySQL (to work with database), CMembers (to work with members) and CPhotos (to work with photos). Well, this file displays Login and Join forms for visitors and Upload form for active members. Also, we display all photos at this page. The second updated file is:
service.php
02 |
if (version_compare(phpversion(), '5.3.0' , '>=' ) == 1) |
03 |
error_reporting (E_ALL & ~E_NOTICE & ~E_DEPRECATED); |
05 |
error_reporting (E_ALL & ~E_NOTICE); |
06 |
require_once ( 'classes/CMySQL.php' ); |
07 |
require_once ( 'classes/CMembers.php' ); |
08 |
require_once ( 'classes/CPhotos.php' ); |
09 |
if (! isset( $_SESSION [ 'member_id' ]) && $_POST [ 'Join' ] == 'Join' ) { |
10 |
$GLOBALS [ 'CMembers' ]->registerProfile(); |
12 |
$i = (int) $_GET [ 'id' ]; |
14 |
header( 'Location: error.php' ); |
17 |
$aPhotoInfo = $GLOBALS [ 'CPhotos' ]->getPhotoInfo( $i ); |
18 |
$aOwnerInfo = $GLOBALS [ 'CMembers' ]->getProfileInfo( $aPhotoInfo [ 'owner' ]); |
19 |
$sOwnerName = ( $aOwnerInfo [ 'first_name' ]) ? $aOwnerInfo [ 'first_name' ] : $aOwnerInfo [ 'email' ]; |
20 |
$sPhotoTitle = $aPhotoInfo [ 'title' ]; |
21 |
$sPhotoDate = $GLOBALS [ 'CPhotos' ]->formatTime( $aPhotoInfo [ 'when' ]); |
23 |
$sFullImgPath = $sFolder . 'f_' . $aPhotoInfo [ 'filename' ]; |
25 |
<div class = "pin bigpin" > |
27 |
<a href= "#" class = "button follow_button" >Follow</a> |
28 |
<a target= "_blank" class = "owner_img" href= "#" > |
29 |
<img alt= "<?= $sOwnerName ?>" src= "images/avatar.jpg" /> |
31 |
<p class = "owner_name" ><a target= "_blank" href= "#" ><?= $sOwnerName ?></a></p> |
32 |
<p class = "owner_when" >Uploaded on <?= $sPhotoDate ?></p> |
36 |
<a href= "#" class = "button" >Repin</a> |
37 |
<a href= "#" class = "button" >Like</a> |
39 |
<a class = "image" href= "#" title= "<?= $sPhotoTitle ?>" > |
40 |
<img alt= "<?= $sPhotoTitle ?>" src= "<?= $sFullImgPath ?>" > |
43 |
<p class = "desc" ><?= $sPhotoTitle ?></p> |
44 |
<div class = "comments" ></div> |
45 |
<form class = "comment" method= "post" action= "#" > |
46 |
<input type= "hidden" name= "id" value= "0" /> |
47 |
<textarea placeholder= "Add a comment..." maxlength= "1000" ></textarea> |
48 |
<button type= "button" class = "button" >Comment</button> |
I just added an user registration. In addition, we do not need to pass the full name of the file to see larger version. Instead, we pass the image ID. The next updated file is uploader:
upload.php
02 |
if (version_compare(phpversion(), '5.3.0' , '>=' ) == 1) |
03 |
error_reporting (E_ALL & ~E_NOTICE & ~E_DEPRECATED); |
05 |
error_reporting (E_ALL & ~E_NOTICE); |
06 |
require_once ( 'classes/CMySQL.php' ); |
07 |
require_once ( 'classes/CMembers.php' ); |
08 |
require_once ( 'classes/CPhotos.php' ); |
09 |
function uploadImageFile() { |
12 |
if ( $_SERVER [ 'REQUEST_METHOD' ] == 'POST' ) { |
13 |
$iWidth = $iHeight = $iFDefWidth ; |
17 |
if (! $_FILES [ 'image_file' ][ 'error' ] && $_FILES [ 'image_file' ][ 'size' ] < 400 * 1024) { |
18 |
if ( is_uploaded_file ( $_FILES [ 'image_file' ][ 'tmp_name' ])) { |
20 |
$sTempFileName = 'photos/' . md5(time().rand()); |
22 |
move_uploaded_file( $_FILES [ 'image_file' ][ 'tmp_name' ], $sTempFileName ); |
24 |
@ chmod ( $sTempFileName , 0644); |
26 |
if ( file_exists ( $sTempFileName ) && filesize ( $sTempFileName ) > 0) { |
27 |
$aSize = getimagesize ( $sTempFileName ); |
29 |
@unlink( $sTempFileName ); |
36 |
$vImg = @imagecreatefromjpeg( $sTempFileName ); |
40 |
$vImg = @imagecreatefrompng( $sTempFileName ); |
43 |
@unlink( $sTempFileName ); |
47 |
$iSrcWidth = imagesx( $vImg ); |
48 |
$iSrcHeight = imagesy( $vImg ); |
50 |
$iHeight = $iSrcHeight * $iWidth / $iSrcWidth ; |
52 |
$vDstImg = @imagecreatetruecolor( $iWidth , $iHeight ); |
54 |
imagecopyresampled( $vDstImg , $vImg , 0, 0, 0, 0, $iWidth , $iHeight , $iSrcWidth , $iSrcHeight ); |
56 |
$iLastId = $GLOBALS [ 'CPhotos' ]->insertBlankPhoto( $_FILES [ 'image_file' ][ 'name' ], $_SESSION [ 'member_id' ]); |
58 |
$sResultFileName = 'photos/f_pic' . $iLastId . $sExt ; |
60 |
$GLOBALS [ 'CPhotos' ]->updateFilename( $iLastId , 'pic' . $iLastId . $sExt ); |
62 |
imagejpeg( $vDstImg , $sResultFileName , $iJpgQuality ); |
63 |
@ chmod ( $sResultFileName , 0644); |
66 |
$iHeight = $iSrcHeight * $iWidth / $iSrcWidth ; |
67 |
$vDstThImg = @imagecreatetruecolor( $iWidth , $iHeight ); |
68 |
imagecopyresampled( $vDstThImg , $vImg , 0, 0, 0, 0, $iWidth , $iHeight , $iSrcWidth , $iSrcHeight ); |
69 |
$sResultThumnName = 'photos/pic' . $iLastId . $sExt ; |
70 |
imagejpeg( $vDstThImg , $sResultThumnName , $iJpgQuality ); |
71 |
@ chmod ( $sResultThumnName , 0644); |
73 |
@unlink( $sTempFileName ); |
74 |
return $sResultFileName ; |
82 |
if ( $_SESSION [ 'member_id' ] && $_SESSION [ 'member_status' ] == 'active' && $_SESSION [ 'member_role' ]) { |
83 |
$sImage = uploadImageFile(); |
Now, only logged members can upload photos (as I told in the beginning). Well, I think that now it is important to review all our new classes as well:
classes/CMembers.php
006 |
function CMembers() { |
010 |
function getLoginData() { |
011 |
if (isset( $_GET [ 'logout' ])) { |
012 |
if (isset( $_SESSION [ 'member_email' ]) && isset( $_SESSION [ 'member_pass' ])) |
013 |
$this ->performLogout(); |
015 |
if ( $_POST && $_POST [ 'email' ] && $_POST [ 'password' ]) { |
016 |
if ( $this ->checkLogin( $_POST [ 'email' ], $_POST [ 'password' ], false)) { |
017 |
$this ->performLogin( $_POST [ 'email' ], $_POST [ 'password' ]); |
018 |
header( 'Location: index.php' ); |
022 |
if (isset( $_SESSION [ 'member_email' ]) && $_SESSION [ 'member_email' ] && $_SESSION [ 'member_pass' ]) { |
024 |
'{name}' => $_SESSION [ 'member_email' ], |
025 |
'{status}' => $_SESSION [ 'member_status' ], |
026 |
'{role}' => $_SESSION [ 'member_role' ], |
030 |
<li><a href= "#add_form" id= "add_pop" >Add +</a></li> |
032 |
<a href= "#" >Profile<span></span></a> |
034 |
<li><a href= "#" >Invite Friends</a></li> |
035 |
<li><a href= "#" >Find Friends</a></li> |
036 |
<li class = "div" ><a href= "#" >Boards</a></li> |
037 |
<li><a href= "#" >Pins</a></li> |
038 |
<li><a href= "#" >Likes</a></li> |
039 |
<li class = "div" ><a href= "#" >Settings</a></li> |
040 |
<li><a href= "#" >Logout</a></li> |
043 |
<li><a href= "index.php?logout" >Logout</a></li> |
047 |
<a href= "#x" class = "overlay" id= "add_form" ></a> |
050 |
<a class = "close" href= "#close" >x</a> |
051 |
<h2>Upload a Pin</h2> |
053 |
<form id= "upload_form" > |
054 |
<input type= "file" name= "image_file" id= "image_file" onchange= "" /> |
056 |
<div id= "upload_result" ></div> |
059 |
return array ( $sLoginMenu , $sExtra ); |
064 |
<li><a href= "#join_form" id= "join_pop" >Join</a></li> |
065 |
<li><a href= "#login_form" id= "login_pop" >Login</a></li> |
069 |
<a href= "#x" class = "overlay2" id= "join_form" ></a> |
072 |
<a class = "close" href= "#close" >x</a> |
073 |
<h2>Create your account</h2> |
075 |
<form method= "POST" action= "service.php" > |
076 |
<ul class = "ctrl_grp" > |
078 |
<input type= "text" name= "email" /> |
079 |
<label>Email Address</label> |
080 |
<span class = "fff" ></span> |
083 |
<input type= "password" name= "password" /> |
084 |
<label>Password</label> |
085 |
<span class = "fff" ></span> |
088 |
<input type= "text" name= "first_name" /> |
089 |
<label>First Name</label> |
090 |
<span class = "fff" ></span> |
093 |
<input type= "text" name= "last_name" /> |
094 |
<label>Last Name</label> |
095 |
<span class = "fff" ></span> |
099 |
<input type= "hidden" name= "Join" value= "Join" /> |
100 |
<button class = "submit_button" type= "submit" >Create Account</button> |
105 |
<a href= "#x" class = "overlay3" id= "login_form" ></a> |
108 |
<a class = "close" href= "#close" >x</a> |
111 |
<form method= "POST" action= "index.php" > |
112 |
<ul class = "ctrl_grp" > |
114 |
<input type= "text" name= "email" id= "id_email" > |
116 |
<span class = "fff" ></span> |
119 |
<input type= "password" name= "password" id= "id_password" > |
120 |
<label>Password</label> |
121 |
<span class = "fff" ></span> |
125 |
<button class = "submit_button" type= "submit" >Login</button> |
130 |
return array ( $sLoginMenu , $sExtra ); |
133 |
function performLogin( $sEmail , $sPass ) { |
134 |
$this ->performLogout(); |
136 |
$sEmail = $GLOBALS [ 'MySQL' ]->escape( $sEmail ); |
137 |
$aProfile = $GLOBALS [ 'MySQL' ]->getRow( "SELECT * FROM `pd_profiles` WHERE `email`='{$sEmail}'" ); |
139 |
$iPid = $aProfile [ 'id' ]; |
140 |
$sSalt = $aProfile [ 'salt' ]; |
141 |
$sStatus = $aProfile [ 'status' ]; |
142 |
$sRole = $aProfile [ 'role' ]; |
143 |
$sPass = sha1(md5( $sPass ) . $sSalt ); |
144 |
$_SESSION [ 'member_id' ] = $iPid ; |
145 |
$_SESSION [ 'member_email' ] = $sEmail ; |
146 |
$_SESSION [ 'member_pass' ] = $sPass ; |
147 |
$_SESSION [ 'member_status' ] = $sStatus ; |
148 |
$_SESSION [ 'member_role' ] = $sRole ; |
151 |
function performLogout() { |
152 |
unset( $_SESSION [ 'member_id' ]); |
153 |
unset( $_SESSION [ 'member_email' ]); |
154 |
unset( $_SESSION [ 'member_pass' ]); |
155 |
unset( $_SESSION [ 'member_status' ]); |
156 |
unset( $_SESSION [ 'member_role' ]); |
159 |
function checkLogin( $sEmail , $sPass , $isHash = true) { |
161 |
$sEmail = $GLOBALS [ 'MySQL' ]->escape( $sEmail ); |
162 |
$sPass = $GLOBALS [ 'MySQL' ]->escape( $sPass ); |
163 |
$aProfile = $GLOBALS [ 'MySQL' ]->getRow( "SELECT * FROM `pd_profiles` WHERE `email`='{$sEmail}'" ); |
164 |
$sPassEn = $aProfile [ 'password' ]; |
165 |
if ( $sEmail && $sPass && $sPassEn ) { |
167 |
$sSalt = $aProfile [ 'salt' ]; |
168 |
$sPass = sha1(md5( $sPass ) . $sSalt ); |
170 |
return ( $sPass == $sPassEn ); |
175 |
function registerProfile() { |
176 |
$sFirstname = $GLOBALS [ 'MySQL' ]->escape( $_POST [ 'first_name' ]); |
177 |
$sLastname = $GLOBALS [ 'MySQL' ]->escape( $_POST [ 'last_name' ]); |
178 |
$sEmail = $GLOBALS [ 'MySQL' ]->escape( $_POST [ 'email' ]); |
179 |
$sPassword = $GLOBALS [ 'MySQL' ]->escape( $_POST [ 'password' ]); |
180 |
if ( $sEmail && $sPassword ) { |
182 |
$aProfile = $GLOBALS [ 'MySQL' ]->getRow( "SELECT * FROM `pd_profiles` WHERE `email`='{$sEmail}'" ); |
183 |
if ( $aProfile [ 'id' ] > 0) { |
185 |
header( 'Location: error.php' ); |
188 |
$sSalt = $this ->getRandSaltCode(); |
189 |
$sPass = sha1(md5( $sPassword ) . $sSalt ); |
192 |
INSERT INTO `pd_profiles` SET |
193 |
`first_name` = '{$sFirstname}' , |
194 |
`last_name` = '{$sLastname}' , |
195 |
`email` = '{$sEmail}' , |
196 |
`password` = '{$sPass}' , |
202 |
$GLOBALS [ 'MySQL' ]->res( $sSQL ); |
204 |
$this ->performLogin( $sEmail , $sPassword ); |
206 |
header( 'Location: index.php' ); |
210 |
header( 'Location: error.php' ); |
214 |
function getRandSaltCode( $iLen = 8) { |
216 |
$sChars = '23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ' ; |
217 |
for ( $i = 0; $i < $iLen ; $i ++) { |
218 |
$z = rand(0, strlen ( $sChars ) -1); |
219 |
$sRes .= $sChars [ $z ]; |
224 |
function getProfileInfo( $i ) { |
230 |
$aInfos = $GLOBALS [ 'MySQL' ]->getAll( $sSQL ); |
234 |
$GLOBALS [ 'CMembers' ] = new CMembers(); |
The main members class contains next functions: getLoginData (this functions does several functions: login and logout processing, also it returns Join & Login menu buttons (with forms) and Upload & Logout buttons (with forms) for members), performLogin (to login), performLogout (to logout), checkLogin (to check login information), registerProfile (to register a new member), getRandSaltCode (to get random salt code), getProfileInfo (to get info about certain member). I think that it is enough functions for members for now. As you noticed, I use a new php file: error.php to generate errors, this is the very easy file:
error.php
01 |
require_once ( 'classes/CMySQL.php' ); |
02 |
require_once ( 'classes/CMembers.php' ); |
04 |
list ( $sLoginMenu , $sExtra ) = $GLOBALS [ 'CMembers' ]->getLoginData(); |
07 |
'{menu_elements}' => $sLoginMenu , |
08 |
'{extra_data}' => $sExtra , |
09 |
'{images_set}' => '<center><h1>Error Occurred, please try again</h1></center>' |
11 |
echo strtr ( file_get_contents ( 'templates/index.html' ), $aKeys ); |
…Finally, our last new class for today is:
classes/CPhotos.php
09 |
function getAllPhotos() { |
15 |
$aPhotos = $GLOBALS [ 'MySQL' ]->getAll( $sSQL ); |
18 |
foreach ( $aPhotos as $i => $aPhoto ) { |
19 |
$iPhotoId = (int) $aPhoto [ 'id' ]; |
20 |
$sFile = $aPhoto [ 'filename' ]; |
21 |
$sTitle = $aPhoto [ 'title' ]; |
22 |
$aPathInfo = pathinfo ( $sFolder . $sFile ); |
23 |
$sExt = strtolower ( $aPathInfo [ 'extension' ]); |
25 |
<!-- pin element { $iPhotoId } --> |
28 |
<div class = "actions" pin_id= "{$iPhotoId}" > |
29 |
<a href= "#" class = "button" >Repin</a> |
30 |
<a href= "#" class = "button" >Like</a> |
31 |
<a href= "#" class = "button comment_tr" >Comment</a> |
33 |
<a class = "image ajax" href= "service.php?id={$iPhotoId}" title= "{$sTitle}" > |
34 |
<img alt= "{$sTitle}" src= "{$sFolder}{$sFile}" > |
37 |
<p class = "desc" >{ $sTitle }</p> |
40 |
<span>XX repins</span> |
42 |
<form class = "comment" method= "post" action= "" style= "display: none" > |
43 |
<input type= "hidden" name= "id" value= "0" /> |
44 |
<textarea placeholder= "Add a comment..." maxlength= "1000" ></textarea> |
45 |
<button type= "button" class = "button" >Comment</button> |
53 |
function getPhotoInfo( $i ) { |
54 |
$sSQL = "SELECT * FROM `pd_photos` WHERE `id` = '{$i}'" ; |
55 |
$aInfos = $GLOBALS [ 'MySQL' ]->getAll( $sSQL ); |
59 |
function formatTime( $iSec ) { |
61 |
return gmdate ( $sFormat , $iSec ); |
64 |
function insertBlankPhoto( $sTitle , $iOwner ) { |
65 |
$sTitle = $GLOBALS [ 'MySQL' ]->escape( $sTitle ); |
66 |
$iOwner = (int) $iOwner ; |
67 |
$sSQL = "INSERT INTO `pd_photos` SET `title` = '{$sTitle}', `owner` = '{$iOwner}', `when` = UNIX_TIMESTAMP()" ; |
68 |
$GLOBALS [ 'MySQL' ]->res( $sSQL ); |
69 |
return $GLOBALS [ 'MySQL' ]->lastId(); |
72 |
function updateFilename( $i , $sFilename ) { |
73 |
$sFilename = $GLOBALS [ 'MySQL' ]->escape( $sFilename ); |
74 |
$sSQL = "UPDATE `pd_photos` SET `filename` = '{$sFilename}' WHERE `id`='{$i}'" ; |
75 |
return $GLOBALS [ 'MySQL' ]->res( $sSQL ); |
78 |
$GLOBALS [ 'CPhotos' ] = new CPhotos(); |
There are several more functions like: getAllPhotos (to get all set of photos for our index page), getPhotoInfo (to get info about certain image), formatTime (to format time for bigger popup version), insertBlankPhoto and updateFilename (to add a new image into database and update filename for that image)
Step 4. CSS
In order to handle with two new forms (Join and Login) I had to update a bit popup styles:
css/main.css
02 |
.overlay, .overlay 2 , .overlay 3 { |
03 |
background-color : #FFFFFF ; |
13 |
.overlay:target, .overlay 2: target, .overlay 3: target { |
17 |
background : none repeat scroll 0 0 #FCF9F9 ; |
18 |
border : 1px solid #F7F5F5 ; |
19 |
box-shadow: 0 2px 5px rgba( 34 , 25 , 25 , 0.5 ); |
20 |
display : inline- block ; |
22 |
padding : 30px 30px 20px ; |
28 |
-webkit-transform: translate( -50% , -50% ); |
29 |
-moz-transform: translate( -50% , -50% ); |
30 |
-ms-transform: translate( -50% , -50% ); |
31 |
-o-transform: translate( -50% , -50% ); |
32 |
transform: translate( -50% , -50% ); |
33 |
-webkit-transition: all 0.3 s ease-in-out 0 s; |
34 |
-moz-transition: all 0.3 s ease-in-out 0 s; |
35 |
-ms-transition: all 0.3 s ease-in-out 0 s; |
36 |
-o-transition: all 0.3 s ease-in-out 0 s; |
37 |
transition: all 0.3 s ease-in-out 0 s; |
39 |
.overlay:target+.popup, .overlay 2: target+.popup, .overlay 3: target+.popup { |
And, I added new styles for our new both forms:
05 |
list-style : none outside none ; |
09 |
.ctrl_grp input[type= "text" ], .ctrl_grp input[type= "password" ] { |
10 |
background-color : transparent ; |
11 |
border : 1px solid #AD9C9C ; |
12 |
border-radius: 6px 6px 6px 6px ; |
13 |
box-shadow: 0 1px rgba( 34 , 25 , 25 , 0.15 ) inset , 0 1px #FFFFFF ; |
20 |
transition: all 0.08 s ease-in-out 0 s; |
24 |
.ctrl_grp input[type= "text" ]:focus, .ctrl_grp input[type= "password" ]:focus { |
25 |
border-color : # #993300 ; |
26 |
box-shadow: 0 1px rgba( 34 , 25 , 25 , 0.15 ) inset , 0 1px rgba( 255 , 255 , 255 , 0.8 ), 0 0 14px rgba( 235 , 82 , 82 , 0.35 ); |
29 |
-moz-user-select: none ; |
37 |
transition: all 0.16 s ease-in-out 0 s; |
41 |
background-color : #FFFFFF ; |
42 |
border-radius: 8px 8px 8px 8px ; |
51 |
background-image : -moz-linear-gradient( center top , #FDFAFB , #F9F7F7 50% , #F6F3F4 50% , #F0EDED ); |
52 |
border : 1px solid #BBBBBB ; |
53 |
border-radius: 6px 6px 6px 6px ; |
54 |
box-shadow: 0 1px rgba( 255 , 255 , 255 , 0.8 ), 0 1px rgba( 255 , 255 , 255 , 0.35 ) inset ; |
57 |
display : inline- block ; |
58 |
font-family : "helvetica neue" , arial , sans-serif ; |
63 |
padding : 0.45em 0.825em ; |
65 |
text-shadow : 0 1px rgba( 255 , 255 , 255 , 0.9 ); |
66 |
transition: all 0.05 s ease-in-out 0 s; |
68 |
.submit_button:hover { |
69 |
box-shadow: 0 1px rgba( 255 , 255 , 255 , 0.8 ), 0 1px rgba( 255 , 255 , 255 , 0.35 ) inset , 0 0 10px rgba( 232 , 230 , 230 , 0.75 ); |
Conclusion
We have just finished our third lesson where we writing our own Pinterest-like script. I hope that you like it. It would be kind of you to share our materials with your friends. Good luck and welcome back!