post

Beginner Developer Series: Setting Up a Local Environment via XAMPP (Apache, PHP, mySQL)

phpmyadmin

When developing, it is always good to have a local site. Many skip this and use only a staging site and the production site. However, having a local environment will make life easy with testing scripts quickly and easily. Change a file, save, and run. However, using a staging site, you have to FTP up and down, and with WordPress and Windows, this sometimes can get you into trouble if not done correctly.

So, we need to install Apache (the server software), PHP (the language that WordPress runs on), and MySQL (the database). To do this on an Apple machine, use the Make WordPress Tutorial for MAMP or see the older tutorial in the Codex: Installing MAMP. For Windows machines, there is XAMPP, which stands for Apache + MySQL + PHP + Perl.

Quick Summary

Here are the simplified steps on how to install WordPress on your local computer that we will walk through this week:

  1. Install a local server ( XAMPP).
  2. Configure PHP
  3. Launching Apache & Troubleshooting with Skype
  4. Create a new database via phpMyAdmin.
  5. Setup XAMPP Security
  6. Download WordPress from wordpress.org and install into the htdocs folder (typically C:/xampp/htdocs).
  7. Run the famous 5 minute install and follow the instructions: wp-admin/install.php.
  8. Done!
post

How to Add a Custom Field Shortcode to Use Any Custom Field in Posts

In another tutorial I am writing, one for non-coders, I needed a way to pull in custom fields into the post. Currently (and sadly), in Genesis there is no way to do this; however, Genesis does have a great php function that already does this, genesis_get_custom_field(). So turning that into a shortcode is rather easy. Just add the following to your functions.php code:

add_shortcode( 'post_field', 'genesis_post_field_shortcode' );
/**
 * Returns the value of a custom field.
 *
 * Supported shortcode attributes are:
 *   field (field name),
 *
 * @param array $atts Shortcode attributes
 * @return string Shortcode output
 */
function genesis_post_field_shortcode( $atts ) {

	$defaults = array(
		'field'  => '',
	);
	$atts = shortcode_atts( $defaults, $atts );

	return genesis_get_custom_field( $atts['field'] );
}

To use the shortcode, you just insert [ post_field field="my_field_name"] (without the space in the front) and boom! It works!

post

Filter Pages by Post Parent and Filter Pages/Posts by Pages/Posts Per on WordPress Edit Pages

Recently I migrated a site that had hundreds of pages, which made page management a potential nightmare. Seeing this potential, I developed a filter that would enable me to see various parts of the pages tree as well as allow me to set the number of pages I wanted to see.

To add a filter on the edit page, you must hook into ‘restrict_manage_posts‘. The function below will add 2 filters: pages_per filter and a post_parent page filter. The pages_per filter is something that can be used on all post types; however, the post_parent filter should only be used on pages (or other hierarchical post types–but for this tutorial, we will only do pages).

So here’s what I did:

add_action ( 'restrict_manage_posts' , 'wps_restrict_manage_posts' );
function wps_restrict_manage_posts() {
	global $typenow;
	
	// only run this filter on page post type
	if ( $typenow == 'page' ) {
	
		// Parent Page Filter (HTML)
		$args = array(
			'child_of' => 0,
			'show_option_none' => 'Show all pages',
			'depth' => 2, //change this to whatever you want
			'name' => 'wps_page_filter',
			'selected' => $_GET['wps_page_filter'],
		);
		$dropdown = wp_dropdown_pages( $args );
	}	
	
	// Per Page Filter (HTML)
	global $wps_per_page;
	$wps_per_page = isset( $_GET['wps_per_page'] ) ? (int) $_GET['wps_per_page'] : $wps_per_page;
	?>
		<select name="wps_per_page" style="width: 110px;">
			<option <?php selected( $wps_per_page, 9999 ); ?> value="9999"><?php _e( 'Show all', FDA_DOMAIN ); ?></option>
			<?php for( $i=10; $i<=100; $i+=10 ) : ?>
			<option <?php selected( $wps_per_page, $i ); ?> value="<?php echo $i; ?>"><?php echo $i; ?> <?php _e( 'per page', FDA_DOMAIN ); ?></option>
			<?php endfor; ?>
			<?php if ( $wps_per_page != -1 && $wps_per_page != 9999 && ( $wps_per_page%10 != 0 || $wps_per_page > 100 ) ) : ?>
		 	<option <?php selected( true ); ?> value="<?php echo (int) $wps_per_page; ?>"><?php echo (int) $wps_per_page; ?> <?php _e( 'per page', FDA_DOMAIN ); ?></option>
		 	<?php endif; ?>
		</select>
	<?php
}

