Top 10 Reasons Why You Need Microsoft Office 365.

[toc] [/toc]

If you are already using Microsoft Office in your organization, I want to share with you,

Top Ten Reasons Why You Need Microsoft Office 365.

Number 1 – New Apps.

 

The traditional office package came software you installed on each user’s computer.

It included core office apps like Word, Excel, PowerPoint, and Outlook.

Office 365 goes beyond those core applications and adds Skype for Business, OneDrive for business, Microsoft Teams, Yammer, and SharePoint.

It also includes a host of enhanced services such as Delve, Power BI, Sway, Stream, Planner, Flow, and Forms.

All these additional tools make Office 365 more potent than the old version of Microsoft Office.

Office New Apps

 

Number 2 – Portability.

 

Office 365 can be installed on the local system as it has traditionally, but you can run online versions of all the Office applications as well.Every user has access to https://office.com using their Active Directory credentials.

From this portal, you can access Mail, Contacts, your Calendar, or create and edit documents online for Word, Excel, PowerPoint, and other apps.The online capability gives you the mobility you can use anywhere you want to go.

 

Office 365 portability

 

Number 3 – Licensing.

 

You get five licenses per user.Each user has up to 5 phone, five tablets, and 5 PC or Mac installs available. To ensure to allow access to Office applications anytime, anywhere.With one valid Enterprise license, you can install Office 365 at work, at home, and on your mobile devices.

The user or your IT admin can manage these installs, and when a license has removed, the applications are deactivated on those devices as well.If you want to install Office on your home computer, as an example, you log in to the portal from your home computer.

Once you’re there, you can click the Install Apps and select Office 2016 from the list, and it will run an installation file, and it will load all of the Office apps on your home computer so that you can access the shared content and data from your work.

To install on a mobile device, choose Other Install Options and select Phone & Tablet from the menu.Select the type of phone or tablet that you want to install to and down below click Get Apps.

It will give you a choice to enter your email address or phone number and sends it.When you send it to your phone as a text, you click on the link, and it downloads all of the mobile applications for your cell phone.Your mobile apps will have access to the same email and files that you have at work or home.

 

Office Licensing

 

Number 4 – Sharing.

 

Sharing with other users is a cornerstone of Office 365 online. All the apps designed to allow you to share documents both internally and externally.

You can even work on documents live and see other user’s edits in real-time. To ensure you’re using the Excel online version or the word or PowerPoint or another app online, and you can click the Share button to enter the name of somebody’s email address that you want to share to within your organization.

You can also send them a copy of the link or attach this to an Outlook email and send it to them that way. Once they access that file, they’ll be accessing the same data that you’re sharing.

Office 365 Sharing

 

Number 5 – Admin Center.

 

IT support for Office 365 covered through the Admin Center.

As an Office 365 Administrator, you can

  • Add and remove users,
  • Grant licenses to users,
  • Manage groups,
  • Handle billing information,
  • Submit support tickets directly to Microsoft
  • Manage security settings,
  • View report statistics,
  • Check reports on security and compliance,
  • And look at the health dashboard to see how Office 365 apps and connectivity is working.

 

Office 365 Admin Center

 

To see a more detailed walk through of the Admin Center click on the  Office Admin Center Walk through Post

Number 6 – Security.

 

Office 365 has award-winning security built-in.It is the best on the market.

In addition to malware and spam filtering you can enable protection using data loss prevention, multi-factor authentication, advanced threat protection, safely audit logging, and monitor all these threats from the threat management dashboard.

Microsoft provides all these tools built-in with your Office 365 licensing and it is often much more secure than what you can implement on-premise in your environment.

 

O365 Security AndC ompliance

 

Number 7 – Reduced Risk.

 

Your office 365 environment is hosted in the cloud using Azure. Microsoft handles all data center requirements. Microsoft patches servers automatically thus taking the load away from your IT staff.

Active Directory is synced from your on-premise servers to Azure and is available even if your on-premise Active Directory is unreachable. You no longer need to build the redundancy in your on-premise environment.

Microsoft manages it for you in the cloud. You can create secondary DR sites in Azure to protect your data, and online services remain even when a localized event may disrupt your internet connectivity. All these features reduce your risk of disruption and data loss.

 

Office Azure AD

 

Number 8 – Storage.

 

Office 365 gives you plenty of storage capacity for files. OneDrive provides up to 5TB  of storage per user, depending on your enterprise license.

Your IT staff will love the fact that they no longer need to manage this storage space locally. When a user account is disabled files  archived, or they will automatically remove after 30 days, and because those files stored in the cloud. You don’t have to worry about losing data if your laptop is damaged or misplaced.

 

Office storage

 

Number 9 – Automated Updates.

 

You no longer need to install updates on each machine or push out updates using Group Policy, System Center Configuration Manager, or similar management tools. All Office 365 updates are automatic just like Windows updates. As an administrator, you can choose to set up users on the standard release or a Targeted Release.

Most companies set up all users on standard release and then IT staff on the Targeted Release so that they have a chance to test the new features before general rollout to the rest of the organization.

Standard Release is usually a few months after Targeted Release. Either way your applications stay current without intervention and users can continue to run office applications while updates are installing in the background.

 

Office 365 Updates

 

Number 10 – User Self-Management.

 

With on-premise file storage and Exchange servers, everything must maintain your IT team. Shared file locations, email distribution lists, archiving, and security groups created and supported directly by IT.

Using Office 365 this functionality become self-managed. It shifts the convenience and the responsibility to the user. Users can create groups, assign members, set up teams, all without requesting these services from IT.

 

 

Office-365-admin

 

 

Conclusion

I have just shared ten reasons why you need office 365 in your corporate environment. For Office 365 implementations or migrations  or planing it shortly, you may look at  our office consulting  and migration services. Medha Hosting provides Office 365 Consulting, Support, and, Migration services. Just in case you need it check it out here. I do appreciate your support.Please let me know what your thoughts| comments on this are.

Email Migration to Office 365 | Medha Hosting

Office-365-Migration

You want to update your organization’s email platform?

But you don’t want to deal with the downtime, hassle, and headaches of switching?

See how Medha Hosting makes migrating to Microsoft Office 365 email a breeze.

office 365 migration

For starters, your Medha Hosting Account Manager will help you choose the best Office 365 email plan for your business.

Next, you determine the most convenient day and time.

To make the switch from your current email platform to your new Office 365 email.

No matter when it is, the migration process requires no downtime for you or your employees.

Schedule

Medha Hosting will work with you to create each employee’s new email account.

Then your employees will get an email requesting a bit of info that is needed to migrate their email messages, calendar entries, and contacts.

Your Employees,who use Windows Outlook will also receive a link to a user-friendly tool that ensures their email settings move smoothly to their new account.

The actual migration takes place while you and your team go about business as usual.

We do all the heavy lifting for you.

Plus, your Medha Hosting Account Manager will be standing by in case you have any questions or concerns during the process.

azure consulting

When the migration is complete,we will notify, and then everyone on your team can start making the most of their new business-grade email, calendars, and contact management.

Finally, just in case you need it, free ongoing support from Medha Hosting’s team of Office 365 experts is available round-the-clock, seven days a week .No hassle; no headaches!

We don’t say we do; We show it! With 100% responsive call and email support. Check out Office 365 Migration Services Page.

Unlocking the Public Cloud Benefits, Strategies, Challenges, and Solutions

Introduction – Public Cloud

