function display_screen()
    {
        ?>
		<div class='wrap'>
			<?php 
        screen_icon('options-general');
        ?>
			<h2>SitePush Options</h2>
			<?php 
        //show errors/notices
        //validation doesn't add errors if we haven't set anything yet, in which case nothing will show here
        SitePushErrors::errors();
        //show debug info if in debug mode
        if (SITEPUSH_DEBUG) {
            echo "<p class='sitepush-debug-info'>{$this->options->get_server_info()}</p>";
        }
        if ($this->plugin->abort) {
            return FALSE;
        }
        ?>
			<form action='options.php' method='post'>
			<?php 
        settings_fields('sitepush_options');
        do_settings_sections('sitepush_options');
        ?>
			<input name="Submit" type='submit' value='Save Changes' class='button-primary' />
			</form>
		</div>
	<?php 
        return TRUE;
    }
 /**
  * Validate a single DB config
  *
  * @param array $params
  * @param string $name label of DB for error reporting
  * @sets $this->errors if any errors encountered
  * @return bool TRUE if validated
  */
 private function db_validate($params, $name = '')
 {
     $errors = FALSE;
     $requireds = array('name', 'user', 'pw');
     foreach ($requireds as $required) {
         if (empty($params[$required])) {
             SitePushErrors::add_error("Required parameter <i>{$required}</i> is missing from config for database <i>{$name}</i>.");
             $errors = TRUE;
         }
     }
     return $errors;
 }
 /**
  * Alert user to any SitePush related config errors.
  * These errors are displayed anywhere in admin, to any SitePush admin user.
  *
  * @return void
  */
 public function show_admin_warnings()
 {
     //don't show warnings if user can't admin SitePush
     if (!current_user_can($this->options->admin_capability)) {
         return;
     }
     //make sure any important warnings are shown throughout WordPress admin
     echo SitePushErrors::errors('important');
     $error = $this->check_wp_config();
     if ($error) {
         echo SitePushErrors::get_error_html($error, 'error');
     }
 }
 /**
  * Copy files using linux rsync
  *
  * @param string $source_path
  * @param string $dest_path
  * @param string $backup_file path to backup file - for undo logging
  * @param string $dir name of directory backed up - for undo logging
  *
  * @return bool TRUE if sync done, FALSE otherwise
  */
 private function linux_rsync($source_path, $dest_path, $backup_file = '', $dir = '')
 {
     //for rsync we need trailing slashes on directories
     $source_path = $this->trailing_slashit($source_path);
     $dest_path = $this->trailing_slashit($dest_path);
     //check that rsync is present
     if (!@shell_exec("{$this->options->rsync_path} --version")) {
         SitePushErrors::add_error('rsync not found, not configured properly or PHP safe mode is preventing it from being run', 'error');
         return FALSE;
     }
     //rsync option parameters
     $rsync_options = "-avz --delete";
     //add the excludes to the options
     foreach ($this->options->get_dont_syncs() as $exclude) {
         $exclude = trim($exclude);
         $rsync_options .= " --exclude='{$exclude}'";
     }
     //create the command
     $command = "{$this->options->rsync_path} {$rsync_options} '{$source_path}' '{$dest_path}'";
     //write file which will undo the push
     if ($this->source_backup_path && $this->save_undo && $dir && $backup_file) {
         $undo_dir = "{$this->dest}-{$this->timestamp}-undo_files";
         $undo['type'] = 'linux_rsync';
         $undo['original'] = $command;
         $undo['undo'][] = "cd '{$this->dest_backup_path}'; mkdir '{$undo_dir}'; cd '{$undo_dir}'; tar -zpxf '{$backup_file}'";
         //prep
         $undo['undo'][] = "'{$this->options->rsync_path}' {$rsync_options} '{$this->dest_backup_path}/{$undo_dir}/{$dir}/' '{$dest_path}'";
         //sync
         $this->write_undo_file($undo);
     }
     //add push type to log
     $this->add_result("Sync type: linux_rsync", 2);
     //run the command
     return (bool) $this->my_exec($command, 3, '/rsync error: /');
 }
 public static function force_show_wp_errors()
 {
     self::$force_show_wp_errors = TRUE;
     set_transient('sitepush_force_show_wp_errors', TRUE, 30);
 }
    public function display_screen()
    {
        //check that the user has the required capability
        if (!$this->plugin->can_use()) {
            wp_die(__('You do not have sufficient permissions to access this page.'));
        }
        ?>
		<div class="wrap">
			<h2>SitePush</h2>
		<?php 
        //initialise options from form data
        $push_options['db_all_tables'] = SitePushPlugin::get_query_var('sitepush_push_db_all_tables') ? TRUE : FALSE;
        $push_options['db_post_content'] = SitePushPlugin::get_query_var('sitepush_push_db_post_content') ? TRUE : FALSE;
        $push_options['db_comments'] = SitePushPlugin::get_query_var('sitepush_push_db_comments') ? TRUE : FALSE;
        $push_options['db_users'] = SitePushPlugin::get_query_var('sitepush_push_db_users') ? TRUE : FALSE;
        $push_options['db_options'] = SitePushPlugin::get_query_var('sitepush_push_db_options') ? TRUE : FALSE;
        $push_options['push_uploads'] = SitePushPlugin::get_query_var('sitepush_push_uploads') ? TRUE : FALSE;
        $push_options['push_theme'] = SitePushPlugin::get_query_var('sitepush_push_theme') ? TRUE : FALSE;
        $push_options['push_themes'] = SitePushPlugin::get_query_var('sitepush_push_themes') ? TRUE : FALSE;
        $push_options['push_plugins'] = SitePushPlugin::get_query_var('sitepush_push_plugins') ? TRUE : FALSE;
        $push_options['push_mu_plugins'] = SitePushPlugin::get_query_var('sitepush_push_mu_plugins') ? TRUE : FALSE;
        $push_options['push_wp_core'] = SitePushPlugin::get_query_var('sitepush_push_wp_core') ? TRUE : FALSE;
        $push_options['clear_cache'] = SitePushPlugin::get_query_var('clear_cache') ? TRUE : FALSE;
        $push_options['dry_run'] = SitePushPlugin::get_query_var('sitepush_dry_run') ? TRUE : FALSE;
        $push_options['do_backup'] = SitePushPlugin::get_query_var('sitepush_push_backup') ? TRUE : FALSE;
        $db_custom_table_groups = SitePushPlugin::get_query_var('sitepush_db_custom_table_groups');
        if ($db_custom_table_groups) {
            foreach ($db_custom_table_groups as $key => $group) {
                $push_options['db_custom_table_groups'][] = $key;
            }
        } else {
            $push_options['db_custom_table_groups'] = array();
        }
        $push_options['source'] = SitePushPlugin::get_query_var('sitepush_source') ? SitePushPlugin::get_query_var('sitepush_source') : '';
        $push_options['dest'] = SitePushPlugin::get_query_var('sitepush_dest') ? SitePushPlugin::get_query_var('sitepush_dest') : '';
        //multisite specific options
        $push_options['db_multisite_tables'] = SitePushPlugin::get_query_var('sitepush_push_db_multisite_tables') ? TRUE : FALSE;
        $user_options = get_user_option('sitepush_options');
        $this->user_last_source = empty($user_options['last_source']) ? '' : $user_options['last_source'];
        $this->user_last_dest = empty($user_options['last_dest']) ? '' : $user_options['last_dest'];
        SitePushErrors::errors('all', 'sitepush');
        if ($push_options['dest']) {
            //output directly to screen... doesn't work on all browsers.
            ob_implicit_flush();
            //save source/dest to user options
            $user_options = get_user_option('sitepush_options');
            $user_options['last_source'] = $push_options['source'];
            $user_options['last_dest'] = $push_options['dest'];
            update_user_option(get_current_user_id(), 'sitepush_options', $user_options);
            // do the push!
            if ($this->plugin->can_admin() && $this->options->debug_output_level) {
                $hide_html = '';
            } else {
                $hide_html = ' style="display: none;"';
                echo "<div id='running'></div>";
            }
            echo "<script>\n\t\t\t\tvar scrollIntervalID = window.setInterval(function(){\n\t\t\t\t\tjQuery('#sitepush-results').scrollTop( jQuery('#sitepush-results').prop('scrollHeight') );\n\t\t\t\t}, 100);\n\t\t\t</script>";
            echo "<h3{$hide_html} class='sitepush-results'>Push results</h3>";
            echo "<pre id='sitepush-results' class='sitepush-results' {$hide_html}>";
            //Do the push!
            $obj_sitepushcore = new SitePushCore($push_options['source'], $push_options['dest']);
            if (!SitePushErrors::count_errors('all-errors')) {
                $push_result = $this->plugin->do_the_push($obj_sitepushcore, $push_options);
            } else {
                $push_result = FALSE;
            }
            echo "</pre>";
            echo "<script>\n\t\t\t\tjQuery('#running').hide();\n\t\t\t\tif( ! jQuery('#sitepush-results').text() ) jQuery('.sitepush-results').hide();\n\t\t\t\tclearInterval( scrollIntervalID );\n\t\t\t\tjQuery('#sitepush-results').scrollTop( jQuery('#sitepush-results').prop('scrollHeight') );\n\t\t\t</script>";
            if ($push_result) {
                if ($push_options['dry_run']) {
                    SitePushErrors::add_error("Dry run complete. Nothing was actually pushed, but you can see what would have been done from the output above.", 'notice');
                } elseif (SitePushErrors::count_errors('warning')) {
                    SitePushErrors::add_error("Push complete (with warnings).", 'notice');
                } else {
                    SitePushErrors::add_error("Push complete.", 'notice');
                }
                //bit of a hack... do one page load for destination site to make sure SitePush has activated plugins etc
                //before any user accesses the site
                wp_remote_get($obj_sitepushcore->dest_params['domain']);
            } else {
                if (!SitePushErrors::is_error()) {
                    SitePushErrors::add_error("Nothing selected to push");
                }
            }
            SitePushErrors::errors();
        }
        //set up what menu options are selected by default
        if (!empty($_REQUEST['sitepush-nonce'])) {
            //already done a push, so redo what we had before
            $default_source = empty($_REQUEST['sitepush_source']) ? '' : $_REQUEST['sitepush_source'];
            $default_dest = empty($_REQUEST['sitepush_dest']) ? '' : $_REQUEST['sitepush_dest'];
        }
        if (empty($default_source)) {
            $default_source = $this->user_last_source ? $this->user_last_source : $this->options->get_current_site();
        }
        if (empty($default_dest)) {
            $default_dest = $this->user_last_dest ? $this->user_last_dest : '';
        }
        ?>
	
			<form method="post" action="">
				<?php 
        wp_nonce_field('sitepush-dopush', 'sitepush-nonce');
        ?>
				<table class="form-table">
					<?php 
        if (SITEPUSH_SHOW_MULTISITE) {
            ?>
					<tr>
						<th scope="row"><label for="sitepush_source">Site</label></th>
						<td>
							<?php 
            bloginfo('name');
            ?>
						</td>
					</tr>
					<?php 
        }
        ?>

					<tr>
						<th scope="row"><label for="sitepush_source">Source</label></th>
						<td>
							<select name="sitepush_source" id="sitepush_source" class="site-selector">
							<?php 
        foreach ($this->plugin->get_sites('source') as $site) {
            echo "<option value='{$site}'";
            if ($default_source == $site) {
                echo " selected='selected'";
            }
            echo ">{$this->options->sites[$site]['label']}</option>";
        }
        ?>
							</select>
						</td>
					</tr>
	
					<tr>
						<th scope="row"><label for="sitepush_dest">Destination</label></th>
						<td>
							<select name="sitepush_dest" id="sitepush_dest" class="site-selector">
							<?php 
        foreach ($this->plugin->get_sites('destination') as $site) {
            $use_cache = $this->options->sites[$site]['use_cache'] ? 'yes' : 'no';
            echo "<option value='{$site}' data-cache='{$use_cache}'";
            if ($default_dest == $site) {
                echo " selected='selected'";
            }
            echo ">{$this->options->sites[$site]['label']}</option>";
        }
        ?>
							</select>
							<span id='sitepush_dest-warning'><span>
						</td>
					</tr>
					<?php 
        $ms_message = SITEPUSH_SHOW_MULTISITE ? "<br /><i>current site only</i>" : '';
        ?>
					<tr>
						<th scope="row">Database content<?php 
        echo $ms_message;
        ?>
</th>
						<td>
							<?php 
        if (!SITEPUSH_SHOW_MULTISITE) {
            echo $this->option_html('sitepush_push_db_all_tables', 'Entire database <i>(this will overwrite all content and settings)</i>', 'admin_only');
        }
        ?>
							<?php 
        echo $this->option_html('sitepush_push_db_post_content', 'All post content <i>(pages, posts, media, links, custom post types, post meta, categories, tags &amp; custom taxonomies)</i>', 'user');
        ?>
							<?php 
        if ($this->plugin->can_admin() || !$this->options->non_admin_exclude_comments) {
            echo $this->option_html('sitepush_push_db_comments', 'Comments', 'user');
        }
        ?>
							<?php 
        if (!SITEPUSH_SHOW_MULTISITE) {
            echo $this->option_html('sitepush_push_db_users', 'Users &amp; user meta', 'admin_only');
        }
        ?>
							<?php 
        if ($this->plugin->can_admin() || !$this->options->non_admin_exclude_options) {
            echo $this->option_html('sitepush_push_db_options', 'WordPress options', 'user');
        }
        ?>
							<?php 
        foreach ($this->options->db_custom_table_groups_array as $key => $table_group) {
            //if label is preceded by $$$ then field only shows to admins
            if (strpos($table_group['label'], '$$$') === 0) {
                $admin_only = TRUE;
                $table_group['label'] = substr($table_group['label'], 3);
            } else {
                $admin_only = FALSE;
            }
            echo $this->option_html(array('sitepush_db_custom_table_groups', $key), $table_group['label'], $admin_only);
        }
        ?>
						</td>
					</tr>

					<?php 
        $files_output = '';
        if (!SITEPUSH_SHOW_MULTISITE) {
            $files_output .= $this->option_html('sitepush_push_theme', 'Current theme <i>(' . _deprecated_get_current_theme() . ')</i>', 'admin_only');
        }
        if (!SITEPUSH_SHOW_MULTISITE) {
            $files_output .= $this->option_html('sitepush_push_themes', 'All themes', 'admin_only');
        }
        if (!SITEPUSH_SHOW_MULTISITE) {
            $files_output .= $this->option_html('sitepush_push_plugins', 'WordPress plugins', 'admin_only');
        }
        if (!SITEPUSH_SHOW_MULTISITE && file_exists($this->options->current_site_conf['web_path'] . $this->options->current_site_conf['wpmu_plugin_dir'])) {
            $files_output .= $this->option_html('sitepush_push_mu_plugins', 'WordPress must-use plugins', 'admin_only');
        }
        if ('ERROR' != $this->options->current_site_conf['wp_uploads_dir']) {
            $files_output .= $this->option_html('sitepush_push_uploads', 'WordPress media uploads', 'user');
        } elseif ($this->plugin->can_admin()) {
            $files_output .= "Uploads directory could not be determined, so uploaded media files cannot be pushed.<br />";
        }
        if ($files_output) {
            echo "<tr><th scope='row'>Files{$ms_message}</th><td>{$files_output}</td></tr>";
        }
        ?>

					<?php 
        if (SITEPUSH_SHOW_MULTISITE && $this->plugin->can_admin()) {
            ?>
					<tr>
						<th scope="row">Multisite database content<br /><i>affects all sites</i></th>
						<td>
							<?php 
            echo $this->option_html('sitepush_push_db_users', 'Users &amp; user meta', 'admin_only');
            ?>
							<?php 
            echo $this->option_html('sitepush_push_db_multisite_tables', 'Multisite tables <i>(blogs, blog_versions, registration_log, signups, site, sitemeta, sitecategories)</i>', 'admin_only');
            ?>
							<?php 
            echo $this->option_html('sitepush_push_db_all_tables', 'Entire database for all sites <i>(Caution! This will overwrite all content and settings for all sites in this network installation)</i>', 'admin_only');
            ?>
						</td>
					</tr>
					<tr>
						<th scope="row">Multisite files<br /><i>affects all sites</i></th>
						<td>
							<?php 
            echo $this->option_html('sitepush_push_theme', 'Current theme <i>(' . _deprecated_get_current_theme() . ')</i>', 'admin_only');
            ?>
							<?php 
            echo $this->option_html('sitepush_push_themes', 'All themes', 'admin_only');
            ?>
							<?php 
            echo $this->option_html('sitepush_push_plugins', 'WordPress plugins', 'admin_only');
            ?>
							<?php 
            if (file_exists($this->options->current_site_conf['web_path'] . $this->options->current_site_conf['wpmu_plugin_dir'])) {
                echo $this->option_html('sitepush_push_mu_plugins', 'WordPress must-use plugins', 'admin_only');
            }
            ?>
						</td>
					</tr>
					<?php 
        }
        ?>

					<?php 
        $output = '';
        if (!empty($this->options->cache_key) && $this->options->use_cache) {
            $output .= $this->option_html('clear_cache', 'Clear cache on destination', 'user', 'checked');
        }
        if ($this->options->backup_path) {
            $output .= $this->option_html('sitepush_push_backup', 'Backup push <i>(note - restoring from a backup is currently a manual process and ideally requires command line access)</i>', 'user', 'checked');
        }
        if ($this->options->debug_output_level >= 3) {
            $output .= $this->option_html('sitepush_dry_run', 'Dry run <i>(show what actions would be performed by push, but don\'t actually do anything)</i>', 'admin_only');
        }
        /* No undo till we get it working properly!
        			<br /><label title="undo"><input type="radio" name="push_type" value="undo"<?php echo $push_type=='undo'?' checked="checked"':'';?> /> Undo the last push (<?php echo date( "D j F, Y \a\t H:i:s e O T",$obj_sitepushcore->get_last_undo_time() );?>)</label>
        			*/
        if ($output) {
            echo "<tr valign='top'><th scope='row'>Push options</th><td>{$output}</td></tr>";
        }
        ?>
	
				<?php 
        if (!$this->plugin->can_admin()) {
            ?>
					<tr>
						<th scope="row">&nbsp;</th>
						<td>
							<br /><span class="description">To push plugins, themes or settings, please ask an administrator.</span>
						</td>
					</tr>
				<?php 
        }
        ?>
	
				</table>
				<p class="submit">
			   	<input type="submit" class="button-primary" value="Push Content" id="push-button" />
				</p>
			</form>
		</div>
	<?php 
    }