Now, I wanted to add an option to show only top level pages only. This has to be done manually, darn WordPress for having no good filters in wp_dropdown_pages().

// Add an option to show top level pages only
add_filter ( 'wp_dropdown_pages' , 'wps_insert_option_in_dropdown' );
function wps_insert_option_in_dropdown ( $output ) {
	$filter = $_GET['wps_page_filter'];
	if ( $filter == 'parent' )
		$selected = ' selected="selected"';
	else
		$selected = '';
    $second_option = 'Show all pages</option><option value="parent"' . $selected . '>Parent Pages Only</option>';
    return preg_replace( '#Show all pages</option>#' , $second_option , $output ); 
}

Now, WordPress won’t execute the filter for us, so we have to make sure this happens. This can be done in two separate functions; however, since it really doesn’t matter pragmatically, we will keep with one function.

add_filter ( 'parse_query', 'wps_admin_posts_filter' );
function wps_admin_posts_filter( $query ) {
    global $pagenow;
	
	// Update pages_per (just because we are here, we do it in this function)
	$wps_per_page = $_GET['wps_per_page'];
	if ( isset( $wps_per_page ) && ( $wps_per_page == 9999 || ( $wps_per_page % 10 ) == 0 ) )
			update_user_option( get_current_user_id(), 'edit_page_per_page', (int) $wps_per_page );

	// Change query based on post_parent
	$wps_page_filter = $_GET['wps_page_filter'];
    if ( is_admin() && $pagenow == 'edit.php' && !empty( $wps_page_filter ) ) {
		if ( $wps_page_filter == 'parent' )
			$query->query_vars['post_parent'] = 0;
		else
			$query->query_vars['post_parent'] = $wps_page_filter;
    }
}
post

How to Add Genesis Custom Content Columns to the Editor (to Appear in Visual Mode)

Custom Columns with add_editor_style()

Recently, I had a need to have the custom columns of WordPress on the backend to be used in the Visual Editor. So thanks to a few tutorials out there regarding this, especially Alison’s Mastering the TinyMCE Styles Dropdown in the WordPress Visual Editor, who has a great plugin, Custom Styles Dropdown, and WPEngineer’s, Customize WordPress WYSIWYG Editor (more for a better understanding). Another option is the Advanced TinyMCE WordPress Plugin. I plan to develop this into a plugin, coming soon…

However, this tutorial will focus solely on the Custom Content Columns for Genesis users. If you need an explanation, please see Alison’s Mastering the TinyMCE Styles Dropdown in the WordPress Visual Editor post.

Add this to your functions.php file.

add_filter( 'mce_buttons_2', 'wps_mce_buttons_2' );
/**
* Show the style dropdown on the second row of the editor toolbar.
*
* @param array $buttons Exising buttons
* @return array Amended buttons
*/
function wps_mce_buttons_2( $buttons ) {

    // Check if style select has not already been added
    if ( isset( $buttons['styleselect'] ) )
        return;

    // Appears not, so add it ourselves.
    array_unshift( $buttons, 'styleselect' );
    return $buttons;

}

add_filter( 'tiny_mce_before_init', 'wps_mce_before_init' );
/**
* Add column entries to the style dropdown.
*
* 'text-domain' should be replaced with your theme or plugin text domain for
* translations.
*
* @param array $settings Existing settings for all toolbar items
* @return array Amended settings
*/
function wps_mce_before_init( $settings ) {

    $style_formats = array(

		array(
			'title' => __( 'First Half', 'text-domain' ),
			'block' => 'div',
			'classes' => 'one-half first',
			),
		array(
			'title' => __( 'Half', 'text-domain' ),
			'block' => 'div',
			'classes' => 'one-half',
			),
		array(
			'title' => __( 'First Third', 'text-domain' ),
			'block' => 'div',
			'classes' => 'one-third first',
			),
		array(
			'title' => __( 'Third', 'text-domain' ),
			'block' => 'div',
			'classes' => 'one-third',
			),
		array(
			'title' => __( 'First Quarter', 'text-domain' ),
			'block' => 'div',
			'classes' => 'one-fourth first',
			),
		array(
			'title' => _( 'Quarter', 'text-domain' ),
			'block' => 'div',
			'classes' => 'one-fourth',
			),
		array(
			'title' => __( 'First Fifth', 'text-domain' ),
			'block' => 'div',
			'classes' => 'one-fifth first',
			),
		array(
			'title' => __( 'Fifth', 'text-domain' ),
			'block' => 'div',
			'classes' => 'one-fifth',
			),
		array(
			'title' => __( 'First Sixth', 'text-domain' ),
			'block' => 'div',
			'classes' => 'one-sixth first',
			),
		array(
			'title' => __( 'Sixth', 'text-domain' ),
			'block' => 'div',
			'classes' => 'one-sixth',
			),
		);

	// Check if there are some styles already
	if ( $settings['style_formats'] )
		$settings['style_formats'] = array_merge( $settings['style_formats'], json_encode( $style_formats ) );
	else
		$settings['style_formats'] = json_encode( $style_formats );

	return $settings;

}

