site_url = get_bloginfo('url'); $actions = array ( array( 'admin_menu', array( &$this, 'add_my_menu_page' ) ), array( 'admin_head', array( &$this, 'add_my_menu_icon' ) ), array( 'admin_init', array( &$this, 'init_hooks' ) ), array( 'network_admin_menu', array( &$this, 'add_my_menu_page' ) ), ); // hook for processing incoming image saves if ( isset( $_GET['aceide_save_image'] ) ) { // force local file method for testing $this->override_fs_method( 'direct' ); $actions[] = array('admin_init', array( &$this, 'save_image') ); } $this->add_actions($actions); } public function add_actions(array $actions) { foreach ($actions as $action_params) { call_user_func_array('add_action', $action_params); } } public function override_fs_method( $method='direct' ) { if ( defined('FS_METHOD') ) { define( 'ACEIDE_FS_METHOD_FORCED_ELSEWHERE', FS_METHOD ); // make a note of the forced method } else { define( 'FS_METHOD', $method ); // force direct } } public function extend(Module $module) { if (did_action('admin_init')) { return new WP_Error( 'editor_extend', 'Can\'t extend after admin_init!' ); } $this->modules[get_class($module)] = $module; } public function init_hooks() { // force local file method until I've worked out how to implement the other methods // main problem being password wouldn't/isn't saved between requests // you could force other methods 'direct', 'ssh', 'ftpext' or 'ftpsockets' $this->override_fs_method( 'direct' ); $hooks = $this->setup_hooks(); $this->add_actions($hooks); foreach ($this->modules as $module) { $hooks = $module->setup_hooks(); $this->add_actions($hooks); } } public function setup_hooks() { // Uncomment any of these calls to add the functionality that you need. // Will only enqueue on AceIDE page return array ( array( 'admin_print_scripts-' . $this->menu_hook, array( &$this, 'add_admin_js' ) ), array( 'admin_print_styles-' . $this->menu_hook, array( &$this, 'add_admin_styles' ) ), array( 'wp_ajax_jqueryFileTree', array( &$this, 'jqueryFileTree_get_list' ) ), array( 'wp_ajax_aceide_image_edit_key', array( &$this, 'image_edit_key' ) ), array( 'wp_ajax_aceide_startup_check', array( &$this, 'startup_check' ) ), // add a warning when navigating away from AceIDE // it has to go after WordPress scripts otherwise WP clears the binding // This has been implemented in load-editor.js // add_action('admin_print_footer_scripts', array( &$this, 'add_admin_nav_warning' ), 99 ); // Add body class to collapse the wp sidebar nav array( 'admin_body_class', array( &$this, 'hide_wp_sidebar_nav' ), 11), // hide the update nag array( 'admin_menu', array( &$this, 'hide_wp_update_nag' ) ), ); } public static function check_perms( $check_referrer=true ) { $capability = ( is_multisite() ? 'manage_network_themes' : 'edit_plugins' ); if ( defined( 'DISALLOW_FILE_EDIT' ) && ! apply_filters( 'aceide_override_disallow_file_edit', ! DISALLOW_FILE_EDIT ) ) { wp_die( '

' . __( 'You do not have sufficient permissions to edit templates for this site. SORRY' ) . '

' ); } if ( $check_referrer ) { check_admin_referer( 'plugin-name-action_aceidenonce' ); } if ( ! current_user_can( $capability ) ) { wp_die( '

' . __( 'You do not have sufficient permissions to edit templates for this site. SORRY' ) . '

