array( 'name' => __( 'Revised Themes' ), 'singular_name' => __( 'Revised Theme' ), ), 'public' => false, 'capability_type' => 'theme', // edit_themes 'hierarchical' => true, 'rewrite' => false, 'query_var' => false, ) ); /* Stores information about each theme file and its revisions. * Hierarchical. Its parent is a revised_theme, but it may also * have children, with the theme_revision parent being the most * recent version, and children being revisions thereof. Similar * to the current post/revision relationship, only with one * post type. (Two might be better.) */ register_post_type( 'theme_revision', array( 'labels' => array( 'name' => __( 'Revisions' ), 'singular_name' => __( 'Revision' ), ), 'public' => false, 'capability_type' => 'theme', // edit_themes 'hierarchical' => true, 'rewrite' => false, 'query_var' => false, ) ); /* Stores a series of revision IDs that make up a single snapshot. * Snapshots can be triggered by the user and also before/after upgrades. */ register_taxonomy( 'snapshot', 'theme_revision', array( 'labels' => array( 'name' => __( 'Snapshots' ), 'singular_name' => __( 'Snapshot' ), ), 'hierarchical' => false, 'query_var' => false, 'show_ui' => false, 'show_in_nav_menus' => false, ) ); } /** * Remove Appearance > Editor. */ function remove_core_editor() { remove_action( 'admin_menu', '_add_themes_utility_last', 101 ); } /** * Initialize the admin menu page. */ function admin_menu() { $this->page = add_theme_page( __('Advanced Editor'), __('Advanced Editor'), 'edit_themes', 'theme-revisions', array( &$this, 'admin_page' ) ); add_action( 'load-' . $this->page, array( &$this, 'admin_load' ) ); add_action( 'load-' . $this->page, array( &$this, 'handle_action' ) ); } /** * Enqueue scripts, register help. */ function admin_load() { add_action( 'admin_print_styles-' . $this->page, array( &$this, 'admin_print_styles' ) ); wp_enqueue_script( 'theme-revisions', plugins_url( 'theme-revisions.js', __FILE__ ), array( 'jquery' ), '0.1-alpha', true ); $help = '
' . __('You can use the Theme Editor to edit the individual CSS and PHP files which make up your theme.') . '
'; $help .= '' . __('Begin by choosing a theme to edit from the dropdown menu and clicking Select. A list then appears of all the template files. Clicking once on any file name causes the file to appear in the large Editor box.') . '
'; $help .= '' . __('For PHP files, you can use the Documentation dropdown to select from functions recognized in that file. Lookup takes you to a web page with reference material about that particular function.') . '
'; $help .= '' . __('After typing in your edits, click Update File.') . '
'; $help .= '' . __('Advice: think very carefully about your site crashing if you are live-editing the theme currently in use.') . '
'; $help .= '' . __('Upgrading to a newer version of the same theme will override changes made here. To avoid this, consider creating a child theme instead.') . '
'; $help .= '' . __('For more information:') . '
'; $help .= '' . __('Documentation on Theme Development') . '
'; $help .= '' . __('Documentation on Using Themes') . '
'; $help .= '' . __('Documentation on Editing Files') . '
'; $help .= '' . __('Documentation on Template Tags') . '
'; $help .= '' . __('Support Forums') . '
'; add_contextual_help( $this->page, $help ); } /** * Enqueue style. */ function admin_print_styles() { wp_admin_css( 'theme-editor' ); wp_enqueue_style( 'theme-revisions', plugins_url( 'theme-revisions.css', __FILE__ ), false, '0.1-alpha' ); } /** * Sets up the live editor. */ function live_editor() { wp_enqueue_script( 'edit-area', plugins_url( 'edit_area/edit_area_full.js', __FILE__ ), false, '0.8.2', true ); add_action( 'admin_print_footer_scripts', array( &$this, '_edit_area_js_init' ), 1100 ); } function _edit_area_js_init() { global $file; $file_type = strtolower( substr( $file, strrpos( $file, '.' ) + 1 ) ); ?> allowed_files = array_merge( $themes[$theme]['Stylesheet Files'], $themes[$theme]['Template Files'] ); $this->requested_file = $file; if ( empty( $file ) ) { $file = $this->allowed_files[0]; } else { $file = stripslashes( $file ); if ( 'theme' == $dir ) $file = dirname( dirname( $themes[$theme]['Template Dir'] ) ) . $file; elseif ( 'style' == $dir ) $file = dirname( dirname( $themes[$theme]['Stylesheet Dir'] ) ) . $file; } validate_file_to_edit( $file, $this->allowed_files ); $scrollto = isset( $_REQUEST['scrollto'] ) ? (int) $_REQUEST['scrollto'] : 0; if ( $this->use_live_editor && in_array( strtolower( substr( $file, strrpos( $file, '.' ) + 1 ) ), array( 'php', 'css', 'html' ) ) ) $this->live_editor(); if ( 'update' != $action ) return; check_admin_referer( 'edit-theme_' . $file . $theme ); $newcontent = stripslashes( $_POST['newcontent'] ); // Standardize on \n for storage // @todo Decide whether this is a bad idea. $newcontent = str_replace( array( "\r\n", "\r" ), "\n", $newcontent ); $theme = urlencode( $theme ); $location = add_query_arg( array( 'file' => $this->requested_file, 'theme' => $theme, 'dir' => $dir, 'scrollto' => $scrollto ), menu_page_url( 'theme_revisions' ) ); // is_writable() not always reliable, check return value. see comments @ http://uk.php.net/is_writable if ( is_writeable( $file ) && false !== ( $f = fopen( $file, 'w+' ) ) ) { fwrite( $f, $newcontent ); fclose( $f ); $location = add_query_arg( array( 'a' => 'te' ), $location ); create_theme_revision( $theme, $file, $newcontent ); } $location = wp_kses_no_null( $location ); $strip = array('%0d', '%0a', '%0D', '%0A'); $location = _deep_replace( $strip, $location ); wp_redirect( $location ); exit(); } /** * Shows the admin page. */ function admin_page() { global $action, $redirect, $profile, $error, $warning, $a, $file, $theme, $dir, $scrollto; update_recently_edited( $file ); if ( ! is_file( $file ) ) $error = 1; if ( ! $error && filesize( $file ) > 0 ) { $f = fopen( $file, 'r' ); $content = fread( $f, filesize( $file ) ); if ( '.php' == substr( $file, strrpos( $file, '.' ) ) ) { $functions = wp_doc_link_parse( $content ); $docs_select = ''; } // Standardize on \r\n for display. // @todo Decide whether this is a bad idea. $content = str_replace( array( "\r\n", "\r" ), array( "\n" ), $content ); $content = str_replace( "\n", "\r\n", $content ); $content = htmlspecialchars( $content ); } ?>' . __('Oops, no such file exists! Double check the name and try again, merci.') . '