This will result in this:
Custom Columns in the Editor

However, the HTML will contain the necessary classes and styles and will be:

<div class="one-half first">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean quam massa, iaculis vel vehicula aliquam, iaculis ut risus. Mauris luctus, justo quis blandit vestibulum, dui lorem rhoncus massa, non aliquam ante erat at dolor. In facilisis libero in libero pharetra eu pellentesque mauris convallis. In vitae tortor lorem. Nullam aliquet ligula vel lectus pretium eget elementum massa laoreet. In hac habitasse platea dictumst. Quisque lacinia odio vitae nisl dictum euismod. Suspendisse eget nisl quis leo pulvinar cursus. Aliquam vel elit vehicula neque consectetur blandit eu eget nisi. Maecenas vitae risus quis lacus feugiat dictum sed eget arcu. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nulla feugiat massa ut mauris viverra porta.</div>
<div class="one-half">Fusce porttitor libero ut libero aliquam vitae faucibus lorem tincidunt. Phasellus pharetra libero et eros pellentesque eget feugiat eros adipiscing. Pellentesque massa augue, interdum ut facilisis et, pellentesque et justo. Proin consectetur venenatis vehicula. Aliquam interdum ullamcorper urna, quis volutpat massa dictum non. Integer placerat nunc porttitor lacus volutpat ultricies. Integer ornare ultrices nibh sed hendrerit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</div>

Now you can also add the following to incorporate your CSS into the Visual Editor to achieve a closer representation on the backend (that will eventually appear on the front end):

add_editor_style();

Now, the add_editor_style(); is a really cool feature. Now you can add a stylesheet to your child theme’s folder called editor-style.css, and any style that you want to appear in the editor will now appear in the visual editor as it would on the external pages. So to get the custom column classes, you will need to create the editor-style.css.

Here is what your visual editor will look like with the use of add_editor_style();
Custom Columns with add_editor_style()

However, you do not need to add the add_editor_style(); for this to work. Adding the add_editor_style(); only allows the style to be applied inside the Visual editor.

/* Column Classes
------------------------------------------------------------ */
 
.five-sixths,
.four-fifths,
.four-sixths,
.one-fifth,
.one-fourth,
.one-half,
.one-sixth,
.one-third,
.three-fifths,
.three-fourths,
.three-sixths,
.two-fifths,
.two-fourths,
.two-sixths,
.two-thirds {
    float: left;
    margin: 0 0 20px;
    padding-left: 3%;
}
 
.one-half,
.three-sixths,
.two-fourths {
    width: 48%;
}
 
.one-third,
.two-sixths {
    width: 31%;
}
 
.four-sixths,
.two-thirds {
    width: 65%;
}
 
.one-fourth {
    width: 22.5%;
}
 
.three-fourths {
    width: 73.5%;
}
 
.one-fifth {
    width: 17.4%;
}
 
.two-fifths {
    width: 37.8%;
}
 
.three-fifths {
    width: 58.2%;
}
 
.four-fifths {
    width: 78.6%;
}
 
.one-sixth {
    width: 14%;
}
 
.five-sixths {
    width: 82%;
}
 
.first {
    clear: both;
    padding-left: 0;
}

Or simply download the file below and place inside your child theme folder.
Download: Genesis Custom Content Columns Editor Stylesheet (297)

post

How to Automatically Add a Class (like ‘first’ or ‘last’) to a WordPress Menu

So recently, I needed a way to dynamically add a ‘first’ class to all the first child nav menu items of a particular parent nav menu item item. On a simple Google, one tutorial by @WPBeginner suggests that we use a filter.

//Filtering a Class in Navigation Menu Item
add_filter( 'nav_menu_css_class' , 'special_nav_class' , 10 , 2 );
function special_nav_class( $classes, $item ){
     if( is_single() && $item->title == 'Blog' ){
             $classes[] = 'current-menu-item';
     }
     return $classes;
}

However great this filter is, this approach won’t and cannot be very dynamic.

