WordPress – 9bit Studios https://9bitstudios.com Web Design, Themes, & Applications Sun, 13 Aug 2017 14:41:43 +0000 en-US hourly 1 https://wordpress.org/?v=4.8.2 Pagination in WordPress https://9bitstudios.com/2014/11/pagination-in-wordpress/ https://9bitstudios.com/2014/11/pagination-in-wordpress/#respond Mon, 10 Nov 2014 13:53:47 +0000 https://9bitstudios.com/?p=1012 You say “tomato” I say “tomoto.” You “pageination” I say “pagination.”

Whatever you call it pagination is something that has abounded on the web since forever. If you’re not 100% sure what term pagination refers to, its the numbered links at the bottom of a page of results. There are different variations, but it often looks kind of like this…

1 2 3 … 37 38 Next > Last >>

If you enter a Google, Yahoo, or Bing Search and scroll to the bottom you will see these numbered links that allow you to the next page of results. That’s one example, but it shows up in many other contexts on the web. There are certainly other ways to do things. Infinite scrolling, for example, which we explored here is another way that sites can give users continual amounts of content. Nonetheless, pagination still remains a very popular way to organize things on websites.

Speaking of popularity, (on a seemingly unrelated note) even as we enter 2015 — the time of writing this — WordPress is still one of the most popular content management systems on the Internet. Despite new up-and-comers on different platforms such as Ghost on Node.js, WordPress is currently still the dominant force for blogging and/or publishing content on the web. So it seems like it would be worth knowing how to fit these 2 popular entities (pagination and WordPress) together. So in what follows, we will look at how to implement this.

So the function we’ll be creating is fairly straightforward. We’ll be making use of the $paged global variable which set to the page number that WordPress is displaying. Then based off of this, we do a few conditionals to figure out where we are in the range of pages.

function create_pagination_markup($pages = '', $range = 4)
{
    $markup = '';
    
    $showitems = ($range * 2)+1;
    
    global $paged;
    if(empty($paged)) $paged = 1;
    
    if($pages == '')
    {
        global $wp_query;
        $pages = $wp_query->max_num_pages;
        if(!$pages)
        {
            $pages = 1;
        }
    }
    
    $pageText = __('Page','ninebit');
    $ofText = __('of','ninebit');
    $firstText = __('First','ninebit');
    $lastText = __('Last','ninebit');
    $previousText = __('Previous','ninebit');
    $nextText = __('Next','ninebit');
         
    if(1 != $pages)
    {
        $markup .= "<div class=\"pagination\"><span>".$pageText." ".$paged." ".$ofText." ".$pages."</span>";
        if($paged > 2 && $paged > $range+1 && $showitems < $pages) $markup .= "<a href='".get_pagenum_link(1)."'>&laquo; ".$firstText."</a>";
        if($paged > 1 && $showitems < $pages) $markup .= "<a href='".get_pagenum_link($paged - 1)."'>&lsaquo; ".$previousText."</a>";
    
        for ($i=1; $i <= $pages; $i++)
        {
            if (1 != $pages &&( !($i >= $paged+$range+1 || $i <= $paged-$range-1) || $pages <= $showitems ))
            {
                $markup .= ($paged == $i)? "<span class=\"current\">".$i."</span>":"<a href='".get_pagenum_link($i)."' class=\"inactive\">".$i."</a>";
            }
        }
    
        if ($paged < $pages && $showitems < $pages) $markup .= "<a href=\"".get_pagenum_link($paged + 1)."\">".$nextText." &rsaquo;</a>";
        if ($paged < $pages-1 &&  $paged+$range-1 < $pages && $showitems < $pages) $markup .= "<a href='".get_pagenum_link($pages)."'>".$lastText." &raquo;</a>";
        $markup .= "</div>\n";
    }
    
    return $markup;
}

Then all we need to do is echo it out where we need it…

<?php echo create_pagination_markup(); ?>

And voila, WordPress pagination.

]]>
https://9bitstudios.com/2014/11/pagination-in-wordpress/feed/ 0
AJAX and WordPress https://9bitstudios.com/2014/04/ajax-and-wordpress/ https://9bitstudios.com/2014/04/ajax-and-wordpress/#respond Sun, 06 Apr 2014 13:53:47 +0000 https://9bitstudios.com/?p=955 When the web moved from HTML4 to HTML5, the rise of AJAX based web applications came along with it. AJAX (which stands for Asynchronous JavaScript and XML) can mean a number of things but in practice it often refers primarily to the client/server interaction where JavaScript can be used to communicate with a server by making calls at various times under various conditions to send and receive data. This can be happening as often as you like in real-time without the user having to navigate to another webpage or refresh their browser (i.e. asynchronously).

AJAX

What is an example of this? Well, say I wanted to put a stock ticker on my webpage or in my web application. I could use JavaScript to make a call to a service like some stock-market API that will give me quotes on a particular stock, get the data back, and display it in the UI in a visually appealing manner. As these market prices update over time, I can periodically update the quotes that I’m displaying on the page. The format that the server returns data in really depends on the service you are calling. It can often be be XML (as the X in AJAX suggests) but another popular format is JSON. I actually like JSON a bit better, myself. The experience of parsing through everything in code just seems a bit cleaner so if there is the option to have the data you are trying to get returned to you in JSON, I’ll usually opt for that.

Because JavaScript is such a universally cross-platform language capable of running on so many different devices in different environments, this can be a great way for different applications to communicate with each other. The result, hopefully, is to give your users the best experience possible whether they are on desktop, mobile, tablet, or some other crazy device.

In the early part of the 21st century, something else that was and has been absolutely ubiquitous across the internet is WordPress. From it’s humble beginnings of being exclusively web-based blog software, it has transformed into essentially the most popular content management system (CMS) used for running small and medium sized websites or web applications.

In what follows, we can look at how we can undertake merging these 2 things together. We’re basically going to look at how we can send and receive JSON data to a WordPress database and read from and write to the tables within WordPress using AJAX.

So let’s get started…

WordPress Options

Perhaps the most common component of customizing WordPress is using options. When you save custom options to your WordPress database they get stored in the wp_options table. A lot of themes and plugins use these in settings panels where you can customize various aspects of whatever plugin or theme you are using. The way that they save these options is by storing them in the wp_options table. NOTE: Recall that the “wp_” is a prefix that is set in the the wp-config.php file and might vary from installation to to installation depending on how your original WordPress database was set up… but an _options table will always be there regardless of the prefix, and the way that you get and save the options will always be the same.

The way that you save an option is to give it a name…

add_option('my_cool_option', 'hooray'); 

And you can get each option by reading it, save it to variables, etc.

$hooray = get_option('my_cool_option');

It perhaps is not a particularly efficient arrangement as sometimes you have to read an individual option for customizing every little piece of your entire WordPress stack. As the number of plugins in use and other custom parts of WordPress start to grow, this can potentially cause some slowdown. However, if we were to leverage saving JSON to our wp_options table we can put multiple options into one entry. We’ll still have to pull the JSON down and parse through it, but it may be that this approach leads to less clutter within or WordPress options table. One thing’s for sure. We’ll definitely have that more AJAXy “appy” feel in our WordPress setup.

This article “AJAX in Plugins” on WordPress.org goes over essentially what we want to accomplish. It’s talking about things in the context of plugins, but the same components also apply to theme settings and other areas of WordPress as well.

Creating the Plugin

So let’s start by creating a place in our WordPress admin panel where we can try to get and post some AJAX data using JSON. It’s always a good idea to wrap what we’re doing up in a class and our plugin here will use the same approach. First things first, we’re going to want to add some generic activation and deactivation hooks for our plugin. We’re also going to want to add a menu item to the WordPress admin panel. The page that this menu item will go to will be in the home.php file and we’ll add that in the same directory as our plugin.

<?php
/* 
Plugin Name: 9bit Studios WordPress AJAX
Plugin URI: https://9bitstudios.com
Description: A plugin demonstrating AJAX in WordPress
Author: 9bit Studios
Version: 1.0.0 
Author URI: https://9bitstudios.com
*/

class NBS_WordPress_Ajax {
     
    function __construct() {
        register_activation_hook(__FILE__,  array($this, 'activation'));
        register_deactivation_hook(__FILE__,  array($this, 'deactivation')); 
        add_action('admin_menu', array($this,'add_admin_menu'));  
    }
     
    function activation() { 
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    }
 
    function deactivation() { 
        /* Nothing to do here */
    }

    function add_admin_menu() {  
        add_menu_page('WordPress AJAX', 'WordPress AJAX', 'publish_posts', __FILE__, array($this,"home"));
    }   

    function home() {  
        include('home.php'); 
    } 

}
$nbsAjax = new NBS_WordPress_Ajax();

The home.php file won’t be too complicated. Just a couple of places that we will hook our JavaScript to for getting and saving our options, and a panel to show some output.