There is no doubt that public clouds are transforming businesses and organizations at nearly every level. Of course, not every organization is there – yet. But those who are, now have the ability to offer great insight to companies considering how to adopt and leverage public clouds or help guide future strategies for those already there.
A year ago, we conducted research that highlighted our understanding of how the cloud became mainstream. This year, we dug deeper across a larger pool of cloud users to find out what they are doing, the challenges they face, and how those challenges are being solved.We found that interest in the public cloud continues to grow: On average, respondents’ have over 40% of their infrastructure in the public cloud, and it appears that this number will increase to 75% in five years. They use services provided by a number of vendors for a variety of reasons, including storage of sensitive data. However, with approximately 50% of firms affected by a cyber attack and another one-third expecting one in the future, security remains a key concern. Only 57% feel their cloud infrastructure is totally secure. The report also illustrates a disconnect between what organizations think they understand about cloud security and the real responsibilities that cloud providers bear. This is reflected in other findings, including how more experienced organizations in the cloud are enhancing security and fixing infrastructure gaps in order to become less prone to attacks; they are also doubling-down on leveraging public clouds.

Demographics

An interview with 300 IT decision makers from organizations across the US using public cloud Infrastructure as a Service (IaaS), widely dispersed across small, medium, and large-sized organizations. The study was part of a global report that analyzed the results of 1,300 interviews with IT leaders worldwide.

Number of employees in US respondents’ organizationsPublic cloud survey

 

Sector of US respondents’ organizations

Public cloud organisation

Key Findings

Public cloud adoption is growing at a rapid rate across industries

Respondents currently run 44% of their infrastructure in the public cloud, with intent to increase to 62% in two years and 76% in five years. Researchers found little discernible difference across vertical segments, with technology organizations understandably a few points above average, while public sector adopters leverage nearly 40% of their infrastructures in public clouds.

Different cloud providers have different strengths

On average, organizations are leveraging three different cloud infrastructures within their overall IT infrastructure. When asked which is the most utilized, Azure leads with 66%, AWS with 46%, and Google Cloud Platform with 36%. The majority of respondents (68%) employ multiple cloud providers because they believe different platforms have different strengths, while 52% feel security is increased through the use of more than one public cloud service provider.

Public clouds offer endless benefits

Ninety-nine percent of respondents report their organizations have seen benefits as a result of moving to the public cloud. While some companies saw 40-50% return on their investment—or even more than 50%—the majority of respondents experienced between 26% and 30% return within their first year of cloud deployments.

Security concerns still prevent widespread cloud adoption

Seventy-four percent of respondents state that security concerns restrict their organizations’migration to the public cloud. In addition, about a quarter of respondents reported that they are concerned over the lack of an expert partner to work with for cloud security (26%), or have a lack of in-house skills to maintain the cloud (23%).

 The Shared Responsibility Model is misunderstood

Although cloud vendors are only responsible for the security of their infrastructures under the shared responsibility model, 77% of respondents believe that public cloud service providers are responsible for securing customer data in the cloud, and 68% suggest public cloud providers are responsible for securing applications running on public clouds.

Organizations lack security measures for proper protection

Despite the lack of clarity around the shared responsibility model, 30% of organizations have not added additional security solutions to their public clouds. Additionally, of those who do have additional security measures in place, 95% of them see a need for added security outside their current scope.

Once in the Cloud, Adoption Soars

Percentage of organizations’ infrastructure running in the public cloud

Percentage of organizations’ infrastructure running in the public cloud

Organizations that have moved their infrastructure to the cloud continue to invest in cloud resources; in five years’ time, their cloud footprints will nearly double. We also looked at different vertical segments across these respondents and found little discernible differences: Technology organizations were understandably a few points ahead of the average, but even public sector adopters have on average nearly 40% of their infrastructures already in public clouds.Are they just using one cloud? The answer is surprising because, on average, organizations leverage three different cloud infrastructures within their overall IT infrastructure. When asked which is the most utilized, we found Azure leads the pack with 66%, AWS with 46%, and Google Cloud Platform with 36%. The reasons for using multiple cloud providers gave more insight into this:

Why do those organizations using more than one public cloud service provider, do so? Asked to those who use more than one (197)

public cloud service provider

The majority of respondents believe that different providers have unique strengths, and are leveraging these cloud providers accordingly. Today, Azure is a dominant player in Info/Sec and IT data centers, whereas AWS has a more significant presence in Dev/Ops. Respondents also believe that leveraging multiple public cloud providers increases security.

However, continuing to use multiple providers will complicate the cloud landscape; further on, we discuss how companies are addressing security issues by mostly leveraging third-party solutions. With multiple infrastructures becoming commonplace, organizations will soon need to look at third parties that can operate inside multiple infrastructures—or their overall IT landscape complexity will grow dramatically, decreasing some of the cloud’s most obvious benefits.

Benefits to Using Public Clouds

Virtually all organizations are gaining benefits from the cloud with 99% stating that they are seeing multiple benefits: The majority reported reduced IT expenditures and greater scalability.Greater agility, less time spent by IT on maintenance, and improved security (both for applications and for infrastructure) are essentially tied at around 45% of all respondents

What benefits have organizations seen from using the public cloud?

Benefits to Using Public Clouds

Respondents noted that better security underscores the fact that the cloud can be made even more secure than on-premises environments — but that protection is not automatic.When asked about returns on cloud expenditures, the majority of companies experience a fairly rapid return on their investments in cloud infrastructure, including services and any third-party solutions added to their cloud infrastructures.

While some organizations saw 40-50% return on their investment, or even more than 50%, the majority of respondents experienced between 26% and 30% return within their first year of cloud deployments. The average ROI is 28.99%.

What positive ROI have organizations seen from using the public cloud?

aws consulting

Also asked how organizations leverage clouds, and what kinds of data they put in public clouds. The responses illustrate that organizations are figuring out public clouds and are learning to navigate security and other concerns.

How do organizations leverage public cloud?

cloud storage

Organizations leverage public clouds for a variety of purposes: The top use is data storage and recovery, followed by website or application hosting. Some organizations use the cloud for data analytics, while others turn to it for desktop virtualization and relationship management systems.Over 40% use the cloud for application testing and development, and over a third for pure development and testing.

What type of sensitive data does your organization store in the public cloud? Asked those who use the public cloud for data storage (257)

 cloud for data storage

Organizations also store sensitive data in the cloud. While employee records and personnel data are among the top sensitive items being stored, organizations are storing business IP in public clouds. Bank details, both for customers and for employees, are included in the sensitive data being stored by organizations in the public cloud.
The responses about sensitive data illustrate a level of trust in cloud security, yet in some ways it’s at odds with organizations’ overall views on security and risks, which we’ll examine next.

Security: Only Partly Understood

The Shared Security Model is standard across all cloud platforms. It states that while the cloud vendor will ensure the security of its infrastructure, organizations are responsible for the security surrounding what they put into the cloud. More than four in five (84%) respondents reported that they fully understand the public cloud security responsibilities of both their organization and IaaS provider and an additional 15% cited that they partly understand public cloud responsibilities.

However, when asked what cloud vendors are responsible for securing, the responses clearly indicate that the Shared Security Model is not fully understood. More than 75% of respondents felt public cloud service providers are responsible for securing customer data in the cloud, and some 68% felt public cloud providers are responsible for securing applications running on their clouds.

However, when asked more directly about security, around three quarters (74%) of those interviewed stated that security concerns restrict their organization’s migration to the public cloud. In addition, the vast majority (89%) of respondents believe that there are threats to their organization’s public cloud infrastructure for securing applications in the public cloud.

What do organizations believe that public cloud service providers have a responsibility to secure? Asked to those who have an understanding of cloud security responsibilities (296)

public cloud service providers

Over nine in ten surveyed IT decision makers (92%) state that they have concerns over their organization’s use of public cloud, with the most likely (58%) being the impact of cyber attacks.In addition, around a quarter of respondents report that they are concerned over the lack of an expert partner to work with for cloud security (26%), or have a lack of in-house skills to maintain the cloud (23%).

What benefits have organizations seen from using the public cloud?

public cloud benefits