' ); } } public function hide_wp_sidebar_nav( $classes ) { global $hook_suffix; if ( apply_filters( 'aceide_sidebar_folded', $hook_suffix === $this->menu_hook ) ) { $classes = str_replace( "auto-fold", "", $classes ) . ' folded'; } return $classes; } public function hide_wp_update_nag() { remove_action( 'admin_notices', 'update_nag', 3 ); } public function add_admin_nav_warning() { ?> ace_version; $idever = get_plugin_data( $plugin_path, false, false ); $idever = $idever['Version']; // include file tree wp_enqueue_script( 'jquery-file-tree', "{$plugin_url}src/js/jqueryFileTree.js", array( 'jquery' ), $idever ); // include ace wp_enqueue_script( 'ace', "{$plugin_url}src/js/ace-{$acever}/ace.js", array(), $idever ); // include ace modes for css, javascript & php wp_enqueue_script( 'ace-mode-css', "{$plugin_url}src/js/ace-{$acever}/mode-css.js", array( 'ace' ), $idever ); wp_enqueue_script( 'ace-mode-scss', "{$plugin_url}src/js/ace-{$acever}/mode-scss.js", array( 'ace' ), $idever ); wp_enqueue_script( 'ace-mode-less', "{$plugin_url}src/js/ace-{$acever}/mode-less.js", array( 'ace' ), $idever ); wp_enqueue_script( 'ace-mode-javascript', "{$plugin_url}src/js/ace-{$acever}/mode-javascript.js", array( 'ace' ), $idever ); wp_enqueue_script( 'ace-mode-php', "{$plugin_url}src/js/ace-{$acever}/mode-php.js", array( 'ace' ), $idever ); wp_enqueue_script( 'ace-mode-twig', "{$plugin_url}src/js/ace-{$acever}/mode-twig.js", array( 'ace' ), $idever ); // include ace theme wp_enqueue_script( 'ace-theme', "{$plugin_url}src/js/ace-{$acever}/theme-dawn.js", array( 'ace' ), $idever ); // ambiance looks really nice for high contrast // load emmet wp_enqueue_script( 'aceide-ext-emmet', "{$plugin_url}src/js/ace-{$acever}/ext-emmet.js", array( 'ace' ), $idever ); wp_enqueue_script( 'aceide-emmet', "{$plugin_url}src/js/emmet.js", array( 'aceide-ext-emmet' ), $idever ); // wordpress-completion tags wp_enqueue_script( 'aceide-wordpress-completion', "{$plugin_url}src/js/autocomplete/wordpress.js", array( 'ace' ), $idever ); // php-completion tags wp_enqueue_script( 'aceide-php-completion', "{$plugin_url}src/js/autocomplete/php.js", array( 'ace' ), $idever ); // load editor wp_enqueue_script( 'aceide-load-editor', "{$plugin_url}src/js/load-editor.js", array( 'ace', 'jquery', 'jquery-ui-core', 'jquery-ui-dialog' ), $idever ); // load filetree menu wp_enqueue_script( 'aceide-load-filetree-menu', "{$plugin_url}src/js/load-filetree-menu.js", array( 'ace', 'jquery' ), $idever ); // load autocomplete dropdown wp_enqueue_script( 'aceide-dd', "{$plugin_url}src/js/jquery.dd.js", array( 'ace', 'jquery' ), $idever ); // Specify custom AJAX handler wp_localize_script( 'aceide-load-editor', 'aceajax', array( 'url' => admin_url( 'admin-ajax.php' ) ) ); // load color picker wp_enqueue_script( 'ImageColorPicker', "{$plugin_url}src/js/ImageColorPicker.js", array( 'jquery', 'jquery-ui-core', 'jquery-ui-widget' ), $idever ); } public function add_admin_styles() { $plugin_path = trailingslashit( dirname( dirname( __FILE__ ) ) ) . 'AceIDE.php'; $plugin_url = trailingslashit( plugin_dir_url( $plugin_path ) ); $acever = $this->ace_version; $idever = get_plugin_data( $plugin_path, false, false ); $idever = $idever['Version']; // main AceIDE styles wp_register_style( 'aceide_style', "{$plugin_url}src/aceide.css", array(), $idever ); wp_enqueue_style( 'aceide_style' ); // filetree styles wp_register_style( 'aceide_filetree_style', "{$plugin_url}src/css/jqueryFileTree.css", array( 'aceide_style' ), $idever ); wp_enqueue_style( 'aceide_filetree_style' ); // autocomplete dropdown styles wp_register_style( 'aceide_dd_style', "{$plugin_url}src/dd.css", array( 'aceide_style' ), $idever ); wp_enqueue_style( 'aceide_dd_style' ); // jquery ui styles wp_register_style( 'aceide_jqueryui_style', "{$plugin_url}src/css/flick/jquery-ui-1.8.20.custom.css", array( 'aceide_style' ), $idever ); wp_enqueue_style( 'aceide_jqueryui_style' ); } public function jqueryFileTree_get_list() { global $wp_filesystem; // check the user has the permissions self::check_perms(); // setup wp_filesystem api $url = wp_nonce_url( 'admin.php?page=aceide', 'plugin-name-action_aceidenonce' ); $form_fields = null; // for now, but at some point the login info should be passed in here $creds = request_filesystem_credentials( $url, FS_METHOD, false, false, $form_fields ); if ( false === $creds ) { // no credentials yet, just produced a form for the user to fill in return true; // stop the normal page form from displaying } if ( ! WP_Filesystem( $creds ) ) { return false; } $_POST['dir'] = urldecode( $_POST['dir'] ); $root = apply_filters( 'aceide_filesystem_root', WP_CONTENT_DIR ); if (ob_get_level()) { ob_end_clean(); } if ( $wp_filesystem->exists( $root . $_POST['dir'] ) ) { $files = $wp_filesystem->dirlist( $root . $_POST['dir'] ); echo ""; } die(); // this is required to return a proper result } public function image_edit_key() { // check the user has the permissions self::check_perms(); if (ob_get_level()) { ob_end_clean(); } // create a nonce based on the image path echo wp_create_nonce( 'aceide_image_edit' . $_POST['file'] ); } public function save_image() { global $wp_filesystem; self::check_perms(false); $filename = explode( '::', $_POST['opt'] ); $filename = reset( $filename ); // filename // setup wp_filesystem api $url = wp_nonce_url( 'admin.php?page=aceide', 'plugin-name-action_aceidenonce' ); $form_fields = null; // for now, but at some point the login info should be passed in here $creds = request_filesystem_credentials( $url, FS_METHOD, false, false, $form_fields ); if ( false === $creds ) { // no credentials yet, just produced a form for the user to fill in return true; // stop the normal page form from displaying } if ( ! WP_Filesystem( $creds ) ) { echo __( "Cannot initialise the WP file system API" ); } // save a copy of the file and create a backup just in case $backup_path = 'backups' . preg_replace( "#\.php$#i", "_" . date( "Y-m-d-H" ) . ".php", $filename ); $backup_path = plugin_dir_path( __FILE__ ) . $backup_path; // create backup directory if not there $new_file_info = pathinfo( $backup_path ); if ( ! $wp_filesystem->is_dir( $new_file_info['dirname'] ) ) { wp_mkdir_p( $new_file_info['dirname'] ); // should use the filesytem api here but there isn't a comparable command right now } // Find absolute path to save to $root = apply_filters( 'aceide_filesystem_root', WP_CONTENT_DIR ); $filename = $root . stripslashes( $filename ); // do backup $wp_filesystem->move( $filename, $backup_path ); // retrieve new file $edited = wp_remote_get( $_POST['url'] ); $edited = wp_remote_retrieve_body( $edited ); // save file if ( $wp_filesystem->put_contents( $filename, $edited ) ) { wp_die( sprintf( '