Next we’re going to want to add our JavaScript/jQuery file. This will also go in the same directory as our plugin. The proper way to do this in WordPress is to use the wp_enqueue_script function. We can use the plugins_url() WordPress function and PHP’s dirname function and __FILE__ constant to specify the path to our plugin directory.

So our plugin now currently looks like this…

<?php
/* 
Plugin Name: 9bit Studios WordPress AJAX
Plugin URI: https://9bitstudios.com
Description: A plugin demonstrating AJAX in WordPress
Author: 9bit Studios
Version: 1.0.0 
Author URI: https://9bitstudios.com
*/

class NBS_WordPress_Ajax {
     
    function __construct() {
        register_activation_hook(__FILE__,  array($this, 'activation'));
        register_deactivation_hook(__FILE__,  array($this, 'deactivation')); 
        add_action('admin_footer', array($this, 'cool_options_javascript'));  
        add_action('admin_menu', array($this,'add_admin_menu'));  
    }
     
    function activation() { 
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    }
 
    function deactivation() { 
        /* Nothing to do here */
    }

    function add_admin_menu() {  
        add_menu_page('WordPress AJAX', 'WordPress AJAX', 'publish_posts', __FILE__, array($this,"home"));
    }   

    function home() {  
        include('home.php'); 
    } 

    function cool_options_javascript() { 
        $pluginDirectory = plugins_url() .'/'. basename(dirname(__FILE__));
        wp_enqueue_script("nbs-wp-ajax", $pluginDirectory . '/nbs-wp-ajax.js');
    }  

}
$nbsAjax = new NBS_WordPress_Ajax();

WordPress AJAX Functions

Now comes the fun part. We’re going to want to create the functions that will handle getting and setting our WordPress options. How does this work in WordPress? Well, as it turns out we can name our function whatever we want, but we have to attach it to a custom action hook and we have to make sure that we prefix our action hook name with “wp_ajax_”. There are a lot of places where WordPress uses specifically named strings as part of its functionality. WordPress is weird like that but that’s how it is and this is one of those cases. We’re going to want to create places to both get and save our options. We need to prefix the string with wp_ajax followed by our_function_name and separate the 2 with an underscore. So our action will be something like “wp_ajax_our_function_name.” So if we were to add these to our plugin it would look something like the following…

<?php
/* 
Plugin Name: 9bit Studios WordPress AJAX
Plugin URI: https://9bitstudios.com
Description: A plugin demonstrating AJAX in WordPress
Author: 9bit Studios
Version: 1.0.0 
Author URI: https://9bitstudios.com
*/

class NBS_WordPress_Ajax {
     
    function __construct() {
         
        register_activation_hook(__FILE__,  array($this, 'activation'));
        register_deactivation_hook(__FILE__,  array($this, 'deactivation')); 
        add_action('admin_menu', array($this,'add_admin_menu'));         
        add_action('admin_footer', array($this, 'cool_options_javascript'));
        add_action('wp_ajax_get_cool_options',  array($this, 'get_cool_options'));		
        add_action('wp_ajax_save_cool_options',  array($this, 'save_cool_options'));

    }
     
    /**** ACTIVATION ****/
     
    function activation() { 
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    }
 
    /**** DEACTIVATION ****/
    function deactivation() { 
        /* Nothing to do here */
    }


    /**** REGISTER MENU & PAGES ****/
    function add_admin_menu() {  
        add_menu_page('WordPress AJAX', 'WordPress AJAX', 'publish_posts', __FILE__, array($this,"home"));
    }     

    function home() {  
        include('home.php'); 
    } 

    function cool_options_javascript() { 
        $pluginDirectory = plugins_url() .'/'. basename(dirname(__FILE__));
        wp_enqueue_script("nbs-wp-ajax", $pluginDirectory . '/nbs-wp-ajax.js');
    }  

    function get_cool_options() {

    } 	
	
    function save_cool_options() {
    }      

}

$nbsAjax = new NBS_WordPress_Ajax();

As you can see, we’ve used the custom action hook names “wp_ajax_get_cool_options” and “wp_ajax_save_cool_options” that will be used to get an save options when we sent data to them using JavaScript / jQuery a bit later on. Then we give these custom action hooks callback function to run when data get gets sent to WordPress’ core AJAX handling PHP file. We can name these callbacks whatever we want. We don’t need to prefix them with anything.

Now let’s utilize WordPress’s $wpdb class and PHP’s json_encode function to create a way to get and save our data. In WordPress’ AJAX functions, data is going to be available to us via the $_POST variables that will get sent to us via AJAX. We’ll then serialize these variables as a JSON string, and save it to the database using WordPress’ update_option function. Lastly, we’re also going to want to return something back to tell the user that his/her save was successful. So in our callback that saves options, it might look something like the following…

function save_cool_options() {
    global $wpdb; // this is how you get access to the database

    $itemArray = array(
        'name' => $_POST['name'],
        'age' => $_POST['age'],
        'favorite_color' => $_POST['color'],
    );    
        
    $saveData = json_encode($itemArray);        
    update_option('cool_json_option', $saveData); 
    
    echo 'true';

    die(); // this is required to return a proper result
}

So as we can see, we’re going to save our option value under the name “cool_json_option.”

Our get_cool_options function is goign to be a bit simpler. All we have to do is get the option from the database and return it to the browser as serialized JSON (which is basically the format that it already is).

function get_cool_options() {
    global $wpdb; // this is how you get access to the database

    $cool_options = get_option('cool_json_option');
    echo $cool_options;

    die(); // this is required to return a proper result
} 

So now that we have our functions all set, we can start calling them with AJAX in JavaScript.

Accessing Our Functions With AJAX

By default, all WordPress AJAX requests are sent to the admin-ajax.php file found in the WordPress core in the wp-admin directory. Fortunately, there is a global variable set by WordPress called “ajaxurl” that points to this file so that we can use in our JavaScript as the URL where we want to send our POST request. So to get or set our options via AJAX we know we’re going to want to send a POST request to a function, but how are we going to tell WordPress which function we want to use to handle our data? Recall, earlier that we gave our action hooks very specific names prefixed by “wp_ajax_.” Well, here is where we’re going to make use of that. This involves sending WordPress an action value in the JSON object we’re going to POST. “action” is the name of the key, and the value will be wp_ajax_our_function_name. So our JSON object that we’re going to send will at least contain the following…

{ action: save_cool_options }

If we wanted to call our function to get our options back from the database, we’d just have to change the “action” value to get_cool_options. We still have to indicate which function we want to call and that’s why we still have to send data to let WordPress know which function we want to use for interchanging data (even if it only involves getting data back).

So to handle this, we’re going to want to send our AJAX requests on the event that gets fired when one of the elements that we defined in our home.php file is clicked. So to do this, we’d create our jQuery file that we’re including in our plugin as follows…

jQuery(document).ready(function($) {

    $('#nbs-ajax-get').click(function(){
    
        var mydata = {
            action: "get_cool_options",
        };

        // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
        
        $.ajax({
            type: "POST",
            url: ajaxurl,

            dataType: "json",
            data: mydata,
            success: function (data, textStatus, jqXHR) {
                var name = data.name;
                var age = data.age;
                var color = data.favorite_color;
				
                $('#display').html('<p>Name: '+name+' Age: '+age+' Favorite Color: '+color+' </p>');
				
            },
            error: function (errorMessage) {

                console.log(errorMessage);
            }
        
        });      
	
    });	
	
    $('#nbs-ajax-save').click(function(){
    
        
        var mydata = {
            
            action: "save_cool_options",
            name: 'Bob Jones',
            age: 35,
            color: 'green'
        };


        // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
        
        $.ajax({
            type: "POST",
            url: ajaxurl,

            dataType: "json",
            data: mydata,
            success: function (data, textStatus, jqXHR) {
                if(data === true)
                    $('#display').html('<p>Options Saved!</p>');		
            },
            
            error: function (errorMessage) {

                console.log(errorMessage);
            }
        
        });    
    
    
    });

});

So as we can see on the click events of getting and saving our option, we’re sending our POST requests to ajaxurl (/wp-admin/admin-ajax.php) and then getting data back. Depending on the result, we’re updating the display panel. If we click the button/link to save options and then we open our database and look at the wp_options table, we can see that serialized JSON is saved under the cool_json_option identifier as serialized JSON. If we click the button/link to get these options, assuming all goes well, we can see the panel updated with the values that we specify.

Conclusion

Thus concludes our brief cursory overview of utilizing AJAX in WordPress. Hopefully you found it helpful. Obviously to use this in a more in-depth manner, we’d want to implement more sophisticated error handling and utilization of data in the UI. But hopefully this gives you a good start to being well on your way with using AJAX in WordPress. Take a look at the files(s) below by installing the plugin and playing around with it to see if using JSON in your WordPress admin panel is a good fit for you.

