<?php

define('THEME_FORUM', 1); //The ID of the forum which the themes are in.
require '/home/wporg/public_html/extend/themes/bb-load.php'; //Load the bbPress Installation

// Register sticky themes as a view for simplicity
bb_register_view( 'featured', 'Featured Themes', array( 'sticky' => '-0' ) );

/*
Debug: DD32's local system doesnt have the BB Views: Its assumed WordPress.org uses these view names based on their URLs.
if ( ! isset($bb_views['featured']) ) {
    define('SAVEQUERIES', true);
    $bb_views['featured'] = array( 'title' => 'Featured Themes', 'query' => array('sticky' => '>0'));
    $bb_views['popular'] = array( 'title' => 'Popular Themes', 'query' => array('order_by'));    //Not working.
    $bb_views['updated'] = array( 'title' => 'Updated Themes', 'query' => array('updated' => '>20080625'));
    $bb_views['newest'] = array( 'title' => 'Newest Themes', 'query' => array('order' => 'ASC', 'order_by' => 'topic_start_time'));    
}
*/

/* hack: Like WordPress, bbPress adds slasheds to GPCS (not R).
 * Don't change the real superglobals in cas bbPress needs to do something with them later
 */
$__get     = stripslashes_deep($_GET );
$__post    = stripslashes_deep($_POST);
if ( get_magic_quotes_gpc() )
	$__request = stripslashes_deep($_REQUEST);
else
	$__request =& $_REQUEST;

$request = isset($__post['request']) ? unserialize(urldecode($__post['request'])) : '';
$action = isset($__request['action']) ? $__request['action'] : '';

$api = new Themes_API( $action, $request );

echo $api->get_result(); 

/* Hardlifting class */
class Themes_API {
    var $request = array();
    var $query = array();
    var $response = null;
    
    var $fields = array( /* field defaults, Overriden by individual sections. */
                        'description' => false,
                        'sections' => false,
                        'tested' => false,
                        'requires' => false,
                        'rating' => false,
                        'downloaded' => false,
                        'downloadlink' => false,
                        'last_updated' => false,
                        'tags' => false
                        
                        );
    
    /* Main access functions */
    function Themes_API( $action = '', $request = array() ) {
        $this->request = $request;
        
        switch( $action ) {
            case 'query_themes':
                $this->query_themes();
                break;
            case 'theme_information':
                $this->theme_information();
                break;
            case 'hot_tags':
                $this->hot_tags();
                break;
            default:
                if ( strtoupper($_SERVER['REQUEST_METHOD']) != 'POST' ) //Assume a friendly wp hacker :)
                    bb_die('Action not implemented. <a href="#" onclick="alert(\'If only I had written some.. Sorry! -DD32\'); return false;">API Docs</a>');
                else
                    $this->response = (object) array('error' => 'Action not implemented');
        }
    }

    function get_result() {
        return serialize($this->response);
    }
    
    /* Action functions */
    //Get the theme hot tags;
    function hot_tags() {
        $this->response = array();
        $limit = isset( $this->request->number ) ? (int)$this->request->number : 100;
        $tags = bb_get_top_tags(true, $limit);
        //Format in the API representation
        foreach ( (array) $tags as $tag )
            $this->response[ $tag->tag ] = array( 'name' => $tag->raw_tag, 'slug' => $tag->tag, 'count' => $tag->tag_count);
    }
    
    //Retrieve specific information about a theme.
    function theme_information() {

        //Theme slug to identify theme.
        if( ! isset($this->request->slug) ) {
            $this->response = (object) array('error' => 'Slug not provided');
            return;
        }

        $this->query['topic'] = $this->request->slug;

        //Set which fields wanted by default:
        $defaults = array(
                        'description' => false,
                        'sections' => true,
                        'tested' => true,
                        'requires' => true,
                        'rating' => true,
                        'downloaded' => true,
                        'downloadlink' => true,
                        'last_updated' => true,
                        'homepage' => true,
                        'tags' => true
                        );
        if ( isset($this->request->fields) && is_array($this->request->fields) )
            $this->fields = array_merge( $this->fields, $defaults, $this->request->fields );
        else
            $this->fields = array_merge( $this->fields, $defaults );

        $this->query['forum_id'] = THEME_FORUM;

        //Query
        $this->result = new BB_Query('topic', $this->query, 'theme_api');

        if( empty($this->result->results) )
            return;

        //Should be the first topic.
        $theme = $this->result->results[0];
        $this->response = $this->fill_theme($theme);
    }
    
