Cleaning up git history with git rebase

Git rebase is good when you want to combine some historical commits into one commit. This might be a good idea because your history contains too many unncessary test commits, or if you want to cut down the size of your git objects. On the other hand, changing history can be a dangerous thing, it means that everyone else using your repo needs to acknowledge the change by force pulling.

for example,

git log --oneline
291423b update setup
7732e24 update deployment files
5e0c60f Merge branch 'develop'
e656609 update paths
1f35b9a Merge branch 'develop'
c914ca6 update prod
746eff5 update readme
8754887 update readme
ce9563d update staging

Now we want to remove everything between 291423b and ce9563d. Basically, you want to crunch everything from 291423b down to a point in history, ie ce9563d. Here comes rebase.

git rebase -i ce9563d
pick 8c79382 update
pick 8754887 update readme
pick 746eff5 update readme
pick c914ca6 update prod
pick e656609 update paths
pick 7732e24 update deployment files
pick 291423b update setup

# Rebase ce9563d..cd268a9 onto ce9563d
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

Note that now the latest commit is at the bottom, exactly reverse of what you see in git log. If you delete any of the lines, the commit will be gone. This is a bad bad idea and its best not to do that, instead, use “f” or ‘s’ and leave the first commit as it is like so:

pick 8c79382 update
f 8754887 update readme
f 746eff5 update readme
f c914ca6 update prod
f e656609 update paths
f 7732e24 update deployment files
f 291423b update setup

# Rebase ce9563d..cd268a9 onto ce9563d
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

rebase will tell you if it encounters any problems. Fix them and you have to force push

git push origin --force

Software developer survival skills

To have a career as a developer, you need to have some important basic skill sets. All (new) technologies are built on top or around some commonly used technologies. People always say, “WOW, this technology is really hot now, you should learn it!”. Yes, but to even know the basics, it will take years to learn the pre-requisites.

Take a modern framework – Symfony for example, to know the framework well, you will need to know HTTP protocols, MVC, Object oriented methodologies, HTML, CSS, Javascript, Forms, Database Relationships, PHP, Version control, Basic Linux…etc.

Technologies evolved so fast that most University curriculum could not catch up. Most of the time. people spend years learning something that you only use 1% in your real job. That is why practical training is so important.

If you are looking to become a developer, learn these skills and you can branch off to anywhere:

1. Git and Git flow
2. HTML, CSS
3. Javascript
4. MVC and Object Oriented thinking
5. Basic system administration (bash scripting)

The last most important skill is personality. Be a human and don’t be a robot.

You will need these skills irregardless whether you want to be a front or backend developer majoring in any framework like rails, angularjs, nodejs, laravel, django, symfony…etc.

When is hardcoding good?

Hardcoding is always seen as a bad practice. It makes the code inflexible. For example, making the code aware of the environment itself is a good thing so that we can reuse the code and avoid code duplication. Here, we are trying to copy a file to a user directory.

cp doc.txt to $HOME/

is better than

cp doc.txt to alex/

If this snippet is used in a deployment script for example, it can save a lot of time.

However if this snippet is used in a live environment, using variables might not be good because it can cause unpredictable behaviour and makes troubleshooting harder. Hence, hardcoding in production environment becomes a good thing.

Custom ajax call in woocommerce

sometimes you need to update database via ajax. wordpress has tools to make it easy. Well not that easy…

here for example, we want to create a link that when clicked, automatically change the order status of a woocommerce order and insert some notes.

In the template,

<script>
function installer_action(id,istatus) {
	jQuery.ajax({
	   type: "post",
	   url: '<?php echo admin_url( 'admin-ajax.php' ); ?>',
	   data: "action=update_order_installer_status&nonce=<?php echo wp_create_nonce('nonce_update_order_installer_status'); ?>&id="+id+"&status="+istatus,  
	   success: function(data){
	   	console.log(data);
	   		jQuery('#order_status_'+id).html(data.status);
	   		jQuery('#installer_actions_'+id).html(data.note);
	   },
	   error: function(xhr, textStatus, errorThrown) {
	     // console.log(xhr.responseText);
	   }
	});
}
</script>

Note that we have to use nonce to prevent csrf. Now we need the html for the link:

<span id="installer_actions_<?php echo $post->ID; ?>">
  <?php
    echo "<a href=\"#\" onclick=\"installer_action('$post->ID','accepted')\">Accept Request</a> | <a href=\"#\" onclick=\"installer_action('$post->ID', 'rejected')\">Reject Request</a>";
  ?>
</span>

The content in the span will be replaced by the ajax.

then in your functions.php, you have a function that deals with the ajax call and return some json. For eg.

function update_order_installer_status() {
  check_ajax_referer( 'nonce_update_order_installer_status', 'nonce' );
  // we are safe now
  $order = new WC_Order($_POST['id']);
  $new_order_status = ($_POST['status'] == 'accepted') ? 'install-accepted' : 'install-rejected' ;
  $note = "Installer ".$_POST['status']." job on ".date('j F Y, g:i a');
  $order->update_status($new_order_status);
  $order->add_order_note($note, 1);

  $notes = $order->get_customer_order_notes();
  $order->note = $notes[0]->comment_content;
  $order->status = wc_get_order_status_name($order->get_status());
  wp_send_json($order);
}