Download Files
]]>
https://9bitstudios.com/2014/04/ajax-and-wordpress/feed/ 0
Create a Backup of Your WordPress Website Locally https://9bitstudios.com/2014/02/create-a-backup-of-your-wordpress-website-locally/ https://9bitstudios.com/2014/02/create-a-backup-of-your-wordpress-website-locally/#respond Tue, 18 Feb 2014 13:30:16 +0000 https://9bitstudios.com/?p=947 … (the hard way).

There are probably a lot of plugins out there that will walk you through this process, but we’re going to be doing this the hard way. Why would we want to do this the hard way? Well, sometimes doing things the hard way gives you a better understanding of the ins and outs of a system as a whole and how things work. And sometimes trying to do things the easy way breaks down and you’re not sure how to resolve the problem. Not all plugins work out of the box and you have to go through all of the necessary support channels to resolve the issue.

However, if you know what needs to happen to accomplish something from the outset, you can forgo any of the headache that comes with automated processes going wrong. So, let’s take a look at how we might accomplish this.

1. You’ll want to get your local environment set up. If you’re on windows you can use WAMP, and if you’re on a Mac you can use MAMP. Create a directory in your WAMP or MAMP www directory and name it something (e.g. my-local-site). This is where you are going to put all of the WordPress files from your site.

2. Using FTP (like FileZilla), pull down all of the files from your WordPress installation on your live server into the newly created directory.

3. Sign in to phpMyAdmin on your localhost (https://localhost/phpmyadmin/) and create a new database. If you have a WordPress stack, you’ve likely had some exposure to phpMyAdmin at some point or another. You don’t really need to do anything further with it at this point. This is where you’ll be importing the .sql file that you’re going to go get from the database on your live site.

4. Now, sign in to your webhost portal and access phpMyAdmin, however that is done on your host. Find the database that contains all of your WordPress data and click into it. If you are not sure which one it is, ask your webhost or systems administrator. You should see a big listing of WordPress tables, like wp_options, wp_posts, wp_postmeta, and others. Note that the “wp_” might be named something different depending on how you set up your site (or how it was set up for you). But you’re in the right place if the names after the _ look familiar.

3. Click on the “Export” button. This will take you to another page where you’ll save the database. Choose the “Save as File” option at the bottom and go ahead and choose “No compression”. This will save a .sql file for you to your machine.

4. Now go back to your local phpMyAdmin web portal click into the empty database you created earlier. Once you are in there, click the “Import” button. Navigate to the .sql file that you just downloaded, and click OK.

NOTE: Sometimes at this step you can get a common error stating that your database file is too big. If this is the case then you need to update your php.ini file to allow for larger file uploads. In WAMP, this file lives in bin/php/php5.4.3/php.ini. Note that your PHP version number might be different depending on which version of WAMP you’ve installed. Edit the php.ini file in notepad and search for the following at different places in the file…

post_max_size = 2M
...
upload_max_filesize = 2M

What this means is that PHP will only accept file uploads and posts up to 2 MB. If your database is larger than this, it will reject it.

But you can change the limit by simply changing these values…

post_max_size = 8M
...
upload_max_filesize = 8M

5. We now have the files we need and the database we need, but we need to go edit wp-config.php in the root directory of your WordPress installation to link up the two. In your localhost www directory go to the folder where you’ve installed all of your WordPress files and open up the wp-config.php file. You’re going to want to edit the following lines. The values set in these lines are probably configured for your live server and have appropriate usernames and passwords set for security purposes so they are probably filled out with a lot of data/values…

define('DB_NAME', 'wp1239823');

/** MySQL database username */
define('DB_USER', 'ivanuser');

/** MySQL database password */
define('DB_PASSWORD', 'superpassword#1234');

/** MySQL hostname */
define('DB_HOST', 'user.domainname.com');

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');

/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');

However, because we want to link these values up with our localhost web server, we need to change these values back to something that is more “default.” In the end you’ll probably want your file to looks something like this…

define('DB_NAME', 'wordpress');

/** MySQL database username */
define('DB_USER', 'root');

/** MySQL database password */
define('DB_PASSWORD', '');

/** MySQL hostname */
define('DB_HOST', 'localhost');

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');

/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');

The important part is your database name. Put the name of the database that you created in step 3 and imported your .sql file into. The database names of your live site and your local site do not have to be the same.

6. We’re almost there, but we just have to fix one final little thing. We need to tell WordPress that your site’s URL is not https://yourlivewebsite.com anymore. We need to tell it that your URL is now https://localhost/your-local-site

Really this can be done in one of 2 ways. Probably the easiest way is to add a couple of lines to your wp-config.php file. Look for the following line…

define('WP_DEBUG', false);

and immediately after it, add the following lines…

define('WP_HOME','https://localhost/your-local-site');
define('WP_SITEURL','https://localhost/your-local-site');

where “your-local-site” is the name of the directory that you copied all of the WordPress. What this does is tell WordPress that your site URL is now your local site and not your live site.

Another option is to go into the wp_options table in your database and edit the option fields there with these same values. Really, you should only do this if you are very comfortable with MySQL databases and your understanding of how WordPress options work.

More information on this can be found here on WordPress.org

7. Now if you go to https://localhost/your-local-site you might get a 404. Not to worry. This is likely because your .htaccess file has not been updated. Go to https://localhost/your-local-site/wp-admin. Sign in and go to “Settings” and click on “Permalinks.” All you have to do is click the “Save Changes” button, if all goes well this will update your URL paths for your site on the local box. The permalink option that you have selected on your live site should already be selected for you here but if for some reason it is not choose this option and click “Save Changes.”

Now, if you go to https://localhost/your-local-site you should be able to see your website running seamlessly on your local machine. This is a great place to do editing / testing and messing around with stuff without affecting anything on your live website.

]]>
https://9bitstudios.com/2014/02/create-a-backup-of-your-wordpress-website-locally/feed/ 0
Create a Google Maps Shortcode in WordPress https://9bitstudios.com/2013/09/create-a-google-maps-shortcode-in-wordpress/ https://9bitstudios.com/2013/09/create-a-google-maps-shortcode-in-wordpress/#comments Wed, 18 Sep 2013 17:09:44 +0000 https://9bitstudios.com/?p=905 Google Maps is one of the most widely used services on the internet. In the first decade of the 21st century, it and its counterparts like Mapquest and Bing maps have completely revolutionized how people find destinations. Before these came on the scene, people used to call each other up and ask for directions and write things like “2nd right after the gas station” on *paper*. How did we live like this? 😀

While there are definitely a lot of great and easy-to-use WordPress plugins out there (maybe, too many in a saturated WordPress plugin market), I’m a fan of not installing a plugin for every little thing if it is something that could be accomplished by adding a relatively small amount of code to a page. In what follows, we’re going to create a Google Maps shortcode to quickly integrate Google Maps into your website without the need for a plugin. That way you can just drop it into your editor and be on your merry way.

First, in order to get Google Maps to work in your WordPress site you’re going to want to include the JavaScript for Google Maps. If you wanted to, you could place the following in the <head> section of your header.php file…

<script src="" type="text/javascript"></script>

However, if you are using the “proper way” that you’re supposed to load scripts in WordPress using the wp_enqueue_script function you could add the following to your functions.php file or a class if you are wrapping your WordPress functionality up in classes

function enqueue_custom_scripts() {
    wp_register_script('googlemaps', ('https://maps.google.com/maps/api/js?sensor=false'), false, null, true);
    wp_enqueue_script('googlemaps');
}
add_action('wp_enqueue_scripts', 'enqueue_custom_scripts');

Here we hook our script registration to the wp_enqueue_scripts action hook.

For our shortcode we’re going to want a bunch of different options that we can set in the attributes of our shortcode. As can be found in the Google Maps Developer Documentation, there are a bunch of different elements of a Google map that we can customize.

First, we’re going to want to have an “id” attribute to support multiple maps on the same page. This can be a simple string value that we’ll use for our element that we create (which will be a <div>). Obviously, we’re going to want to be able to center the map around a locale that we specify. Unfortunately with Google Maps we can’t just pass in an address in code. Rather than dealing with parsing all of the different formats of addresses all the world over, Google Maps instead uses a latitude/longitude system. Fortunately, there are good services out there like this one from iTouchMap where you can enter an address and you’ll get the correct latitude/longitude coordinates back.

We’re going to want to control the zoom (how far away or how close we’re zoomed in to our locale) and we’re also going to want to be able to customize the “type” of map to initialize: satellite, terrain, roadmap, or hybrid. Finally, we’ll also want to add a click handler so that when we click on the marker, we get a message box that pops-up with a message. Width and height are also good things to specify so we can set how large we want our map to be.

So with all of those options taken into account the finished shortcode is below…

