Type a keyword and hit enter to start searching. Press Esc to cancel.

Wordpress Development

Recently I had a new client approach me with their website recently hacked.  The site on first load within the browser was redirecting to another ( frenkulok, oshona ).

First part to solving the problem is to see what it is being redirected to, and each of the stages.

Using Google Chrome Inspector, click into the console tab and ensure ‘Preserve Log’ is checked.  This allows the site to run on load and continue to logging whilst the redirect occurs

As you can see below there are a few XHR requests.  What we are looking for a certain keywords that we can use to do string search matches in our /wp-content files so that we can find where the script is sitting.  In this case, the first one I tried was ‘oshona.in’ an Indian domain that has nothing to do with the website.  This domain then has further control on what domains get redirected so that they can then update that at any time they want without having to update the code on the clients website.

Opening the first XHR request toggle, it showed that it was loading on line 1441 on the site, which was in the sites footer, so that was a good clue to being able to find it.

However to make it even easier to myself the next step was to install a temporary plugin called String locator.  Which can search for any string of text in the theme directory.

I searched the first suspect keyword that I was sure to be found in the website files somewhere, and very quickly this file popped up.  The footer.php file – as suspected in the parent theme.

Loading the file initially it displayed as what would appear as a normal footer.php file, however the code was hidden 80 lines off screen, scrolling down revealed the script hidden just before the </body> tag of the footer.

Select it all, and delete, and the final footer.php looked like the following.

Update the file to the server, and then hit save.

And to ensure this didn’t happen again, security was hardened on the site, and requested that the user update their password, and remove any plugins that were not essential.


Best of luck to anyone that has any of these problems in the future, usually pretty quick to fix, total of 5 mins to do, however can seem overwhelming if you aren’t familiar with some of the tools and methods that you can use to direct you to where the redirect script is triggering.

I’ve noticed that Elementor usually will have a FOUC (Flash of Unstyled Content) when building a new site – I ended up going an overly complicated route of pulling in the post id and printing out that pages specific css in the header.

But the answer is a lot simpler than I thought.

Simply go into Elementor Settings » Advanced CSS » Print Method » Internal Embedding.

IF your system is still doing this however I’ve put together a simple script that gets the post ID and then echos the pages specific styles into the header.  This is also great as well if you are using an AJAX navigation with Push state urls (PJAX), and using ELEMENTOR is part of what is being loaded via ajax. Keep in mind Javascript events will need to be destroyed and reinitialised each time.

global $post;
$elementorcss = "https://" . $_SERVER['SERVER_NAME'] .
"/wp-content/uploads/elementor/css/post-" . $post->ID . ".css";
<link rel='stylesheet' id='elementor-fouc-fix'
href='<?php echo $elementorcss; ?>' type='text/css' media='all' />;

Place this in your template or header, and walla ! you have your content styled again!

The negatives to note about this method:
Its not a registered style sheet in the WordPress admin header – so will be uneffected by caching plugins – possibly a good thing if you are getting css render issues.
And if you print this out in the body – for purposes of AJAX pages – it won’t be HTML valid – however it will still render perfectly fine.

Recently a project where I didn’t have access to a database, and only able to export the forms from within the wordpress administration – It was important to keep the same id’s as the other website.  The problem however is importing forms into a new database means also new ID’s as well.  And having the project linked with custom notification string that was going via Pardot to Sales force meant that both the website content / thank you pages / pardot strings and pardot console would all need to be updated and tested again.

For this you will need access to phpMyAdmin (your cPanel or custom wordpress hosting should give you access to this).

Navigate to wp_gf_form table – the only 2 tables we will edit is wp_gf_form and wp_gf_form_meta

From here you will see the following displayed.  For this example I am changing the contact form from ID 5 to ID 20.

Double click on the id and you can edit in the console – otherwise click edit at the start of the row.

Navigate to the wp_gf_form_meta table > Browse > Edit (row id 5)

Only 2 values need to be changed the ID at the top under value and at the bottom of the display_meta field, another ID will display.

Change these to the desired id – in my case it was 20.

And the form ID will change from 5 > 20

Linking all previous field ids, confirmations, and notifications.

