| 1 | <?php |
| 2 | /** |
| 3 | * WordPress Theme Install Administration API |
| 4 | * |
| 5 | * @package WordPress |
| 6 | * @subpackage Administration |
| 7 | */ |
| 8 | |
| 9 | /** |
| 10 | * Retrieve theme installer pages from WordPress Themes API. |
| 11 | * |
| 12 | * It is possible for a theme to override the Themes API result with three |
| 13 | * filters. Assume this is for themes, which can extend on the Theme Info to |
| 14 | * offer more choices. This is very powerful and must be used with care, when |
| 15 | * overridding the filters. |
| 16 | * |
| 17 | * The first filter, 'themes_api_args', is for the args and gives the action as |
| 18 | * the second parameter. The hook for 'themes_api_args' must ensure that an |
| 19 | * object is returned. |
| 20 | * |
| 21 | * The second filter, 'themes_api', is the result that would be returned. |
| 22 | * |
| 23 | * @since 2.8.0 |
| 24 | * |
| 25 | * @param string $action |
| 26 | * @param array|object $args Optional. Arguments to serialize for the Theme Info API. |
| 27 | * @return mixed |
| 28 | */ |
| 29 | function themes_api($action, $args = null) { |
| 30 | |
| 31 | if( is_array($args) ) |
| 32 | $args = (object)$args; |
| 33 | |
| 34 | if ( !isset($args->per_page) ) |
| 35 | $args->per_page = 24; |
| 36 | |
| 37 | $args = apply_filters('themes_api_args', $args, $action); //NOTE: Ensure that an object is returned via this filter. |
| 38 | $res = apply_filters('themes_api', false, $action, $args); //NOTE: Allows a theme to completely override the builtin WordPress.org API. |
| 39 | |
| 40 | if ( ! $res ) { |
| 41 | $request = wp_remote_post('http://api.wordpress.org/themes/info/1.0/', array( 'body' => array('action' => $action, 'request' => serialize($args))) ); |
| 42 | if ( is_wp_error($request) ) { |
| 43 | $res = new WP_Error('themes_api_failed', __('An Unexpected HTTP Error occured during the API request.</p> <p><a href="?" onclick="document.location.reload(); return false;">Try again</a>'), $request->get_error_message() ); |
| 44 | } else { |
| 45 | $res = unserialize($request['body']); |
| 46 | if ( ! $res ) |
| 47 | $res = new WP_Error('themes_api_failed', __('An unknown error occured'), $request['body']); |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | return apply_filters('themes_api_result', $res, $action, $args); |
| 52 | } |
| 53 | |
| 54 | /** |
| 55 | * Retrieve popular WordPress theme tags. |
| 56 | * |
| 57 | * @since 2.8.0 |
| 58 | * |
| 59 | * @param array $args |
| 60 | * @return array |
| 61 | */ |
| 62 | function install_themes_popular_tags( $args = array() ) { |
| 63 | if ( !$cache = get_option('wporg_theme_popular_tags') ) |
| 64 | add_option('wporg_theme_popular_tags', array(), '', 'no'); ///No autoload. |
| 65 | |
| 66 | if ( $cache && $cache->timeout + 3 * 60 * 60 > time() ) |
| 67 | return $cache->cached; |
| 68 | |
| 69 | $tags = themes_api('hot_tags', $args); |
| 70 | |
| 71 | if ( is_wp_error($tags) ) |
| 72 | return $tags; |
| 73 | |
| 74 | $cache = (object) array('timeout' => time(), 'cached' => $tags); |
| 75 | |
| 76 | update_option('wporg_theme_popular_tags', $cache); |
| 77 | |
| 78 | return $tags; |
| 79 | } |
| 80 | |
| 81 | add_action('install_themes_search', 'install_theme_search', 10, 1); |
| 82 | /** |
| 83 | * Display theme search results and display as tag cloud. |
| 84 | * |
| 85 | * @since 2.8.0 |
| 86 | * |
| 87 | * @param string $page |
| 88 | */ |
| 89 | function install_theme_search($page) { |
| 90 | $type = isset($_REQUEST['type']) ? stripslashes( $_REQUEST['type'] ) : ''; |
| 91 | $term = isset($_REQUEST['s']) ? stripslashes( $_REQUEST['s'] ) : ''; |
| 92 | |
| 93 | $args = array(); |
| 94 | |
| 95 | switch( $type ){ |
| 96 | case 'tag': |
| 97 | $args['tag'] = sanitize_title_with_dashes($term); |
| 98 | break; |
| 99 | case 'term': |
| 100 | $args['search'] = $term; |
| 101 | break; |
| 102 | case 'author': |
| 103 | $args['author'] = $term; |
| 104 | break; |
| 105 | } |
| 106 | |
| 107 | $args['page'] = $page; |
| 108 | |
| 109 | $api = themes_api('query_themes', $args); |
| 110 | |
| 111 | if ( is_wp_error($api) ) |
| 112 | wp_die($api); |
| 113 | |
| 114 | add_action('install_themes_table_header', 'install_theme_search_form'); |
| 115 | |
| 116 | display_themes($api->themes, $api->info['page'], $api->info['pages']); |
| 117 | } |
| 118 | |
| 119 | add_action('install_themes_dashboard', 'install_themes_dashboard'); |
| 120 | function install_themes_dashboard() { |
| 121 | ?> |
| 122 | <p><?php _e('Themes give your WordPress a personalized feel & touch. You may automatically install themes from the <a href="http://wordpress.org/extend/themes/">WordPress Theme Directory</a> or upload a theme in .zip format via this page.') ?></p> |
| 123 | |
| 124 | <h4><?php _e('Search') ?></h4> |
| 125 | <?php install_theme_search_form('<a href="' . add_query_arg('show-help', !isset($_REQUEST['show-help'])) .'" onclick="jQuery(\'#search-help\').toggle(); return false;">' . __('[need help?]') . '</a>') ?> |
| 126 | <div id="search-help" style="display: <?php echo isset($_REQUEST['show-help']) ? 'block' : 'none'; ?>;"> |
| 127 | <p> <?php _e('You may search based on 3 criteria:') ?><br /> |
| 128 | <?php _e('<strong>Term:</strong> Searches theme names and descriptions for the specified term') ?><br /> |
| 129 | <?php _e('<strong>Tag:</strong> Searches for themes tagged as such') ?><br /> |
| 130 | <?php _e('<strong>Author:</strong> Searches for themes created by the Author, or which the Author contributed to.') ?></p> |
| 131 | </div> |
| 132 | |
| 133 | <h4><?php _e('Install a theme in .zip format') ?></h4> |
| 134 | <p><?php _e('If you have a theme in a .zip format, You may install it by uploading it here.') ?></p> |
| 135 | <form method="post" enctype="multipart/form-data" action="<?php echo admin_url('theme-install.php?tab=upload') ?>"> |
| 136 | <?php wp_nonce_field( 'theme-upload') ?> |
| 137 | <input type="file" name="themezip" /> |
| 138 | <input type="submit" class="button" value="<?php _e('Install Now') ?>" /> |
| 139 | </form> |
| 140 | |
| 141 | <h4><?php _e('Popular tags') ?></h4> |
| 142 | <p><?php _e('You may also browse based on the most popular tags in the Theme Directory:') ?></p> |
| 143 | <?php |
| 144 | |
| 145 | $api_tags = install_themes_popular_tags(); |
| 146 | |
| 147 | //Set up the tags in a way which can be interprated by wp_generate_tag_cloud() |
| 148 | $tags = array(); |
| 149 | foreach ( (array)$api_tags as $tag ) |
| 150 | $tags[ $tag['name'] ] = (object) array( |
| 151 | 'link' => clean_url( admin_url('theme-install.php?tab=search&type=tag&s=' . urlencode($tag['name'])) ), |
| 152 | 'name' => $tag['name'], |
| 153 | 'id' => sanitize_title_with_dashes($tag['name']), |
| 154 | 'count' => $tag['count'] ); |
| 155 | echo '<p>'; |
| 156 | echo wp_generate_tag_cloud($tags, array( 'single_text' => __('%d theme'), 'multiple_text' => __('%d themes') ) ); |
| 157 | echo '</p><br class="clear" />'; |
| 158 | } |
| 159 | |
| 160 | /** |
| 161 | * Display search form for searching themes. |
| 162 | * |
| 163 | * @since 2.8.0 |
| 164 | */ |
| 165 | function install_theme_search_form(){ |
| 166 | $type = isset($_REQUEST['type']) ? stripslashes( $_REQUEST['type'] ) : ''; |
| 167 | $term = isset($_REQUEST['s']) ? stripslashes( $_REQUEST['s'] ) : ''; |
| 168 | |
| 169 | ?><form id="search-themes" method="post" action="<?php echo admin_url('theme-install.php?tab=search') ?>"> |
| 170 | <select name="type" id="typeselector"> |
| 171 | <option value="term"<?php selected('term', $type) ?>><?php _e('Term') ?></option> |
| 172 | <option value="author"<?php selected('author', $type) ?>><?php _e('Author') ?></option> |
| 173 | <option value="tag"<?php selected('tag', $type) ?>><?php _e('Tag') ?></option> |
| 174 | </select> |
| 175 | <input type="text" name="s" id="search-field" value="<?php echo attribute_escape($term) ?>" /> |
| 176 | <input type="submit" name="search" value="<?php echo attribute_escape(__('Search')) ?>" class="button" /> |
| 177 | </form><?php |
| 178 | } |
| 179 | |
| 180 | add_action('install_themes_featured', 'install_themes_featured', 10, 1); |
| 181 | /** |
| 182 | * Display featured themes. |
| 183 | * |
| 184 | * @since 2.8.0 |
| 185 | * |
| 186 | * @param string $page |
| 187 | */ |
| 188 | function install_themes_featured($page = 1) { |
| 189 | $args = array('browse' => 'featured', 'page' => $page); |
| 190 | $api = themes_api('query_themes', $args); |
| 191 | if ( is_wp_error($api) ) |
| 192 | wp_die($api); |
| 193 | display_themes($api->themes, $api->info['page'], $api->info['pages']); |
| 194 | } |
| 195 | |
| 196 | add_action('install_thems_popular', 'install_themes_popular', 10, 1); |
| 197 | /** |
| 198 | * Display popular themes. |
| 199 | * |
| 200 | * @since 2.8.0 |
| 201 | * |
| 202 | * @param string $page |
| 203 | */ |
| 204 | function install_themes_popular($page = 1) { |
| 205 | $args = array('browse' => 'popular', 'page' => $page); |
| 206 | $api = themes_api('query_themes', $args); |
| 207 | display_themes($api->themes, $api->info['page'], $api->info['pages']); |
| 208 | } |
| 209 | |
| 210 | add_action('install_themes_new', 'install_themes_new', 10, 1); |
| 211 | /** |
| 212 | * Display new themes/ |
| 213 | * |
| 214 | * @since 2.8.0 |
| 215 | * |
| 216 | * @param string $page |
| 217 | */ |
| 218 | function install_themes_new($page = 1) { |
| 219 | $args = array('browse' => 'new', 'page' => $page); |
| 220 | $api = themes_api('query_themes', $args); |
| 221 | if ( is_wp_error($api) ) |
| 222 | wp_die($api); |
| 223 | display_themes($api->themes, $api->info['page'], $api->info['pages']); |
| 224 | } |
| 225 | |
| 226 | add_action('install_themes_updated', 'install_themes_updated', 10, 1); |
| 227 | /** |
| 228 | * Display recently updated themes. |
| 229 | * |
| 230 | * @since 2.8.0 |
| 231 | * |
| 232 | * @param string $page |
| 233 | */ |
| 234 | function install_themes_updated($page = 1) { |
| 235 | $args = array('browse' => 'updated', 'page' => $page); |
| 236 | $api = themes_api('query_themes', $args); |
| 237 | display_themes($api->themes, $api->info['page'], $api->info['pages']); |
| 238 | } |
| 239 | |
| 240 | /** |
| 241 | * Display theme content based on theme list. |
| 242 | * |
| 243 | * @since 2.8.0 |
| 244 | * |
| 245 | * @param array $themes List of themes. |
| 246 | * @param string $page |
| 247 | * @param int $totalpages Number of pages. |
| 248 | */ |
| 249 | function display_themes($themes, $page = 1, $totalpages = 1) { |
| 250 | $type = isset($_REQUEST['type']) ? stripslashes( $_REQUEST['type'] ) : ''; |
| 251 | $term = isset($_REQUEST['s']) ? stripslashes( $_REQUEST['s'] ) : ''; |
| 252 | |
| 253 | $themes_allowedtags = array('a' => array('href' => array(),'title' => array(), 'target' => array()), |
| 254 | 'abbr' => array('title' => array()),'acronym' => array('title' => array()), |
| 255 | 'code' => array(), 'pre' => array(), 'em' => array(),'strong' => array()); |
| 256 | |
| 257 | ?> |
| 258 | <div class="tablenav"> |
| 259 | <div class="alignleft actions"> |
| 260 | <?php do_action('install_themes_table_header'); ?> |
| 261 | </div> |
| 262 | <?php |
| 263 | $url = clean_url($_SERVER['REQUEST_URI']); |
| 264 | if ( ! empty($term) ) |
| 265 | $url = add_query_arg('s', $term, $url); |
| 266 | if ( ! empty($type) ) |
| 267 | $url = add_query_arg('type', $type, $url); |
| 268 | |
| 269 | $page_links = paginate_links( array( |
| 270 | 'base' => add_query_arg('paged', '%#%', $url), |
| 271 | 'format' => '', |
| 272 | 'prev_text' => __('«'), |
| 273 | 'next_text' => __('»'), |
| 274 | 'total' => $totalpages, |
| 275 | 'current' => $page |
| 276 | )); |
| 277 | |
| 278 | if ( $page_links ) |
| 279 | echo "\t\t<div class='tablenav-pages'>$page_links</div>"; |
| 280 | ?> |
| 281 | <br class="clear" /> |
| 282 | </div> |
| 283 | <table class="widefat" id="install-themes" cellspacing="0"> |
| 284 | <thead> |
| 285 | <tr> |
| 286 | <th scope="col" class="name"><?php _e('Name'); ?></th> |
| 287 | <th scope="col" class="num"><?php _e('Version'); ?></th> |
| 288 | <th scope="col" class="num"><?php _e('Rating'); ?></th> |
| 289 | <th scope="col" class="desc"><?php _e('Description'); ?></th> |
| 290 | <th scope="col" class="action-links"><?php _e('Actions'); ?></th> |
| 291 | </tr> |
| 292 | </thead> |
| 293 | |
| 294 | <tfoot> |
| 295 | <tr> |
| 296 | <th scope="col" class="name"><?php _e('Name'); ?></th> |
| 297 | <th scope="col" class="num"><?php _e('Version'); ?></th> |
| 298 | <th scope="col" class="num"><?php _e('Rating'); ?></th> |
| 299 | <th scope="col" class="desc"><?php _e('Description'); ?></th> |
| 300 | <th scope="col" class="action-links"><?php _e('Actions'); ?></th> |
| 301 | </tr> |
| 302 | </tfoot> |
| 303 | |
| 304 | <tbody class="themes"> |
| 305 | <?php |
| 306 | if( empty($themes) ) |
| 307 | echo '<tr><td colspan="5">', __('No themes match your request.'), '</td></tr>'; |
| 308 | |
| 309 | foreach( (array) $themes as $theme ){ |
| 310 | if ( is_object($theme) ) |
| 311 | $theme = (array) $theme; |
| 312 | |
| 313 | $title = wp_kses($theme['name'], $themes_allowedtags); |
| 314 | $description = wp_kses($theme['description'], $themes_allowedtags); |
| 315 | $version = wp_kses($theme['version'], $themes_allowedtags); |
| 316 | |
| 317 | $name = strip_tags($title . ' ' . $version); |
| 318 | |
| 319 | $author = $theme['author']; |
| 320 | if( ! empty($theme['author']) ) |
| 321 | $author = ' <cite>' . sprintf( __('By %s'), $author ) . '.</cite>'; |
| 322 | |
| 323 | $author = wp_kses($author, $themes_allowedtags); |
| 324 | |
| 325 | if( isset($theme['homepage']) ) |
| 326 | $title = '<a target="_blank" href="' . attribute_escape($theme['homepage']) . '">' . $title . '</a>'; |
| 327 | |
| 328 | $action_links = array(); |
| 329 | $action_links[] = '<a href="' . admin_url('theme-install.php?tab=theme-information&theme=' . $theme['slug'] . |
| 330 | '&TB_iframe=true&width=600&height=800') . '" class="thickbox onclick" title="' . |
| 331 | attribute_escape($name) . '">' . __('Install') . '</a>'; |
| 332 | |
| 333 | $action_links = apply_filters('theme_install_action_links', $action_links, $theme); |
| 334 | ?> |
| 335 | <tr> |
| 336 | <td class="name"><?php echo $title; ?></td> |
| 337 | <td class="vers"><?php echo $version; ?></td> |
| 338 | <td class="vers"> |
| 339 | <div class="star-holder" title="<?php printf(__ngettext('(based on %s rating)', '(based on %s ratings)', $theme['num_ratings']), number_format_i18n($theme['num_ratings'])) ?>"> |
| 340 | <div class="star star-rating" style="width: <?php echo attribute_escape($theme['rating']) ?>px"></div> |
| 341 | <div class="star star5"><img src="<?php echo admin_url('images/star.gif'); ?>" alt="<?php _e('5 stars') ?>" /></div> |
| 342 | <div class="star star4"><img src="<?php echo admin_url('images/star.gif'); ?>" alt="<?php _e('4 stars') ?>" /></div> |
| 343 | <div class="star star3"><img src="<?php echo admin_url('images/star.gif'); ?>" alt="<?php _e('3 stars') ?>" /></div> |
| 344 | <div class="star star2"><img src="<?php echo admin_url('images/star.gif'); ?>" alt="<?php _e('2 stars') ?>" /></div> |
| 345 | <div class="star star1"><img src="<?php echo admin_url('images/star.gif'); ?>" alt="<?php _e('1 star') ?>" /></div> |
| 346 | </div> |
| 347 | </td> |
| 348 | <td class="desc"><p><?php echo $description, $author; ?></p></td> |
| 349 | <td class="action-links"><?php if ( !empty($action_links) ) echo implode(' | ', $action_links); ?></td> |
| 350 | </tr> |
| 351 | <?php |
| 352 | } |
| 353 | ?> |
| 354 | </tbody> |
| 355 | </table> |
| 356 | |
| 357 | <div class="tablenav"> |
| 358 | <?php if ( $page_links ) |
| 359 | echo "\t\t<div class='tablenav-pages'>$page_links</div>"; ?> |
| 360 | <br class="clear" /> |
| 361 | </div> |
| 362 | |
| 363 | <?php |
| 364 | } |
| 365 | |
| 366 | add_action('install_themes_pre_theme-information', 'install_theme_information'); |
| 367 | |
| 368 | /** |
| 369 | * Display theme information in dialog box form. |
| 370 | * |
| 371 | * @since 2.8.0 |
| 372 | */ |
| 373 | function install_theme_information() { |
| 374 | //TODO: This function needs a LOT of UI work :) |
| 375 | global $tab; |
| 376 | |
| 377 | $api = themes_api('theme_information', array('slug' => stripslashes( $_REQUEST['theme'] ) )); |
| 378 | |
| 379 | if ( is_wp_error($api) ) |
| 380 | wp_die($api); |
| 381 | |
| 382 | $themes_allowedtags = array('a' => array('href' => array(), 'title' => array(), 'target' => array()), |
| 383 | 'abbr' => array('title' => array()), 'acronym' => array('title' => array()), |
| 384 | 'code' => array(), 'pre' => array(), 'em' => array(), 'strong' => array(), |
| 385 | 'div' => array(), 'p' => array(), 'ul' => array(), 'ol' => array(), 'li' => array(), |
| 386 | 'h1' => array(), 'h2' => array(), 'h3' => array(), 'h4' => array(), 'h5' => array(), 'h6' => array(), |
| 387 | 'img' => array('src' => array(), 'class' => array(), 'alt' => array())); |
| 388 | //Sanitize HTML |
| 389 | foreach ( (array)$api->sections as $section_name => $content ) |
| 390 | $api->sections[$section_name] = wp_kses($content, $themes_allowedtags); |
| 391 | foreach ( array('version', 'author', 'requires', 'tested', 'homepage', 'downloaded', 'slug') as $key ) |
| 392 | $api->$key = wp_kses($api->$key, $themes_allowedtags); |
| 393 | |
| 394 | $section = isset($_REQUEST['section']) ? stripslashes( $_REQUEST['section'] ) : 'description'; //Default to the Description tab, Do not translate, API returns English. |
| 395 | if( empty($section) || ! isset($api->sections[ $section ]) ) |
| 396 | $section = array_shift( $section_titles = array_keys((array)$api->sections) ); |
| 397 | |
| 398 | iframe_header( __('Theme Install') ); |
| 399 | echo "<div id='$tab-header'>\n"; |
| 400 | echo "<ul id='sidemenu'>\n"; |
| 401 | foreach ( (array)$api->sections as $section_name => $content ) { |
| 402 | |
| 403 | $title = $section_name; |
| 404 | $title = ucwords(str_replace('_', ' ', $title)); |
| 405 | |
| 406 | $class = ( $section_name == $section ) ? ' class="current"' : ''; |
| 407 | $href = add_query_arg( array('tab' => $tab, 'section' => $section_name) ); |
| 408 | $href = clean_url($href); |
| 409 | $san_title = attribute_escape(sanitize_title_with_dashes($title)); |
| 410 | echo "\t<li><a name='$san_title' target='' href='$href'$class>$title</a></li>\n"; |
| 411 | } |
| 412 | echo "</ul>\n"; |
| 413 | echo "</div>\n"; |
| 414 | ?> |
| 415 | <div class="alignright fyi"> |
| 416 | <?php if ( ! empty($api->download_link) ) : ?> |
| 417 | <p class="action-button"> |
| 418 | <?php |
| 419 | //Default to a "new" theme |
| 420 | $type = 'install'; |
| 421 | //Check to see if this theme is known to be installed, and has an update awaiting it. |
| 422 | $update_themes = get_option('update_themes'); |
| 423 | foreach ( (array)$update_themes->response as $file => $theme ) { |
| 424 | if ( $theme->slug === $api->slug ) { |
| 425 | $type = 'update_available'; |
| 426 | $update_file = $file; |
| 427 | break; |
| 428 | } |
| 429 | } |
| 430 | /*if ( 'install' == $type && is_dir( WP_PLUGIN_DIR . '/' . $api->slug ) ) { |
| 431 | $installed_theme = get_themes('/' . $api->slug); |
| 432 | if ( ! empty($installed_theme) ) { |
| 433 | $key = array_shift( $key = array_keys($installed_theme) ); //Use the first theme regardless of the name, Could have issues for multiple-themes in one directory if they share different version numbers |
| 434 | if ( version_compare($api->version, $installed_theme[ $key ]['Version'], '>') ){ |
| 435 | $type = 'latest_installed'; |
| 436 | } elseif ( version_compare($api->version, $installed_theme[ $key ]['Version'], '<') ) { |
| 437 | $type = 'newer_installed'; |
| 438 | $newer_version = $installed_theme[ $key ]['Version']; |
| 439 | } else { |
| 440 | //If the above update check failed, Then that probably means that the update checker has out-of-date information, force a refresh |
| 441 | delete_option('update_themes'); |
| 442 | $update_file = $api->slug . '/' . $key; //This code branch only deals with a theme which is in a folder the same name as its slug, Doesnt support themes which have 'non-standard' names |
| 443 | $type = 'update_available'; |
| 444 | } |
| 445 | } |
| 446 | }*/ |
| 447 | |
| 448 | switch ( $type ) : |
| 449 | default: |
| 450 | case 'install': |
| 451 | if ( current_user_can('install_themes') ) : |
| 452 | ?><a href="<?php echo wp_nonce_url(admin_url('theme-install.php?tab=install&theme=' . $api->slug), 'install-theme_' . $api->slug) ?>" target="_parent"><?php _e('Install Now') ?></a><?php |
| 453 | endif; |
| 454 | break; |
| 455 | case 'update_available': |
| 456 | if ( current_user_can('update_themes') ) : |
| 457 | ?><a href="<?php echo wp_nonce_url(admin_url('update.php?action=upgrade-theme&theme=' . $update_file), 'upgrade-theme_' . $update_file) ?>" target="_parent"><?php _e('Install Update Now') ?></a><?php |
| 458 | endif; |
| 459 | break; |
| 460 | case 'newer_installed': |
| 461 | if ( current_user_can('install_themes') || current_user_can('update_themes') ) : |
| 462 | ?><a><?php printf(__('Newer Version (%s) Installed'), $newer_version) ?></a><?php |
| 463 | endif; |
| 464 | break; |
| 465 | case 'latest_installed': |
| 466 | if ( current_user_can('install_themes') || current_user_can('update_themes') ) : |
| 467 | ?><a><?php _e('Latest Version Installed') ?></a><?php |
| 468 | endif; |
| 469 | break; |
| 470 | endswitch; ?> |
| 471 | </p> |
| 472 | <?php endif; ?> |
| 473 | <h2 class="mainheader"><?php _e('FYI') ?></h2> |
| 474 | <ul> |
| 475 | <?php if ( ! empty($api->version) ) : ?> |
| 476 | <li><strong><?php _e('Version:') ?></strong> <?php echo $api->version ?></li> |
| 477 | <?php endif; if ( ! empty($api->author) ) : ?> |
| 478 | <li><strong><?php _e('Author:') ?></strong> <?php echo links_add_target($api->author, '_blank') ?></li> |
| 479 | <?php endif; if ( ! empty($api->last_updated) ) : ?> |
| 480 | <li><strong><?php _e('Last Updated:') ?></strong> <span title="<?php echo $api->last_updated ?>"><?php |
| 481 | printf( __('%s ago'), human_time_diff(strtotime($api->last_updated)) ) ?></span></li> |
| 482 | <?php endif; if ( ! empty($api->requires) ) : ?> |
| 483 | <li><strong><?php _e('Requires WordPress Version:') ?></strong> <?php printf(__('%s or higher'), $api->requires) ?></li> |
| 484 | <?php endif; if ( ! empty($api->tested) ) : ?> |
| 485 | <li><strong><?php _e('Compatible up to:') ?></strong> <?php echo $api->tested ?></li> |
| 486 | <?php endif; if ( ! empty($api->downloaded) ) : ?> |
| 487 | <li><strong><?php _e('Downloaded:') ?></strong> <?php printf(__ngettext('%s time', '%s times', $api->downloaded), number_format_i18n($api->downloaded)) ?></li> |
| 488 | <?php endif; if ( ! empty($api->slug) ) : ?> |
| 489 | <li><a target="_blank" href="http://wordpress.org/extend/themes/<?php echo $api->slug ?>/"><?php _e('WordPress.org Theme Page »') ?></a></li> |
| 490 | <?php endif; if ( ! empty($api->homepage) ) : ?> |
| 491 | <li><a target="_blank" href="<?php echo $api->homepage ?>"><?php _e('Theme Homepage »') ?></a></li> |
| 492 | <?php endif; ?> |
| 493 | </ul> |
| 494 | <h2><?php _e('Average Rating') ?></h2> |
| 495 | <div class="star-holder" title="<?php printf(__ngettext('(based on %s rating)', '(based on %s ratings)', $api->num_ratings), number_format_i18n($api->num_ratings)); ?>"> |
| 496 | <div class="star star-rating" style="width: <?php echo attribute_escape($api->rating) ?>px"></div> |
| 497 | <div class="star star5"><img src="<?php echo admin_url('images/star.gif'); ?>" alt="<?php _e('5 stars') ?>" /></div> |
| 498 | <div class="star star4"><img src="<?php echo admin_url('images/star.gif'); ?>" alt="<?php _e('4 stars') ?>" /></div> |
| 499 | <div class="star star3"><img src="<?php echo admin_url('images/star.gif'); ?>" alt="<?php _e('3 stars') ?>" /></div> |
| 500 | <div class="star star2"><img src="<?php echo admin_url('images/star.gif'); ?>" alt="<?php _e('2 stars') ?>" /></div> |
| 501 | <div class="star star1"><img src="<?php echo admin_url('images/star.gif'); ?>" alt="<?php _e('1 star') ?>" /></div> |
| 502 | </div> |
| 503 | <small><?php printf(__ngettext('(based on %s rating)', '(based on %s ratings)', $api->num_ratings), number_format_i18n($api->num_ratings)); ?></small> |
| 504 | </div> |
| 505 | <div id="section-holder" class="wrap"> |
| 506 | <?php |
| 507 | if ( version_compare($GLOBALS['wp_version'], $api->tested, '>') ) |
| 508 | echo '<div class="updated"><p>' . __('<strong>Warning:</strong> This theme has <strong>not been tested</strong> with your current version of WordPress.') . '</p></div>'; |
| 509 | else if ( version_compare($GLOBALS['wp_version'], $api->requires, '<') ) |
| 510 | echo '<div class="updated"><p>' . __('<strong>Warning:</strong> This theme has not been marked as <strong>compatible</strong> with your version of WordPress.') . '</p></div>'; |
| 511 | foreach ( (array)$api->sections as $section_name => $content ) { |
| 512 | $title = $section_name; |
| 513 | $title[0] = strtoupper($title[0]); |
| 514 | $title = str_replace('_', ' ', $title); |
| 515 | |
| 516 | $content = links_add_base_url($content, 'http://wordpress.org/extend/themes/' . $api->slug . '/'); |
| 517 | $content = links_add_target($content, '_blank'); |
| 518 | |
| 519 | $san_title = attribute_escape(sanitize_title_with_dashes($title)); |
| 520 | |
| 521 | $display = ( $section_name == $section ) ? 'block' : 'none'; |
| 522 | |
| 523 | echo "\t<div id='section-{$san_title}' class='section' style='display: {$display};'>\n"; |
| 524 | echo "\t\t<h2 class='long-header'>$title</h2>"; |
| 525 | echo $content; |
| 526 | echo "\t</div>\n"; |
| 527 | } |
| 528 | echo "</div>\n"; |
| 529 | |
| 530 | iframe_footer(); |
| 531 | exit; |
| 532 | } |
| 533 | |
| 534 | |
| 535 | add_action('install_themes_upload', 'upload_theme'); |
| 536 | function upload_theme() { |
| 537 | |
| 538 | if ( ! ( ( $uploads = wp_upload_dir() ) && false === $uploads['error'] ) ) |
| 539 | wp_die($uploads['error']); |
| 540 | |
| 541 | if ( !empty($_FILES) ) |
| 542 | $filename = $_FILES['themezip']['name']; |
| 543 | else if ( isset($_GET['package']) ) |
| 544 | $filename = $_GET['package']; |
| 545 | |
| 546 | check_admin_referer('theme-upload'); |
| 547 | |
| 548 | echo '<div class="wrap">'; |
| 549 | echo '<h2>', sprintf( __('Installing Theme from file: %s'), basename($filename) ), '</h2>'; |
| 550 | |
| 551 | //Handle a newly uploaded file, Else assume it was |
| 552 | if ( !empty($_FILES) ) { |
| 553 | $filename = wp_unique_filename( $uploads['basedir'], $filename ); |
| 554 | $local_file = $uploads['basedir'] . '/' . $filename; |
| 555 | |
| 556 | // Move the file to the uploads dir |
| 557 | if ( false === @ move_uploaded_file( $_FILES['themezip']['tmp_name'], $local_file) ) |
| 558 | wp_die( sprintf( __('The uploaded file could not be moved to %s.' ), $uploads['path'])); |
| 559 | } else { |
| 560 | $local_file = $uploads['basedir'] . '/' . $filename; |
| 561 | } |
| 562 | |
| 563 | do_theme_install_local_package($local_file, $filename); |
| 564 | echo '</div>'; |
| 565 | } |
| 566 | |
| 567 | add_action('install_themes_install', 'install_theme'); |
| 568 | |
| 569 | /** |
| 570 | * Display theme link and execute install. |
| 571 | * |
| 572 | * @since 2.8.0 |
| 573 | */ |
| 574 | function install_theme() { |
| 575 | |
| 576 | $theme = isset($_REQUEST['theme']) ? stripslashes( $_REQUEST['theme'] ) : ''; |
| 577 | |
| 578 | check_admin_referer('install-theme_' . $theme); |
| 579 | $api = themes_api('theme_information', array('slug' => $theme, 'fields' => array('sections' => false) ) ); //Save on a bit of bandwidth. |
| 580 | |
| 581 | if ( is_wp_error($api) ) |
| 582 | wp_die($api); |
| 583 | |
| 584 | echo '<div class="wrap">'; |
| 585 | echo '<h2>', sprintf( __('Installing Theme: %s'), $api->name . ' ' . $api->version ), '</h2>'; |
| 586 | |
| 587 | do_theme_install($api->download_link, $api); |
| 588 | echo '</div>'; |
| 589 | |
| 590 | } |
| 591 | |
| 592 | /** |
| 593 | * Retrieve theme and install. |
| 594 | * |
| 595 | * @since 2.8.0 |
| 596 | * |
| 597 | * @param string $download_url Download URL. |
| 598 | * @param object $theme_information Optional. Theme information |
| 599 | */ |
| 600 | function do_theme_install($download_url, $theme_information = null) { |
| 601 | global $wp_filesystem; |
| 602 | |
| 603 | if ( empty($download_url) ) { |
| 604 | show_message( __('No theme Specified') ); |
| 605 | return; |
| 606 | } |
| 607 | |
| 608 | $theme = isset($_REQUEST['theme']) ? stripslashes( $_REQUEST['theme'] ) : ''; |
| 609 | |
| 610 | $url = 'theme-install.php?tab=install'; |
| 611 | $url = add_query_arg(array('theme' => $theme, 'theme_name' => stripslashes( $_REQUEST['theme_name'] ), 'download_url' => stripslashes( $_REQUEST['download_url'] ) ), $url); |
| 612 | |
| 613 | $url = wp_nonce_url($url, 'install-theme_' . $theme); |
| 614 | if ( false === ($credentials = request_filesystem_credentials($url)) ) |
| 615 | return; |
| 616 | |
| 617 | if ( ! WP_Filesystem($credentials) ) { |
| 618 | request_filesystem_credentials($url, '', true); //Failed to connect, Error and request again |
| 619 | return; |
| 620 | } |
| 621 | |
| 622 | if ( $wp_filesystem->errors->get_error_code() ) { |
| 623 | foreach ( $wp_filesystem->errors->get_error_messages() as $message ) |
| 624 | show_message($message); |
| 625 | return; |
| 626 | } |
| 627 | |
| 628 | $result = wp_install_theme( $download_url, 'show_message' ); |
| 629 | |
| 630 | if ( is_wp_error($result) ) { |
| 631 | show_message($result); |
| 632 | show_message( __('Installation Failed') ); |
| 633 | } else { |
| 634 | show_message( sprintf(__('Successfully installed the theme <strong>%s %s</strong>.'), $theme_information->name, $theme_information->version) ); |
| 635 | $theme_file = $result; |
| 636 | |
| 637 | $install_actions = apply_filters('install_theme_complete_actions', array( |
| 638 | //'activate_theme' => '<a href="' . wp_nonce_url('themes.php?action=activate&theme=' . $theme_file, 'activate-theme_' . $theme_file) . '" title="' . attribute_escape(__('Activate this theme')) . '" target="_parent">' . __('Activate Theme') . '</a>', |
| 639 | 'themes_page' => '<a href="' . admin_url('themes.php') . '" title="' . attribute_escape(__('Goto themes page')) . '" target="_parent">' . __('Return to Themes page') . '</a>' |
| 640 | ), $theme_information, $theme_file); |
| 641 | if ( ! empty($install_actions) ) |
| 642 | show_message('<strong>' . __('Actions:') . '</strong> ' . implode(' | ', (array)$install_actions)); |
| 643 | } |
| 644 | } |
| 645 | |
| 646 | /** |
| 647 | * Install a theme from a local file. |
| 648 | * |
| 649 | * @since 2.8.0 |
| 650 | * |
| 651 | * @param string $package Local Theme zip |
| 652 | * @param string $filename Optional. Original filename |
| 653 | * @param object $theme_information Optional. Theme information |
| 654 | */ |
| 655 | function do_theme_install_local_package($package, $filename = '') { |
| 656 | global $wp_filesystem; |
| 657 | |
| 658 | if ( empty($package) ) { |
| 659 | show_message( __('No theme Specified') ); |
| 660 | return; |
| 661 | } |
| 662 | |
| 663 | if ( empty($filename) ) |
| 664 | $filename = basename($package); |
| 665 | |
| 666 | $url = 'theme-install.php?tab=upload'; |
| 667 | $url = add_query_arg(array('package' => $filename), $url); |
| 668 | |
| 669 | $url = wp_nonce_url($url, 'theme-upload'); |
| 670 | if ( false === ($credentials = request_filesystem_credentials($url)) ) |
| 671 | return; |
| 672 | |
| 673 | if ( ! WP_Filesystem($credentials) ) { |
| 674 | request_filesystem_credentials($url, '', true); //Failed to connect, Error and request again |
| 675 | return; |
| 676 | } |
| 677 | |
| 678 | if ( $wp_filesystem->errors->get_error_code() ) { |
| 679 | foreach ( $wp_filesystem->errors->get_error_messages() as $message ) |
| 680 | show_message($message); |
| 681 | return; |
| 682 | } |
| 683 | |
| 684 | $result = wp_install_theme_local_package( $package, 'show_message' ); |
| 685 | |
| 686 | if ( is_wp_error($result) ) { |
| 687 | show_message($result); |
| 688 | show_message( __('Installation Failed') ); |
| 689 | } else { |
| 690 | show_message( __('Successfully installed the theme.') ); |
| 691 | $theme_file = $result; |
| 692 | |
| 693 | $install_actions = apply_filters('install_theme_complete_actions', array( |
| 694 | //'activate_theme' => '<a href="' . wp_nonce_url('themes.php?action=activate&theme=' . $theme_file, 'activate-theme_' . $theme_file) . '" title="' . __('Activate this theme') . '" target="_parent">' . __('Activate Theme') . '</a>', |
| 695 | 'themes_page' => '<a href="' . admin_url('themes.php') . '" title="' . __('Goto themes page') . '" target="_parent">' . __('Return to Themes page') . '</a>' |
| 696 | ), array(), $theme_file); |
| 697 | if ( ! empty($install_actions) ) |
| 698 | show_message('<strong>' . __('Actions:') . '</strong> ' . implode(' | ', (array)$install_actions)); |
| 699 | } |
| 700 | } |
| 701 | |
| 702 | /** |
| 703 | * Install theme. |
| 704 | * |
| 705 | * @since 2.8.0 |
| 706 | * |
| 707 | * @param string $package |
| 708 | * @param string $feedback Optional. |
| 709 | * @return mixed. |
| 710 | */ |
| 711 | function wp_install_theme($package, $feedback = '') { |
| 712 | global $wp_filesystem; |
| 713 | |
| 714 | if ( !empty($feedback) ) |
| 715 | add_filter('install_feedback', $feedback); |
| 716 | |
| 717 | // Is a filesystem accessor setup? |
| 718 | if ( ! $wp_filesystem || ! is_object($wp_filesystem) ) |
| 719 | WP_Filesystem(); |
| 720 | |
| 721 | if ( ! is_object($wp_filesystem) ) |
| 722 | return new WP_Error('fs_unavailable', __('Could not access filesystem.')); |
| 723 | |
| 724 | if ( $wp_filesystem->errors->get_error_code() ) |
| 725 | return new WP_Error('fs_error', __('Filesystem error'), $wp_filesystem->errors); |
| 726 | |
| 727 | //Get the base theme folder |
| 728 | $themes_dir = $wp_filesystem->wp_themes_dir(); |
| 729 | if ( empty($themes_dir) ) |
| 730 | return new WP_Error('fs_no_themes_dir', __('Unable to locate WordPress Theme directory.')); |
| 731 | |
| 732 | //And the same for the Content directory. |
| 733 | $content_dir = $wp_filesystem->wp_content_dir(); |
| 734 | if( empty($content_dir) ) |
| 735 | return new WP_Error('fs_no_content_dir', __('Unable to locate WordPress Content directory (wp-content).')); |
| 736 | |
| 737 | $themes_dir = trailingslashit( $themes_dir ); |
| 738 | $content_dir = trailingslashit( $content_dir ); |
| 739 | |
| 740 | if ( empty($package) ) |
| 741 | return new WP_Error('no_package', __('Install package not available.')); |
| 742 | |
| 743 | // Download the package |
| 744 | apply_filters('install_feedback', sprintf(__('Downloading theme package from %s'), $package)); |
| 745 | $download_file = download_url($package); |
| 746 | |
| 747 | if ( is_wp_error($download_file) ) |
| 748 | return new WP_Error('download_failed', __('Download failed.'), $download_file->get_error_message()); |
| 749 | |
| 750 | $working_dir = $content_dir . 'upgrade/' . basename($package, '.zip'); |
| 751 | |
| 752 | // Clean up working directory |
| 753 | if ( $wp_filesystem->is_dir($working_dir) ) |
| 754 | $wp_filesystem->delete($working_dir, true); |
| 755 | |
| 756 | apply_filters('install_feedback', __('Unpacking the theme package')); |
| 757 | // Unzip package to working directory |
| 758 | $result = unzip_file($download_file, $working_dir); |
| 759 | |
| 760 | // Once extracted, delete the package |
| 761 | @unlink($download_file); |
| 762 | |
| 763 | if ( is_wp_error($result) ) { |
| 764 | $wp_filesystem->delete($working_dir, true); |
| 765 | return $result; |
| 766 | } |
| 767 | |
| 768 | //Get a list of the directories in the working directory before we delete it, We need to know the new folder for the theme |
| 769 | $filelist = array_keys( $wp_filesystem->dirlist($working_dir) ); |
| 770 | |
| 771 | if( $wp_filesystem->exists( $themes_dir . $filelist[0] ) ) { |
| 772 | $wp_filesystem->delete($working_dir, true); |
| 773 | return new WP_Error('install_folder_exists', __('Folder already exists.'), $filelist[0] ); |
| 774 | } |
| 775 | |
| 776 | apply_filters('install_feedback', __('Installing the theme')); |
| 777 | // Copy new version of theme into place. |
| 778 | $result = copy_dir($working_dir, $themes_dir); |
| 779 | if ( is_wp_error($result) ) { |
| 780 | $wp_filesystem->delete($working_dir, true); |
| 781 | return $result; |
| 782 | } |
| 783 | |
| 784 | //Get a list of the directories in the working directory before we delete it, We need to know the new folder for the theme |
| 785 | $filelist = array_keys( $wp_filesystem->dirlist($working_dir) ); |
| 786 | |
| 787 | // Remove working directory |
| 788 | $wp_filesystem->delete($working_dir, true); |
| 789 | |
| 790 | if( empty($filelist) ) |
| 791 | return false; //We couldnt find any files in the working dir, therefor no theme installed? Failsafe backup. |
| 792 | |
| 793 | |
| 794 | //TODO: TODO: TODO |
| 795 | $stylesheet = $filelist[0]; |
| 796 | // $theme = get_themes('/' . $folder); //Ensure to pass with leading slash //TODO: TODO: TODO |
| 797 | // $themefiles = array_keys($theme); //Assume the requested theme is the first in the list |
| 798 | |
| 799 | //Return the theme files name. |
| 800 | return $stylesheet; //$folder . '/' . $themefiles[0]; |
| 801 | } |
| 802 | |
| 803 | /** |
| 804 | * Install theme from local package |
| 805 | * |
| 806 | * @since 2.8.0 |
| 807 | * |
| 808 | * @param string $package |
| 809 | * @param string $feedback Optional. |
| 810 | * @return mixed. |
| 811 | */ |
| 812 | function wp_install_theme_local_package($package, $feedback = '') { |
| 813 | global $wp_filesystem; |
| 814 | |
| 815 | if ( !empty($feedback) ) |
| 816 | add_filter('install_feedback', $feedback); |
| 817 | |
| 818 | // Is a filesystem accessor setup? |
| 819 | if ( ! $wp_filesystem || ! is_object($wp_filesystem) ) |
| 820 | WP_Filesystem(); |
| 821 | |
| 822 | if ( ! is_object($wp_filesystem) ) |
| 823 | return new WP_Error('fs_unavailable', __('Could not access filesystem.')); |
| 824 | |
| 825 | if ( $wp_filesystem->errors->get_error_code() ) |
| 826 | return new WP_Error('fs_error', __('Filesystem error'), $wp_filesystem->errors); |
| 827 | |
| 828 | //Get the base theme folder |
| 829 | $themes_dir = $wp_filesystem->wp_themes_dir(); |
| 830 | if ( empty($themes_dir) ) |
| 831 | return new WP_Error('fs_no_themes_dir', __('Unable to locate WordPress Theme directory.')); |
| 832 | |
| 833 | //And the same for the Content directory. |
| 834 | $content_dir = $wp_filesystem->wp_content_dir(); |
| 835 | if( empty($content_dir) ) |
| 836 | return new WP_Error('fs_no_content_dir', __('Unable to locate WordPress Content directory (wp-content).')); |
| 837 | |
| 838 | $themes_dir = trailingslashit( $themes_dir ); |
| 839 | $content_dir = trailingslashit( $content_dir ); |
| 840 | |
| 841 | if ( empty($package) ) |
| 842 | return new WP_Error('no_package', __('Install package not available.')); |
| 843 | |
| 844 | $working_dir = $content_dir . 'upgrade/' . basename($package, '.zip'); |
| 845 | |
| 846 | |
| 847 | // Clean up working directory |
| 848 | if ( $wp_filesystem->is_dir($working_dir) ) |
| 849 | $wp_filesystem->delete($working_dir, true); |
| 850 | |
| 851 | apply_filters('install_feedback', __('Unpacking the theme package')); |
| 852 | // Unzip package to working directory |
| 853 | $result = unzip_file($package, $working_dir); |
| 854 | |
| 855 | // Once extracted, delete the package |
| 856 | unlink($package); |
| 857 | |
| 858 | if ( is_wp_error($result) ) { |
| 859 | $wp_filesystem->delete($working_dir, true); |
| 860 | return $result; |
| 861 | } |
| 862 | |
| 863 | //Get a list of the directories in the working directory before we delete it, We need to know the new folder for the theme |
| 864 | $filelist = array_keys( $wp_filesystem->dirlist($working_dir) ); |
| 865 | |
| 866 | if( $wp_filesystem->exists( $themes_dir . $filelist[0] ) ) { |
| 867 | $wp_filesystem->delete($working_dir, true); |
| 868 | return new WP_Error('install_folder_exists', __('Folder already exists.'), $filelist[0] ); |
| 869 | } |
| 870 | |
| 871 | apply_filters('install_feedback', __('Installing the theme')); |
| 872 | // Copy new version of theme into place. |
| 873 | $result = copy_dir($working_dir, $themes_dir); |
| 874 | if ( is_wp_error($result) ) { |
| 875 | $wp_filesystem->delete($working_dir, true); |
| 876 | return $result; |
| 877 | } |
| 878 | |
| 879 | //Get a list of the directories in the working directory before we delete it, We need to know the new folder for the theme |
| 880 | $filelist = array_keys( $wp_filesystem->dirlist($working_dir) ); |
| 881 | |
| 882 | // Remove working directory |
| 883 | $wp_filesystem->delete($working_dir, true); |
| 884 | |
| 885 | if( empty($filelist) ) |
| 886 | return false; //We couldnt find any files in the working dir, therefor no theme installed? Failsafe backup. |
| 887 | |
| 888 | //TODO TODO TODO |
| 889 | $stylesheet = $filelist[0]; |
| 890 | // $theme = get_themes('/' . $folder); //Ensure to pass with leading slash |
| 891 | // $themefiles = array_keys($theme); //Assume the requested theme is the first in the list |
| 892 | |
| 893 | //Return the theme files name. |
| 894 | return $stylsheet; //$folder . '/' . $themefiles[0]; |
| 895 | } |