/*** Google Map ***/
function googleMapShortcode($atts, $content = null) 
{
    extract(shortcode_atts(array("id" => 'myMap', "type" => 'road', "latitude" => '36.394757', "longitude" => '-105.600586', "zoom" => '9', "message" => 'This is the message...', "width" => '300', "height" => '300'), $atts));
    
    $mapType = '';
    if($type == "satellite") 
        $mapType = "SATELLITE";
    else if($type == "terrain")
        $mapType = "TERRAIN";  
    else if($type == "hybrid")
        $mapType = "HYBRID";
    else 
        $mapType = "ROADMAP";  
        
    echo '<!-- Google Map -->
        <script type="text/javascript">  
        $(document).ready(function() {
          function initializeGoogleMap() {
    
              var myLatlng = new google.maps.LatLng('.$latitude.','.$longitude.');
              var myOptions = {
                center: myLatlng,  
                zoom: '.$zoom.',
                mapTypeId: google.maps.MapTypeId.'.$mapType.'
              };
              var map = new google.maps.Map(document.getElementById("'.$id.'"), myOptions);
    
              var contentString = "'.$message.'";
              var infowindow = new google.maps.InfoWindow({
                  content: contentString
              });
              
              var marker = new google.maps.Marker({
                  position: myLatlng
              });
              
              google.maps.event.addListener(marker, "click", function() {
                  infowindow.open(map,marker);
              });
              
              marker.setMap(map);
            
          }
          initializeGoogleMap();
    
        });
        </script>';
    
        return '<div id="'.$id.'" style="width:'.$width.'px; height:'.$height.'px;" class="googleMap"></div>';
} 

We also have to make sure that we register the shortcode. Add the following immediately after the googleMapShortcode function…

add_shortcode('googlemap','googleMapShortcode');

Then to use the shortcode you just have to do the following…

[googlemap id="myMap" zoom="9" latitude="21.306944" longitude="-157.858333" message="We are here"]

If you wanted to use this code outside of the WordPress Loop, such as your sidebar.php or footer.php files, you could use the following….

echo do_shortcode(‘[googlemap id="anotherMap" zoom="9" latitude="21.306944" longitude="-157.858333" message="We are here"]‘);

Now we have an easy way of adding Google Maps to our WordPress website!

]]>
https://9bitstudios.com/2013/09/create-a-google-maps-shortcode-in-wordpress/feed/ 9
WordPress Custom Posts and Plugins https://9bitstudios.com/2013/08/wordpress-custom-posts-and-plugins/ https://9bitstudios.com/2013/08/wordpress-custom-posts-and-plugins/#respond Sat, 31 Aug 2013 13:59:22 +0000 https://9bitstudios.com/?p=897 A lot has been written about WordPress over the years with a lot of the literature describing how flexible it is as a CMS and how you can, with a little know-how and a little work, turn it into whatever you want it to be. Much of this flexibility comes from the ability to register custom post types, where you can create “post types” of any kind within the WordPress CMS. For example, if I were using WordPress to run a company website I could create a “staff” post type, where every entry that I create would contain custom fields for the name of the staff member, their picture, their e-mail, and links to social media profiles. The same thing goes for just about any other post type you could think of: image galleries, sliders, portfolios, etc.

And if there is some functionality that you need that happens to be lacking in the native installation of WordPress, chances are you’ll be able to find something close to what you need in one of the tens of thousands of plugins that exist out on the web. By combining these 2 features (along with a host of others) WordPress is an immensely flexible content management system (CMS) and this is likely one of the reasons it has gained such popularity since it’s inception.

In what follows, we’re going to combine custom post types and WordPress plugin development and create a plugin that registers a custom “portfolio” post type and wraps all of the functionality for both the front and the back end within it. So we’re going to need to to create fields for the name of the portfolio item, fields for featured images, and fields for links to where the project is showcased. After we get through everything, this should give you a good roadmap to create any post type/plugin that you like. In fact, a lot of plugins do little more than register post types inside of some generic WordPress plugin scaffolding code. Because there is so much you can do with custom post types, this is often all you need.

We’re going to be wrapping our entire custom post type plugin up in a class. For reasons discussed in this article it’s a good idea to wrap functionality up in classes. Because we are using classes, it would be beneficial for you to have a fairly good grasp on some basics of object-oriented programming (OOP).

To get started we’re going to want to register all of the functionality we need initially within our constructor. Below is an empty constructor which we’ll be adding to. Notice that immediately following the class we create a new instance of the class. This is how we’ll actually get all of our code to run.

class NBS_Portfolio {

    function __construct() {

    }
}
$portfolio = new NBS_Portfolio();

You may have noticed that we’ve added “NBS_” to our class name. It’s often a good idea to add prefixes to your class names to prevent potential naming collisions. Although we could probably just name our class “Portfolio,” there is the outside possibility that some plugin or theme you have installed has a class that is also named “Portfolio”. I use NBS (for nine bit studios), but you could use whatever prefix you want. The only caveat to this is that you want to make sure that you don’t use “WP_” as a prefix. WordPress uses this prefix for its own native classes.

To start all we need is an activation and deactivation functions to our class. These are functions that WordPress looks for when users activate and deactivate plugins. We’re not actually going to be doing much with these functions. As a best practice, we’ll include a reference to an upgrade.php file that will be used to allow users to update their plugins if we were to ever host this plugin on the WordPress plugins repository.

class NBS_Portfolio {
    
    function __construct() {
        register_activation_hook(__FILE__,  array($this, 'activation'));
        register_deactivation_hook(__FILE__,  array($this, 'deactivation'));     
    }

    /**** ACTIVATION ****/
    
    function activation() { 
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    }

    /**** DEACTIVATION ****/
    function deactivation() { 
        /* Nothing to do here */
    }

}

__FILE__ is one of the magic constants in PHP. Essentially, it means path of the current file on the server.

Now we’re going to want to some action hooks. Action hooks along with filters are two of the most important functions used in WordPress plugin development. The way that WordPress works is that on every page load — a blog post, a page, or even a section of the dashboard/admin panel — there are all of these events that fire. These are events like “init” or “plugins_loaded” or “after_setup_theme” … basically a sequence of events that occur each time a WordPress page is loaded (which, again, also includes admin pages). Your job, as a WordPress developer, is to add to the functionality that occurs when one or more of these actions fire by adding callback functions to run code at the proper time. This is why it’s referred to as “hooking” to these actions with action hooks. We’re essentially hooking functionality onto the WordPress core by telling WordPress: “Load the WordPress core functionality when this action event occurs but also register this custom post type and add these pages to the admin panel to manage it.”

We can also add filters to WordPress events. Filters modify the output and/or the display of any data that WordPress shows be it posts, lists, images or anything else. Often times filters will be used to override the default display of certain types of result sets retrieved from the WordPress database.

Obviously, this is just a brief introduction and is not an exhaustive discussion of action hooks and filters. For more on these topics and other topics related to them, please consult the WordPress codex. But hopefully this is enough of an introduction to get started and things will likely get a little bit clearer we go along.

So getting back to our class that we were working on, let’s add our action hooks and filters to our constructor code…

class NBS_Portfolio {
    
    function __construct() {     

        register_activation_hook(__FILE__,  array($this, 'activation'));
        register_deactivation_hook(__FILE__,  array($this, 'deactivation')); 
        add_action('init',  array($this, 'create_portfolio'));
        add_filter("manage_edit-portfolio-post-type_columns",  array($this, "portfolio_edit_columns"));
        add_action("manage_posts_custom_column",   array($this,"portfolio_columns_display"));
        add_action("admin_init",  array($this,"add_portfolio_meta"));
        add_action('save_post',  array($this,'update_portfolio_meta'));   
    }
    
    function create_portfolio() { }
    
    function portfolio_edit_columns($portfolio_columns) { }    
    
    function portfolio_columns_display($portfolio_columns) { }

    function add_portfolio_meta() { }
    
    function update_portfolio_meta() { }
   
}

Here we have added a number of actions and filters in our constructor. The first parameter is the string name of the event that we are attaching our actions and filters to and the second parameter specifies the name of the callback function that will run when that particular event occurs. Notice too that we have added all of the callback functions that will run on those particular events to the class as well (though they’re empty now, we’ll be adding code to them shortly).

Registering a Custom Post Type

With the constructor code set up declaring the methods that our plugin will use, we can now fill out the body of each of these methods with code. The first thing we’re going to want to do is register our new post type that will be the backbone of the new functionality that our plugin adds to WordPress. We can use the register post type function to register our custom post type.

class NBS_Portfolio {
    
    function __construct() {     

        register_activation_hook(__FILE__,  array($this, 'activation'));
        register_deactivation_hook(__FILE__,  array($this, 'deactivation')); 
        add_action('init',  array($this, 'create_portfolio'));
        add_filter("manage_edit-portfolio-post-type_columns",  array($this, "portfolio_edit_columns"));
        add_action("manage_posts_custom_column",   array($this,"portfolio_columns_display"));
        add_action("admin_init",  array($this,"add_portfolio_meta"));
        add_action('save_post',  array($this,'update_portfolio_meta'));   
    }
    