If organizations haven’t been targeted yet by a cyber attack, a large majority feel such an attack is imminent. It doesn’t matter whether organizations are large or small, the perceived risk is nearly identical. And while larger organizations tend to report already having been attacked, small organizations are also being attacked. Eighty-eight percent of the organizations who have suffered a cyberattack reported that the attack had measurable negative impacts on their operations. Loss of faith in the public cloud is the most consistent impact, but over 25% of impacted organizations faced either regulatory or compensatory fines as the result of a cyber attack.

Overcoming Security Challenges

It’s very clear from the results of this survey that despite security concerns and the real threat of attacks, organizations continue to leverage the cloud and grow their cloud infrastructures.Two thirds (67%) of respondents say that their organizations have already added some additional security solutions to their public cloud to protect it during access. Additionally, 30% cite that they have not yet, but plan to do so in the future.

Which of the following security solutions have organizations added to their public cloud? Asked to those who have added additional security (200)

public cloud security

When we asked what organizations are doing, two strategies emerged. The most prevalent strategy involved routing traffic to and through a central firewall or other security measures and then rerouting traffic back out. The second strategy is to provide branch locations with fully functional local breakouts using distributed firewalls or a similar security routine for all internet traffic and access.

Sixty-four percent of organizations that have added additional security solutions route their branch locations’ traffic to headquarters, and then pass it to the cloud using a dedicated MPLS circuit in a central location. However, more than nine in ten (95%) respondents report that they see a need for additional security solutions to be added to their public cloud to protect it during access.

While organizations are investing in additional security to address perceived gaps in their cloud infrastructures, we found other concerns as well. Security dominates the discussion, but regulatory requirements and the cost to maintain cloud infrastructure were also raised as concerns. Over 25% of all organizations reported issues with either needing a shadow IT organization to shepherd their cloud infrastructure, or the lack of an expert partner to help bolster cloud security.

What are the concerns that organization have regarding the use of public cloud?

public cloud concerns

Conclusion

What are the ten most important drivers for choosing a public cloud service provider?

public cloud conclusions

Despite the challenges, the overall benefits of leveraging cloud infrastructure are pushing organizations to accelerate their cloud adoptions. More than half of respondents report that easy integration with legacy technology (61%) and strong protection of applications in the public cloud (54%) are important drivers when choosing a public cloud IaaS provider to use in their organization, while around half (48%) said the same regarding strong protection of access to applications in the public cloud.

Scalability, support, and innovation are also reported as important drivers of cloud adoption.Organizations applauded the support they are offered by public cloud providers, and more and more are seeing the cloud as an effective means of disaster recovery. For readers of this summary, a key takeaway is that security remains a key concern. The upside is that organizations can (and are) augmenting support with third-party providers. These solutions allow them to create infrastructures that are even more secure than those on-premises.
As cloud infrastructures evolve and organizations deploy more clouds, a corresponding challenge will be ensuring they have chosen third parties who provide cross-platform solutions and expertise. Additionally, it should not be forgotten that these organizations are coming from somewhere (i.e., on-premises infrastructures), and their chosen third parties need a strong understanding of hybrid deployments as well as pure cloud ones.

Medha Hosting Protecting users, applications, and data for many organizations worldwide, Medha Hosting has developed a global reputation as the trusted partner for powerful, easy to hire, affordable IT solutions Provider. The company’s proven customer-centric business model focuses on delivering high value, subscription-based IT solutions for security and data protection. For additional information, please visit Azure Consulting, Google Cloud Consulting, and AWS consulting .

How to Install Webmin on CentOS 7 step by step ?

Upate your system

Connect to your Linux server via putty and update all the currently installed software to the latest version available using the command

Yum -y update.

 

Download and install the RPM version of Webmin

