CakePHP Wordpress Component

This CakePHP component integrates WordPress with CakePHP by utilizing the WordPress API.

WordPress and CakePHP don't like each other because of one little reason: The double underscore function. The "__()" function is an imcompatible global function between the frameworks. One solution is to rename or alter the function but that would require hundreds of hacks directly to WordPress, plugins, themes and/or CakePHP. That would be a nightmare.

This CakePHP component gets around the problem by accessing WordPress via a web service file. The solution uses 2 files: The CakePHP component and a PHP file that connects the component to the WordPress API. Input is sent to the web service file with POST variables and returned to the component JSON encoded. This way users can use this component even if they don't have SOAP or XML-RPC enabled on their server.

Further more this component takes advantage of the CakePHP caching system and uses a simple authentication system to keep unauthorized users from accessing your copy of WordPress through the web service file.

 

Install

  1. Install WordPress into a folder in your CakePHP app/webroot/ folder.
  2. wordpress.php goes into your CakePHP app/controllers/components/ folder.
  3. wordpress_service.php goes into your CakePHP app/webroot/ folder.
  4. Set the PASSWORD variable at the top of both files to any random string of characters. Just as long as they are the same.

Usage

  • Add the component to your controller: var $components = array('Wordpress');
  • Customize the component either by:
    • Directly edit the settings in the component file.
    • OR Specify settings in your controller: var $components = array('Wordpress' => array('setting_name' => 'value'));
  • Use the component: $this->Wordpress->wp_api_func_name('arg1', 'arg2');
  • Visit the WordPress Codex for a list of available WordPress functions.

Settings

  • PASSWORD
    Set to a random string of characters. This field should match the $PASSWORD variable in the wordpress_service.php file. Used to ensure only the component can access your WordPress API functions.
  • PATH_TO_WP
    The absolute path to your WordPress folder. If you leave it blank it will assume you have installed WordPress into a folder named 'wp' in your CakePHP app/webroot/ folder.
  • CACHE
    Set to true or false if you would like CakePHP to cache results from WordPress.
  • WP_SERVICE_URL
    The relative URL to your wordpress_service.php file. If you have put the web service file into your CakePHP app/webroot/ folder then leave it set to '/wordpress_service.php'.

Example

<?php
class TestsController extends AppController
{
    var $components = array('Wordpress' => array('PASSWORD' => 'lkjfdafkjda90fdajkdfn'));
    var $uses = array();
    var $autoRender = false;
    
    function index()
    {
    	// GET TAG CLOUD
        debug($this->Wordpress->wp_tag_cloud('target=_top&title_li=&format=list&smallest=10&largest=24&unit=px'));
        
        // GET YOUR 5 MOST RECENT POSTS
        debug($this->Wordpress->wp_get_recent_posts(5));
        
    } // index
    
} // TestsController
?>
		

Source

app/controllers/components/wordpress.php
<?php
/**
 * CAKEPHP WORDPRESS COMPONENT v0.2
 * Connects Cakephp to the Wordpress API via a service file.
 * 
 * Copyright (C) 2010 Kyle Robinson Young
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * 
 * 
 * @author Kyle Robinson Young <kyle at kyletyoung.com>
 * @copyright 2010 Kyle Robinson Young
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 * @version 0.2
 * @link http://www.kyletyoung.com/code/cakephp_wordpress_component
 *
 */
class WordpressComponent extends Object
{
    var $settings = array(    
        /**
         * SET THIS PASSWORD TO SOMETHING UNIQUE
         * THEN SET THE SAME PASSWORD IN webroot/wordpress_service.php
         * 
         */
        'PASSWORD'		    => 'PleaseChangeThisPassword',
    
        /**
         * LEAVE BLANK TO DEFAULT TO webroot/wp/
         * OTHERWISE SPECIFY AN ABSOLUTE PATH TO YOUR WORDPRESS FOLDER
         */
        'PATH_TO_WP'	    => '',
        
        /**
         * SET TO FALSE TO DISABLE CACHING WORDPRESS RESPONSES
         */
        'CACHE'			    => true,
    
        /**
         * SET TO RELATIVE URL OF WORDPRESS SERVICE FILE
         */
        'WP_SERVICE_URL'	=> '/wordpress_service.php'
        
    );
    