    function create_portfolio() { 

        $portfolio_args = array(
            'label' => __('Portfolio', 'ninebit'),
            'singular_label' => __('Portfolio', 'ninebit'),
            'public' => true,
            'show_ui' => true,
            'capability_type' => 'post',
            'hierarchical' => false,
            'rewrite' => array('slug' => __('portfolio', 'ninebit')),
            'supports' => array('title', 'editor', 'thumbnail')
        );
        register_post_type('portfolio-post-type', $portfolio_args);

    }
    
    function portfolio_edit_columns($portfolio_columns) { }    
    
    function portfolio_columns_display($portfolio_columns) { }

    function add_portfolio_meta() { }
    
    function update_portfolio_meta() { }
   
}

NOTE: For my string values, I’m using the __(‘String name’, ‘ninebit’) convention because it is used to support localization where ‘ninebit’ is my unique domain for gettext. You should follow this convention wherever possible, but if perfer not to you could just pass the string value in directly.

Notice a couple of things here. The “rewrite” setting allows us to set what our URL will be when viewing single items of our particular post type. So in this case our URL for viewing a portfolio item’s page is going to be something like: https://yourwebsite.com/portfolio/my-portfolio-item. If you want “portfolio” to be something else, you just have to set it in the “rewrite” setting.

One thing that’s particularly important, notice how our actual post type is called “portfolio-post-type”? We could have easily just called our post type “portfolio.” However, with the way that WordPress handles rewriting rules if both the actual name of the post-type and the “rewrite” setting are exactly the same you can run into problems with 404 errors when trying to access single custom post type items. So just be sure to keep these 2 different. It’s unlikely that someone is going to want to name their rewrite “portfolio-post-type”, so we’re probably okay there.

Notice too that we can also set what our post type supports. The title field and editor field you’re probably familiar with as they are standard in WordPress pages and posts. But there may be some cases where we wouldn’t need the title, or editor field. Say we had an “image” post type for an image gallery and all we needed was one meta field to enter the URL to the image. In that case, we could leave “title” and “editor” out of the “supports” setting.

We’ll also give the user the ability to add a thumbnail for each post of our custom post type (which you may have seen before if you’ve worked with themes). We won’t really be using it because we’re going to set the path to our image in a meta field, but we’ll put it in there in case you want to use it in some manner later. It might actually be easier because with the thumbnail you get all of the handy native WordPress image picking functionality from the media manager when you add a thumbnail. Then to display the image on the front end, you’d just have to use the get_the_post_thumbnail function to get the path to the image.

Registering a Custom Taxonomy

Now we’re going to want to do something else: create a custom taxonomy by using the register_taxonomy function. A taxonomy in WordPress describes a concept like “categories” or “tags.” It’s essentially data that you can use to categorize your posts and custom posts in different ways. We could use the native WordPress categories here, but we’re going to want to have something that we can use to specifically categorize *only* our portfolio items. So we’ll create a “portfolio categories” taxonomy. We’ll call the register_taxonomy function and pass in a bunch of initializing data. We can just register our taxonomy in the same method that we registered our custom post type…

class NBS_Portfolio {
    
    function __construct() {     

        register_activation_hook(__FILE__,  array($this, 'activation'));
        register_deactivation_hook(__FILE__,  array($this, 'deactivation')); 
        add_action('init',  array($this, 'create_portfolio'));
        add_filter("manage_edit-portfolio-post-type_columns",  array($this, "portfolio_edit_columns"));
        add_action("manage_posts_custom_column",   array($this,"portfolio_columns_display"));
        add_action("admin_init",  array($this,"add_portfolio_meta"));
        add_action('save_post',  array($this,'update_portfolio_meta'));   
    }
    
    function create_portfolio() { 

        $portfolio_args = array(
            'label' => __('Portfolio', 'ninebit'),
            'singular_label' => __('Portfolio', 'ninebit'),
            'public' => true,
            'show_ui' => true,
            'capability_type' => 'post',
            'hierarchical' => false,
            'rewrite' => array('slug' => __('portfolio', 'ninebit')),
            'supports' => array('title', 'editor', 'thumbnail')
        );
        register_post_type('portfolio-post-type', $portfolio_args);

        register_taxonomy('portfolio-category', array('portfolio-post-type'), 
            array(
                'hierarchical' => true,                 
                'labels' => array(
                    'name' => __( 'Portfolio Categories', 'ninebit' ),
                    'singular_name' => __( 'Portfolio Category', 'ninebit' ),
                    'add_new_item' => __( 'Add Portfolio Category','ninebit' ),
                    'separate_items_with_commas' => __( 'Separate categories with commas', 'ninebit' ),
                    'add_or_remove_items' => __( 'Add or remove portfolio categories', 'ninebit' ),
                    'choose_from_most_used' => __( 'Choose from the most used portfolio categories', 'ninebit' ),      
                ),
                'show_ui' => true,
                'rewrite' => array('slug' => __('portfolio-category', 'ninebit')),
                'query_var' => true,
            )
        );

    }
    
    function portfolio_edit_columns($portfolio_columns) { }    
    
    function portfolio_columns_display($portfolio_columns) { }

    function add_portfolio_meta() { }
    
    function update_portfolio_meta() { }
   
}

There are a lot of different options that you can set for your custom taxonomy. A taxonomy can function like either categories or tags in that they can be grouped into sub-groups (like categories can be for regular blog posts) or not (like tags). The ‘hierarchical’ true/false setting that you pass in specifies whether to turn this component on or not (true = on, false = off). If this is set to true, then your custom taxonomy will behave like categories. If it is set to false, it will behave like tags do.

Customizing the Display of Columns in the WordPress Panel

For our next two functions, we’re going work on the display of the different columns in the WordPress admin panel when we enter the portfolio suction. The first uses the manage_edit_post_type function and sets the column headers (at the top of the table in the dashboard). The second uses the manage_posts_custom_column function and this handles what is actually going to be displayed in each column row. In our case we’re going to want to display the project title (which is a supported default built-in type) and our portfolio categories taxonomy (which is custom). Because we have set that as a custom configuration, we’re going to need to write some code to tell WordPress how to display this custom column.

class NBS_Portfolio {
    
    function __construct() {    

        register_activation_hook(__FILE__,  array($this, 'activation'));
        register_deactivation_hook(__FILE__,  array($this, 'deactivation')); 
        add_action('init',  array($this, 'create_portfolio'));
        add_filter("manage_edit-portfolio-post-type_columns",  array($this, "portfolio_edit_columns"));
        add_action("manage_posts_custom_column",   array($this,"portfolio_columns_display"));
        add_action("admin_init",  array($this,"add_portfolio_meta"));
        add_action('save_post',  array($this,'update_portfolio_meta'));   
    }
    
    function create_portfolio() {
        
        $portfolio_args = array(
            'label' => __('Portfolio', 'ninebit'),
            'singular_label' => __('Portfolio', 'ninebit'),
            'public' => true,
            'show_ui' => true,
            'capability_type' => 'post',
            'hierarchical' => false,
            'rewrite' => array('slug' => __('portfolio', 'ninebit')),
            'supports' => array('title', 'editor', 'thumbnail')
        );
        register_post_type('portfolio-post-type', $portfolio_args);

        register_taxonomy('portfolio-category', array('portfolio-post-type'), 
            array(
                'hierarchical' => true,                 
                'labels' => array(
                    'name' => __( 'Portfolio Categories', 'ninebit' ),
                    'singular_name' => __( 'Portfolio Category', 'ninebit' ),
                    'add_new_item' => __( 'Add Portfolio Category','ninebit' ),
                    'separate_items_with_commas' => __( 'Separate categories with commas', 'ninebit' ),
                    'add_or_remove_items' => __( 'Add or remove portfolio categories', 'ninebit' ),
                    'choose_from_most_used' => __( 'Choose from the most used portfolio categories', 'ninebit' ),      
                ),
                'show_ui' => true,
                'rewrite' => array('slug' => __('portfolio-category', 'ninebit')),
                'query_var' => true,
            )
        );

    }
    
    function portfolio_edit_columns($portfolio_columns) {
        
        $portfolio_columns = array(
            "cb" => "<input type=\"checkbox\" />",
            "title" => __('Project Title', 'ninebit'),
            "portfolio_categories" => __('Portfolio Categories', 'ninebit'),
        );
        return $portfolio_columns;
    }    
    
    function portfolio_columns_display($portfolio_columns) {
    
        global $post;
    
        switch ($portfolio_columns) {
            case "portfolio_categories":
                $item_terms = get_the_terms($post->ID, 'portfolio-category');
                $numItems = count($item_terms);
                $i = 0;
    
                if(!$item_terms)
                    echo "--";
                else {
                    foreach($item_terms as $item) {
                        if(++$i === $numItems) { // last item
                            echo $item->name;
                        }
                        else {
                            echo $item->name.", ";
                        }
                    }
                }
                break;
        }
    }
        
    
    function add_portfolio_meta() { }
    
    
    function update_portfolio_meta() { }    
   
}