So I wrote a function (and generalized it) that would accomplish this easily and nicely. This uses a function that I wrote about previously called get_nav_menu_item_children() in a post called How to Get All the Children of a Specific Nav Menu Item that I have modified (12/6).

Given a menu id and a parent item id and the optional class name, the function will automatically add that class to the first child nav menu item. So here is the new function:

/*
   * Adds a class to the first menu item.
   *
   * Uses update_post_meta() to update a nav menu item.
   *
   * @param int $menu_id Menu ID, defaults to 0.
   * @param int $parent_id Menu item ID, defaults to 0.
   * @param string $newclass Class to add, defaults to 'first'.
   * @param boolean $remove Remove class from other children, defaults to true.
   * @return boolean, false: if no $menu_id or $parent_id, else true.
*/
function wps_update_classes( $menu_id = 0 , $parent_id = 0 , $newclass = 'first' , $remove = true ) {
	
	// Validate inputs
	$menu_id = intval ( $menu_id );
	$parent_id = intval ( $parent_id );
	
	if ( ( $menu_id == 0 ) || ( $parent_id == 0 ) || ( !is_bool ( $remove ) ) || ( !is_string ( $newclass ) ) )
		return false;
	
	// Get & filter nav menu items
	$nav_menu_items = wp_get_nav_menu_items( $menu_id , array( 'post_status' => 'publish,draft' ) );
	$children = get_nav_menu_item_children( $parent_id , $nav_menu_items );
	$first_item = true;
	
	// Cycle through child nav menu items
	foreach ( $children as $child ) {
		if ( $first_item ) {
			//found first item
			$first_item = false;
			$match = false;
			
			// Cycle through to check for first
			foreach ( $child->classes as $class ) {
				// Match found
				if ( $class == $newclass ) {
					$match = true;
					break;
				}
			}
			
			// Update Post if match found
			if ( ! $match ) {
				if ( $child->classes[0] == '' )
					$child->classes[0] = $newclass;
				else
					$child->classes[] = $newclass;

				$menu_item_data = array(
					'menu-item-classes' => $child->classes,
				);
				update_post_meta( $child->ID, '_menu_item_classes', $child->classes );
			}
			continue;
		}
		
		// Cycle through and remove $newclass from other children
		if ( $remove ) {
			foreach ( $child->classes as $key => $class ) {
				
				// If match, remove $newclass from other children
				if ( $class == $newclass ) {
					$child->classes[$key] = '';
					update_post_meta( $child->ID, '_menu_item_classes', $child->classes );
				}
			}
		}
	}
	
	return true;
}

So to call this function, you can use something like this:

add_action( 'init' , 'wps_update_menus' );
function wps_update_menus() {
	wps_update_classes( 3 , 277 );
	wps_update_classes( 3 , 7 , 'test-class' );
}

This bit of code adds ‘first’ to the first child of menu item 277 on menu 3 and ‘test-class’ to the first child of menu item 7 on menu 3.

If you want to add the ability to add a ‘last’ class, you can use this:

/*
   * Sorts a multidimensional array of nav menu items.
   *
   * @link http://php.net/manual/en/function.sort.php
   * @param array $array Multidimensional array to be sorted.
   * @param string $index Index to determine the sort.
   * @param string $order Must be either asc or desc.
   * @param boolean $natsort Sort an array using a "natural order" algorithm.
   * @param boolean $case_sensitive Sort via case sensitivity.
   * @return boolean, false: if no $menu_id or $parent_id, else true.
*/
function wps_sort_nav_menu_items ( $array, $index, $order, $natsort = FALSE, $case_sensitive = FALSE ) {
	if( is_array ( $array ) && count( $array ) > 0 ) {
		foreach ( array_keys ( $array ) as $key ) 
		$temp[$key] = $array[$key]->$index;
		if( ! $natsort ) {
			if ( strtolower( $order ) == 'asc' )
				asort( $temp );
			else    
				arsort( $temp );
		}
		else 
		{
			if ( $case_sensitive === true )
				natsort( $temp );
			else
				natcasesort( $temp );
		if( strtolower( $order ) != 'asc' ) 
			$temp = array_reverse ( $temp , TRUE );
		}
		foreach( array_keys ( $temp ) as $key ) 
			if ( is_numeric ( $key ) )
				$sorted[] = $array[$key];
			else    
				$sorted[$key] = $array[$key];
		return $sorted;
	}
	return $sorted;
}

