#!/bin/bash
#title			: wordpress_updater.sh
#description		: A simple wordpress updater script.
#author			: Cagri Ersen <cagri(dot)ersen(at)gmail.com>
#date			: 05.11.2013
#version		: 0.2    
#usage			: bash wordpress_updater.sh sitename
#			The sitename has to be a part of the wordpress installation path like: /var/www/SITENAME/
#			This is the most important thing since the script will detect the old wp installation directory
#			by using this value. (Also your web server must be up and running.)
#
#			Old wp files and mysql db will be backed up to specified place if the db user has enough priviliges like LOCK.
#			So that I highly recommend to take your db backup manually.

# -----------------------------------------
# VARIABLES :
# (Change these three values as your needs)
# -----------------------------------------
www_dir=/var/www/vhosts		# Where is your web root path ?
backups_dir=/backups		# Which directory that you want to place the backup files ?
download_dir=/root			# A directory for download and extracting wp files

# Don't change anything below
DATE=$(date +"%m-%d-%Y")
wp_package=$download_dir/latest.zip
wp_origdir=$download_dir/wordpress
domain_name=$1
nginx_confs=/etc/nginx/
apache_confs_deb=/etc/apache2/
apache_confs_rhel=/etc/httpd/

function isitOK() {
while true
do
echo -n "Please confirm ==> [ Yes / No ]: "
read isitOK
case $isitOK in
y|Y|Yes|yes|YES) break ;;
n|N|No|NO|no)
echo "Aborting..."
exit
;;
*) echo "Please type Yes or No"
esac
done
echo "OK! Continue..." && sleep 1
}

# Check if logged in as root
printf "\nDid you run the script as root ?\n" && sleep 1
if [[ $EUID -ne 0 ]]; then

	printf "\nNeed to be logged in as root to continue... \nPlease run the script with root privileges."
	exit 1	
	fi
printf "Yes you're root! Continue...\n\n" && sleep 1

# Check usage
if [[ -z "$1" ]]; then
    printf "\nPlease provide the sitename that you want to update,\nand it's should be a part of the wordpress installation path like: /var/www/SITENAME/

This is the most important thing since the script will detect the old wp installation \ndirectory by using this value.\n
Usage: ./wordpress_updater syslogs.org\n" && exit 0
fi

# Detect the old wp root directory from the web server config files and set it as $wp_old_dir variable.
printf "Detecting the old wordpress installation directory:\n" && sleep 2

# Detect the webserver's config file first
webserver=$(netstat -antp |grep LISTEN |grep ":80" |awk '{print $7}' |cut -d/ -f2)
if [ $webserver = apache2 ]; then
	http_conf_file=$(grep -r $domain_name $apache_confs_deb* |grep DocumentRoot |head -n 1 |awk '{print $1}' |tr -d ':')
elif [ $webserver = httpd ]; then
	http_conf_file=$(grep -r $domain_name $apache_confs_rhel* |grep DocumentRoot |head -n 1 |awk '{print $1}' |tr -d ':')
elif [ $webserver = nginx ]; then
	http_conf_file=$(grep -r $domain_name $nginx_confs* |grep "root " |awk '{print $1}' |tr -d ':' |head -n 1)
fi

# and than detect the wordpress installation path
if [ $webserver = apache2 ]; then
	wp_old_dir=$(grep -r $domain_name $apache_confs_deb* |grep DocumentRoot |head -n 1 |awk '{print $3}')
elif [ $webserver = httpd ]; then
	wp_old_dir=$(grep -r $domain_name $apache_confs_rhel* |grep DocumentRoot |head -n 1 |awk '{print $3}')
elif [ $webserver = nginx ]; then
	wp_old_dir=$(grep -r $domain_name $nginx_confs* |grep "root " |awk '{print $3}' |tr -d ';' |head -n 1)
fi

# check $wp_old_dir and continue if it's exist.
if [ -z "$wp_old_dir" ]; then
	printf "The old wp root dir couldn't be detected.\nProbably you didn't provide a correct sitename that mentioned on the usage section or your web server isn't running.\n
Aborting...\n" && exit 1
else
	printf "Detected as $wp_old_dir\n" && sleep 0.5 && isitOK && sleep 0.8
fi