Toward download Webmin, please visit the Webmin download page {http://www.webmin.com/download.html} and check for the Webmin RPM package. The RPM package is appropriate for any RedHat, Fedora or CentOS system. To download the package, you can use.

# wget http://prdownloads.sourceforge.net/webadmin/webmin-1.831-1.noarch.rpm

 

The order continue with the installation, your requirement to make sure that all dependencies are installed on your CentOS VPS. If they aren’t installed you can install use below command.

# yum -y install perl perl-Net-SSLeay openssl perl-IO-Tty

 

Once the All dependences are installed, you can install Webmin using the below command:

# rpm -U webmin-1.831-1.noarch.rpm

 

Install Webmin using the YUM repository

Another way to install Webmin is by using the official YUM repository. First, you create a webmin.repo file:

# vi /etc/yum.repos.d/webmin.repo

 

Add them below content to the file and save it.

[Webmin]

name=Webmin Distribution Neutral

#baseurl=http://download.webmin.com/download/yum

mirrorlist=http://download.webmin.com/download/yum/mirrorlist

enabled=1

 

Then, make and install the GPG key which is used to sign the Webmin packages.

# wget http://www.webmin.com/jcameron-key.asc

 

# rpm --import jcameron-key.asc

 

Finally, install Webmin and all the dependencies using the below command:

# yum install webmin

 

Start Webmin and enable it on system reboot

To start Webmin, you can use the below command:

# service webmin start

 

To enable Webmin on system reboot use the below command:# chkconfig webmin on

Webmin lets you to set up user accounts, configure the Apache web server, manage DNS, arrange the Postfix mail server, configure the Dovecot IMAP and POP3 mail server and many other things. It has a which you can install and use for your own purposes.

Accessing Webmin

To access Webmin, open your favorite web browser, enter HTTPS as protocol, enter your server IP address and use 10000 as a port number.

https://xx.xx.xx.xx:10000

 

By default, Webmin uses Assign self SSL certificate your web browser will caution you that the connection is not secure. You can accept the SSL certificate and proceed to the log in screen.

The administration username which you can use to sign in is set to root and the password is your current root password. In the Webmin dashboard, you can see some basic information about your system and recent logins. The modules and services which you can manage through Webmin are listed on the left panel.

Creating a very simple blog in php

This post will cover creating a very simple blog in php. It will only consist of posts. The front-end will only be two pages, an index page to list all posts and a view page to view a post.

There will be a backend control panel for managing posts and admins, this guide will also include a user authentication system to login administrators.

There will be two mysql tables, blog_posts and blog_members.

blog_posts structure:

blog_posts structure

blog_members structure

blog_members structure

Every page will need a database connection, this will be opened in config.php:

includes/config.php

Start output buffering, then headers can be used anywhere. Start sessions this will be needed for the admin area.

Define the database connection details then open a PDO connection.

Also set the timezone, adjust this as needed.

<?php

ob_start();

session_start();

//database credentials

define('DBHOST','localhost');

define('DBUSER','database username');

define('DBPASS','database password');

define('DBNAME','database name');

$db = new PDO("mysql:host=".DBHOST.";port=8889;dbname=".DBNAME, DBUSER, DBPASS);

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

//set timezone

date_default_timezone_set('Europe/London');

 

Next create an autoload function this will include any class as it is called this stops you having to manually include all classes, for this project there is only a single class but this set up the feature for more classes in future developments.

Inside the function, the name passed to is is converted into lowercase then check to see if the file exists if it does it is then included.

Lastly the user class is instantiated and passed the database connection ($db) so the class has access to the database.

//load classes as needed

function __autoload($class) {



$class = strtolower($class);

$classpath = 'classes/class.'.$class . '.php';

if ( file_exists($classpath)) {

require_once $classpath;

}

$classpath = '../classes/class.'.$class . '.php';

if ( file_exists($classpath)) {

require_once $classpath;

}





}

$user = new User($db);

index.php

The index file will list all posts from the posts table.
A query is ran to select the columns from blog_posts then ordered by the postID in descending order.
Then the posts are looped through on each loop display the title, description date posted and a link to read the full post.

The query is wrapped inside a try catch statement so if there is any errors a PDO Exception will be used to display them.

The id for the post is past to the next page in what’s called a query string ?id will become a variable in the url = assignes the value.

<?php

try {

$stmt = $db->query('SELECT postID, postTitle, postDesc, postDate FROM blog_posts ORDER BY postID DESC');

while($row = $stmt->fetch()){



echo '<div>';

echo '<h1><a href="viewpost.php?id='.$row['postID'].'">'.$row['postTitle'].'</a></h1>';

echo '<p>Posted on '.date('jS M Y H:i:s', strtotime($row['postDate'])).'</p>';

echo '<p>'.$row['postDesc'].'</p>';

echo '<p><a href="viewpost.php?id='.$row['postID'].'">Read More</a></p>';

echo '</div>';

}

} catch(PDOException $e) {

echo $e->getMessage();

}

?>

 

viewpost.php

viewpost.php is used to display any post that has been clicked on.

This query will use a prepared statement, the record to be selected is based upon the id been passed from a $_GET[‘id’] request, as such a normally query is not recommended, a prepared statement is much better. The prepare will ‘prepare’ the database for query to be run then when $stmt->execute is ran the items from the array will be bound and sent to the database server, at no point does the two connect to there is no way to tamper with the database.

$stmt = $db->prepare('SELECT postID, postTitle, postCont, postDate FROM blog_posts WHERE postID = :postID');

$stmt->execute(array(':postID' => $_GET['id']));

$row = $stmt->fetch();

If there is no postID coming from the database, their is no record so redirect the user to the index page.

if($row['postID'] == ''){

header('Location: ./');

exit;

}

Lastly display the select post in full:

echo '<div>';

echo '<h1>'.$row['postTitle'].'</h1>';

echo '<p>Posted on '.date('jS M Y', strtotime($row['postDate'])).'</p>';

echo '<p>'.$row['postCont'].'</p>';

echo '</div>';

 

That’s it for the front end! its very simple but its also very easy to expand and add more features.

Admin

Every page in the admin area will start by including the config file and checking if the admin is logged in, otherwise they are redirect to the login page.

//include config

require_once('../includes/config.php');

//if not logged in redirect to login page

if(!$user->is_logged_in()){ header('Location: login.php'); }

admin/login.php

The login page will check if the user is already logged in, if they are they will be redirect to the main admin area.

The login page is very simple there is a login form which accepts a username and password.

<form action="" method="post">

<p><label>Username</label><input type="text" name="username" value="" /></p>

<p><label>Password</label><input type="password" name="password" value="" /></p>

<p><label></label><input type="submit" name="submit" value="Login" /></p>

</form>

 

Once submitted the username and password are collected from the form then passed to a login method in the user class (I’ll come to that shortly) if this returns true, they have logged in are are taken to the admin otherwise they are shown an error.

//process login form if submitted

if(isset($_POST['submit'])){

$username = trim($_POST['username']);

$password = trim($_POST['password']);



if($user->login($username,$password)){

//logged in return to index page

header('Location: index.php');

exit;



} else {

$message = '<p class="error">Wrong username or password</p>';

}

}//end if submit

if(isset($message)){ echo $message; }

 

classes/class.user.php

The user class is used to login and logout users verify their password and create a hash of their password.

The first function that will get called as soon as the class is ran is an automatic function called __construct this method is passed a database connection this is then assigned to a variable within the class so all methods will have access to it.

private $db;

public function __construct($db){

$this->db = $db;

}

 

To check if a user is logged in a method is_logged_in() looks for a session called loggedin if its set and is true their is a logged in user and returns true otherwise is would return nothing.

public function is_logged_in(){

if(isset($_SESSION['loggedin']) && $_SESSION['loggedin'] == true){

return true;

}

}

The get_user_hash method is used to get the columns from the database and return them.

private function get_user_hash($username){

try {

$stmt = $this->_db->prepare('SELECT MemberID, username, password FROM blog_members WHERE username = :username');

$stmt->execute(array('username' => $username));

return $stmt->fetch();

} catch(PDOException $e) {

echo '<p class="error">'.$e->getMessage().'</p>';

}

}

To verify a hash, the below method is used. pass the password from the form and the hashed password from the database this should equal to 1 otherwise they do not match.

if($this->password_verify($password,$user['password']) == 1){

//match

}

 

In order to verify a password matched a password given on login the hashed password needs to be fetched from the database, the username is passed to the database and the hashed password is returned.

The login method expects the users username and password then the fetches users password based on their username from the get_user_hash method in order to use the verify_hash method.
If a match is found a session is set and the method returns true.

public function login($username,$password){

$hashed = $this->get_user_hash($username);



if($this->password_verify($password,$hashed) == 1){



$_SESSION['loggedin'] = true;

$_SESSION['memberID'] = $user['memberID'];

$_SESSION['username'] = $user['username'];

return true;

}

}

 

admin/index.php

The blog posts are listed in a table, again using a query to select all records and display them ordered by the postID in descending order, then looped through to list all posts, each post has an edit and delete link the edit link passes the postID to edit-post.php in order to edit the selected post.
The delete link calls a javascript function (delpost) it expects the id of the post and the title of the post, when clicked the javascript function is executed which will run a confirmation popup asking to confirm to delete the post.

<table>

<tr>

<th>Title</th>

<th>Date</th>

<th>Action</th>

</tr>

<?php

try {

$stmt = $db->query('SELECT postID, postTitle, postDate FROM blog_posts ORDER BY postID DESC');

while($row = $stmt->fetch()){



echo '<tr>';

echo '<td>'.$row['postTitle'].'</td>';

echo '<td>'.date('jS M Y', strtotime($row['postDate'])).'</td>';

?>

<td>

<a href="edit-post.php?id=<?php echo $row['postID'];?>">Edit</a> |

<a href="javascript:delpost('<?php echo $row['postID'];?>','<?php echo $row['postTitle'];?>')">Delete</a>

</td>



<?php

echo '</tr>';

}

} catch(PDOException $e) {

echo $e->getMessage();

}

?>

</table>

 

The javascript confirm function, once confirmed a command window.locaation.href is ran which will redirect the page, in this case it goes to index.php again but appends ?delpost= and the id of the post to be deleted, which in turn will execute a php function.

<script language="JavaScript" type="text/javascript">

function delpost(id, title)

{

if (confirm("Are you sure you want to delete '" + title + "'"))

{

window.location.href = 'index.php?delpost=' + id;

}

}

</script>

 

PHP Delete function

If the get request delpost has been sent then a prepared statement is ran to delete the post where the postID matches the id passed in the array. Then the page is reloaded passing a status to the url in indexphp?action= the action is used on the page to confirm the deletion.

if(isset($_GET['delpost'])){

$stmt = $db->prepare('DELETE FROM blog_posts WHERE postID = :postID') ;

$stmt->execute(array(':postID' => $_GET['delpost']));

header('Location: index.php?action=deleted');

exit;

}

if there has been an action passed in a $_GET request then display it.

if(isset($_GET['action'])){

echo '<h3>Post '.$_GET['action'].'.</h3>';

}

 

There is an admin menu that will be display on every page, whilst this could be added to each page it makes more sense to add links to a separate file called menu.php that can be included into every file, that way any changes only need to be applied once.

<?php include('menu.php');?>

 

admin/menu.php

The menu is very simple for this site the links are inside a ul list, the view website links back to the root of the project by going back a directory using ../ in the href path.

<h1>Blog</h1>

<p>Logged in as <?=$_SESSION['username'];?></p>

<ul id='adminmenu'>

<li><a href='index.php'>Blog</a></li>

<li><a href='users.php'>Users</a></li>

<li><a href="../" target="_blank">View Website</a></li>

<li><a href='logout.php'>Logout</a></li>

</ul>

<div class='clear'></div>

<hr />

 

admin/add-post.php

The form to add a post is made up of input’s and textareas, each section has a name which will become a variable in php when the form is submitted.
The forms also use what’s called sticky forms meaning if validation fails then show all content entered into the form.

<form action='' method='post'>

<p><label>Title</label><br />

<input type='text' name='postTitle' value='<?php if(isset($error)){ echo $_POST['postTitle'];}?>'></p>

<p><label>Description</label><br />

<textarea name='postDesc' cols='60' rows='10'><?php if(isset($error)){ echo $_POST['postDesc'];}?></textarea></p>

<p><label>Content</label><br />

<textarea name='postCont' cols='60' rows='10'><?php if(isset($error)){ echo $_POST['postCont'];}?></textarea></p>

<p><input type='submit' name='submit' value='Submit'></p>

</form>

 

For textarea’s rather then making the admins enter the html for the text themselves its better to use an editor, I’ve chosen to use a popular one called <a href=’http://www.tinymce.com’>TinyMCE</a> To use it you would normally have to download the files from tinyMCE’s website upload them and configure the config, thankfully they have recently released a CDN version so you can include tinyMCE by simply referencing the CDN and then your setup options:

This will convert all textarea’s into editors.

<script src="//tinymce.cachefly.net/4.0/tinymce.min.js"></script>

<script>

tinymce.init({

selector: "textarea",

plugins: [

"advlist autolink lists link image charmap print preview anchor",

"searchreplace visualblocks code fullscreen",

"insertdatetime media table contextmenu paste"

],

toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"

});

</script>

 

To process the form data once its been submitted is a simple process first make sure the form has been submitted. Then remove any slashed in the $_POST array. Then extract all posts items inside $_POST by using extract($_POST) any post element is then accessible by using just its name so $_POST[‘postTitle’] becomes $postTitle.

Next validate the data, these are very basic validation rules. These can be improved upon, if any of the if statements are true then an error is needed, adding an error to an array called error is a simple way to collect multiple errors.

//if form has been submitted process it

if(isset($_POST['submit'])){

$_POST = array_map( 'stripslashes', $_POST );

//collect form data

extract($_POST);

//very basic validation

if($postTitle ==''){

$error[] = 'Please enter the title.';

}

if($postDesc ==''){

$error[] = 'Please enter the description.';

}

if($postCont ==''){

$error[] = 'Please enter the content.';

}

 

Next if no error has been set then insert the data into the database, this is using prepared statements the place holders :postTitle, :postDesc etc are using to bind the matching array elements when execute to add the data into the correct columns. Once inserted the user is redirected back to the admin a action status is appended to the url ?action=added.

if(!isset($error)){

try {

//insert into database

$stmt = $db->prepare('INSERT INTO blog_posts (postTitle,postDesc,postCont,postDate) VALUES (:postTitle, :postDesc, :postCont, :postDate)') ;

$stmt->execute(array(

':postTitle' => $postTitle,

':postDesc' => $postDesc,

':postCont' => $postCont,

':postDate' => date('Y-m-d H:i:s')

));

//redirect to index page

header('Location: index.php?action=added');

exit;

} catch(PDOException $e) {

echo $e->getMessage();

}

}

If there has been any errors set then loop through the error array and display them.

if(isset($error)){

foreach($error as $error){

echo '<p class="error">'.$error.'</p>';

}

}

 

admin/edit-post.php

This is very much like the add page except before the menu a query must be ran to select the correct post from the database to populate the form with.

The query needs to select the record where the postID matched the id passed in the $_GET[‘id’] request, as this can be manipulated a prepared statement is used.
The form also has an hidden field with the name postID and a value from the database this is used when updating the record to determine which post to make the changes to.

<?php

try {

$stmt = $db->prepare('SELECT postID, postTitle, postDesc, postCont FROM blog_posts WHERE postID = :postID');

$stmt->execute(array(':postID' => $_GET['id']));

$row = $stmt->fetch();

} catch(PDOException $e) {

echo $e->getMessage();

}

?>

<form action='' method='post'>

<input type='hidden' name='postID' value='<?php echo $row['postID'];?>'>

<p><label>Title</label><br />

<input type='text' name='postTitle' value='<?php echo $row['postTitle'];?>'></p>

<p><label>Description</label><br />

<textarea name='postDesc' cols='60' rows='10'><?php echo $row['postDesc'];?></textarea></p>

<p><label>Content</label><br />

<textarea name='postCont' cols='60' rows='10'><?php echo $row['postCont'];?></textarea></p>

<p><input type='submit' name='submit' value='Update'></p>

</form>

When the form is submitted the same checks are done that were done on the add post page:

if(isset($_POST['submit'])){

$_POST = array_map( 'stripslashes', $_POST );

//collect form data

extract($_POST);

//very basic validation

if($postID ==''){

$error[] = 'This post is missing a valid id!.';

}

if($postTitle ==''){

$error[] = 'Please enter the title.';

}

if($postDesc ==''){

$error[] = 'Please enter the description.';

}

if($postCont ==''){

$error[] = 'Please enter the content.';

}

if(!isset($error)){

To update the post a prepared statement is ran this time an update command is used updating the specified columns by the matching place holders/ executed array. Once completed the user is redirected to index with an action status.

try {

//insert into database

$stmt = $db->prepare('UPDATE blog_posts SET postTitle = :postTitle, postDesc = :postDesc, postCont = :postCont WHERE postID = :postID') ;

$stmt->execute(array(

':postTitle' => $postTitle,

':postDesc' => $postDesc,

':postCont' => $postCont,

':postID' => $postID

));

//redirect to index page

header('Location: index.php?action=updated');

exit;

} catch(PDOException $e) {

echo $e->getMessage();

}

admin/users.php

This page lists all administrators of the blog.

While looping through the admins edit and delete links are created, the first admin will have an id of 1 this user should not be deleted, therefor an if statement is used to make sure the delete link is not shown for the first admin.

$stmt = $db->query('SELECT memberID, username, email FROM blog_members ORDER BY username');

while($row = $stmt->fetch()){



echo '<tr>';

echo '<td>'.$row['username'].'</td>';

echo '<td>'.$row['email'].'</td>';

?>

<td>

<a href="edit-user.php?id=<?php echo $row['memberID'];?>">Edit</a>

<?php if($row['memberID'] != 1){?>

| <a href="javascript:deluser('<?php echo $row['memberID'];?>','<?php echo $row['username'];?>')">Delete</a>

<?php } ?>

</td>



<?php

echo '</tr>';

}

Deleting a user is the same as a post:

<script language="JavaScript" type="text/javascript">

function deluser(id, title)

{

if (confirm("Are you sure you want to delete '" + title + "'"))

{

window.location.href = 'users.php?deluser=' + id;

}

}

</script>

if(isset($_GET['deluser'])){

//if user id is 1 ignore

if($_GET['deluser'] !='1'){

$stmt = $db->prepare('DELETE FROM blog_members WHERE memberID = :memberID') ;

$stmt->execute(array(':memberID' => $_GET['deluser']));

header('Location: users.php?action=deleted');

exit;

}

}

 

admin/add-user.php

Adding and editing users is very similar to posts I will go over only what’s different.

Present the form to be filled in, notice the password have a type of password this stops the password being show in the form.

<form action='' method='post'>

<p><label>Username</label><br />

<input type='text' name='username' value='<?php if(isset($error)){ echo $_POST['username'];}?>'></p>

<p><label>Password</label><br />

<input type='password' name='password' value='<?php if(isset($error)){ echo $_POST['password'];}?>'></p>

<p><label>Confirm Password</label><br />

<input type='password' name='passwordConfirm' value='<?php if(isset($error)){ echo $_POST['passwordConfirm'];}?>'></p>

<p><label>Email</label><br />

<input type='text' name='email' value='<?php if(isset($error)){ echo $_POST['email'];}?>'></p>



<p><input type='submit' name='submit' value='Add User'></p>

</form>

 

As part of processing the form new users will need a hash to be created from the user class this is done by passing the password from the form into the class object and use the create_hash method.
Next a normal insert statement is ran in the array the password is not used but instead the hashedpassword is given.

$hashedpassword = $user->create_hash($password);

try {

//insert into database

$stmt = $db->prepare('INSERT INTO blog_members (username,password,email) VALUES (:username, :password, :email)') ;

$stmt->execute(array(

':username' => $username,

':password' => $hashedpassword,

':email' => $email

));

//redirect to index page

header('Location: users.php?action=added');

exit;

} catch(PDOException $e) {

echo $e->getMessage();

}

 

admin/edit-user.php

To edit a user first the user needs to be retrieved from the database using a prepared statement where the memberID matches the id passed in the get request.

The password fields are not populated, this are only filled in to change the password.

<?php

try {

$stmt = $db->prepare('SELECT memberID, username, email FROM blog_members WHERE memberID = :memberID') ;

$stmt->execute(array(':memberID' => $_GET['id']));

$row = $stmt->fetch();

} catch(PDOException $e) {

echo $e->getMessage();

}

?>

<form action='' method='post'>

<input type='hidden' name='memberID' value='<?php echo $row['memberID'];?>'>

<p><label>Username</label><br />

<input type='text' name='username' value='<?php echo $row['username'];?>'></p>

<p><label>Password (only to change)</label><br />

<input type='password' name='password' value=''></p>

<p><label>Confirm Password</label><br />

<input type='password' name='passwordConfirm' value=''></p>

<p><label>Email</label><br />

<input type='text' name='email' value='<?php echo $row['email'];?>'></p>

<p><input type='submit' name='submit' value='Update User'></p>

</form>

 

 

When running validation the password checks should only run if a password has been entered.

if( strlen($password) > 0){

if($password ==''){

$error[] = 'Please enter the password.';

}

if($passwordConfirm ==''){

$error[] = 'Please confirm the password.';

}

if($password != $passwordConfirm){

$error[] = 'Passwords do not match.';

}

}

 

When updating the database a check is made to see if the password has been set, if so then the password is updated otherwise another update is ran without updating the password.
When the password is to be updated a new hash is created from the user object.

if(isset($password)){

$hashedpassword = $user->create_hash($password);

//update into database

$stmt = $db->prepare('UPDATE blog_members SET username = :username, password = :password, email = :email WHERE memberID = :memberID') ;

$stmt->execute(array(

':username' => $username,

':password' => $hashedpassword,

':email' => $email,

':memberID' => $memberID

));

} else {

//update database

$stmt = $db->prepare('UPDATE blog_members SET username = :username, email = :email WHERE memberID = :memberID') ;

$stmt->execute(array(

':username' => $username,

':email' => $email,

':memberID' => $memberID

));

}

 

That’s all the notable differences the files in full are available in the download I’ll also list the full files below:

Source Files

index.php

<?php require('includes/config.php'); ?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<title>Blog</title>

<link rel="stylesheet" href="style/normalize.css">

<link rel="stylesheet" href="style/main.css">

</head>

<body>

<div id="wrapper">

<h1>Blog</h1>

<hr />

<?php

try {

$stmt = $db->query('SELECT postID, postTitle, postDesc, postDate FROM blog_posts ORDER BY postID DESC');

while($row = $stmt->fetch()){



echo '<div>';

echo '<h1><a href="viewpost.php?id='.$row['postID'].'">'.$row['postTitle'].'</a></h1>';

echo '<p>Posted on '.date('jS M Y H:i:s', strtotime($row['postDate'])).'</p>';

echo '<p>'.$row['postDesc'].'</p>';

echo '<p><a href="viewpost.php?id='.$row['postID'].'">Read More</a></p>';

echo '</div>';

}

} catch(PDOException $e) {

echo $e->getMessage();

}

?>

</div>

</body>

</html>

viewpost.php

<?php require('includes/config.php');

$stmt = $db->prepare('SELECT postID, postTitle, postCont, postDate FROM blog_posts WHERE postID = :postID');

$stmt->execute(array(':postID' => $_GET['id']));

$row = $stmt->fetch();

//if post does not exists redirect user.

if($row['postID'] == ''){

header('Location: ./');

exit;

}

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<title>Blog - <?php echo $row['postTitle'];?></title>

<link rel="stylesheet" href="style/normalize.css">

<link rel="stylesheet" href="style/main.css">

</head>

<body>

<div id="wrapper">

<h1>Blog</h1>

<hr />

<p><a href="./">Blog Index</a></p>

<?php

echo '<div>';

echo '<h1>'.$row['postTitle'].'</h1>';

echo '<p>Posted on '.date('jS M Y', strtotime($row['postDate'])).'</p>';

echo '<p>'.$row['postCont'].'</p>';

echo '</div>';

?>

</div>

</body>

</html>

includes/config.php

<?php

ob_start();

session_start();

//database credentials

define('DBHOST','localhost');

define('DBUSER','database username');

define('DBPASS','database password');

define('DBNAME','database name');

$db = new PDO("mysql:host=".DBHOST.";port=8889;dbname=".DBNAME, DBUSER, DBPASS);

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

//set timezone

date_default_timezone_set('Europe/London');

//load classes as needed

function __autoload($class) {



$class = strtolower($class);

//if call from within /assets adjust the path

$classpath = 'classes/class.'.$class . '.php';

if ( file_exists($classpath)) {

require_once $classpath;

}



//if call from within admin adjust the path

$classpath = '../classes/class.'.$class . '.php';

if ( file_exists($classpath)) {

require_once $classpath;

}



//if call from within admin adjust the path

$classpath = '../../classes/class.'.$class . '.php';

if ( file_exists($classpath)) {

require_once $classpath;

}



}

$user = new User($db);

?>

classes/class.user.php

<?php

class User{

private $db;



public function __construct($db){

$this->db = $db;

}

public function is_logged_in(){

if(isset($_SESSION['loggedin']) && $_SESSION['loggedin'] == true){

return true;

}

}

public function create_hash($value)

{

return $hash = crypt($value, '$2a$12.substr(str_replace('+', '.', base64_encode(sha1(microtime(true), true))), 0, 22));

}

private function verify_hash($password,$hash)

{

return $hash == crypt($password, $hash);

}

private function get_user_hash($username){

try {

//echo $this->create_hash('demo');

$stmt = $this->db->prepare('SELECT password FROM blog_members WHERE username = :username');

$stmt->execute(array('username' => $username));



$row = $stmt->fetch();

return $row['password'];

} catch(PDOException $e) {

echo '<p class="error">'.$e->getMessage().'</p>';

}

}



public function login($username,$password){

$hashed = $this->get_user_hash($username);



if($this->verify_hash($password,$hashed) == 1){



$_SESSION['loggedin'] = true;

return true;

}

}





public function logout(){

session_destroy();

}



}

?>

admin/index.php

<?php

//include config

require_once('../includes/config.php');

//if not logged in redirect to login page

if(!$user->is_logged_in()){ header('Location: login.php'); }

//show message from add / edit page

if(isset($_GET['delpost'])){

$stmt = $db->prepare('DELETE FROM blog_posts WHERE postID = :postID') ;

$stmt->execute(array(':postID' => $_GET['delpost']));

header('Location: index.php?action=deleted');

exit;

}

?>

<!doctype html>

<html lang="en">

<head>

<meta charset="utf-8">

<title>Admin</title>

<link rel="stylesheet" href="../style/normalize.css">

<link rel="stylesheet" href="../style/main.css">

<script language="JavaScript" type="text/javascript">

function delpost(id, title)

{

if (confirm("Are you sure you want to delete '" + title + "'"))

{

window.location.href = 'index.php?delpost=' + id;

}

}

</script>

</head>

<body>

<div id="wrapper">

<?php include('menu.php');?>

<?php

//show message from add / edit page

if(isset($_GET['action'])){

echo '<h3>Post '.$_GET['action'].'.</h3>';

}

?>

<table>

<tr>

<th>Title</th>

<th>Date</th>

<th>Action</th>

</tr>

<?php

try {

$stmt = $db->query('SELECT postID, postTitle, postDate FROM blog_posts ORDER BY postID DESC');

while($row = $stmt->fetch()){



echo '<tr>';

echo '<td>'.$row['postTitle'].'</td>';

echo '<td>'.date('jS M Y', strtotime($row['postDate'])).'</td>';

?>

<td>

<a href="edit-post.php?id=<?php echo $row['postID'];?>">Edit</a> |

<a href="javascript:delpost('<?php echo $row['postID'];?>','<?php echo $row['postTitle'];?>')">Delete</a>

</td>



<?php

echo '</tr>';

}

} catch(PDOException $e) {

echo $e->getMessage();

}

?>

</table>

<p><a href='add-post.php'>Add Post</a></p>

</div>

</body>

</html>

admin/login.php

<?php

//include config

require_once('../includes/config.php');

//check if already logged in

if( $user->is_logged_in() ){ header('Location: index.php'); }

?>

<!doctype html>

<html lang="en">

<head>

<meta charset="utf-8">

<title>Admin Login</title>

<link rel="stylesheet" href="../style/normalize.css">

<link rel="stylesheet" href="../style/main.css">

</head>

<body>

<div id="login">

<?php

//process login form if submitted

if(isset($_POST['submit'])){

$username = trim($_POST['username']);

$password = trim($_POST['password']);



if($user->login($username,$password)){

//logged in return to index page

header('Location: index.php');

exit;



} else {

$message = '<p class="error">Wrong username or password</p>';

}

}//end if submit

if(isset($message)){ echo $message; }

?>

<form action="" method="post">

<p><label>Username</label><input type="text" name="username" value="" /></p>

<p><label>Password</label><input type="password" name="password" value="" /></p>

<p><label></label><input type="submit" name="submit" value="Login" /></p>

</form>

</div>

</body>

</html>

admin/logout.php

<?php

//include config

require_once('../includes/config.php');

//log user out

$user->logout();

header('Location: index.php');

?>

admin/menu.php

<h1>Blog</h1>

<ul id='adminmenu'>

<li><a href='index.php'>Blog</a></li>

<li><a href='users.php'>Users</a></li>

<li><a href="../" target="_blank">View Website</a></li>

<li><a href='logout.php'>Logout</a></li>

</ul>

<div class='clear'></div>

<hr />

admin/add-post.php

<?php //include config

require_once('../includes/config.php');

//if not logged in redirect to login page

if(!$user->is_logged_in()){ header('Location: login.php'); }

?>

<!doctype html>

<html lang="en">

<head>

<meta charset="utf-8">

<title>Admin - Add Post</title>

<link rel="stylesheet" href="../style/normalize.css">

<link rel="stylesheet" href="../style/main.css">

<script src="//tinymce.cachefly.net/4.0/tinymce.min.js"></script>

<script>

tinymce.init({

selector: "textarea",

plugins: [

"advlist autolink lists link image charmap print preview anchor",

"searchreplace visualblocks code fullscreen",

"insertdatetime media table contextmenu paste"

],

toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"

});

</script>

</head>

<body>

<div id="wrapper">

<?php include('menu.php');?>

<p><a href="./">Blog Admin Index</a></p>

<h2>Add Post</h2>

<?php

//if form has been submitted process it

if(isset($_POST['submit'])){

$_POST = array_map( 'stripslashes', $_POST );

//collect form data

extract($_POST);

//very basic validation

if($postTitle ==''){

$error[] = 'Please enter the title.';

}

if($postDesc ==''){

$error[] = 'Please enter the description.';

}

if($postCont ==''){

$error[] = 'Please enter the content.';

}

if(!isset($error)){

try {

//insert into database

$stmt = $db->prepare('INSERT INTO blog_posts (postTitle,postDesc,postCont,postDate) VALUES (:postTitle, :postDesc, :postCont, :postDate)') ;

$stmt->execute(array(

':postTitle' => $postTitle,

':postDesc' => $postDesc,

':postCont' => $postCont,

':postDate' => date('Y-m-d H:i:s')

));

//redirect to index page

header('Location: index.php?action=added');

exit;

} catch(PDOException $e) {

echo $e->getMessage();

}

}

}

//check for any errors

if(isset($error)){

foreach($error as $error){

echo '<p class="error">'.$error.'</p>';

}

}

?>

<form action='' method='post'>

<p><label>Title</label><br />

<input type='text' name='postTitle' value='<?php if(isset($error)){ echo $_POST['postTitle'];}?>'></p>

<p><label>Description</label><br />

<textarea name='postDesc' cols='60' rows='10'><?php if(isset($error)){ echo $_POST['postDesc'];}?></textarea></p>

<p><label>Content</label><br />

<textarea name='postCont' cols='60' rows='10'><?php if(isset($error)){ echo $_POST['postCont'];}?></textarea></p>

<p><input type='submit' name='submit' value='Submit'></p>

</form>

</div>

admin/edit-post.php

<?php //include config

require_once('../includes/config.php');

//if not logged in redirect to login page

if(!$user->is_logged_in()){ header('Location: login.php'); }

?>

<!doctype html>

<html lang="en">

<head>

<meta charset="utf-8">

<title>Admin - Edit Post</title>

<link rel="stylesheet" href="../style/normalize.css">

<link rel="stylesheet" href="../style/main.css">

<script src="//tinymce.cachefly.net/4.0/tinymce.min.js"></script>

<script>

tinymce.init({

selector: "textarea",

plugins: [

"advlist autolink lists link image charmap print preview anchor",

"searchreplace visualblocks code fullscreen",

"insertdatetime media table contextmenu paste"

],

toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"

});

</script>

</head>

<body>

<div id="wrapper">

<?php include('menu.php');?>

<p><a href="./">Blog Admin Index</a></p>

<h2>Edit Post</h2>

<?php

//if form has been submitted process it

if(isset($_POST['submit'])){

$_POST = array_map( 'stripslashes', $_POST );

//collect form data

extract($_POST);

//very basic validation

if($postID ==''){

$error[] = 'This post is missing a valid id!.';

}

if($postTitle ==''){

$error[] = 'Please enter the title.';

}

if($postDesc ==''){

$error[] = 'Please enter the description.';

}

if($postCont ==''){

$error[] = 'Please enter the content.';

}

if(!isset($error)){

try {

//insert into database

$stmt = $db->prepare('UPDATE blog_posts SET postTitle = :postTitle, postDesc = :postDesc, postCont = :postCont WHERE postID = :postID') ;

$stmt->execute(array(

':postTitle' => $postTitle,

':postDesc' => $postDesc,

':postCont' => $postCont,

':postID' => $postID

));

//redirect to index page

header('Location: index.php?action=updated');

exit;

} catch(PDOException $e) {

echo $e->getMessage();

}

}

}

?>

<?php

//check for any errors

if(isset($error)){

foreach($error as $error){

echo $error.'<br />';

}

}

try {

$stmt = $db->prepare('SELECT postID, postTitle, postDesc, postCont FROM blog_posts WHERE postID = :postID') ;

$stmt->execute(array(':postID' => $_GET['id']));

$row = $stmt->fetch();

} catch(PDOException $e) {

echo $e->getMessage();

}

?>

<form action='' method='post'>

<input type='hidden' name='postID' value='<?php echo $row['postID'];?>'>

<p><label>Title</label><br />

<input type='text' name='postTitle' value='<?php echo $row['postTitle'];?>'></p>

<p><label>Description</label><br />

<textarea name='postDesc' cols='60' rows='10'><?php echo $row['postDesc'];?></textarea></p>

<p><label>Content</label><br />

<textarea name='postCont' cols='60' rows='10'><?php echo $row['postCont'];?></textarea></p>

<p><input type='submit' name='submit' value='Update'></p>

</form>

</div>

</body>

</html>

admin/users.php

<?php

//include config

require_once('../includes/config.php');

//if not logged in redirect to login page

if(!$user->is_logged_in()){ header('Location: login.php'); }

//show message from add / edit page

if(isset($_GET['deluser'])){

//if user id is 1 ignore

if($_GET['deluser'] !='1'){

$stmt = $db->prepare('DELETE FROM blog_members WHERE memberID = :memberID') ;

$stmt->execute(array(':memberID' => $_GET['deluser']));

header('Location: users.php?action=deleted');

exit;

}

}

?>

<!doctype html>

<html lang="en">

<head>

<meta charset="utf-8">

<title>Admin - Users</title>

<link rel="stylesheet" href="../style/normalize.css">

<link rel="stylesheet" href="../style/main.css">

<script language="JavaScript" type="text/javascript">

function deluser(id, title)

{

if (confirm("Are you sure you want to delete '" + title + "'"))

{

window.location.href = 'users.php?deluser=' + id;

}

}

</script>

</head>

<body>

<div id="wrapper">

<?php include('menu.php');?>

<?php

//show message from add / edit page

if(isset($_GET['action'])){

echo '<h3>User '.$_GET['action'].'.</h3>';

}

?>

<table>

<tr>

<th>Username</th>

<th>Email</th>

<th>Action</th>

</tr>

<?php

try {

$stmt = $db->query('SELECT memberID, username, email FROM blog_members ORDER BY username');

while($row = $stmt->fetch()){



echo '<tr>';

echo '<td>'.$row['username'].'</td>';

echo '<td>'.$row['email'].'</td>';

?>

<td>

<a href="edit-user.php?id=<?php echo $row['memberID'];?>">Edit</a>

<?php if($row['memberID'] != 1){?>

| <a href="javascript:deluser('<?php echo $row['memberID'];?>','<?php echo $row['username'];?>')">Delete</a>

<?php } ?>

</td>



<?php

echo '</tr>';

}

} catch(PDOException $e) {

echo $e->getMessage();

}

?>

</table>

<p><a href='add-user.php'>Add User</a></p>

</div>

</body>

</html>

admin/add-user.php

<?php //include config

require_once('../includes/config.php');

//if not logged in redirect to login page

if(!$user->is_logged_in()){ header('Location: login.php'); }

?>

<!doctype html>

<html lang="en">

<head>

<meta charset="utf-8">

<title>Admin - Add User</title>

<link rel="stylesheet" href="../style/normalize.css">

<link rel="stylesheet" href="../style/main.css">

</head>

<body>

<div id="wrapper">

<?php include('menu.php');?>

<p><a href="users.php">User Admin Index</a></p>

<h2>Add User</h2>

<?php

//if form has been submitted process it

if(isset($_POST['submit'])){

//collect form data

extract($_POST);

//very basic validation

if($username ==''){

$error[] = 'Please enter the username.';

}

if($password ==''){

$error[] = 'Please enter the password.';

}

if($passwordConfirm ==''){

$error[] = 'Please confirm the password.';

}

if($password != $passwordConfirm){

$error[] = 'Passwords do not match.';

}

if($email ==''){

$error[] = 'Please enter the email address.';

}

if(!isset($error)){

$hashedpassword = $user->create_hash($password);

try {

//insert into database

$stmt = $db->prepare('INSERT INTO blog_members (username,password,email) VALUES (:username, :password, :email)') ;

$stmt->execute(array(

':username' => $username,

':password' => $hashedpassword,

':email' => $email

));

//redirect to index page

header('Location: users.php?action=added');

exit;

} catch(PDOException $e) {

echo $e->getMessage();

}

}

}

//check for any errors

if(isset($error)){

foreach($error as $error){

echo '<p class="error">'.$error.'</p>';

}

}

?>

<form action='' method='post'>

<p><label>Username</label><br />

<input type='text' name='username' value='<?php if(isset($error)){ echo $_POST['username'];}?>'></p>

<p><label>Password</label><br />

<input type='password' name='password' value='<?php if(isset($error)){ echo $_POST['password'];}?>'></p>

<p><label>Confirm Password</label><br />

<input type='password' name='passwordConfirm' value='<?php if(isset($error)){ echo $_POST['passwordConfirm'];}?>'></p>

<p><label>Email</label><br />

<input type='text' name='email' value='<?php if(isset($error)){ echo $_POST['email'];}?>'></p>



<p><input type='submit' name='submit' value='Add User'></p>

</form>

</div>

admin/edit-user.php

<?php //include config

require_once('../includes/config.php');

//if not logged in redirect to login page

if(!$user->is_logged_in()){ header('Location: login.php'); }

?>

<!doctype html>

<html lang="en">

<head>

<meta charset="utf-8">

<title>Admin - Edit User</title>

<link rel="stylesheet" href="../style/normalize.css">

<link rel="stylesheet" href="../style/main.css">

</head>

<body>

<div id="wrapper">

<?php include('menu.php');?>

<p><a href="users.php">User Admin Index</a></p>

<h2>Edit User</h2>

<?php

//if form has been submitted process it

if(isset($_POST['submit'])){

//collect form data

extract($_POST);

//very basic validation

if($username ==''){

$error[] = 'Please enter the username.';

}

if( strlen($password) > 0){

if($password ==''){

$error[] = 'Please enter the password.';

}

if($passwordConfirm ==''){

$error[] = 'Please confirm the password.';

}

if($password != $passwordConfirm){

$error[] = 'Passwords do not match.';

}

}



if($email ==''){

$error[] = 'Please enter the email address.';

}

if(!isset($error)){

try {

if(isset($password)){

$hashedpassword = $user->create_hash($password);

//update into database

$stmt = $db->prepare('UPDATE blog_members SET username = :username, password = :password, email = :email WHERE memberID = :memberID') ;

$stmt->execute(array(

':username' => $username,

':password' => $hashedpassword,

':email' => $email,

':memberID' => $memberID

));

} else {

//update database

$stmt = $db->prepare('UPDATE blog_members SET username = :username, email = :email WHERE memberID = :memberID') ;

$stmt->execute(array(

':username' => $username,

':email' => $email,

':memberID' => $memberID

));

}



//redirect to index page

header('Location: users.php?action=updated');

exit;

} catch(PDOException $e) {

echo $e->getMessage();

}

}

}

?>

<?php

//check for any errors

if(isset($error)){

foreach($error as $error){

echo $error.'<br />';

}

}

try {

$stmt = $db->prepare('SELECT memberID, username, email FROM blog_members WHERE memberID = :memberID') ;

$stmt->execute(array(':memberID' => $_GET['id']));

$row = $stmt->fetch();

} catch(PDOException $e) {

echo $e->getMessage();

}

?>

<form action='' method='post'>

<input type='hidden' name='memberID' value='<?php echo $row['memberID'];?>'>

<p><label>Username</label><br />

<input type='text' name='username' value='<?php echo $row['username'];?>'></p>

<p><label>Password (only to change)</label><br />

<input type='password' name='password' value=''></p>

<p><label>Confirm Password</label><br />

<input type='password' name='passwordConfirm' value=''></p>

<p><label>Email</label><br />

<input type='text' name='email' value='<?php echo $row['email'];?>'></p>

<p><input type='submit' name='submit' value='Update User'></p>

</form>

</div>

</body>

</html>