If you wanted to add more columns for other taxonomies, you’d just need to add a key to the array for the column headers. You don’t have to do anything if it’s one of the built-in types, but if it’s another custom set of data then you’d need to add a case matching the associative array key to show the output in each column item.

Meta Boxes

Next we’re going to define some functionality when editing a single portfolio item in WordPress. More specifically, we’re going to add a “meta box” to our post type using the add_meta_box function. A meta box is simply some fields where we can attach some additional data to each custom post type. In our case, we’re going to want to add a field for a URL to a preview image and a field for a URL to our actual portfolio site. A lot of times a portfolio demo is external (because it is often a project you’ve done for a client that’s now live on the client’s web site). Because of this, we’re going to want to set a place where we can link to somewhere where our work is hosted.

In the function where we register our meta box using add_meta_box we need to specify a callback where we can set the actual markup for each field. We’ll do that by specifying the “portfolio_meta” function as this callback. We’ll also need to attach the functionality that we need when we’re actually saving a post. When this event occurs, we’re going to want to dig the current values out of our meta fields (based on the “name” attribute set in the <input> field HTML) and save them to the database using the update_post_meta function.

class NBS_Portfolio {
    
    function __construct() {      
        
        register_activation_hook(__FILE__,  array($this, 'activation'));
        register_deactivation_hook(__FILE__,  array($this, 'deactivation')); 
        add_action('init',  array($this, 'create_portfolio'));
        add_filter("manage_edit-portfolio-post-type_columns",  array($this, "portfolio_edit_columns"));
        add_action("manage_posts_custom_column",   array($this,"portfolio_columns_display"));
        add_action("admin_init",  array($this,"add_portfolio_meta"));
        add_action('save_post',  array($this,'update_portfolio_meta'));   
    }
    
    function create_portfolio() {
        
        $portfolio_args = array(
            'label' => __('Portfolio', 'ninebit'),
            'singular_label' => __('Portfolio', 'ninebit'),
            'public' => true,
            'show_ui' => true,
            'capability_type' => 'post',
            'hierarchical' => false,
            'rewrite' => array('slug' => __('portfolio', 'ninebit')),
            'supports' => array('title', 'editor', 'thumbnail')
        );
        register_post_type('portfolio-post-type', $portfolio_args);

        register_taxonomy('portfolio-category', array('portfolio-post-type'), 
            array(
                'hierarchical' => true,                 
                'labels' => array(
                    'name' => __( 'Portfolio Categories', 'ninebit' ),
                    'singular_name' => __( 'Portfolio Category', 'ninebit' ),
                    'add_new_item' => __( 'Add Portfolio Category','ninebit' ),
                    'separate_items_with_commas' => __( 'Separate categories with commas', 'ninebit' ),
                    'add_or_remove_items' => __( 'Add or remove portfolio categories', 'ninebit' ),
                    'choose_from_most_used' => __( 'Choose from the most used portfolio categories', 'ninebit' ),      
                ),
                'show_ui' => true,
                'rewrite' => array('slug' => __('portfolio-category', 'ninebit')),
                'query_var' => true,
            )
        );

    }
    
    function portfolio_edit_columns($portfolio_columns) {
        
        $portfolio_columns = array(
            "cb" => "<input type=\"checkbox\" />",
            "title" => __('Project Title', 'ninebit'),
            "portfolio_categories" => __('Portfolio Categories', 'ninebit'),
        );
        return $portfolio_columns;
    }    
    
    function portfolio_columns_display($portfolio_columns) {
    
        global $post;
    
        switch ($portfolio_columns) {
            case "portfolio_categories":
                $item_terms = get_the_terms($post->ID, 'portfolio-category');
                $numItems = count($item_terms);
                $i = 0;
    
                if(!$item_terms)
                    echo "--";
                else {
                    foreach($item_terms as $item) {
                        if(++$i === $numItems) { // last item
                            echo $item->name;
                        }
                        else {
                            echo $item->name.", ";
                        }
                    }
                }
                break;
        }
    }
        
    
    function add_portfolio_meta(){
        add_meta_box("portfolio_details", __("Portfolio Item Details", 'ninebit'), array($this, "portfolio_meta"), "portfolio-post-type", "normal", "low");
    }
    
    function portfolio_meta() {
        
        global $post;
        $custom = get_post_custom($post->ID);
        $website_url = isset( $custom['website_url'] ) ? $custom['website_url'][0] : "";;
        $preview_image = isset( $custom['preview_image'] ) ? $custom['preview_image'][0] : "";
        wp_nonce_field('nbs_meta_box_nonce', 'meta_box_nonce');
    
        echo '<p><label>'.__('Preview Image', 'ninebit').':</label><br />';
        echo '<input name="preview_image" id="nbs-meta-preview-image" style="width: 97%;" value="'.$preview_image.'" /></a></p>';
        
        echo '<p><label>'.__('Website URL', 'ninebit').':</label><br />';
        echo '<input name="website_url" style="width: 97%;" value="'.$website_url.'" /></p>';
        
    }
    
    function update_portfolio_meta() {
    
        global $post;
    
        if( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
        return;
    
        if(!isset( $_POST['meta_box_nonce'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'nbs_meta_box_nonce' ))
        return;
    
        if(!current_user_can('edit_post'))
        return;
    
        if(isset($_POST["website_url"]))
        update_post_meta($post->ID, "website_url", $_POST["website_url"]);
    
        if(isset($_POST["preview_image"]))
        update_post_meta($post->ID, "preview_image", $_POST["preview_image"]);
    }    
   
}

We are also using a nonce for a little extra security.

Front End

Now that we have all of our functionality there in our plugin, how would we go about displaying this on the front-end? To do this, all we need to do is use WP_Query to loop through our custom post type entries and display them. We could do something like the following in a page template file or a shortcode that we’ve registered…

$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$wp_query = new WP_Query( array('post_type' => 'portfolio-post-type', 'ignore_sticky_posts'=>1, 'posts_per_page' => 6, 'paged'=>$paged) );
while ( $wp_query->have_posts() ) : $wp_query->the_post(); 

    $custom = get_post_custom($post->ID);
    $preview_image = $custom["preview_image"][0];
    $website_url = $custom["website_url"][0];

    echo '<a href="'.$website_url.'"><img src="'.$preview_image.'" alt="'.get_the_title().'" /></a>';
    echo '<h3>'.get_the_title().'</h3>';
    echo '<a href="'.$website_url.'">View Project</a>';

endwhile;

Of course, we’d probably want to add a few more <div> elements to our output with some classes so we could use CSS to style it up all nice, but all of the basic elements that we need are there.

Page templates are nice, but sometimes you also may want to access the elements of your portfolio on another page (say like on the home page of your website to showcase your most recent projects). To do this, we can register a shortcode to our plugin. A lot of the code will be very similar to what we did in the page template.

The first thing we’re going to want to add a shortcode to our constructor…

class NBS_Portfolio {

    function __construct() {
        
        register_activation_hook(__FILE__,  array($this, 'activation'));
        register_deactivation_hook(__FILE__,  array($this, 'deactivation')); 
        add_action('init',  array($this, 'create_portfolio'));
        add_filter("manage_edit-portfolio-post-type_columns",  array($this, "portfolio_edit_columns"));
        add_action("manage_posts_custom_column",   array($this,"portfolio_columns_display"));
        add_action("admin_init",  array($this,"add_portfolio_meta"));
        add_action('save_post',  array($this,'update_portfolio_meta'));
        add_shortcode('portfolio', array($this, 'display_portfolio_shortcode'));   
    }

...

Then we just have to add the following method to our class…

...

function display_portfolio_shortcode($atts, $content = null) {

    $wp_query = new WP_Query( array('post_type' => 'portfolio-post-type', 'ignore_sticky_posts'=>1, 'posts_per_page' => 6, ) );

    $portfolioMarkup = '';

    while ( $wp_query->have_posts() ) : $wp_query->the_post(); 

        $custom = get_post_custom($post->ID);
        $preview_image = $custom["preview_image"][0];
        $website_url = $custom["website_url"][0];

        $portfolioMarkup .= '<a href="'.$website_url.'"><img src="'.$preview_image.'" alt="'.get_the_title().'" /></a>';
        $portfolioMarkup .= '<h3>'.get_the_title().'</h3>';
        $portfolioMarkup .= '<a href="'.$website_url.'">View Project</a>';

    endwhile;

    return $portfolioMarkup;

}

The difference here is that in this case we are returning markup instead of echoing it out to the browser.

Now when the user types the [portfolio] shortcode into their editor WordPress will parse the shortcode and execute our code to return the portfolio markup. The name of the shortcode is specifed as the first parameter in the add_shortcode function. We set it to “portfolio” but you could change it to anything else that you wanted to.

If we wanted to we could also set some attributes for our shortcodes for the user to pass in to customize the output of the portfolio items. For more information on how to do that, see the WordPress shortcode documentation.

Conclusion

So there you have it. What we have done here is useful because we have covered a substantial amount of the details involved in customizing WordPress via custom posts the form of a plugin. There will be challenges involved in extending the functionality further in other ways, but most of it likely involves expanding on the topics discussed above in some manner or another. You could basically repeat this process with other custom post types and extend the functionality of WordPress however you want! Because we’ve covered such a wide array of topics, we’ve only scratched the surface of many of these topics. So be sure to consult the WordPress codex for all of the options that you can utilize for the functions that we’ve covered to further customize your post types to suit your needs.

You can grab the final code below. Extract the plugin to the wp-content/plugins directory and then login to your WordPress dashboard and activate it. It also has some metadata in the comment added to it to distinguish it from other plugins in the plugin section of the WordPress dashboard. This is discussed in the WordPress documentation for writing plugins

Demo Files

Until next time… happy WordPressing!

]]>
https://9bitstudios.com/2013/08/wordpress-custom-posts-and-plugins/feed/ 0
How to WordPress – Install WordPress on WAMP Server https://9bitstudios.com/2013/05/how-to-wordpress-install-wordpress-on-wamp-server/ https://9bitstudios.com/2013/05/how-to-wordpress-install-wordpress-on-wamp-server/#respond Sat, 25 May 2013 15:01:17 +0000 https://9bitstudios.com/?p=853 Welcome to another episode of “How to WordPress”.. an ever-continuing collection of WordPress how to tutorials, resources, and videos.

In this session of “How to WordPress” we’ll discuss how to install WordPress on WAMP Server. Recall that in a previous episode we looked at how to install WAMP Server. Now that we have that in place we can install WordPress on WAMP Server and start running our installation just as we would be doing if this were a production environment. There are a lot of benefits to having a local WordPress setup. We can do all of our editing of pages and posts offline before publishing them. We can do our theme development locally. And we can install different plugins to test them out to see if we like them and we don’t have to worry about mucking up our production environment.

Those using Macs will want to look into MAMP server, which is essentially the same idea behind WAMP server (only for Mac).

Video below…

]]>
https://9bitstudios.com/2013/05/how-to-wordpress-install-wordpress-on-wamp-server/feed/ 0
How to WordPress – Set Up a Local Web Server for WordPress https://9bitstudios.com/2013/05/how-to-wordpress-set-up-a-local-web-server-for-wordpress/ https://9bitstudios.com/2013/05/how-to-wordpress-set-up-a-local-web-server-for-wordpress/#respond Fri, 17 May 2013 12:24:47 +0000 https://9bitstudios.com/?p=847 Welcome to another episode of “How to WordPress.” How to WordPress is an ongoing collection of WordPress how to resources, tutorials, and videos aimed at making a better WordPress experience for both beginners and seasoned vetrans alike.