if [ -f $wp_package ]; then
	printf "\nThere is an old version of wordpress zip package in the download directory. Removing...\n" && sleep 2 && mv $wp_package $wp_package.$DATE
	if [ -f $wp_origdir ]; then 
	  printf "\nThere is an unzipped wordpress directory that contains old version files in the download directory. Removing...\n" && sleep 2 &&  mv $wp_origdir $wp_origdir.$DATE
	else
	  printf "\nDownloading the latest wordpress package...\n\n" && sleep 2 && wget http://wordpress.org/latest.zip -O $wp_package
	fi
else 
	printf "\nDownloading the latest wordpress package...\n\n" && sleep 2 && wget http://wordpress.org/latest.zip -O $wp_package
fi

# Check download
wp_package_size=$(stat -c%s "$wp_package")
if [ $wp_package_size -gt 10240 ]; then
	printf "Download completed...\n" && sleep 1
else
	printf "\nWordpress package couldn't be downloded... Please check your internet connection...\n" && sleep 1 && exit 1
fi

# Extract the zip package
printf "\nExtracting the package...\n\n" && sleep 1 && unzip $wp_package -d $download_dir && sleep 1

printf "\n-------------------------------------------------------
In this section, the old (installed) and the new versions \nwill be detected to be sure.
-------------------------------------------------------\n" && sleep 3

# Detect the old wp version by parsing the old version.php
wp_old_version=$(cat $wp_old_dir/wp-includes/version.php |grep "wp_version =" |awk '{print $3}' |sed "s/[\;\']//g")
wp_old_version=$(echo $wp_old_version)

printf "\nYour old wordpress version is $wp_old_version\n" && sleep 0.5 && isitOK && sleep 0.5

# Detecting new wp version by parsing version.php
wp_new_version=$(cat $wp_origdir/wp-includes/version.php |grep "wp_version =" |awk '{print $3}' |sed "s/[\;\']//g")
wp_new_version=$(echo $wp_new_version)

printf "\nThe new wordpress version is $wp_new_version\n" && sleep 0.5 && isitOK && sleep 0.5

# Set the new wp directory
wp_new_dir=$www_dir/$domain_name-$wp_new_version.$DATE
printf "\nand the new wordpress installation directory will be $wp_new_dir\n" && sleep 0.5 && isitOK && sleep 0.5

# Move the new wp directory to the production place with a proper name.
printf "\nMoving the new wp directory to the production place as $wp_new_dir...\n" 
if [ -d $wp_new_dir ]
	then
	printf "Oooops.... The installation dir for the new version is already exist (which should not.) 
	Probably you've run this script and interrupt it before its completion. 
	Please review your directory structures and remove the new installation directory.\n" && sleep 2 && exit 1
fi
mv $wp_origdir $wp_new_dir && sleep 2

# replace default wp_content directory with the customized one
printf "\nReplacing the default wp_content directory with the old one...\n" && rm -rf $wp_new_dir/wp-content && cp -pr $wp_old_dir/wp-content $wp_new_dir/ && sleep 2

# Get the diff between the old and the new directories.
printf "\nGetting the differencies between the old and the new wordpress directories\n" && sleep 2
diff=$(diff -rq $wp_old_dir $wp_new_dir |egrep -v "differ|wp-admin|wp-include|revisions-js.php|$wp_new_dir" |awk '{print $3 $4}' |tr ':' '/')

# Copy the old customized files and folders to the new wp dir.
printf "\nCopying custom files and folders to the new wp dir...\n" && sleep 2
for my_wp_files in $diff 
	do target=$(echo $my_wp_files | sed "s#$wp_old_dir#$wp_new_dir#g") 
		echo "cp -pr $my_wp_files $target" && sleep 0.2
		cp -pr $my_wp_files $target
	done

# Check if there is ant .htaccess file on wp-admin directory and copy it to the new wp-admin
wpadminhtaccess=$(find $wp_old_dir/wp-admin -name ".htaccess")

if [ -n $wpadminhtaccess ]; then
    sleep 0.2 && echo "cp -pr $wpadminhtaccess $wp_new_dir/wp-admin/"
    cp -pr $wpadminhtaccess $wp_new_dir/wp-admin/
fi

sleep 2

##################################################
# Backup old wp dir and database to $backups_dir
##################################################

printf "\n-------------------------------------------------------
Backing up the old wordpress folder and the database
-------------------------------------------------------\n" && sleep 3

# Create Backup Dir
if [ -d $backups_dir ]
then
  printf "\nBackups dir exist.\n\n" && sleep 0.8
else
  mkdir -p $backups_dir