%s
%s.

', __( 'Image saved.' ), __( 'You may close this window / tab' ) ) ); } else { wp_die( sprintf( '

%s
%s

', __( 'Problem saving image.' ), __( 'Close this window / tab and try editing the image again.' ) ) ); } } public function startup_check() { global $wp_filesystem, $wp_version; // check the user has the permissions self::check_perms(); if (ob_get_level()) { ob_end_clean(); } echo "\n\n\n\n" . __( 'ACEIDE STARTUP CHECKS' ) . "\n"; echo "___________________ \n\n"; // WordPress version if ($wp_version > 3){ printf( __( 'WordPress version = %s' ), $wp_version ); }else{ printf( __( 'WordPress version = %s (which is too old to run AceIDE)' ), $wp_version ); } echo "\n\n"; if ( defined( 'ACEIDE_FS_METHOD_FORCED_ELSEWHERE' ) ) { echo __( sprintf( "WordPress filesystem API has been forced to use the %s method by another plugin/WordPress", ACEIDE_FS_METHOD_FORCED ) ) . "\n"; } if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ) { echo __( 'WordPress constant "DISALLOW_FILE_EDIT" defined but overridden by the "aceide_override_disallow_file_edit" filter.' ) . "\n"; } echo "\n"; // setup wp_filesystem api $aceide_filesystem_before = $wp_filesystem; $url = wp_nonce_url( 'admin.php?page=aceide','plugin-name-action_acepidenonce' ); $form_fields = null; // for now, but at some point the login info should be passed in here $creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields); ob_start(); if ( false === $creds ) { // if we get here, then we don't have credentials yet, // but have just produced a form for the user to fill in, // so stop processing for now // return true; // stop the normal page form from displaying } ob_end_clean(); if ( ! WP_Filesystem( $creds ) ) { echo __( "There has been a problem initialising the filesystem API" ) . "\n\n"; echo __( "Filesystem API before this plugin ran:" ) . " \n\n" . print_r( $aceide_filesystem_before, true ); echo __( "Filesystem API now:" ) . " \n\n" . print_r( $wp_filesystem, true ); } unset( $aceide_filesystem_before ); $root = apply_filters( 'aceide_filesystem_root', WP_CONTENT_DIR ); if ( isset( $wp_filesystem ) ) { // Running webservers user and group printf( __( 'Web server user/group = %s:%s' ), getenv( 'APACHE_RUN_USER' ), getenv( 'APACHE_RUN_GROUP' ) ); echo "\n"; // wp-content user and group printf( __( 'Root folder owner/group = %s:%s' ), $wp_filesystem->owner( $root ), $wp_filesystem->group( $root ) ); echo "\n\n"; // check we can list wp-content files if ( $wp_filesystem->exists( $root ) ) { $files = $wp_filesystem->dirlist( $root ); if ( count( $files ) > 0) { printf( __( 'Root folder exists and contains %d files' ), count( $files ) ); } else { echo __( 'Root folder exists but we cannot read it\'s contents' ); } echo "\n"; } echo "\n" . __( "Using the {$wp_filesystem->method} method of the WP filesystem API" ) . "\n"; $is_readable = $wp_filesystem->is_readable( $root ) == 1; $is_writable = $wp_filesystem->is_writable( $root ) == 1; if ( $is_readable && $is_writable ) { echo __( "The root folder IS readable and IS writable by this method" ); } elseif ( $is_readable && ! $is_writable ) { echo __( "The root folder IS readable but IS NOT writable by this method" ); } elseif ( ! $is_readable && $is_writable ) { echo __( "The root folder IS NOT readable but IS writable by this method" ); } else { echo __( "The root folder IS NOT readable and IS NOT writable by this method" ); } echo "\n"; if ($is_readable || $is_writable) { $real_root = trailingslashit(realpath($root)); $real_wpc = trailingslashit(WP_CONTENT_DIR); $wp_content_accessible = (strpos($real_wpc, $real_root) !== false); if ($wp_content_accessible) { $is_readable = $wp_filesystem->is_readable( $real_wpc . 'plugins' ) == 1; $is_writable = $wp_filesystem->is_writable( $real_wpc . 'plugins' ) == 1; // plugins folder editable if ( $is_readable && $is_writable ) { echo __( "The wp-content/plugins folder IS readable and IS writable by this method" ); } elseif ( $is_readable && ! $is_writable ) { echo __( "The wp-content/plugins folder IS readable but IS NOT writable by this method" ); } elseif ( ! $is_readable && $is_writable ) { echo __( "The wp-content/plugins folder IS NOT readable but IS writable by this method" ); } else { echo __( "The wp-content/plugins folder IS NOT readable and IS NOT writable by this method" ); } echo "\n"; // themes folder editable $is_readable = $wp_filesystem->is_readable( $real_wpc . 'themes' ) == 1; $is_writable = $wp_filesystem->is_writable( $real_wpc . 'themes' ) == 1; // plugins folder editable if ( $is_readable && $is_writable ) { echo __( "The wp-content/themes folder IS readable and IS writable by this method" ); } elseif ( $is_readable && ! $is_writable ) { echo __( "The wp-content/themes folder IS readable but IS NOT writable by this method" ); } elseif ( ! $is_readable && $is_writable ) { echo __( "The wp-content/themes folder IS NOT readable but IS writable by this method" ); } else { echo __( "The wp-content/themes folder IS NOT readable and IS NOT writable by this method" ); } } else { echo __( "The wp-content folder is not accessible from the current AceIDE root directory" ); } echo "\n"; } } echo "___________________ \n\n\n\n"; echo __( " If the file tree to the right is empty there is a possibility that your server permissions are not compatible with this plugin. \n The startup information above may shed some light on things. \n Paste that information into the support forum for further assistance." ); die(); } public function add_my_menu_page() { global $wp_version; // We should not even display a menu item if we can't edit files if ( defined( 'DISALLOW_FILE_EDIT' ) && ! apply_filters( 'aceide_override_disallow_file_edit', ! DISALLOW_FILE_EDIT ) ) { return; } if ( version_compare( $wp_version, '3.8', '<' ) ) { $this->menu_hook = add_menu_page( 'AceIDE', 'AceIDE', 'edit_plugins', "aceide", array( &$this, 'my_menu_page' ) ); } else { $this->menu_hook = add_menu_page( 'AceIDE', 'AceIDE', 'edit_plugins', "aceide", array( &$this, 'my_menu_page' ), 'dashicons-editor-code' ); } } public function add_my_menu_icon() { global $wp_version; // We should not even display a menu icon if we can't edit files if ( defined( 'DISALLOW_FILE_EDIT' ) && ! apply_filters( 'aceide_override_disallow_file_edit', ! DISALLOW_FILE_EDIT ) ) { return; } if ( version_compare( $wp_version, '3.8', '<' ) ): ?>

Files