add_action( 'wp_ajax_update_order_installer_status', 'update_order_installer_status' );
add_action( 'wp_ajax_nopriv_update_order_installer_status', 'update_order_installer_status' );

Creating custom pages in woocommerce

what if you want to have a custom page in woocommerce? For example a page called abc under my-account

best way is to use shortcodes. Create a new page under my-account, ie my-account/abc and put in the shortcode [abc_shortcode]

then in functions.php

function abc_function( $atts ){
	wc_get_template( 'myaccount/abc.php' );
}
add_shortcode( 'abc_shortcode', 'abc_function' );

now you need to create the abc.php file which can contain anything

Symfony: Quick way to change bundle name

You have generated a new bundle under src/Oldnamespace/oldbundle and decided to change the bundle name or move it to a new name space. Symfony doesn’t provide any tools to do that. Sounds like a tedious job…

There is no short cut to this solution but some Bash scripting can save your lots of time. Use it at your own risk. Mass replace could replace stuff that you dont want though..

# in the bundle folder
find . -type f | while read s; do sed -i 's/Oldnamespace\OldBundle/Newnamespace\NewBundle/g' $s ; done
find . -type f | while read s; do sed -i 's/OldnamespaceOldBundle/NewnamespaceNewBundle/g' $s ; done
find . -type f | while read s; do sed -i 's/OldnamespaceOldBundle/NewnamespaceNewBundle/g' $s ; done
# now renaming dir and files
find . | grep Article | xargs rename Article Page -

Once done, change the bundle folder name and configuration in app/AppKernel.php, app/config/routing.yml, app/config/config.yml

Installing phpmyadmin in hhvm

when installing phpmyadmin under hhvm and nginx especially, you might get an error like so:

“Error during session start; please check your PHP and/or webserver log file and configure your PHP installation properly”

this is due to hhvm settings, got /etc/hhvm/php.ini and comment out all the php options like so:

; php options
;session.save_handler = files
;session.save_path = /var/lib/php5
;session.gc_maxlifetime = 1440

restart hhvm and it should work.

How to harden and optimise whm/cpanel

Cpanel website provides some good tips to harden your server

After login to whm, go to configserver security & firewall and add your IP to the “allow ip” list.

https://documentation.cpanel.net/display/CKB/How+to+Prevent+Email+Abuse

WHM > Server Configuration > Tweak Settings, Mail -> Set Initial default/catch-all forwarder destination to false

https://documentation.cpanel.net/display/CKB/Tips+to+Make+Your+Server+More+Secure

go to security center -> security advisor and follows the advise from there.
-> Allow modsecurity and rebuilt apache.
-> Update password strength to something greater than 70
-> disable ssh password authentication
-> run security advisor and update as necessary

go to service configuration -> service manager and disables unused services like mailman.

if php is showing ini_set error, go to home -> service configuration -> php configuration editor and remove ini_set under safe_mode. might as well allow proc_open for composer. restart apache

If cannot access files after updating or transferring cpanel accts, try changing permission for all files. suphp means owner and group user must be acct user and all dir must be 755 and file 644.

find /home/user/public_html -type d -exec chmod 755 {} \;
find /home/user/public_html -type f -exec chmod 644 {} \;

To optimise php, use apc cache with fcgi

http://virtualhosts.dk/centos-6-with-cpanel-and-whm-using-litespeed-webserver-and-php-apc/step-6-install-php-apc-alternative-php-cache

or better still go for hhvm (but cpanel doesnt yet support this)

https://codeable.io/community/speed-up-wp-admin-redis-hhvm/

Deploying to wordpress from git

If you are using git and are writing plugins for wordpress, its a hassle to switch between the 2 SCM. Why not commit once and deploy to 2 places? that is what many people are trying to do.

this script does exactly that: https://github.com/benbalter/Github-to-WordPress-Plugin-Directory-Deployment-Script

Create a plugin first. I suggest using all lowercase, eg blarblar-blarblar-blarblar. create a repo for it in github. git clone that plugin in your plugins folder. Make all changes.

Create the version number in the readme and plugin master file.

copy the deploy.sh into the wp-content/plugins folder, one level above your plugin. then run:

 ./deploy.sh

you will be prompted to enter the name of the plugin and everything should work.

cpanel php exec – memory or cannot fork error

If you are using php, and try to run command line scripts containing php command, you will get a loop that fails with a warning “cannot fork” or memory error.

This is because you are most likely using suphp in cpanel. While suphp is popular, it fails misery when trying to execute php command line. You might have something like this:

exec(‘composer update’,$output);

to see the errors:

exec(‘composer update 2>&1’, $output);
print_r($ouput);

You could have use the php system() function instead. The result is the same. You will see lots of loops and php die with cannot fork error.

So what is the error? Google doesn’t reveal anything. The reason is that php by default is using /usr/bin/php which suphp works on top of. You need to use a php free from suphp and use the full path. try this

exec(‘/usr/local/bin/php /usr/local/bin/composer update 2>&1’, $ouput);
print_r($output);

it will work. viola!