fi

# Backup the old wordpress directory
tar -czf $backups_dir/$domain_name-$DATE.tar.gz $wp_old_dir

# Get db credentials from old wp-config.php
wp_db_name=$(cat $wp_old_dir/wp-config.php |grep DB_NAME |awk '{print $2}' |sed -e s/\'//g -e s/\)//g -e s/\;//g)
wp_db_user=$(cat $wp_old_dir/wp-config.php |grep DB_USER |awk '{print $2}' |sed -e s/\'//g -e s/\)//g -e s/\;//g)
wp_db_password=$(cat $wp_old_dir/wp-config.php |grep DB_PASSWORD |awk '{print $2}' |sed -e s/\'//g -e s/\)//g -e s/\;//g)
wp_db_host=$(cat $wp_old_dir/wp-config.php |grep DB_HOST |awk '{print $2}' |sed -e s/\'//g -e s/\)//g -e s/\;//g)
wp_table_prefix=$(cat $wp_old_dir/wp-config.php |grep table_prefix |awk '{print $3}' |sed -e s/\'//g -e s/\)//g -e s/\;//g)
wp_url=$(mysql -u $wp_db_user -p$wp_db_password -e "use ${wp_db_name}; SELECT option_value FROM ${wp_table_prefix}options WHERE option_name='siteurl'" |tail -n 1)

# Check if mysqld alive
check_mysqld=$(mysqladmin -u ${wp_db_user} -p${wp_db_password} ping)

if [ "$check_mysqld" != "mysqld is alive" ]; then
   printf "\n\n MySQL'd does'nt work! We can't continue..\n Exit"
   exit 1
else
# Get the db backup
mysqldump -h $wp_db_host -u $wp_db_user -p${wp_db_password} $wp_db_name > $backups_dir/$wp_db_name.$DATE.sql
	if [ "$?" -ne 0 ]; then
		printf "\n It seems, we didn't take the db dump; probably your db user doesn't have enough privileges to take a dump.\nPlease backup your db manually...\n"
		isitOK
		sleep 1
	else
		gzip -1 $backups_dir/$wp_db_name.$DATE.sql		
	fi
fi
sleep 1
printf "\nAll files are backed up to $backups_dir \n" && sleep 2

printf "\n-------------------------------------------------------
Now the new version of wordpress directory is in place (including
your customized files) and the old directory path will be changed
with the new one in your webserver config file.\n
Here is a summary:
Your old wordpress installation dir = $wp_old_dir
New wordpress installation dir = $wp_new_dir
Old wordpress version = $wp_old_version
New wordpress version = $wp_new_version
Old wordpress installation dir = $wp_old_dir
New wordpress installation dir == $wp_new_dir
-------------------------------------------------------\n" && sleep 3
isitOK

# Change installation path in http conf file
sed -i.orig -e s#$wp_old_dir#$wp_new_dir#g $http_conf_file

# Set permissions
if [ $webserver = apache2 ]; then
	chown -fR root:www-data $wp_new_dir
	find $wp_new_dir/ -type f -exec chmod 644 {} \;
	find $wp_new_dir/ -type d -exec chmod 755 {} \;
	chmod 775 $wp_new_dir/wp-content/uploads 
elif [ $webserver = httpd ]; then
	chown -fR root:apache $wp_new_dir
	find $wp_new_dir/ -type f -exec chmod 644 {} \;
	find $wp_new_dir/ -type d -exec chmod 755 {} \;
	chmod 775 $wp_new_dir/wp-content/uploads
elif [ $webserver = nginx ]; then
	if [ -f /etc/redhat-release ]; then
		chown -fR root:nginx $wp_new_dir
	elif [ -f /etc/debian_version ]; then
		chown -fR root:www-data $wp_new_dir
	fi
	find $wp_new_dir/ -type f -exec chmod 644 {} \;
	find $wp_new_dir/ -type d -exec chmod 755 {} \;
	chmod 775 $wp_new_dir/wp-content/uploads
fi

# Reload http daemon to take the chnage effect
if [ $webserver = apache2 ]; then
    /etc/init.d/apache2 reload
elif [ $webserver = httpd ]; then
    /etc/init.d/apache2 reload
elif [ $webserver = nginx ]; then
	/etc/init.d/nginx reload
fi

# and trigger db upgrade
wget -q $wp_url/wp-admin/upgrade.php?step=1 -O /dev/null