Keep in mind this was what worked for me, if you have more complicated gravity forms, you may have other ID references, however for me it was simply changing 3 references in 2 tables – and in the process saving a lot of headaches, time and reducing room for human error.

I’ve recently had a situation where a client needed a ‘Terms and Conditions’ page hidden from search so that it made it harder for competitors to find where their demo software was installed – this of course doesn’t deter users that have a link to the page – however this is how it was designed so that targetted clients could get access to the page however competitors couldn’t.

  1. function hide_page_search($query) {
  2. if ( $query->is_main_query() ) {
  4. if ($query->is_search) {
  5. $query->set('post__not_in', array(5231));
  6. }}}
  8. add_action('pre_get_posts','hide_page_search');

Replace the ‘5231’ with the ID of the page you want removed.

Add this into your functions.php and check your search results – one less result will now show.

If you want more pages removed just add them after the id with a seperated comma.. eg. ‘5231, 921, 7290’.

A small feature that I always end up adding to most client websites I make, particularly larger template themes that I use for rapidly developing multiple projects is a very simple but useful shortcode for displaying the current year.

Paste this into your functions.php of your child theme.

/* create shortcode for displaying dynamic year in copyright footer */
function year_shortcode() {
   $year = date('Y');
   return $year;
add_shortcode('year', 'year_shortcode');

Place the year shortcode into any wordpress text edit / text field and it will print out the current year.


Ideal for including in footers or copyright content so that it’s always up to date (particularly if you start needing to edit an entire template page for just that one date or you don’t have easy access to those areas in your theme files.

Although wordpress has got better over the years with being able to combat spam issues, through DNS protection, various CAPTCHA, honeypot methods and the impressive Akismet service developed by AUTOMATTIC (the wordpress foundation).  I always just find that sites run better, are simpler to manage and less stressful to the customer by removing the whole concept of comments out of the software.

The following code is perfect for just stripping it out of the wordpress administration area and from theme files.

  1. // Remove comments from Wordpress completely
  2. // Disable support for comments and trackbacks in post types
  4. function df_disable_comments_post_types_support() {
  5. $post_types = get_post_types();
  6. foreach ($post_types as $post_type) {
  7. if(post_type_supports($post_type, 'comments')) {
  8. remove_post_type_support($post_type, 'comments');
  9. remove_post_type_support($post_type, 'trackbacks');
  10. }
  11. }
  12. }
  13. add_action('admin_init', 'df_disable_comments_post_types_support');
  14. // remove comments on front end
  15. function df_disable_comments_status() {
  16. return false;
  17. }
  18. add_filter('comments_open', 'df_disable_comments_status', 20, 2);
  19. add_filter('pings_open', 'df_disable_comments_status', 20, 2);
  20. // remove existing comments
  21. function df_disable_comments_hide_existing_comments($comments) {
  22. $comments = array();
  23. return $comments;
  24. }
  25. add_filter('comments_array', 'df_disable_comments_hide_existing_comments', 10, 2);
  26. // remove comments page in admin menu
  27. function df_disable_comments_admin_menu() {
  28. remove_menu_page('edit-comments.php');
  29. }
  30. add_action('admin_menu', 'df_disable_comments_admin_menu');
  31. // redirect user from accessing the comments page
  32. function df_disable_comments_admin_menu_redirect() {
  33. global $pagenow;
  34. if ($pagenow === 'edit-comments.php') {
  35. wp_redirect(admin_url()); exit;
  36. }
  37. }
  38. add_action('admin_init', 'df_disable_comments_admin_menu_redirect');
  39. // remove comments meta from admin dashboard
  40. function df_disable_comments_dashboard() {
  41. remove_meta_box('dashboard_recent_comments', 'dashboard', 'normal');
  42. }
  43. add_action('admin_init', 'df_disable_comments_dashboard');
  44. // remove comments from top admin menu bar
  45. function my_admin_bar_render() {
  46.     global $wp_admin_bar;
  47.     $wp_admin_bar-&gt;remove_menu('comments');
  48. }
  49. add_action( 'wp_before_admin_bar_render', 'my_admin_bar_render' );

Want the comments functionality back? – Remove the code and it will be restored.

By default WordPress will automatically delete anything added to trash after 30 days.
To disable the built in WordPress auto trash feature, you can use the following scripts:
Either disable the scheduled delete job as triggered by the wp_scheduled_delete() function.

  1. // Removes the job to delete from trash after 30 days.
  2. function my_remove_schedule_delete() {
  3. remove_action( 'wp_scheduled_delete', 'wp_scheduled_delete' );
  4. }
  5. add_action( 'init', 'my_remove_schedule_delete' );

Of you could just extend the days to an much higher number. The method above is probably the best, however it might be worth also including this as a fall back.

  1. // As a fallback, changes removal of trash after 30 days to infinite
  2. define( 'EMPTY_TRASH_DAYS', 1000000 );

Rather than extending / disabling the trash feature, you could just disable it, by setting the total days to 0. This will mean that when you click to delete, it skips the trash and is permanently deleted straight away.

  1. // Disables Trash - and permanently deletes post / image
  2. define( 'EMPTY_TRASH_DAYS', 0 ); // Zero days

The following Query can be run once in your functions.php file. This will remove all the varation weights from your woocommerce install, and allow your products to use the default weight that is set by the product.

  1. $querystr = "SELECT $wpdb->posts.ID, $wpdb->posts.post_type, $wpdb->postmeta.meta_id, $wpdb->postmeta.meta_key, $wpdb->postmeta.meta_value
  2. FROM `$wpdb->posts`, `$wpdb->postmeta`
  3. WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id
  4. AND `post_type` = 'product_variation'
  5. AND `meta_key` = '_weight'";
  7. $results = $wpdb->get_results($querystr, OBJECT);
  9. foreach ( $results as $result ) {
  10.   $metaid = $result->meta_id;
  11.   $table = "aus_postmeta";
  12.   $data = array('meta_value' => '');
  13.   $where = array('meta_key' => '_weight', 'meta_id' => $metaid);
  14.   $wpdb->update( $table, $data, $where );
  15. }

Currently, March 2014, there is a bug that does not show any external system fonts such as those loaded through Google Fonts and other remote font hosting services.  The bug will result in a page that will appear to have no text, until the page is repainted, which can be triggered by using inspect element, and removing, or resizing the page.  The only fonts, if any that do show are the ones that are referenced on your system, like Arial, Times New Roman and serif.

The code below is a modification of the one found in the Google Chrome bug issue queue that has helped me fix this up for a few clients.  Even though this is temporary, it is a little easier than telling the client to wait until Google Chrome patch an update.

  1. /* https://code.google.com/p/chromium/issues/detail?id=336476 */
  2. body, p, span, div {
  3.     -webkit-animation-delay:0.1s;
  4.     -webkit-animation-name:fontfix;
  5.     -webkit-animation-duration:0.1s;
  6.     -webkit-animation-iteration-count:1;
  7.     -webkit-animation-timing-function:linear;
  8. }
  10. @-webkit-keyframes fontfix {
  11.     from { opacity: 1;}
  12.     to   {opacity:1;}
  13. }

The Easy Way to use Google Fonts in Photoshop

Ever since Google Fonts came out, I have been a big fan of the ease of the use and integration of these fonts into the web – giving much more appetising selection than the standard 6-20 web safe fonts available since the late 90′s. A great cheer from both designers, developers and clients a like.

The previous methods the bridge the gaps have been using convoluted solutions like Cufón (Canvas replacement) or sIFR (flash embedded replacement – great for smooth fonts – bad for non flash friendly devices aka apple touch devices) – which really limited you to primary text areas like Headings – which can become an additional drag and introduces new issues and limitations – however props to them, still offer smooth font rendering and anti-aliasing – that Google Fonts still can’t offer on windows machines.

One of the most frustrating processes of Google Fonts however was using them in design mockups through Photoshop and other design programs. You would select the font » download » install » then reboot your app (photoshop) that you wanted to have it applied in. And if you missed a font or the client changed their mind you would need to go through the process again.

A much easier process now is through a company called Monotype SkyFonts aka SkyFonts (currently championed on by Google themselves) which allows you to install a program that syncs with your selected fonts that you want on your computer. So as fonts get new Glyphs updated, or anti-aliasing fixes, these will then sync through the cloud through to your desktop ready to use. Essentially it is “Desktop Fonts on Cloud Steroids”. Additionally if you don’t have a font on your system, you just search and click add to SkyFonts, and it will download install and push it live into your open program, and you can just apply the font straight away, so no more rebooting your application, a big timesaver depending on how large your document is, and how powerful your system can handle the open and closing. Much, much easier than it used to be. The only thing and final step that is not currently endorsed by SkyFonts at the moment, would be the complete selection of all fonts through Google Fonts – however these features may become available at later stages as the service improves.

Alternative font services as well are included currently such as fonts.com and MyFonts with more coming in the future. Missing and desirable ones would be for things like FontAwesome, which from what I can see are not available through the current 3 offered cloud sources. However as mentioned above, updates to Glyphs and additional characters, as definately seen with the progressive generations like FontAwesome, font cloud solutions like this are perfect – as they get there micro delta updates seeping through to your desktop in the background.

This simple Woocommerce WordPress script can be modified for a variety of purposes, such adding in Country specific currency symbols like AUD, USD, or appending additional information. The example below shows login or register links until they are logged in, and when logged in will see the normal price as listed.add_filter(‘woocommerce_get_price_html’,’members_only_pricing’);

function members_only_pricing($price){
if(is_user_logged_in() ) {
 return $price;
else {
 remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart' );
 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
 remove_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );
 return '&lt;a href="'.site_url('/wp-login.php?action=register&amp;redirect_to=' . get_permalink()).'"&gt;Login&lt;/a&gt; to view our prices.'; 

Place in your themes functions.php – Let me know how it goes.

The new WordPress 3.8 was released today, and the first thing I did was go through and look for any new annoyances with this big new interface change (yet to know whether I like it yet).

The first thing I noticed was that the column options in the Dashboard area was removed, and was only allowing 1-4 options based off css media queries.

  1. function add_back_dashboard_columns() 
  2. {
  3. add_screen_option(
  4. 'layout_columns',
  5.   array(
  6.      'max' =>; 2,
  7.      'default' =>; 1 ) );
  8. }
  9. add_action( 'admin_head-index.php', 'add_back_dashboard_columns' );

Too add the option back, and to set a max and a default option, use the function above and place in your themes functions.php file.

Sometimes when developing plugins or testing things on a WordPress website, you may end up some ghost or orphaned postmeta – and no posts.

This will delete all postmeta, where the post does not exist any more.

  1. DELETE FROM `wp_postmeta` WHERE wp_postmeta.post_id NOT IN (SELECT id FROM `wp_posts`)

If you need to delete the post and the postmeta via phpMyAdmin, you could use the following: Delete the postmeta first, then the post by post type or whatever your conditions may be.  In this example I have chosen to delete posts and postmeta if its post_type is a product.

  1. # Deletes ALL postmeta WHERE the post_type IS a product
  2. DELETE FROM `wp_postmeta` WHERE wp_postmeta.post_id IN (SELECT id FROM `wp_posts` WHERE post_type = 'product')
  4. # This THEN deletes ALL posts WHERE post_type IS a product
  5. DELETE FROM `wp_posts` WHERE post_type = 'product'

If you want to edit or add social icons to the end of WordPress Main menu, or any menu, you can use a filter to append what you want onto the end without having to hack with CSS, or overwrite your theme template files.

The following example appends a like button Icon to the end of the ‘secondary’ menu. You can wrap this in <li> tags as well if you want to preserve the formatting that has been applied to the menu – and float it right, or just use span or appropriate HTML tags that are suitable.

  1. // Add content to end of main menu
  2. add_filter('wp_nav_menu_items', 'menu_follow_icons', 10, 3);
  3. function menu_follow_icons($menu, $args) {
  5. $args = (array)$args;
  6. if ( 'secondary' !== $args['theme_location'] )
  8. return $menu;
  10. $follow = '<li>Facebook Icon or any HTML content Goes Here</li>';
  12. return $menu . $follow;
  13. }

This function checks if you want to target a particular menu by the systems menu name. In this case, the ‘secondary’ menu was targeted within a genesis theme.

If you have any feedback or suggestions, I’d love to hear your thoughts.