    /**
     * INITIALIZE
     * @param class $controller
     * @param array $settings
     */
    function initialize(&$controller, $settings=array())
    {
        $this->settings = array_merge($this->settings, (array)$settings);
        $this->settings['PASSWORD'] = md5($this->settings['PASSWORD']);
        $this->settings['WP_SERVICE_URL'] = Router::url($this->settings['WP_SERVICE_URL'], true);
        if (empty($this->settings['PATH_TO_WP']))
        {
            $this->settings['PATH_TO_WP'] = APP.WEBROOT_DIR.DS.'wp'.DS;
        } // empty
    } // initialize
    
    /**
     * __CALL
     * Connects to the wordpress service file and calls the wordpress api.
     * 
     * @param str $func
     * @param array $args
     * @return mixed
     */
    function __call($func=null, $args=null)
    {
        $cache_name = '';
        
        // CHECK CACHE FIRST
        if ($this->settings['CACHE'])
        {
            // BUILD CACHE NAME
            $cache_name = 'wordpress_'.$func.'_';
            if (is_array($args)) $cache_name .= preg_replace("/[^A-Za-z0-9]/", "", implode('', $args));
            else $cache_name .= preg_replace("/[^A-Za-z0-9]/", "", $args);
            $cache_name = substr($cache_name, 0, 255);
            
            if (Cache::read($cache_name) !== false)
            {
                return Cache::read($cache_name);
            } // if no read
        } // if CACHE
        
        // BUILD URL
        $url = $this->settings['WP_SERVICE_URL'].'?passwd='.$this->settings['PASSWORD'];
        $url .= '&path='.urlencode($this->settings['PATH_TO_WP']);
        $url .= '&func='.urlencode($func);
        if (!empty($args))
        {
            $args = json_encode($args);
            $url .= '&args='.urlencode($args);
        } // !empty
        
        // CALL WP SERVICE
        if (function_exists('curl_init')) 
        {
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_REFERER, Router::url('/', true));
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_TIMEOUT, 60);
            $output = curl_exec($ch);
            curl_close($ch);
        } // function_exists
        else
        {
            $output = implode('', file($url));
        } // else
        
        // JSON DECODE
        if (!empty($output))
        {
            $output = json_decode($output);
            if (empty($output->output)) return false;
            else $output = $output->output;
            
            // IF CACHING
            if ($this->settings['CACHE']) Cache::write($cache_name, $output);
            else Cache::delete($cache_name);
            
            // RETURN
            return $output;
        } // !empty
        
        return false;
    } // call
    
} // WordpressComponent
?>
app/webroot/wordpress_service.php
<?php
/**
 * WORDPRESS SERVICE v0.2
 * For CakePHP Wordpress Component to connect to the Wordpress API.
 * 
 * Copyright (C) 2010 Kyle Robinson Young
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * 
 * 
 * @author Kyle Robinson Young <kyle at kyletyoung.com>
 * @copyright 2010 Kyle Robinson Young
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 * @version 0.2
 * @link http://www.kyletyoung.com/code/cakephp_wordpress_component
 * 
 */

/**
 * PASSWORD
 * Set this password to the same as the 
 * PASSWORD var in the components/wordpress.php file.
 */
$PASSWORD = 'PleaseChangeThisPassword';



/* - - DO NOT EDIT BELOW THIS LINE - - */

// CHECK PASSWORD
if (md5($PASSWORD) != preg_replace('/[^A-Za-z0-9]/', '', $_REQUEST['passwd'])) 
{
    //die("Not Authorized. Please update the PASSWORD in 'webroot/wordpress_service.php' and 'controllers/components/wordpress.php' to match.");
} // passwords dont match 

// GET INPUT
$_WPSERVICE['path'] = urldecode($_REQUEST['path']);
$_WPSERVICE['func'] = urldecode($_REQUEST['func']);
$_WPSERVICE['args'] = urldecode($_REQUEST['args']);

// CALL WP
global $wpdb;
define('WP_USE_THEMES', false);
require_once $_WPSERVICE['path'].'wp-config.php';

ob_start();
$return = call_user_func_array($_WPSERVICE['func'], (array)json_decode($_WPSERVICE['args']));
$ob = ob_get_clean();

// DETERMINE WHICH TO RETURN
if (empty($return)) echo json_encode(array('output' => $ob));
else echo json_encode(array('output' => $return));
?>