In this episode of “How to WordPress” we look at an all important first step: setting up a local installation of a web server using WAMP Server. There is also a MAMP server available for Mac users. What “setting up a local web server” means is that you can run a website or web application entirely on your own computer and have things run just as they would (or close to it at least) as if it were your live server that hosts your website out on the internet. So you could run an entire WordPress website entirely self-contained on your own personal machine. Your local setup is not exposed to the Internet, no nobody can access your site or see anything you’re doing.

Setting up a local web server is great for development, testing, and experimenting with anything else that you might want to do before you push something live to your production server on the Internet. This particular video is more of a general overview of the installation process, but it’s still a very important first step in getting WordPress set up locally.

]]>
https://9bitstudios.com/2013/05/how-to-wordpress-set-up-a-local-web-server-for-wordpress/feed/ 0
Create a Theme Config File in WordPress https://9bitstudios.com/2013/05/create-a-theme-config-file-in-wordpress/ https://9bitstudios.com/2013/05/create-a-theme-config-file-in-wordpress/#respond Wed, 01 May 2013 14:18:30 +0000 https://9bitstudios.com/?p=839 One of the aspects of WordPress that people really like is the ability to add options. This is something that WordPress theme and plugin creators use heavily. They’ll create an options page or pages so that anyone who uses their theme or plugin can customize numerous different components of the theme… everything from look and feel, to contact form data, to portfolios, to just about anything else under the sun. Creating an option is as easy as storing adding an option:

<?php add_option('nbs_background_color', '#FFCC66'); ?>

Then to use an option in your webpages you just need to call get_option…

get_option('nbs_background_color')

Note: Notice that I used the prefix “nbs” (for Nine Bit Studios) before my option name. This is a common practice to prevent potential collision with other options because each option has to have a unique name. It’s very possible that another plugin that I have installed may have used the option “background_color”. By adding a prefix this is no longer an issue.

That’s all well and good, but there are a few potential downsides to this. For one, depending how your options are set up, it can be a fair amount of work to add, update, or remove options because you have to edit the code to register the option, edit the form for the user to set or update the option, edit the code to handle the values they set, etc. Hopefully, you have your theme or plugin options set up such that making changes is as smooth and easy as possible. It’s not a difficult process, but it can get a bit involved as the number of options that you want to handle grows in size and complexity.

On top of this, when you deactivate themes or plugins, options do not necessarily get deleted. As a result, there’s the potential that you’ll have old unused options lingering around in your wp_options table which is not the best situation for efficiency. There are plugins out there that supposedly are able to do clean up for you, but their efficacy likely varies (as with many things) :).

All that being said, options should still be used for most of your theme or plugin configuration since they are the default go-to for customizations of WordPress installs. You’ll want to give your less tech-savvy users an easy interface to customize things. But as WordPress continually grows in maturity from being not just a blogging platform as it was in it’s early days, to a full-fledged CMS, and even on to a web application platform, there comes a desire to start introducing some useful components that have been popular and effective in other web application platforms. One of these things that you’ll often find in web application platforms like Django, CodeIgniter, Laravel and countless others is a main “config” file where all sorts of constants can be set. These are useful for everything from running debug code, to setting name strings, to language settings, to charsets, to whatever else. It can be pretty much anything you want.

WordPress uses this approach with its wp-config.php file. It’s the file you edit when you first set up and install WordPress where you set your database name, password, prefix, and a number of other settings. You can also set other settings here as well by adding definitions to this file. For example…

define('WP_DEBUG', false);
define('WP_ALLOW_MULTISITE', true);
define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', false);
define('DOMAIN_CURRENT_SITE', 'localhost');
define('PATH_CURRENT_SITE', '/central/');
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);
define('WP_POST_REVISIONS', false );

Here you can see there are debug settings, multisite settings, post-revision settings and a number of others. This is a great place for adding values that will never change (or will only need to be changed when pushing from a development environment to production or vice-versa). A lot of times database names and site base URLs with be different from one environment to the next. The great thing about config files is that if you make a change in one place, you make a change everywhere across all of your files.

However, if you wanted to define constants that are only applicable to your theme or plugin, the wp-config.php file is probably not be the best place to do it because if you were to change you theme or plugin those settings would go away. So another option is creating a theme-config.php file and putting it into the root of your theme directory. Then at the very beginning of your functions.php file, include your theme-config file…

include('theme-config.php');

Now you can add your own constants to this file and then use them across all of your theme files. Below is an example of a few constants that I might set my theme config files.

<?php 

define("NBS_THEME_NAME", "9bit Studios");
define("NBS_THEME_PREVIEW", TRUE);

?>

Note: Here again I have prefixed the definitions with “NBS” (for Nine Bit Studios) so that there is no collisions with duplicate constant names.

The first is my “Theme Name”. I actually use this as a string to set menu names and page titles in the theme options of my WordPress. The “theme preview” constant is just a toggle that configures whether or not to show a little preview panel where you can dynamically change font sizes, colors, and other visual display components directly on the page. You see these used a lot in premium themes. All I need to do to remove this when moving the theme to production or shipping it is to set this value to false. Change once, change everywhere.

Then in your code, you can use the constant wherever you like…

My theme name is <?php NBS_THEME_NAME ?>

For a theme preview you’d just have to set the condition in your code…

<?php 

if(NBS_THEME_PREVIEW) {

    // code to show theme preview panel here

}

?>

So here we have essentially used variables for our theme much in the same way when we use WordPress options. However, we haven’t had to write the form to record the option into the admin panel we haven’t had to write the code to go retrieve it from the database. We’ve achieved something that’s functionally the same, but the process is as easy as editing a text file.

What about plugins? Well, the same thing applies there. It’s a fairly straightforward process to create a plugin-config.php file and include it on initializing the plugin. Like with theme-options.php, you can use it to set any value that you want and have it be specific only to the plugin and have it not affect anything else in your WordPress installation if you choose to deactivate it one day down the road.

