<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Braindonor Network &#187; php</title>
	<atom:link href="http://www.braindonor.net/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.braindonor.net</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Tue, 01 Jun 2010 17:42:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Custom Pages with WordPress Plugins</title>
		<link>http://www.braindonor.net/coding-blog/custom-pages-with-wordpress-plugins/230/</link>
		<comments>http://www.braindonor.net/coding-blog/custom-pages-with-wordpress-plugins/230/#comments</comments>
		<pubDate>Tue, 18 Aug 2009 20:16:43 +0000</pubDate>
		<dc:creator>John Hoff</dc:creator>
				<category><![CDATA[Coding Blog]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.braindonor.net/?p=230</guid>
		<description><![CDATA[One of the more interesting challenges I have faced with WordPress is offering custom pages. These could be pages such taking a survey, asking a question, or suggesting a topic. Previously, I had gone about coding these kinds of pages by just sticking the php file in the web root. The problem with that strategy [...]]]></description>
			<content:encoded><![CDATA[One of the more interesting challenges I have faced with WordPress is offering custom pages.  These could be pages such taking a survey, asking a question, or suggesting a topic. Previously, I had gone about coding these kinds of pages by just sticking the php file in the web root.<span id="more-230"></span> The problem with that strategy is twofold.  The page cannot be disabled without going to the file system. The page also doesn't respect theme changes cleanly.<br /><br />

The solution comes in three parts.  The first step is updating the rewrite rules to map a url to an internal value.  Next, we map this internal value to a template.  Finally, we map this internal template to the theme template.<br /><br />

Most WordPress installations take advantage of URL rewriting on the part of the web server. The goal is to rewrite all blog page requests to index.php.  From there, WordPress examines the original URL to determine what content to send.  The WordPress rewrite rules allow us to modify this URL. In our case, we want to map a custom page to query variable that we are going to pass into index.php, sending it down the $wp_query.<br />
<code>add_filter('generate_rewrite_rules', 'custom_page_generate_rewrite_rules');
function custom_page_generate_rewrite_rules($wp_rewrite) {
    $custom_page_rules = array(
        'survey' =&gt; 'index.php?custom_page=survey',
    );
    $wp_rewrite-&gt;rules = $custom_page_rules + $wp_rewrite-&gt;rules;
}</code><br />

Now that we are able to map a url to the $wp_query, we need to resolve that into a template.  For this, we utilize the template redirect of WordPress. This allows our plugin to resolve the request into a template call and exit before wordpress attempts to resolve the request.<br />
<code>add_action('template_redirect', 'custom_page_template_redirect');
fnction custom_page_template_redirect() {
    global $wp_query;
    $custom_page = $wp_query-&gt;query_vars['custom_page'];
    if ($custom_page == 'survey') {
        include(ABSPATH.'wp-content/plugins/custom_page/survey_page.php');
        exit;
    }
}</code><br />

For the final piece, we will take a look at just one of the custom pages, survey_page.php. The template redirect hands off the request processing to this page and exits. It is up to this page to interact with the existing theme and display our custom page.  The only catch is that the theme must utilize the <b>the_content()</b> template function of WordPress. Otherwise, the proper hooks will not be called and our page will not display correctly.<br /><br />

Fetching the proper file to use from the existing theme is very simple.  To do so, we resolve the page template first, single post template second, and finally default to the index.<br />
<code>if (file_exists(TEMPLATEPATH.'/page.php')) {
    include(get_page_template());
}
elseif (file_exists(TEMPLATEPATH.'/single.php')) {
    include(get_single_template());
}
else {
    include(TEMPLATEPATH.'/index.php');
}</code><br />

Updating the content involves inserting filters onto <b>the_title</b> and <b>the_content</b>.  However, we only want these filters to be called during <b>the_loop</b>.  Surpressing the filters from <b>get_header</b>, <b>get_sidebar</b>, and <b>get_footer</b> will prevent the custom filters from overrideing page template content.<br />
<code>add_action('get_header', 'custom_page_remove_filters');
add_action('get_sidebar', 'custom_page_remove_filters');
add_action('get_footer', 'custom_page_remove_filters');
function custom_page_remove_filters() {
    remove_filter('the_title', 'custom_page_title');
    remove_filter('the_content', 'custom_page_content');
}

add_action('loop_start', 'custom_page_add_filters');
function custom_page_add_filters() {
    add_filter('the_title', 'custom_page_title');
    add_filter('the_content', 'custom_page_content');
}</code><br />

I went ahead and put all of this together into a plugin on this site.  You can see it in action with the following pages:<br />
<ul>
<li><a href="/survey/" target="_blank"><b>Survey Page</b></a></li>
<li><a href="/topic/" target="_blank"><b>Suggest-a-Topic Page</b></a></li>
<li><a href="/question/" target="_blank"><b>Ask-a-Question Page</b></a></li>
</ul>

I have also attached the source code for the plugin as a full example. You can download it <a href="http://www.braindonor.net/wp-content/uploads/2009/08/custom_page.zip">here</a>.]]></content:encoded>
			<wfw:commentRss>http://www.braindonor.net/coding-blog/custom-pages-with-wordpress-plugins/230/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Hijack the WordPress Media Gallery</title>
		<link>http://www.braindonor.net/coding-blog/hijack-the-wordpress-media-gallery/228/</link>
		<comments>http://www.braindonor.net/coding-blog/hijack-the-wordpress-media-gallery/228/#comments</comments>
		<pubDate>Thu, 06 Aug 2009 21:05:57 +0000</pubDate>
		<dc:creator>John Hoff</dc:creator>
				<category><![CDATA[Coding Blog]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.braindonor.net/?p=228</guid>
		<description><![CDATA[I have a friend that wants to update a banner on his WordPress blog homepage without changing the template files. I tell him I'd be glad to help him out and start working on a plugin that provides a custom administration page to allow for this. As I am a firm believer in the power [...]]]></description>
			<content:encoded><![CDATA[I have a friend that wants to update a banner on his <a href="http://wordpress.org/" target="_blank">WordPress</a> blog homepage without changing the template files. I tell him I'd be glad to help him out and start working on a plugin that provides a <a href="http://codex.wordpress.org/Adding_Administration_Menus" target="_blank">custom administration page</a> to allow for this. As I am a firm believer in the power of a lazy coder to get things done faster and better, my first thought was: "Why don't I just see if I can hijack the 'Select Image From Gallery' page to do this?"<span id="more-228"></span> After all, it just pops up into an Iframe page and tells post editer to insert an image. Hijacking that process for my own ends shouldn't take me but a few minutes...and a lot less time than trying to build my own media selector. Like nearly all the content on my site, if you are reading this, I wasn't able to find my answer elsewhere.<br /><br />

First, we will examine how the media library iframe is launched from the post editor and how we can duplicate that in our plugin. So lets crack open the page source and see what we can find:<br />
<code>&lt;a href="media-upload.php?post_id=-1249588072&amp;type=image&amp;TB_iframe=true" id="add_image" class="thickbox" title='Add an Image' onclick="return false;"&gt;&lt;img src='images/media-button-image.gif' alt='Add an Image' /&gt;&lt;/a&gt;
</code><br />

Looks like a standard hyperlink, with some extra information in the tag. What first jumps out at me is the <b>onclick="return false;"</b>. By having an onclick return <i>false</i> in a hyperlink, you ensure that a browser with javascript will never open the link when it is clicked. Sounds pretty silly until you remember that WordPress is a big user of <a href="http://jquery.com/" target="_blank">JQuery</a>. From there, we know to look at the class of the hyperlink, <b>class="thickbox"</b>.  This is a reference to the Thickbox 3.1 library found at /wp-includes/js/thickbox/thickbox.js.  This is a library to load an iframe inside an overlay with the background greyed out.  Further, it uses the href of the anchor tag to know where to pull the iframe content from.
<br /><br />

A quick check of the source on our custom page shows that Thickbox is being loaded in the footer, so we do not have to call it directly from our custom wp-admin page. I can just call up the media library with some html code:
<code>&lt;a href="media-upload.php?type=image&amp;TB_iframe=true" class="thickbox" title="Select A Banner Image From Gallery" onclick="return false;" class="thickbox"&gt;
&lt;img id="banner_image" src="&lt;?php echo(htmlentities($banner_image)); ?&gt;" width="450" height="25" /&gt;
&lt;/a&gt;
&lt;input type="hidden" id="banner_image_input" name="banner_image" value="&lt;?php echo(htmlentities($banner_image)); ?&gt;" /&gt;
</code><br />

The snippet displays an image with the source of <b>$banner_image</b> that can be clicked on to open the Media Gallery iframe. I have also added a hidden form input to store the resulting information passed back from the media library.  Once done, I now have an image on my admin page that I can click on to call up the media library.<br /><br />

We're half-way there now! All we have to do next is figure out how the media library sends an image to the post editor. This part isn't as easy. Thanks to thickbox, the media library opens up in an inline-iframe. This means that we can't just view the page source and find our answer. Instead, the only clue we have to hunt for is the "Insert into Post" button.  A quick file search turns that up in /wp-admin/includes/media.php. From there, we discover the onclick of the button, <b>onclick="addExtImage.insert();"</b>, which is thankfully also in the media.php file. At the end of the function, we see exactly what we are looking for:
<code>var win = window.dialogArguments || opener || parent || top;
win.send_to_editor(html);
</code><br />

The media library calls the function <b>send_to_editor</b> in the scope of the window that opened the media library--our admin page! We can add our own function into the admin page and collect the html that the media library sends us:
<code>function send_to_editor(html) {
    alert(html);
    tb_remove();
}
</code><br />

Once done, we can open the media library from our admin page and select an image.  When we hit the "Insert into Post" button, we get an alert with the following content:<br />
<code>&lt;img src="http://127.0.0.1/devel/wp-content/uploads/2009/09/banner.jpg" alt="banner" title="banner" class="alignnone size-full wp-image-494" /&gt;
</code><br />

All we have to do now, is strip out everything but the image source and updates the form.  First, the function eliminates all of the text returned except the image source.  It then updates the banner image and the hidden input value that I am using in my form:
<code>function send_to_editor(html) {
    var source = html.match(/src=\".*\" alt/);
    source = source[0].replace(/^src=\"/, "").replace(/" alt$/, "");
    $("#banner_image").attr('src', source);
    $('#banner_image_input").attr('value', source);
    tb_remove();
}
</code><br />

I fire up the admin page a final time, and everything works! I now have a custom admin page that allows my friend to update a banner on his wordpress site using the media gallery.
]]></content:encoded>
			<wfw:commentRss>http://www.braindonor.net/coding-blog/hijack-the-wordpress-media-gallery/228/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Custom Field Searching WordPress Using Sphinx</title>
		<link>http://www.braindonor.net/coding-blog/custom-field-searching-wordpress-using-sphinx/199/</link>
		<comments>http://www.braindonor.net/coding-blog/custom-field-searching-wordpress-using-sphinx/199/#comments</comments>
		<pubDate>Wed, 20 May 2009 19:15:59 +0000</pubDate>
		<dc:creator>John Hoff</dc:creator>
				<category><![CDATA[Coding Blog]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sphinx]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.braindonor.net/?p=199</guid>
		<description><![CDATA[In my previous post on implementing a custom field search in WordPress, I showed how to modify the internal SQL LIKE search that is the default search engine of WordPress. There are other search engines that WordPress can make use of, most notably Sphinx Search. Sphinx is a great open-source full-text search engine. I have [...]]]></description>
			<content:encoded><![CDATA[In my <a href="http://www.braindonor.net/coding-blog/wordpress-custom-field-search-plugin/102/">previous post</a> on implementing a custom field search in WordPress, I showed how to modify the internal SQL LIKE search that is the default search engine of WordPress.  There are other search engines that WordPress can make use of, most notably <a href="http://wordpress.org/extend/plugins/wordpress-sphinx-plugin/">Sphinx Search</a>.<span id="more-199"></span><br /><br />

<a href="http://www.sphinxsearch.com/">Sphinx</a> is a great open-source full-text search engine.  I have used it several times to implement search functionality in content management systems.  I didn't go into using Sphinx with WordPress initially because it is a lot more work.  The default WordPress search is an SQL query performed by PHP.  Sphinx is composed of an indexer, a search daemon, and a client library and the installation of the package is unavailable in shared-hosting environments.<br /><br />

Since more and more people are using WordPress on dedicated servers, I'm not surprised that questions on implementing custom field searching using Sphinx has arrisen.  The good news is that it is very easy to implement!  All you have to do is update the sphinx.conf to pull out the custom fields as fields in the sql_query of your sources.<br /><br />

In my previous example, I worked with the fields: bio, byline, kicker, and deck.  I'll use these same fields again for continuity sake. I'm also using those fields because I have a site that uses these fields for custom search and I could test the changes needed for Sphinx.<br /><br />

In order to add each field, we have to do three things.  Add the column to the select on the wp_post, add a left join to the select on the wp_post, and add a placeholder to the select on wp_comments.<br /><br />

Example Columns:<br />
<code>p.post_content as body, \
t.name as category, \
bio_meta.meta_value as bio, \
byline_meta.meta_value as byline, \
kicker_meta.meta_value as kicker, \
deck_meta.meta_value as deck, \
IF(p.post_type = 'post', 1, 0) as isPost, \
0 as isComment, \</code><br />

Example Joins:<br />
<code>inner join \
{wp_terms} t on (tt.term_id = t.term_id) \
left join \
{wp_postmeta} bio_meta on (p.ID = bio_meta.post_id and bio_meta.meta_key = 'bio') \
left join \
{wp_postmeta} byline_meta on (p.ID = byline_meta.post_id and byline_meta.meta_key = 'byline') \
left join \
{wp_postmeta} kicker_meta on (p.ID = kicker_meta.post_id and kicker_meta.meta_key = 'kicker') \
left join \
{wp_postmeta} deck_meta on (p.ID = deck_meta.post_id and deck_meta.meta_key = 'deck') \
where \</code><br />

Example Placeholders:<br />
<code>c.comment_content as body, \
'' as category, \
'' as bio, \
'' as byline, \
'' as kicker, \
'' as deck, \
0 as isPost, \</code><br />

I have also attached the sphinx.conf distributed with the WordPress plugin so that you can see a more complete example of the implementation.<br /><br />

I hope everyone enjoys this as much as they did the last!]]></content:encoded>
			<wfw:commentRss>http://www.braindonor.net/coding-blog/custom-field-searching-wordpress-using-sphinx/199/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>WordPress Custom Field Search Plugin</title>
		<link>http://www.braindonor.net/coding-blog/wordpress-custom-field-search-plugin/102/</link>
		<comments>http://www.braindonor.net/coding-blog/wordpress-custom-field-search-plugin/102/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 18:30:39 +0000</pubDate>
		<dc:creator>John Hoff</dc:creator>
				<category><![CDATA[Coding Blog]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.braindonor.net/?p=102</guid>
		<description><![CDATA[Some friends of mine that have started offering custom WordPress designed sites and consulting hit me up a couple of weeks ago for some help. They had a site for a client that was utilizing custom fields to provide some additional CMS-like functionality to WordPress and had hit a snag. Their custom fields were not [...]]]></description>
			<content:encoded><![CDATA[Some friends of mine that have started offering custom WordPress designed sites and consulting hit me up a couple of weeks ago for some help.  They had a site for a client that was utilizing custom fields to provide some additional CMS-like functionality to WordPress and had hit a snag.  Their custom fields were not being searched.<span id="more-102"></span><br /><br />

Why custom fields in the first place?  Using the custom fields allowed them to add deck, byline, bio, kicker text that their custom template was checking for and formatting appropriately.  It really makes life easier when you are dealing with clients that come from the standard publishing background.  Not to mention how much easier it is to apply a global formatting change to those elements since you don't have to manually edit each post body.<br /><br />

Here's where I came in.  The client noticed that when they entered in a post authors' name(custom field, byline) no search results were being returned.  So they called me up for help.<br /><br />

I did some quick digging online and found a few blog posts that had people writing custom queries to fetch the search information.  Further digging revealed the WordPress filters that are responsible for building the SQL query for the search: posts_join, posts_groupby, posts_where, and posts_request.

For those wanting to play around, the posts_request filter is likely the first place you will want to look.  I tossed the following code into our plugin and was able to echo out the entire sql request that was being made for each page:<br /><br />
<code>function custom_search_request($request) {
    echo($request);
    return($request);
}
add_filter('posts_request', 'custom_search_request');
</code><br /><br />

Once that is done, a few page views will let you know what WordPress is doing internally to pull up the posts for each page.  You can then update the above to work with the other filters to show you how everything is assembled.<br /><br />

From there, it was a matter of looking at the existing code in the get_posts funciton in wp-includes/query.php and figuring out what additional query information needs to be passed in the filters.  Since that function is the densest code I've seen yet in WordPress, I won't go into all of the details.  I'll leave that to folks who have good eyes and brave hearts.<br /><br />

When putting it all together, there are several things to note.  Always check to make sure that you are currently in a search page and return the original query snippet if you are not.  The example I have below adds the custom fields: bio, byline, kicker, and deck.<br /><br />

<code>function custom_search_join($join) {
    if ( is_search() &#038;& isset($_GET['s'])) {
        global $wpdb;

       $join = " LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id ";
    }
    return($join);
}
add_filter('posts_join', 'custom_search_join');

function custom_search_groupby($groupby) {
    if ( is_search() &#038;& isset($_GET['s'])) {
        global $wpdb;
        $groupby = " $wpdb->posts.ID ";
    }
    return($groupby);
}
add_filter('posts_groupby', 'custom_search_groupby');

function custom_search_where($where) {
    $old_where = $where;
    if (is_search() &#038;& isset($_GET['s'])) {
        global $wpdb;
        $customs = Array('bio', 'byline', 'kicker', 'deck');
        $query = '';
        $var_q = stripslashes($_GET['s']);
        if ($_GET['sentence']) {
            $search_terms = array($var_q);
        }
        else {
            preg_match_all('/".*?("|$)|((?<=[\\s",+])|^)[^\\s",+]+/', $var_q, $matches);
            $search_terms = array_map(create_function('$a', 'return trim($a, "\\"\'\\n\\r ");'), $matches[0]);
        }
        $n = ($_GET['exact']) ? '' : '%';
        $searchand = '';
        foreach((array)$search_terms as $term) {
            $term = addslashes_gpc($term);
            $query .= "{$searchand}(";
                        $query .= "($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')";
            $query .= " OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}')";
            foreach($customs as $custom) {
                $query .= " OR (";
                $query .= "($wpdb->postmeta.meta_key = '$custom')";
                $query .= " AND ($wpdb->postmeta.meta_value  LIKE '{$n}{$term}{$n}')";
                $query .= ")";
            }
            $query .= ")";
            $searchand = ' AND ';
        }
        $term = $wpdb->escape($var_q);
        if (!$_GET['sentense'] &#038;& Count($search_terms) > 1 &#038;& $search_terms[0] != $var_q) {
            $search .= " OR ($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')";
            $search .= " OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}')";
        }

        if (!empty($query)) {
            $where = " AND ({$query}) AND ($wpdb->posts.post_status = 'publish') ";
        }
    }

    return($where);
}
add_filter('posts_where', 'custom_search_where');
</code><br /><br />

With all of that done, I added the above code into their plugin and the new fields were being used in the search.  It should be noted that the code is adding significant overhead to the post searching.  In the above example, each keyword in a search generates 5 SQL LIKE statements instead of 1.  In addition, these LIKEs are being performed across joined tables. Because this was for a small website, I do not know the full performance trade-off of the changes.  For larger sites, I'll almost always advocate using an external search engine such as Google or Sphinx.]]></content:encoded>
			<wfw:commentRss>http://www.braindonor.net/coding-blog/wordpress-custom-field-search-plugin/102/feed/</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
		<item>
		<title>New Site Launched</title>
		<link>http://www.braindonor.net/news-events/new-site-launched/4/</link>
		<comments>http://www.braindonor.net/news-events/new-site-launched/4/#comments</comments>
		<pubDate>Wed, 12 Nov 2008 16:36:04 +0000</pubDate>
		<dc:creator>John Hoff</dc:creator>
				<category><![CDATA[News & Events]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.braindonor.net/?p=4</guid>
		<description><![CDATA[The new Braindonor Network site is up and running! I took down the static place-holder page that I have been running for about five years and finally have some content for general consumption. The site is a WordPress blog with a custom written theme. With all the time and effort I have been putting in [...]]]></description>
			<content:encoded><![CDATA[The new Braindonor Network site is up and running!<span id="more-4"></span> I took down the static place-holder page that I have been running for about five years and finally have some content for general consumption.<br /><br />

The site is a <a href="http://wordpress.org/" target="_blank">WordPress</a> blog with a custom written theme.  With all the time and effort I have been putting in to creating custom WordPress sites, it only made sense to get one of my own up and running.  I should be releasing my theme soon to share some of the tips and tricks I've learned with WordPress along the way.]]></content:encoded>
			<wfw:commentRss>http://www.braindonor.net/news-events/new-site-launched/4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
