| 1 | <?php |
|---|
| 2 | |
|---|
| 3 | define('THEME_FORUM', 1); //The ID of the forum which the themes are in. |
|---|
| 4 | require '/home/wporg/public_html/extend/themes/bb-load.php'; //Load the bbPress Installation |
|---|
| 5 | |
|---|
| 6 | // Register sticky themes as a view for simplicity |
|---|
| 7 | bb_register_view( 'featured', 'Featured Themes', array( 'sticky' => '-0' ) ); |
|---|
| 8 | |
|---|
| 9 | /* |
|---|
| 10 | Debug: DD32's local system doesnt have the BB Views: Its assumed WordPress.org uses these view names based on their URLs. |
|---|
| 11 | if ( ! isset($bb_views['featured']) ) { |
|---|
| 12 | define('SAVEQUERIES', true); |
|---|
| 13 | $bb_views['featured'] = array( 'title' => 'Featured Themes', 'query' => array('sticky' => '>0')); |
|---|
| 14 | $bb_views['popular'] = array( 'title' => 'Popular Themes', 'query' => array('order_by')); //Not working. |
|---|
| 15 | $bb_views['updated'] = array( 'title' => 'Updated Themes', 'query' => array('updated' => '>20080625')); |
|---|
| 16 | $bb_views['newest'] = array( 'title' => 'Newest Themes', 'query' => array('order' => 'ASC', 'order_by' => 'topic_start_time')); |
|---|
| 17 | } |
|---|
| 18 | */ |
|---|
| 19 | |
|---|
| 20 | /* hack: Like WordPress, bbPress adds slasheds to GPCS (not R). |
|---|
| 21 | * Don't change the real superglobals in cas bbPress needs to do something with them later |
|---|
| 22 | */ |
|---|
| 23 | $__get = stripslashes_deep($_GET ); |
|---|
| 24 | $__post = stripslashes_deep($_POST); |
|---|
| 25 | if ( get_magic_quotes_gpc() ) |
|---|
| 26 | $__request = stripslashes_deep($_REQUEST); |
|---|
| 27 | else |
|---|
| 28 | $__request =& $_REQUEST; |
|---|
| 29 | |
|---|
| 30 | $request = isset($__post['request']) ? unserialize(urldecode($__post['request'])) : ''; |
|---|
| 31 | $action = isset($__request['action']) ? $__request['action'] : ''; |
|---|
| 32 | |
|---|
| 33 | $api = new Themes_API( $action, $request ); |
|---|
| 34 | |
|---|
| 35 | echo $api->get_result(); |
|---|
| 36 | |
|---|
| 37 | /* Hardlifting class */ |
|---|
| 38 | class Themes_API { |
|---|
| 39 | var $request = array(); |
|---|
| 40 | var $query = array(); |
|---|
| 41 | var $response = null; |
|---|
| 42 | |
|---|
| 43 | var $fields = array( /* field defaults, Overriden by individual sections. */ |
|---|
| 44 | 'description' => false, |
|---|
| 45 | 'sections' => false, |
|---|
| 46 | 'tested' => false, |
|---|
| 47 | 'requires' => false, |
|---|
| 48 | 'rating' => false, |
|---|
| 49 | 'downloaded' => false, |
|---|
| 50 | 'downloadlink' => false, |
|---|
| 51 | 'last_updated' => false, |
|---|
| 52 | 'tags' => false |
|---|
| 53 | |
|---|
| 54 | ); |
|---|
| 55 | |
|---|
| 56 | /* Main access functions */ |
|---|
| 57 | function Themes_API( $action = '', $request = array() ) { |
|---|
| 58 | $this->request = $request; |
|---|
| 59 | |
|---|
| 60 | switch( $action ) { |
|---|
| 61 | case 'query_themes': |
|---|
| 62 | $this->query_themes(); |
|---|
| 63 | break; |
|---|
| 64 | case 'theme_information': |
|---|
| 65 | $this->theme_information(); |
|---|
| 66 | break; |
|---|
| 67 | case 'hot_tags': |
|---|
| 68 | $this->hot_tags(); |
|---|
| 69 | break; |
|---|
| 70 | default: |
|---|
| 71 | if ( strtoupper($_SERVER['REQUEST_METHOD']) != 'POST' ) //Assume a friendly wp hacker :) |
|---|
| 72 | bb_die('Action not implemented. <a href="#" onclick="alert(\'If only I had written some.. Sorry! -DD32\'); return false;">API Docs</a>'); |
|---|
| 73 | else |
|---|
| 74 | $this->response = (object) array('error' => 'Action not implemented'); |
|---|
| 75 | } |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | function get_result() { |
|---|
| 79 | return serialize($this->response); |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | /* Action functions */ |
|---|
| 83 | //Get the theme hot tags; |
|---|
| 84 | function hot_tags() { |
|---|
| 85 | $this->response = array(); |
|---|
| 86 | $limit = isset( $this->request->number ) ? (int)$this->request->number : 100; |
|---|
| 87 | $tags = bb_get_top_tags(true, $limit); |
|---|
| 88 | //Format in the API representation |
|---|
| 89 | foreach ( (array) $tags as $tag ) |
|---|
| 90 | $this->response[ $tag->tag ] = array( 'name' => $tag->raw_tag, 'slug' => $tag->tag, 'count' => $tag->tag_count); |
|---|
| 91 | } |
|---|
| 92 | |
|---|
| 93 | //Retrieve specific information about a theme. |
|---|
| 94 | function theme_information() { |
|---|
| 95 | |
|---|
| 96 | //Theme slug to identify theme. |
|---|
| 97 | if( ! isset($this->request->slug) ) { |
|---|
| 98 | $this->response = (object) array('error' => 'Slug not provided'); |
|---|
| 99 | return; |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | $this->query['topic'] = $this->request->slug; |
|---|
| 103 | |
|---|
| 104 | //Set which fields wanted by default: |
|---|
| 105 | $defaults = array( |
|---|
| 106 | 'description' => false, |
|---|
| 107 | 'sections' => true, |
|---|
| 108 | 'tested' => true, |
|---|
| 109 | 'requires' => true, |
|---|
| 110 | 'rating' => true, |
|---|
| 111 | 'downloaded' => true, |
|---|
| 112 | 'downloadlink' => true, |
|---|
| 113 | 'last_updated' => true, |
|---|
| 114 | 'homepage' => true, |
|---|
| 115 | 'tags' => true |
|---|
| 116 | ); |
|---|
| 117 | if ( isset($this->request->fields) && is_array($this->request->fields) ) |
|---|
| 118 | $this->fields = array_merge( $this->fields, $defaults, $this->request->fields ); |
|---|
| 119 | else |
|---|
| 120 | $this->fields = array_merge( $this->fields, $defaults ); |
|---|
| 121 | |
|---|
| 122 | $this->query['forum_id'] = THEME_FORUM; |
|---|
| 123 | |
|---|
| 124 | //Query |
|---|
| 125 | $this->result = new BB_Query('topic', $this->query, 'theme_api'); |
|---|
| 126 | |
|---|
| 127 | if( empty($this->result->results) ) |
|---|
| 128 | return; |
|---|
| 129 | |
|---|
| 130 | //Should be the first topic. |
|---|
| 131 | $theme = $this->result->results[0]; |
|---|
| 132 | $this->response = $this->fill_theme($theme); |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | function query_themes() { |
|---|
| 136 | //Paging |
|---|
| 137 | $this->query['page'] = isset($this->request->page) ? $this->request->page : 1; |
|---|
| 138 | $this->query['per_page'] = isset($this->request->per_page) ? $this->request->per_page : 0; |
|---|
| 139 | |
|---|
| 140 | $this->query['count'] = true; |
|---|
| 141 | $this->query['forum_id'] = THEME_FORUM; |
|---|
| 142 | |
|---|
| 143 | |
|---|
| 144 | //Views |
|---|
| 145 | if( isset($this->request->browse) && ! empty($this->request->browse) ) { |
|---|
| 146 | if ( !$this->result = bb_view_query( $this->request->browse ) ) |
|---|
| 147 | return; |
|---|
| 148 | } else { |
|---|
| 149 | |
|---|
| 150 | //Tags |
|---|
| 151 | if( isset($this->request->tag) && ! empty($this->request->tag) ) { |
|---|
| 152 | if( is_array($this->request->tag) ) |
|---|
| 153 | $this->query['tag'] = $this->request->tag[0]; //Current generation bbPress only handles one tag? |
|---|
| 154 | else |
|---|
| 155 | $this->query['tag'] = $this->request->tag; |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | //Search |
|---|
| 159 | if( isset($this->request->search) && ! empty($this->request->search) ) { |
|---|
| 160 | $this->query['search'] = $this->request->search; |
|---|
| 161 | $this->query['meta_key'] = 'rating_score'; |
|---|
| 162 | $this->query['order_by'] = '0 + tm.meta_value'; |
|---|
| 163 | } |
|---|
| 164 | |
|---|
| 165 | //Author |
|---|
| 166 | if( isset($this->request->author) && ! empty($this->request->author) ) { |
|---|
| 167 | $this->query['topic_author'] = $this->request->author; |
|---|
| 168 | $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 |
|---|
| 169 | } else { |
|---|
| 170 | //Query |
|---|
| 171 | $this->result = new BB_Query('topic', $this->query, 'theme_api'); |
|---|
| 172 | } |
|---|
| 173 | } |
|---|
| 174 | |
|---|
| 175 | //Set which fields wanted by default: |
|---|
| 176 | $defaults = array( |
|---|
| 177 | 'description' => true, |
|---|
| 178 | 'rating' => true, |
|---|
| 179 | 'homepage' => true |
|---|
| 180 | ); |
|---|
| 181 | if ( isset($this->request->fields) && is_array($this->request->fields) ) |
|---|
| 182 | $this->fields = array_merge( $this->fields, $defaults, $this->request->fields ); |
|---|
| 183 | else |
|---|
| 184 | $this->fields = array_merge( $this->fields, $defaults ); |
|---|
| 185 | |
|---|
| 186 | |
|---|
| 187 | //Cache the first posts for the descriptions. |
|---|
| 188 | $topic_ids = array(); |
|---|
| 189 | foreach( (array) $this->result->results as $theme ) |
|---|
| 190 | $topic_ids[] = $theme->topic_id; |
|---|
| 191 | |
|---|
| 192 | bb_cache_first_posts($topic_ids, false); |
|---|
| 193 | |
|---|
| 194 | //Basic information about the request. |
|---|
| 195 | $this->response = (object) array( |
|---|
| 196 | 'info' => array( |
|---|
| 197 | 'page' => $this->query['page'], |
|---|
| 198 | 'pages' => $this->result->query_vars['per_page'] > 0 ? |
|---|
| 199 | (int)ceil($this->result->found_rows / $this->result->query_vars['per_page']) : 1, |
|---|
| 200 | 'results' => $this->result->found_rows |
|---|
| 201 | ), |
|---|
| 202 | 'themes' => array() |
|---|
| 203 | ); |
|---|
| 204 | //Fill up the themes lists. |
|---|
| 205 | foreach( (array) $this->result->results as $theme ) |
|---|
| 206 | $this->response->themes[] = $this->fill_theme($theme); |
|---|
| 207 | } |
|---|
| 208 | |
|---|
| 209 | /* Fill */ |
|---|
| 210 | function fill_theme($theme) { /* $theme == $topic*/ |
|---|
| 211 | |
|---|
| 212 | $p = array( |
|---|
| 213 | 'name' => $theme->topic_title, |
|---|
| 214 | 'slug' => $theme->topic_slug, |
|---|
| 215 | 'version' => $theme->version, |
|---|
| 216 | 'author' => $theme->author |
|---|
| 217 | ); |
|---|
| 218 | |
|---|
| 219 | if ( strpos($p['author'], '<a') !== false ) |
|---|
| 220 | $p['author'] = html_entity_decode($p['author'], ENT_NOQUOTES); |
|---|
| 221 | else if ( !empty($theme->author_uri) ) |
|---|
| 222 | $p['author'] = sprintf('<a href="%s">%s</a>', $theme->author_uri, $theme->author); |
|---|
| 223 | |
|---|
| 224 | if ( $this->fields['requires'] ) |
|---|
| 225 | $p['requires'] = $theme->requires; |
|---|
| 226 | |
|---|
| 227 | if ( $this->fields['tested'] ) |
|---|
| 228 | $p['tested'] = $theme->tested; |
|---|
| 229 | |
|---|
| 230 | if ( $this->fields['rating'] ) { |
|---|
| 231 | //Return a % rating; Rating range: 0~5 |
|---|
| 232 | $p['rating'] = $theme->avg_rating * 20; |
|---|
| 233 | $p['num_ratings'] = count($theme->rating); |
|---|
| 234 | } |
|---|
| 235 | |
|---|
| 236 | if ( $this->fields['downloaded'] ) |
|---|
| 237 | $p['downloaded'] = $theme->downloads; |
|---|
| 238 | |
|---|
| 239 | if ( $this->fields['last_updated'] ) { |
|---|
| 240 | //We dont want the time, just the date: |
|---|
| 241 | list($date, $time) = explode(' ', $theme->topic_time); |
|---|
| 242 | $p['last_updated'] = $date; |
|---|
| 243 | } |
|---|
| 244 | |
|---|
| 245 | if ( $this->fields['homepage'] ) |
|---|
| 246 | $p['homepage'] = $theme->uri; |
|---|
| 247 | |
|---|
| 248 | if ( $this->fields['description'] || $this->fields['sections'] ) { |
|---|
| 249 | $post = bb_get_first_post( $theme->topic_id ); |
|---|
| 250 | if ( ! $this->fields['sections'] ) { |
|---|
| 251 | //No sections, Ok, Just return the Description (First field?) |
|---|
| 252 | if( strpos($post->post_text, '<!--') ) |
|---|
| 253 | $p['description'] = trim(substr($post->post_text, 0, strpos($post->post_text, '<!--'))); |
|---|
| 254 | else |
|---|
| 255 | $p['description'] = trim($post->post_text); |
|---|
| 256 | } else { |
|---|
| 257 | //Client wants Sections |
|---|
| 258 | $p['sections'] = array(); |
|---|
| 259 | if ( preg_match_all('|--theme-data-(.+?)-->(.*?)<!|ims', $post->post_text, $pieces) ) { |
|---|
| 260 | for ( $i = 0; $i < count($pieces[1]); $i++ ) |
|---|
| 261 | $p['sections'][ $pieces[1][$i] ] = trim($pieces[2][$i]); |
|---|
| 262 | } else { |
|---|
| 263 | //Doesnt have any sections: |
|---|
| 264 | $p['sections']['description'] = trim($post->post_text); |
|---|
| 265 | } |
|---|
| 266 | } |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | if ( $this->fields['downloadlink'] ) |
|---|
| 270 | $p['download_link'] = $this->create_download_link($theme); |
|---|
| 271 | |
|---|
| 272 | if ( $this->fields['tags'] ) { |
|---|
| 273 | $p['tags'] = array(); |
|---|
| 274 | foreach( (array) $tag_list = bb_get_public_tags($theme->topic_id) as $tag ) |
|---|
| 275 | $p['tags'][ $tag->tag ] = $tag->raw_tag; |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | return (object)$p; |
|---|
| 279 | } |
|---|
| 280 | |
|---|
| 281 | /* Helper functions */ |
|---|
| 282 | |
|---|
| 283 | function create_download_link($theme) { |
|---|
| 284 | /* One tricky thing is the download url. |
|---|
| 285 | It's calculated from the "stable_tag" topicmeta. |
|---|
| 286 | |
|---|
| 287 | if trunk: theme.zip |
|---|
| 288 | else: theme.{$tag}.zip |
|---|
| 289 | |
|---|
| 290 | where $tag is the stable_tag meta_value with the following caveats: |
|---|
| 291 | if the meta_value starts with a ".", prepend a "0" |
|---|
| 292 | if the meta_value ends with a ".", append a "0" |
|---|
| 293 | */ |
|---|
| 294 | |
|---|
| 295 | $url = 'http://downloads.wordpress.org/theme/'; |
|---|
| 296 | $file = $theme->topic_slug; |
|---|
| 297 | |
|---|
| 298 | if ( 'trunk' != $theme->stable_tag && ! empty($theme->stable_tag) ) { |
|---|
| 299 | //Handle versions |
|---|
| 300 | $file .= '.'; |
|---|
| 301 | if ( '.' == $theme->stable_tag[0] ) |
|---|
| 302 | $file .= '0' . $theme->stable_tag; |
|---|
| 303 | else |
|---|
| 304 | $file .= $theme->stable_tag; |
|---|
| 305 | |
|---|
| 306 | if ( '.' == substr($file, -1) ) |
|---|
| 307 | $file .= '0'; |
|---|
| 308 | } |
|---|
| 309 | $file .= '.zip'; |
|---|
| 310 | return $url . $file; |
|---|
| 311 | } |
|---|
| 312 | } |
|---|