/*
   * Adds a class to first/last menu item.
   *
   * Uses update_post_meta() to update a nav menu item.
   *
   * @param int $menu_id Menu ID, defaults to 0.
   * @param int $parent_id Menu item ID, defaults to 0.
   * @param string $newclass Class to add, defaults to 'first'.
   * @param boolean $remove Remove class from other children, defaults to true.
   * @return boolean, false: if no $menu_id or $parent_id, else true.
*/
function wps_update_classes( $menu_id = 0 , $parent_id = 0 , $newclass = 'first' , $firstlast = 'first' , $remove = true ) {
	
	// Validate inputs
	$menu_id = intval ( $menu_id );
	$parent_id = intval ( $parent_id );
	
	if ( ( $menu_id == 0 ) || ( $parent_id == 0 ) || ( !is_bool ( $remove ) ) || ( !is_string ( $newclass ) ) || ( !is_string ( $firstlast ) ) )
		return false;
	
	// Get & filter nav menu items
	$nav_menu_items = wp_get_nav_menu_items( $menu_id , array( 'post_status' => 'publish,draft' ) );
	$children = get_nav_menu_item_children( $parent_id , $nav_menu_items );
	if ( strtolower( $firstlast ) == 'last' )
		$children = wps_sort_nav_menu_items( $children , 'menu_order' , 'desc' );
	$first_item = true;
	
	// Cycle through child nav menu items
	foreach ( $children as $child ) {
		if ( $first_item ) {
			//found first item
			$first_item = false;
			$match = false;
			
			// Cycle through to check for first
			foreach ( $child->classes as $class ) {
				// Match found
				if ( $class == $newclass ) {
					$match = true;
					break;
				}
			}
			
			// Update Post if match found
			if ( ! $match ) {
				if ( $child->classes[0] == '' )
					$child->classes[0] = $newclass;
				else
					$child->classes[] = $newclass;

				$menu_item_data = array(
					'menu-item-classes' => $child->classes,
				);
				update_post_meta( $child->ID, '_menu_item_classes', $child->classes );
			}
			continue;
		}
		
		// Cycle through and remove $newclass from other children
		if ( $remove ) {
			foreach ( $child->classes as $key => $class ) {
				
				// If match, remove $newclass from other children
				if ( $class == $newclass ) {
					$child->classes[$key] = '';
					update_post_meta( $child->ID, '_menu_item_classes', $child->classes );
				}
			}
		}
	}
	
	return true;
}

So to call this function, you can use something like this:

add_action( 'init' , 'wps_update_menus' );
function wps_update_menus() {
	wps_update_classes( 3 , 277 );
	wps_update_classes( 3 , 7 , 'last' , 'last' );
}

This bit of code adds ‘first’ to the first child of menu item 277 on menu 3 and ‘last’ to the last child of menu item 7 on menu 3.

post

How to Add a Login Form to the Primary Navigation Menu in Genesis

Primary Navigation with Login

Someone contacted me to develop a function that would add a login form to the primary navigation for their Genesis menu, and I would like to share it with you.

Primary Navigation with Login

<?php
add_filter( 'wp_nav_menu_items' , 'wps_nav_login_right' , 10 , 2 );
function wps_nav_login_right( $menu , $args ) {
	$args = ( array )$args;

	//if not primary, return
	//change primary to secondary for secondary menu (though will need some CSS done)
	if ( $args['theme_location'] != 'primary' ) 
		return $menu;
	
	//check if user is NOT logged in, do login form
	if ( !is_user_logged_in() ) {
		$login .= '<form action="' . get_bloginfo( 'wpurl' ) . '/wp-login.php" method="post">';
		$login .= '<input type="text" name="log" id="log" value="' . wp_specialchars(stripslashes($user_login), 1) . '" size="20" />';
		$login .= '<input type="password" name="pwd" id="pwd" size="20" />';
		$login .= '<input type="submit" name="submit" value="Submit" class="button" />';
		$login .= '<label for="rememberme"><input name="rememberme" id="rememberme" type="checkbox" checked="checked" value="forever" /> Remember me</label>';
		$login .= '<input type="hidden" name="redirect_to" value="' . $_SERVER['REQUEST_URI'] . '" />';
		$menu .= '<li class="right login">' . $login . '</li>';
	}
	// if logged in, do logout link
	else {
		global $current_user;
		get_currentuserinfo();
		$logout = '';
		$logout = 'Welcome ' . $current_user->display_name;
		$logout .= '<a href="' . wp_logout_url( $_SERVER['REQUEST_URI'] ) . '">Logout</a>';
		$menu .= '<li class="right logout">' . $logout . '</li>';
	}
	
	return $menu;
}