Should your theme-config.php and plugin-config.php values replace options? No… especially not for items you want your end-user to be able to customize. But they can be a great supplement to options? Absolutely! They can be especially useful for values that you as the developer are interested in handling (i.e. those that not need to be set by an end-user in the theme options or plugin options). They can be great for test and can be great for quick customizations when moving your theme or plugin from development to production. They can be incredibly useful if you so choose to use them.

]]>
https://9bitstudios.com/2013/05/create-a-theme-config-file-in-wordpress/feed/ 0
Add Additional Comment Form Validation in WordPress https://9bitstudios.com/2013/04/add-additional-comment-form-validation-in-wordpress/ https://9bitstudios.com/2013/04/add-additional-comment-form-validation-in-wordpress/#respond Mon, 22 Apr 2013 15:25:21 +0000 https://9bitstudios.com/?p=829 Spam is inevitable. It’s just a reality of life on the Internet. And if you have a blog or a website running WordPress and you open up your comments form, spam is going to come your way. Fortunately there are great tools such as the WordPress staple Akismet or Antispam Bee that you can use to catch spam in your spam filter. But even though these sorts of tools provide an extra layer of protection, I also think it’s still a decent practice to to moderate all comments because there are times when those spammy comments can still sneak through.

What is the downside to this? Well for one, you’re going to have to be actively monitoring your blog spam filter because there is always the possibility that some actual legit comments get caught in the filter. But if you get a lot of spam, this isn’t really feasible. Who want’s to sift through 10,000 spam comments about larger penises or Louis Vitton handbags on a daily basis. If you’re into those things maybe you do… but for most, they’d probably rather not.

Fortunately there are ways to reduce the number of spam comments that actually get through into your filter. Before I implemented the following approach, I used to get hundreds and hundreds of spam comments a day in my spam filter. After this though, I reduced the amount that came through to around 10% of what it was. On that note, I just want to reiterate though that, this is not a bulletproof solution. You are still going to get some spam (so don’t go setting your WordPress settings to “Allow all comments all the time” just yet). But what this can do is provide a little extra validation to stop some of the the dumber bots from continually hammering your comment form submission system. Less spam to sort through is always a better situation overall. Nobody wishes for more spam.

We are going to add a nonce to our WordPress comment form to provide some additional validation. A nonce is as stated on the WordPress codex…

The nonce field is used to validate that the contents of the form request came from the current site and not somewhere else. A nonce does not offer absolute protection, but should protect against most cases. It is very important to use nonce fields in forms.

You can find more information on the general use of nonces elsewhere on the web. They’re not specific or unique to WordPress.

But what’s great about this is that you don’t even have to limit this additional validation to nonces. You could repeat this process and provide additional fields of validation by adding to the following areas of code and you wouldn’t even have to create new functions or anything. You could just add to the functions below.

In your functions.php file (or wherever you are handling your functionality) add the following 2 functions and the corresponding action hook and filter.

 function nbs_additional_comment_validation($comment_data) {
    if(!isset( $_POST['comment_nonce'] ) || !wp_verify_nonce( $_POST['comment_nonce'], 'nbs_comment_nonce' ))
        exit;
    else 
        return $comment_data;
}
add_filter('preprocess_comment', 'nbs_additional_comment_validation');

function nbs_additional_fields () {
    wp_nonce_field('nbs_comment_nonce', 'comment_nonce');
} 
add_action('comment_form_after_fields', 'nbs_additional_fields' );

NOTE: I use the “nbs_” (for Nine Bit Studios) prefix for naming my functions that occupy the global namespace to prevent collision and duplicate function definition errors. This is good practice and you should do it with your global custom functions as well. Or, you could wrap your functions in classes as an alternative.

What this code does is add the nonce comment field by hooking into the “comment_form_after_fields” action. You could add any additional validation fields that you wanted to this function. wp_nonce_field echos an input field out but you could do this manually if you wanted to add other validation.

function nbs_additional_fields () {
    wp_nonce_field('nbs_comment_nonce', 'comment_nonce');
    echo '<input type="hidden" id="myAdditionalValidation" />';
} 

The nbs_additional_comment_validation function is where you do your checks on your additional fields (as you normally do on POST requests). If validation fails on our nonce, we just exit (i.e. stop executing any code). You could all the validation checks that you want for any additional fields here in this function. You could even add (*cringe*) CAPTCHA here if you wanted, but, fair warning, your readers may despise you for doing so.

So that’s a general overview of how you can shore up your comment form a bit more. It’s not a bulletproof solution, but it’s something. And in the continual war against spam, every little bit can help. If somebody really wants to tell you how you can increase the size of various reproductive organs on your body by up to 300%, you gotta make them work for it.

]]>
https://9bitstudios.com/2013/04/add-additional-comment-form-validation-in-wordpress/feed/ 0
Creating a Facebook “Like” Box in WordPress https://9bitstudios.com/2013/04/creating-a-facebook-like-box-in-wordpress/ https://9bitstudios.com/2013/04/creating-a-facebook-like-box-in-wordpress/#respond Sun, 07 Apr 2013 10:21:19 +0000 https://9bitstudios.com/?p=815 In what follows, we’re going to take a look at how to create a Facebook Like Box in WordPress. If you create a Facebook Like box on the Facebook developer’s page, Facebook will give you some code to paste into your website. Something like the following…

<iframe src="//facebook.com/plugins/likebox.php?href=http%3A%2F%2Ffacebook.com%2Fplatform&amp;width=292&amp;height=590&amp;show_faces=true&amp;colorscheme=light&amp;stream=true&amp;border_color&amp;header=true" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:292px; height:590px;" allowTransparency="true"></iframe>

This is an example of the iframe generated code, though there are a number of different types of code they’ll give you to choose from (HTML5, XFBML, etc).

You could certainly take the approach to paste this code directly into the PHP files in your WordPress theme where you want to show your Facebook Like box, but we’re going to do this in the form of a WordPress shortcode. That way we can pass in variable content to our Facebook Like box and we don’t have to update the raw code anytime we want to make a change.

Create a function in the location in your theme where you normally register your shortcodes. A lot of times this is the functions.php file but in the author’s humble opinion I believe that there are ways to keep your code more organized. Whether you are using functions.php or a class, add the following function to your code wherever it seems good to you…

function facebookBoxShortcode($atts, $content = null) 
{
	extract(shortcode_atts(array("id" => '', "path" => '', "showfaces" => 'true', "colorscheme" => 'light', "bordercolor" => 'white'), $atts));
	
	$scheme = '';
	$faces = '';
	if ($colorscheme == "dark")
		$scheme = "dark";
	else 
		$scheme = "light";
	
	if ($showfaces == "false")
		$faces = "false";
	else 
		$faces = "true";	
		
	return '<iframe id="'.$id.'" class="facebookBox" src="//facebook.com/plugins/likebox.php?href='.$path.'&amp;colorscheme='.$scheme.'&amp;show_faces='.$faces.'&amp;border_color='.$bordercolor.'&amp;stream=false&amp;header=false" scrolling="no" frameborder="0" style="border:none; overflow:hidden;" allowTransparency="true"></iframe>';
} 

Then immediately after this you’ll want to register your shortcode…

add_shortcode('facebookbox', 'facebookBoxShortcode');	

If you are registering your shortcode in a class — which I think is a good idea — then you’d use the following slightly different code instead…

add_shortcode('facebookbox', array($this, 'facebookBoxShortcode'));	

What we are doing in our function is allowing for a number of different variables to be passed into our shortcode.

  • id: This is where we can set the “name” of your Facebook box. It is used as an identifier if you want to have multiple different Facebook boxes on the same page. It can have any single word string value but each should be unique because (as you can see in the code), it maps to a CSS ID selector.
  • path: This where you’d want to se the URL of the Facebook page you want people to “Like”. The default we have set is https://facebook.com/platform, but you’d want to change this to your own page.
  • colorscheme: This setting could have the string value of either “dark” or “light”
  • showfaces:
  • bordercolor: Set the color of the border here. The default value is “white.”

We are now all set. Once you have your variables all configured the way that you want them, to use our newly implemented shortcode you could just add the following to your page or post…

[facebookbox id="myFacebookBox" path="https://facebook.com/yourpage here" showfaces="true" colorscheme="light" bordercolor="white"]

If you wanted to use this code outside of the WordPress Loop, such as your sidebar.php or footer.php files, you could use the following….

echo do_shortcode(‘[facebookbox id="myFacebookBox" path="https://facebook.com/yourpage here" showfaces="true" colorscheme="light" bordercolor="white"]‘);

May many Facebook “Likes” follow you wherever you go for all the days of your life.

]]>
https://9bitstudios.com/2013/04/creating-a-facebook-like-box-in-wordpress/feed/ 0