    function query_themes() {
        //Paging
        $this->query['page'] = isset($this->request->page) ? $this->request->page : 1;
        $this->query['per_page'] = isset($this->request->per_page) ? $this->request->per_page : 0;
        
        $this->query['count'] = true;
        $this->query['forum_id'] = THEME_FORUM;


        //Views
        if( isset($this->request->browse) && ! empty($this->request->browse) ) {
            if ( !$this->result = bb_view_query( $this->request->browse ) )
                return;
        } else {
    
            //Tags
            if( isset($this->request->tag) && ! empty($this->request->tag) ) {
                if( is_array($this->request->tag) )
                    $this->query['tag'] = $this->request->tag[0]; //Current generation bbPress only handles one tag?
                else
                    $this->query['tag'] = $this->request->tag;
            }
        
            //Search
            if( isset($this->request->search) && ! empty($this->request->search) ) {
                $this->query['search'] = $this->request->search;
                $this->query['meta_key'] = 'rating_score';
                $this->query['order_by'] = '0 + tm.meta_value';
            }
        
            //Author
            if( isset($this->request->author) && ! empty($this->request->author) ) {
                $this->query['topic_author'] = $this->request->author;
                $this->result = new BB_Query( 'topic', $this->query, 'get_recent_user_threads' ); // Use bbPress' query id for this so that other themes can modify it
            } else {
                //Query        
                $this->result = new BB_Query('topic', $this->query, 'theme_api');
            }
        }

        //Set which fields wanted by default:
        $defaults = array(
                        'description' => true,
                        'rating' => true,
                        'homepage' => true
                        );
        if ( isset($this->request->fields) && is_array($this->request->fields) )
            $this->fields = array_merge( $this->fields, $defaults, $this->request->fields );
        else
            $this->fields = array_merge( $this->fields, $defaults );


        //Cache the first posts for the descriptions.
        $topic_ids = array();
        foreach( (array) $this->result->results as $theme )
            $topic_ids[] = $theme->topic_id;

        bb_cache_first_posts($topic_ids, false);

        //Basic information about the request.
        $this->response = (object) array(
                                'info' => array(
                                                'page' => $this->query['page'],
                                                'pages' => $this->result->query_vars['per_page'] > 0 ?
                                                            (int)ceil($this->result->found_rows / $this->result->query_vars['per_page']) : 1,
                                                'results' => $this->result->found_rows
                                                ),
                                'themes' => array()
                                );
        //Fill up the themes lists.
        foreach( (array) $this->result->results as $theme )
            $this->response->themes[] = $this->fill_theme($theme);
    }
    
    /* Fill */
    function fill_theme($theme) { /*  $theme == $topic*/
    
        $p = array(
            'name' => $theme->topic_title,            
            'slug' => $theme->topic_slug,
            'version' => $theme->version,
            'author' => $theme->author
            );
        
        if ( strpos($p['author'], '&lt;a') !== false )
            $p['author'] = html_entity_decode($p['author'], ENT_NOQUOTES);
        else if ( !empty($theme->author_uri) )
            $p['author'] = sprintf('<a href="%s">%s</a>', $theme->author_uri, $theme->author);
        
        if ( $this->fields['requires'] )
            $p['requires'] = $theme->requires;

        if ( $this->fields['tested'] )
            $p['tested'] = $theme->tested;

        if ( $this->fields['rating'] ) {
            //Return a % rating; Rating range: 0~5
            $p['rating'] = $theme->avg_rating * 20;
            $p['num_ratings'] = count($theme->rating);
        }

        if ( $this->fields['downloaded'] )
            $p['downloaded'] = $theme->downloads;

        if ( $this->fields['last_updated'] ) {
            //We dont want the time, just the date:
            list($date, $time) = explode(' ', $theme->topic_time);
            $p['last_updated'] = $date;
        }

        if ( $this->fields['homepage'] )
            $p['homepage'] = $theme->uri;

        if ( $this->fields['description'] || $this->fields['sections'] ) {
            $post = bb_get_first_post( $theme->topic_id );
            if ( ! $this->fields['sections'] ) {
                //No sections, Ok, Just return the Description (First field?)
                if( strpos($post->post_text, '<!--') )
                    $p['description'] = trim(substr($post->post_text, 0, strpos($post->post_text, '<!--')));
                else
                    $p['description'] = trim($post->post_text);
            } else { 
                //Client wants Sections
                $p['sections'] = array();
                if ( preg_match_all('|--theme-data-(.+?)-->(.*?)<!|ims', $post->post_text, $pieces) ) {
                    for ( $i = 0; $i < count($pieces[1]); $i++ )
                        $p['sections'][ $pieces[1][$i] ] = trim($pieces[2][$i]);
                } else {
                    //Doesnt have any sections:
                    $p['sections']['description'] = trim($post->post_text);
                }
            }
        }
        
        if ( $this->fields['downloadlink'] ) 
            $p['download_link'] = $this->create_download_link($theme);
        
        if ( $this->fields['tags'] ) {
            $p['tags'] = array();
            foreach( (array) $tag_list = bb_get_public_tags($theme->topic_id) as $tag )
                $p['tags'][ $tag->tag ] = $tag->raw_tag;
        }    
        
        return (object)$p;
    }
    
    /* Helper functions */
    
    function create_download_link($theme) {
        /*    One tricky thing is the download url.
            It's calculated from the "stable_tag" topicmeta.
             
            if trunk: theme.zip
            else: theme.{$tag}.zip
             
            where $tag is the stable_tag meta_value with the following caveats:
            if the meta_value starts with a ".", prepend  a "0"
            if the meta_value ends with a ".", append a "0"
        */

        $url = 'http://downloads.wordpress.org/theme/';
        $file = $theme->topic_slug;

        if ( 'trunk' != $theme->stable_tag && ! empty($theme->stable_tag) ) {
            //Handle versions
            $file .= '.';
            if ( '.' == $theme->stable_tag[0] )
                $file .= '0' . $theme->stable_tag;
            else
                $file .= $theme->stable_tag;

            if ( '.' == substr($file, -1) )
                $file .= '0';
        }
        $file .= '.zip';
        return $url . $file;
    }
}
