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 "";
if( count( $files ) > 0 ) {
// build seperate arrays for folders and files
$dir_array = array();
$file_array = array();
foreach ( $files as $file => $file_info ) {
if ( $file != '.' && $file != '..' && $file_info['type'] == 'd' ) {
$file_string = strtolower( preg_replace( "[._-]", "", $file ) );
$dir_array[$file_string] = $file_info;
} elseif ( $file != '.' && $file != '..' && $file_info['type'] == 'f' ){
$file_string = strtolower( preg_replace( "[._-]", "", $file ) );
$file_array[$file_string] = $file_info;
}
}
// shot those arrays
ksort( $dir_array );
ksort( $file_array );
// All dirs
foreach ( $dir_array as $file => $file_info ) {
echo "- " . esc_html( $file_info['name'] ) . "
";
}
// All files
foreach ( $file_array as $file => $file_info ) {
$ext = preg_replace( '/^.*\./', '', $file_info['name'] );
echo "- " . esc_html( $file_info['name'] ) . "
";
}
}
// output toolbar for creating new file, folder etc
echo "-
";
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', '<' ) ):
?>