/plugins/wp-table-reloaded/controllers/controller-admin.php
PHP | 1922 lines | 1484 code | 130 blank | 308 comment | 100 complexity | 66101b57c9f2d3a43f2dec20f7d79e9b MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- <?php
- /**
- * Admin Controller for WP-Table Reloaded with functions for the backend
- *
- * @package WP-Table Reloaded
- * @subpackage Admin Controller
- * @author Tobias Bäthge
- * @since 1.6
- */
- /**
- * Include file with the Base Controller Class
- */
- require_once ( WP_TABLE_RELOADED_ABSPATH . 'controllers/controller-base.php' );
- /**
- * Define the WP-Table Reloaded Text Domain, used to separate between plugin and core localization
- */
- define( 'WP_TABLE_RELOADED_TEXTDOMAIN', 'wp-table-reloaded' );
- /**
- * Admin Controller class, extends Base Controller Class
- */
- class WP_Table_Reloaded_Controller_Admin extends WP_Table_Reloaded_Controller_Base {
- /**
- * Nonce for security of links/forms, to prevent "CSRF"
- * @var string
- */
- var $nonce_base = 'wp-table-reloaded-nonce';
- /**
- * List of allowed actions that a user can perform with tables or the plugin
- * @var array
- */
- var $allowed_actions = array( 'list', 'add', 'edit', 'bulk_edit', 'copy', 'delete', 'import', 'export', 'options', 'uninstall', 'about', 'hide_donate_nag', 'hide_welcome_message' );
- // 'ajax_list', 'ajax_preview' also exist, but are handled separately
- /**
- * current action that is performed in this page load, populated in load_manage_page()
- * @var string
- */
- var $action = 'list';
- /**
- * List of available translations of WP-Table Reloaded, init in __construct, because of the translations
- * @var array
- */
- var $available_plugin_languages = array();
- /**
- * Default plugin options and their default values, fresh installs use those, updated installs update their options accordingly
- * @var array
- */
- var $default_options = array(
- 'installed_version' => '0',
- 'plugin_language' => 'auto',
- 'uninstall_upon_deactivation' => false,
- 'show_exit_warning' => true,
- 'growing_textareas' => true,
- 'use_datatables_on_table_list' => true,
- 'add_target_blank_to_links' => false,
- 'enable_tablesorter' => true,
- 'tablesorter_script' => 'datatables', // others are 'datatables-tabletools', 'tablesorter', and 'tablesorter_extended'
- 'use_default_css' => true,
- 'use_custom_css' => true,
- 'custom_css' => '',
- 'enable_search' => true,
- 'admin_menu_parent_page' => 'tools.php',
- 'user_access_plugin' => 'author', // others are 'contributor', 'editor', and 'admin'
- 'user_access_plugin_options' => 'author', // others are 'editor', and 'admin'
- 'frontend_edit_table_link' => true,
- 'install_time' => 0,
- 'show_donate_nag' => true,
- 'show_welcome_message' => 0, // 0 = no message, 1 = install message, 2 = update message
- 'update_message' => array(),
- 'last_id' => 0
- );
-
- /**
- * Default list of tables (empty, because there are no tables right after installation)
- * @var array
- */
- var $default_tables = array();
- /**
- * Instance of the WP_Table_Reloaded_Helper class, which has additional functions for frontend and backend, stored in separate file for better overview and maintenance
- * @var object
- */
- var $helper;
- /**
- * Instance of the WP_Table_Reloaded_Export class
- * @var object
- */
- var $export_instance;
-
- /**
- * Instance of the WP_Table_Reloaded_Import class
- * @var object
- */
- var $import_instance;
- /**
- * Hook (i.e. name) WordPress uses for the WP-Table Reloaded page, needed for certain plugin actions and filters, populated in add_manage_page()
- * @var string
- */
- var $hook = '';
- /**
- * Name of the file, WP-Table Reloaded is accessible under, dependant of whether admin has moved the WP-Table Reloaded menu entry
- * @var string
- */
- var $page_url = '';
- /**
- * PHP4 class constructor, calls the PHP5 class constructor __construct()
- */
- function WP_Table_Reloaded_Controller_Admin() {
- $this->__construct();
- }
- /**
- * PHP5 class constructor
- *
- * Initiate Backend functionality, by checking for AJAX calls, eventually answering those or setting up the admin page
- */
- function __construct() {
- register_activation_hook( WP_TABLE_RELOADED__FILE__, array( &$this, 'plugin_activation_hook' ) );
- register_deactivation_hook( WP_TABLE_RELOADED__FILE__, array( &$this, 'plugin_deactivation_hook' ) );
- $this->helper = $this->create_class_instance( 'WP_Table_Reloaded_Helper', 'helper.class.php' );
- // load plugin options and existing tables
- $this->init_plugin();
- // WordPress 3.1 requires new update check
- if ( version_compare( $this->options['installed_version'], WP_TABLE_RELOADED_PLUGIN_VERSION, '<' ) )
- add_action( 'init', array( &$this, 'plugin_update' ) );
- // init variables to check whether we do valid AJAX
- $doing_ajax = defined( 'DOING_AJAX' ) ? DOING_AJAX : false;
- $valid_ajax_call = ( isset( $_GET['page'] ) && $this->page_slug == $_GET['page'] ) ? true : false;
- // have to check for possible "export all" request this early,
- // because otherwise http-headers will be sent by WP before we can send download headers
- if ( !$doing_ajax && $valid_ajax_call && isset( $_POST['export_all'] ) ) {
- // can be done in plugins_loaded, as no language support is needed
- add_action( 'plugins_loaded', array( &$this, 'do_action_export_all' ) );
- $doing_ajax = true;
- }
- // have to check for possible export file download request this early,
- // because otherwise http-headers will be sent by WP before we can send download headers
- if ( !$doing_ajax && $valid_ajax_call && isset( $_POST['download_export_file'] ) && 'true' == $_POST['download_export_file'] ) {
- // can be done in plugins_loaded, as no language support is needed
- add_action( 'plugins_loaded', array( &$this, 'do_action_export' ) );
- $doing_ajax = true;
- }
- // have to check for possible call by editor button to show list of tables
- // and possible call to show a table preview in a thickbox on "List Tables" screen
- if ( !$doing_ajax && $valid_ajax_call && isset( $_GET['action'] ) && ( 'ajax_list' == $_GET['action'] || 'ajax_preview' == $_GET['action'] ) ) {
- // can not be done earlier, because we need language support
- add_action( 'init', array( &$this, 'do_action_' . $_GET['action'] ) );
- $doing_ajax = true;
- }
- // we are not doing AJAX, so we call the main plugin handler
- if ( !$doing_ajax ) {
- add_action( 'admin_menu', array( &$this, 'add_manage_page' ) );
- // add JS to add button to editor on admin pages that might have an editor
- $pages_with_editor_button = array( 'post.php', 'post-new.php', 'page.php', 'page-new.php' );
- foreach ( $pages_with_editor_button as $page )
- add_action( 'load-' . $page, array( &$this, 'add_editor_button' ) );
- }
- // add message to list of plugins, if an update is available / add additional links on Plugins page, for both regular visits and AJAX calls
- add_action( 'in_plugin_update_message-' . WP_TABLE_RELOADED_BASENAME, array( &$this, 'add_plugin_update_message' ), 10, 2 );
- add_filter( 'plugin_row_meta', array( &$this, 'add_plugin_row_meta' ), 10, 2);
- }
- /**
- * Add admin page to the correct place in the admin menu, and set handler for when page is loaded or shown
- */
- function add_manage_page() {
- // user needs at least this capability to view WP-Table Reloaded config page
- // capabilities from http://codex.wordpress.org/Roles_and_Capabilities
- $user_group = $this->options['user_access_plugin'];
- $capabilities = array(
- 'admin' => 'manage_options',
- 'editor' => 'publish_pages',
- 'author' => 'publish_posts',
- 'contributor' => 'edit_posts'
- );
- $min_capability = isset( $capabilities[ $user_group ] ) ? $capabilities[ $user_group ] : 'manage_options';
- $min_capability = apply_filters( 'wp_table_reloaded_min_needed_capability', $min_capability ); // plugins may filter/change this though
-
- $display_name = 'WP-Table Reloaded'; // the name that is displayed in the admin menu on the left
- $display_name = apply_filters( 'wp_table_reloaded_plugin_display_name', $display_name ); // can be filtered to something shorter maybe
- $admin_menu_page = apply_filters( 'wp_table_reloaded_admin_menu_parent_page', $this->options['admin_menu_parent_page'] );
- // backward-compatibility for the filter
- if ( 'top-level' == $admin_menu_page )
- $admin_menu_page = 'admin.php';
- // 'edit-pages.php' was renamed to 'edit.php?post_type=page' in WP 3.0
- if ( 'edit-pages.php' == $admin_menu_page )
- $admin_menu_page = 'edit.php?post_type=page';
- if ( !in_array( $admin_menu_page, $this->possible_admin_menu_parent_pages ) )
- $admin_menu_page = 'tools.php';
- // Top-Level menu is created in different function, all others are created with the filename as a parameter
- if ( 'admin.php' == $admin_menu_page )
- $this->hook = add_menu_page( 'WP-Table Reloaded', $display_name, $min_capability, $this->page_slug, array( &$this, 'show_manage_page' ), plugins_url( 'admin/plugin-icon-small.png', WP_TABLE_RELOADED__FILE__ ) );
- else
- $this->hook = add_submenu_page( $admin_menu_page, 'WP-Table Reloaded', $display_name, $min_capability, $this->page_slug, array( &$this, 'show_manage_page' ) );
- $this->page_url = $admin_menu_page;
- add_action( 'load-' . $this->hook, array( &$this, 'load_manage_page' ) );
- }
- /**
- * Function is loaded by WordPress, if WP-Table Reloaded's admin menu entry is called,
- * Load the scripts, stylesheets and language, all of this will be done before the page is shown by show_manage_page()
- */
- function load_manage_page() {
- // show admin footer message (only on pages of WP-Table Reloaded)
- add_filter( 'admin_footer_text', array( &$this->helper, 'add_admin_footer_text' ) );
- $this->init_language_support();
- // get and check action parameter from passed variables
- $default_action = 'list';
- $default_action = apply_filters( 'wp_table_reloaded_default_action', $default_action );
- $this->allowed_actions = apply_filters( 'wp_table_reloaded_allowed_actions', $this->allowed_actions );
- $action = ( !empty( $_REQUEST['action'] ) ) ? $_REQUEST['action'] : $default_action;
- // check if action is in allowed actions and if method is callable, if yes, call it
- if ( in_array( $action, $this->allowed_actions ) )
- $this->action = $action;
- add_thickbox();
- // load js and css for admin, needs to stand below thickbox script
- $this->add_manage_page_js(); // will add script to footer
- $this->add_manage_page_css(); // needs to be added to the header
- // done after determining the action, because needs action parameter to load correct help string
- add_contextual_help( $this->hook, $this->helper->get_contextual_help_string() );
- }
- /**
- * Function is loaded by WordPress, if WP-Table Reloaded's admin menu entry is called,
- * responsible for calling the appropriate action handler, output of WP admin menu and header is already done here
- */
- function show_manage_page() {
- $this->available_plugin_languages = array(
- 'ar' => __( 'Arabic', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'be_BY' => __( 'Belarusian', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'bg_BG' => __( 'Bulgarian', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'cs_CZ' => __( 'Czech', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'de_DE' => __( 'German', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'en_US' => __( 'English', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'es_ES' => __( 'Spanish', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'fi' => __( 'Finnish', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'fr_FR' => __( 'French', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'he_IL' => __( 'Hebrew', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'hi_IN' => __( 'Hindi', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'id_ID' => __( 'Indonesian', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'it_IT' => __( 'Italian', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'ja' => __( 'Japanese', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'nl_NL' => __( 'Dutch', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'pl_PL' => __( 'Polish', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'pt_BR' => __( 'Brazilian Portuguese', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'pt_PT' => __( 'Portuguese (Portugal)', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'ru_RU' => __( 'Russian', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'sk_SK' => __( 'Slovak', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'sv_SE' => __( 'Swedish', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'ua_UA' => __( 'Ukrainian', WP_TABLE_RELOADED_TEXTDOMAIN ),
- 'zh_CN' => __( 'Chinese (Simplified)', WP_TABLE_RELOADED_TEXTDOMAIN ),
- // the following are inactive because they are not up-to-date
- // 'ga_IR' => __( 'Irish', WP_TABLE_RELOADED_TEXTDOMAIN ),
- // 'sq_AL' => __( 'Albanian', WP_TABLE_RELOADED_TEXTDOMAIN ),
- // 'tr_TR' => __( 'Turkish', WP_TABLE_RELOADED_TEXTDOMAIN ),
- );
- asort( $this->available_plugin_languages );
- // do WP plugin action (before action is fired) -> can stop further plugin execution by returning true
- $overwrite = apply_filters( 'wp_table_reloaded_action_pre_' . $this->action, false );
- if ( $overwrite )
- return;
-
- // call appropriate action, $this->action is populated in load_manage_page
- if ( is_callable( array( &$this, 'do_action_' . $this->action ) ) )
- call_user_func( array( &$this, 'do_action_' . $this->action ) );
- }
-
- // ###################################################################################################################
- // ########################################## ######################################################
- // ########################################## ACTIONS ######################################################
- // ########################################## ######################################################
- // ###################################################################################################################
- /**
- * "List Tables" action handler
- */
- function do_action_list() {
- $messages = array(
- 0 => false,
- 1 => sprintf( __( 'Welcome to WP-Table Reloaded %s. If you encounter any questions or problems, please refer to the <a href="%s">FAQ</a>, the <a href="%s">documentation</a>, and the <a href="%s">support</a> section.', WP_TABLE_RELOADED_TEXTDOMAIN ), $this->options['installed_version'], 'http://tobias.baethge.com/go/wp-table-reloaded/faq/', 'http://tobias.baethge.com/go/wp-table-reloaded/documentation/', 'http://tobias.baethge.com/go/wp-table-reloaded/support/' ),
- 2 => sprintf( __( 'Thank you for upgrading to WP-Table Reloaded %s.', WP_TABLE_RELOADED_TEXTDOMAIN ), $this->options['installed_version'] ) . ' ' . __( 'This version includes several bugfixes and a few enhancements.', WP_TABLE_RELOADED_TEXTDOMAIN ) . ' ' . sprintf( __( 'Please read the <a href="%s">release announcement</a> for more information.', WP_TABLE_RELOADED_TEXTDOMAIN ), "http://tobias.baethge.com/go/wp-table-reloaded/release-announcement/{$this->options['installed_version']}/" ) . '<br/>' . sprintf( __( 'If you like the new features and enhancements, I would appreciate a small <a href="%s">donation</a>. Thank you.', WP_TABLE_RELOADED_TEXTDOMAIN ), 'http://tobias.baethge.com/go/wp-table-reloaded/donate/' )
- );
- $message = ( isset( $messages[ $this->options['show_welcome_message'] ] ) ) ? $messages[ $this->options['show_welcome_message'] ] : false;
- if ( $message ) {
- $hide_welcome_message_url = $this->get_action_url( array( 'action' => 'hide_welcome_message' ), true );
- $this->helper->print_header_message( $message . '<br/><br/>' . sprintf( '<a href="%s" style="font-weight:normal;">%s</a>', $hide_welcome_message_url, __( 'Hide this message', WP_TABLE_RELOADED_TEXTDOMAIN ) ) );
- }
- if ( $this->may_print_donate_nag() ) {
- $donate_url = 'http://tobias.baethge.com/go/wp-table-reloaded/donate/message/';
- $donated_true_url = $this->get_action_url( array( 'action' => 'hide_donate_nag', 'user_donated' => true ), true );
- $donated_false_url = $this->get_action_url( array( 'action' => 'hide_donate_nag', 'user_donated' => false ), true );
- $this->helper->print_header_message(
- __( 'Thanks for using this plugin! You\'ve installed WP-Table Reloaded over a month ago.', WP_TABLE_RELOADED_TEXTDOMAIN ) . ' ' . sprintf( _n( 'If it works and you are satisfied with the results of managing your %s table, isn\'t it worth at least one dollar or euro?', 'If it works and you are satisfied with the results of managing your %s tables, isn\'t it worth at least one dollar or euro?', count( $this->tables ), WP_TABLE_RELOADED_TEXTDOMAIN ), count( $this->tables ) ) . '<br/><br/>' .
- sprintf( __( '<a href="%s">Donations</a> help me to continue support and development of this <i>free</i> software - things for which I spend countless hours of my free time! Thank you!', WP_TABLE_RELOADED_TEXTDOMAIN ), $donate_url ) . '<br/><br/>' .
- sprintf( '<a href="%s" target="_blank">%s</a>', $donate_url, __( 'Sure, no problem!', WP_TABLE_RELOADED_TEXTDOMAIN ) ) . ' · ' .
- sprintf( '<a href="%s" style="font-weight:normal;">%s</a>', $donated_true_url, __( 'I already donated.', WP_TABLE_RELOADED_TEXTDOMAIN ) ) . ' · ' .
- sprintf( '<a href="%s" style="font-weight:normal;">%s</a>', $donated_false_url, __( 'No, thanks. Don\'t ask again.', WP_TABLE_RELOADED_TEXTDOMAIN ) )
- );
- }
- $this->load_view( 'list' );
- }
-
- /**
- * "Add new Table" action handler
- */
- function do_action_add() {
- if ( isset( $_POST['submit'] ) && isset( $_POST['table'] ) ) {
- check_admin_referer( $this->get_nonce( 'add' ) );
- $rows = ( 0 < $_POST['table']['rows'] ) ? $_POST['table']['rows'] : 1;
- $cols = ( 0 < $_POST['table']['cols'] ) ? $_POST['table']['cols'] : 1;
- $table = $this->default_table;
- $table['id'] = $this->get_new_table_id();
- $table['data'] = $this->helper->create_empty_table( $rows, $cols );
- $table['visibility']['rows'] = array_fill( 0, $rows, false );
- $table['visibility']['columns'] = array_fill( 0, $cols, false );
- $table['name'] = $_POST['table']['name'];
- $table['description'] = $_POST['table']['description'];
- $this->save_table( $table );
- $this->helper->print_header_message( sprintf( __( 'Table "%s" added successfully.', WP_TABLE_RELOADED_TEXTDOMAIN ), $this->helper->safe_output( $table['name'] ) ) );
- $table_id = $table['id'];
- $this->load_view( 'edit', compact( 'table_id' ) );
- } else {
- $this->load_view( 'add' );
- }
- }
- /**
- * "Edit Table" action handler
- */
- function do_action_edit() {
- if ( isset( $_POST['submit'] ) && isset( $_POST['table'] ) ) {
- check_admin_referer( $this->get_nonce( 'edit' ) );
-
- $subactions = array_keys( $_POST['submit'] );
- $subaction = $subactions[0];
-
- switch( $subaction ) {
- case 'update':
- case 'save_back':
- $table = $_POST['table']; // careful here to not miss any stuff!!! (options, etc.)
- // do we want to change the ID?
- $new_table_id = ( isset( $_POST['table_id'] ) ) ? $_POST['table_id'] : $table['id'] ;
- if ( $new_table_id != $table['id'] && is_numeric( $new_table_id ) && ( 0 < $new_table_id ) ) {
- if ( !$this->table_exists( $new_table_id ) ) {
- // delete table with old ID
- $old_table_id = $table['id'];
- $this->delete_table( $old_table_id );
- // set new table ID
- $table['id'] = $new_table_id;
- $message = sprintf( __( "Table edited successfully. This Table now has the ID %s. You'll need to adjust existing shortcodes accordingly.", WP_TABLE_RELOADED_TEXTDOMAIN ), $new_table_id );
- } else {
- $message = sprintf( __( 'The ID could not be changed from %s to %s, because there already is a Table with that ID.', WP_TABLE_RELOADED_TEXTDOMAIN ), $table['id'], $new_table_id );
- }
- } else {
- $message = __( 'Table edited successfully.', WP_TABLE_RELOADED_TEXTDOMAIN );
- }
- // save table options (checkboxes!), only checked checkboxes are submitted (then as true)
- $table['options']['alternating_row_colors'] = isset( $_POST['table']['options']['alternating_row_colors'] );
- $table['options']['row_hover'] = isset( $_POST['table']['options']['row_hover'] );
- $table['options']['first_row_th'] = isset( $_POST['table']['options']['first_row_th'] );
- $table['options']['table_footer'] = isset( $_POST['table']['options']['table_footer'] );
- $table['options']['print_name'] = isset( $_POST['table']['options']['print_name'] );
- $table['options']['print_description'] = isset( $_POST['table']['options']['print_description'] );
- $table['options']['cache_table_output'] = isset( $_POST['table']['options']['cache_table_output'] );
- $table['options']['custom_css_class'] = trim( $table['options']['custom_css_class'] ); // more complex sanitize_* functions would change spaces to hyphens...
- $table['options']['use_tablesorter'] = isset( $_POST['table']['options']['use_tablesorter'] );
- $table['options']['datatables_sort'] = isset( $_POST['table']['options']['datatables_sort'] );
- $table['options']['datatables_paginate'] = isset( $_POST['table']['options']['datatables_paginate'] );
- $table['options']['datatables_lengthchange'] = isset( $_POST['table']['options']['datatables_lengthchange'] );
- $table['options']['datatables_filter'] = isset( $_POST['table']['options']['datatables_filter'] );
- $table['options']['datatables_info'] = isset( $_POST['table']['options']['datatables_info'] );
- $table['options']['datatables_tabletools'] = isset( $_POST['table']['options']['datatables_tabletools'] );
- $table['options']['datatables_paginate_entries'] = ( is_numeric( $table['options']['datatables_paginate_entries'] ) ) ? absint( $table['options']['datatables_paginate_entries'] ) : $this->default_table['options']['datatables_paginate_entries'];
- // $table['options']['datatables_customcommands'] is an input type=text field that is always submitted
- // $table['options']['print_name|description_position'] are select fields that are always submitted
- // save visibility settings (checkboxes!)
- foreach ( $table['data'] as $row_idx => $row )
- $table['visibility']['rows'][$row_idx] = ( isset( $_POST['table']['visibility']['rows'][$row_idx] ) && ( 'true' == $_POST['table']['visibility']['rows'][$row_idx] ) );
- foreach ( $table['data'][0] as $col_idx => $col )
- $table['visibility']['columns'][$col_idx] = ( isset( $_POST['table']['visibility']['columns'][$col_idx] ) && ( 'true' == $_POST['table']['visibility']['columns'][$col_idx] ) );
- if ( !empty( $table['custom_fields'] ) )
- uksort( $table['custom_fields'], 'strnatcasecmp' ); // sort the keys naturally
- $this->save_table( $table );
- break;
- case 'swap_rows':
- $table_id = $_POST['table']['id'];
- $row_id1 = ( isset( $_POST['swap']['row'][1] ) ) ? $_POST['swap']['row'][1] : -1;
- $row_id2 = ( isset( $_POST['swap']['row'][2] ) ) ? $_POST['swap']['row'][2] : -1;
- $table = $this->load_table( $table_id );
- $rows = count( $table['data'] );
- // swap rows $row_id1 and $row_id2
- if ( ( 1 < $rows ) && ( -1 < $row_id1 ) && ( -1 < $row_id2 ) && ( $row_id1 != $row_id2 ) ) {
- $temp_row = $table['data'][$row_id1];
- $table['data'][$row_id1] = $table['data'][$row_id2];
- $table['data'][$row_id2] = $temp_row;
- $temp_visibility = $table['visibility']['rows'][$row_id1];
- $table['visibility']['rows'][$row_id1] = $table['visibility']['rows'][$row_id2];
- $table['visibility']['rows'][$row_id2] = $temp_visibility;
- }
- $this->save_table( $table );
- $message = __( 'Rows swapped successfully.', WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- case 'swap_cols':
- $table_id = $_POST['table']['id'];
- $col_id1 = ( isset( $_POST['swap']['col'][1] ) ) ? $_POST['swap']['col'][1] : -1;
- $col_id2 = ( isset( $_POST['swap']['col'][2] ) ) ? $_POST['swap']['col'][2] : -1;
- $table = $this->load_table( $table_id );
- $rows = count( $table['data'] );
- $cols = (0 < $rows) ? count( $table['data'][0] ) : 0;
- // swap rows $col_id1 and $col_id2
- if ( ( 1 < $cols ) && ( -1 < $col_id1 ) && ( -1 < $col_id2 ) && ( $col_id1 != $col_id2 ) ) {
- foreach ( $table['data'] as $row_idx => $row ) {
- $temp_col = $table['data'][$row_idx][$col_id1];
- $table['data'][$row_idx][$col_id1] = $table['data'][$row_idx][$col_id2];
- $table['data'][$row_idx][$col_id2] = $temp_col;
- }
- $temp_visibility = $table['visibility']['columns'][$col_id1];
- $table['visibility']['columns'][$col_id1] = $table['visibility']['columns'][$col_id2];
- $table['visibility']['columns'][$col_id2] = $temp_visibility;
- }
- $this->save_table( $table );
- $message = __( 'Columns swapped successfully.', WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- case 'sort':
- $table_id = $_POST['table']['id'];
- $column = ( isset( $_POST['sort']['col'] ) ) ? $_POST['sort']['col'] : -1;
- $sort_order = ( isset( $_POST['sort']['order'] ) ) ? $_POST['sort']['order'] : 'ASC';
- $table = $this->load_table( $table_id );
- $rows = count( $table['data'] );
- $cols = (0 < $rows) ? count( $table['data'][0] ) : 0;
- // sort array for $column in $sort_order
- if ( ( 1 < $rows ) && ( -1 < $column ) ) {
- // for sorting: temporarily store row visibility in data, so that it gets sorted, too
- foreach ( $table['data'] as $row_idx => $row )
- array_splice( $table['data'][$row_idx], $cols, 0, $table['visibility']['rows'][$row_idx] );
- $array_to_sort = $table['data'];
- if ( isset( $table['options']['first_row_th'] ) && $table['options']['first_row_th'] )
- $first_row = array_shift( $array_to_sort );
- if ( isset( $table['options']['table_footer'] ) && $table['options']['table_footer'] )
- $last_row = array_pop( $array_to_sort );
- $sortarray = $this->create_class_instance( 'arraysort', 'arraysort.class.php' );
- $sortarray->input_array = $array_to_sort;
- $sortarray->column = $column;
- $sortarray->order = $sort_order;
- $sortarray->sort();
- $sorted_array = $sortarray->sorted_array;
- if ( isset( $table['options']['first_row_th'] ) && $table['options']['first_row_th'] )
- array_unshift( $sorted_array, $first_row );
- if ( isset( $table['options']['table_footer'] ) && $table['options']['table_footer'] )
- array_push( $sorted_array, $last_row );
- $table['data'] = $sorted_array;
- // then restore row visibility from sorted data and remove temporary column
- foreach ( $table['data'] as $row_idx => $row ) {
- $table['visibility']['rows'][$row_idx] = $table['data'][$row_idx][$cols];
- array_splice( $table['data'][$row_idx], $cols, 1 );
- }
- }
- $this->save_table( $table );
- $message = __( 'Table sorted successfully.', WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- case 'move_row':
- $table_id = $_POST['table']['id'];
- $row_id1 = ( isset( $_POST['move']['row'][1] ) ) ? $_POST['move']['row'][1] : -1;
- $row_id2 = ( isset( $_POST['move']['row'][2] ) ) ? $_POST['move']['row'][2] : -1;
- $move_where = ( isset( $_POST['move']['row']['where'] ) ) ? $_POST['move']['row']['where'] : 'before';
- if ( 'after' == $move_where )
- $row_id2 = $row_id2 + 1; // move after is the same as move before the next row
- $table = $this->load_table( $table_id );
- $rows = count( $table['data'] );
- // move row $row_id1 before/after $row_id2
- if ( ( 1 < $rows ) && ( -1 < $row_id1 ) && ( -1 < $row_id2 ) && ( $row_id1 != $row_id2 ) ) {
- if ( $row_id2 > $row_id1 )
- $row_id2 = $row_id2 - 1; // if target higher than source, source element is removed, so target index smaller by one
- $temp_row = array( $table['data'][$row_id1] );
- unset( $table['data'][$row_id1] );
- array_splice( $table['data'], $row_id2, 0, $temp_row );
- $temp_visibility = $table['visibility']['rows'][$row_id1];
- unset( $table['visibility']['rows'][$row_id1] );
- array_splice( $table['visibility']['rows'], $row_id2, 0, $temp_visibility );
- }
- $this->save_table( $table );
- $message = __( 'Row moved successfully.', WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- case 'move_col':
- $table_id = $_POST['table']['id'];
- $col_id1 = ( isset( $_POST['move']['col'][1] ) ) ? $_POST['move']['col'][1] : -1;
- $col_id2 = ( isset( $_POST['move']['col'][2] ) ) ? $_POST['move']['col'][2] : -1;
- $move_where = ( isset( $_POST['move']['col']['where'] ) ) ? $_POST['move']['col']['where'] : 'before';
- if ( 'after' == $move_where )
- $col_id2 = $col_id2 + 1; // move after is the same as move before the next row
- $table = $this->load_table( $table_id );
- $rows = count( $table['data'] );
- $cols = (0 < $rows) ? count( $table['data'][0] ) : 0;
- // move col $col_id1 before/after $col_id2
- if ( ( 1 < $cols ) && ( -1 < $col_id1 ) && ( -1 < $col_id2 ) && ( $col_id1 != $col_id2 ) ) {
- if ( $col_id2 > $col_id1 )
- $col_id2 = $col_id2 - 1; // if target higher than source, source element is removed, so target index smaller by one
- foreach ( $table['data'] as $row_idx => $row ) {
- $temp_col = $table['data'][$row_idx][$col_id1];
- unset( $table['data'][$row_idx][$col_id1] );
- array_splice( $table['data'][$row_idx], $col_id2, 0, $temp_col );
- }
- $temp_visibility = $table['visibility']['columns'][$col_id1];
- unset( $table['visibility']['columns'][$col_id1] );
- array_splice( $table['visibility']['columns'], $col_id2, 0, $temp_visibility );
- }
- $this->save_table( $table );
- $message = __( 'Column moved successfully.', WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- case 'delete_rows':
- $table_id = $_POST['table']['id'];
- $delete_rows = ( isset( $_POST['table_select']['rows'] ) ) ? $_POST['table_select']['rows'] : array();
- $table = $this->load_table( $table_id );
- $rows = count( $table['data'] );
- $cols = (0 < $rows) ? count( $table['data'][0] ) : 0;
- $message = _n( 'Row could not be deleted.', 'Rows could not be deleted.', count( $delete_rows ), WP_TABLE_RELOADED_TEXTDOMAIN ); // only used if deletion fails below
- if ( ( 1 < $rows ) && ( 0 < count( $delete_rows ) ) && ( count( $delete_rows ) < $rows ) ) {
- // remove rows and re-index
- foreach ( $delete_rows as $row_idx => $value) {
- unset( $table['data'][$row_idx] );
- unset( $table['visibility']['rows'][$row_idx] );
- }
- $table['data'] = array_merge( $table['data'] );
- $table['visibility']['rows'] = array_merge( $table['visibility']['rows'] );
- $message = _n( 'Row deleted successfully.', 'Rows deleted successfully.', count( $delete_rows ), WP_TABLE_RELOADED_TEXTDOMAIN );
- }
- $this->save_table( $table );
- break;
- case 'delete_cols':
- $table_id = $_POST['table']['id'];
- $delete_columns = ( isset( $_POST['table_select']['columns'] ) ) ? $_POST['table_select']['columns'] : array();
- $table = $this->load_table( $table_id );
- $rows = count( $table['data'] );
- $cols = (0 < $rows) ? count( $table['data'][0] ) : 0;
- $message = _n( 'Column could not be deleted.', 'Columns could not be deleted.', count( $delete_columns ), WP_TABLE_RELOADED_TEXTDOMAIN ); // only used if deletion fails below
- if ( ( 1 < $cols ) && ( 0 < count( $delete_columns ) ) && ( count( $delete_columns ) < $cols ) ) {
- foreach ( $table['data'] as $row_idx => $row ) {
- // remove columns and re-index
- foreach ( $delete_columns as $col_idx => $value) {
- unset( $table['data'][$row_idx][$col_idx] );
- }
- $table['data'][$row_idx] = array_merge( $table['data'][$row_idx] );
- }
- foreach ( $delete_columns as $col_idx => $value) {
- unset( $table['visibility']['columns'][$col_idx] );
- }
- $table['visibility']['columns'] = array_merge( $table['visibility']['columns'] );
- $message = _n( 'Column deleted successfully.', 'Columns deleted successfully.', count( $delete_columns ), WP_TABLE_RELOADED_TEXTDOMAIN );
- }
- $this->save_table( $table );
- break;
- case 'insert_rows': // insert row before each selected row
- $table_id = $_POST['table']['id'];
- $insert_rows = ( isset( $_POST['table_select']['rows'] ) ) ? $_POST['table_select']['rows'] : array();
- $table = $this->load_table( $table_id );
- $rows = count( $table['data'] );
- $cols = (0 < $rows) ? count( $table['data'][0] ) : 0;
- // insert rows and re-index
- $row_change = 0; // row_change is growing parameter, needed because indices change
- $new_row = array( array_fill( 0, $cols, '' ) );
- foreach ( $insert_rows as $row_idx => $value) {
- $row_id = $row_idx + $row_change;
- // init new empty row (with all columns) and insert it before row with key $row_id
- array_splice( $table['data'], $row_id, 0, $new_row );
- array_splice( $table['visibility']['rows'], $row_id, 0, false );
- $row_change++;
- }
-
- $this->save_table( $table );
- $message = _n( 'Row inserted successfully.', 'Rows inserted successfully.', count( $insert_rows ), WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- case 'insert_cols': // insert column before each selected column
- $table_id = $_POST['table']['id'];
- $insert_columns = ( isset( $_POST['table_select']['columns'] ) ) ? $_POST['table_select']['columns'] : array();
- $table = $this->load_table( $table_id );
- $rows = count( $table['data'] );
- $cols = (0 < $rows) ? count( $table['data'][0] ) : 0;
- // insert cols and re-index
- $new_col = '';
- foreach ( $table['data'] as $row_idx => $row ) {
- $col_change = 0; // col_change is growing parameter, needed because indices change
- foreach ( $insert_columns as $col_idx => $value) {
- $col_id = $col_idx + $col_change;
- array_splice( $table['data'][$row_idx], $col_id, 0, $new_col );
- $col_change++;
- }
- }
- $col_change = 0; // col_change is growing parameter, needed because indices change
- foreach ( $insert_columns as $col_idx => $value) {
- $col_id = $col_idx + $col_change;
- array_splice( $table['visibility']['columns'], $col_id, 0, false );
- $col_change++;
- }
- $this->save_table( $table );
- $message = _n( 'Column inserted successfully.', 'Columns inserted successfully.', count( $insert_columns ), WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- case 'append_rows':
- $table_id = $_POST['table']['id'];
- $number = ( isset( $_POST['insert']['row']['number'] ) && ( 0 < $_POST['insert']['row']['number'] ) ) ? $_POST['insert']['row']['number'] : 1;
- $row_id = $_POST['insert']['row']['id'];
- $table = $this->load_table( $table_id );
- $rows = count( $table['data'] );
- $cols = (0 < $rows) ? count( $table['data'][0] ) : 0;
- // init new empty row (with all columns) and insert it before row with key $row_id
- $new_rows = $this->helper->create_empty_table( $number, $cols, '' );
- $new_rows_visibility = array_fill( 0, $number, false );
- array_splice( $table['data'], $row_id, 0, $new_rows );
- array_splice( $table['visibility']['rows'], $row_id, 0, $new_rows_visibility );
- $this->save_table( $table );
- $message = _n( 'Row added successfully.', 'Rows added successfully.', $number, WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- case 'append_cols':
- $table_id = $_POST['table']['id'];
- $number = ( isset( $_POST['insert']['col']['number'] ) && ( 0 < $_POST['insert']['col']['number'] ) ) ? $_POST['insert']['col']['number'] : 1;
- $col_id = $_POST['insert']['col']['id'];
- $table = $this->load_table( $table_id );
- // init new empty row (with all columns) and insert it before row with key $col_id
- $new_cols = array_fill( 0, $number, '' );
- $new_cols_visibility = array_fill( 0, $number, false );
- foreach ( $table['data'] as $row_idx => $row )
- array_splice( $table['data'][$row_idx], $col_id, 0, $new_cols );
- array_splice( $table['visibility']['columns'], $col_id, 0, $new_cols_visibility );
- $this->save_table( $table );
- $message = _n( 'Column added successfully.', 'Columns added successfully.', $number, WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- case 'insert_cf':
- $table_id = $_POST['table']['id'];
- $table = $this->load_table( $table_id );
- $name = ( isset( $_POST['insert']['custom_field'] ) ) ? $_POST['insert']['custom_field'] : '';
- if ( empty( $name ) ) {
- $message = __( 'Could not add Custom Data Field, because you did not enter a name.', WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- }
- $reserved_names = array( 'name', 'description', 'last_modified', 'last_editor' );
- if ( in_array( $name, $reserved_names ) ) {
- $message = __( 'Could not add Custom Data Field, because the name you entered is reserved for other table data.', WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- }
- // Name can only contain lowercase letters, numbers, _ and - (like permalink slugs)
- $clean_name = sanitize_title_with_dashes( $name );
- if ( $name != $clean_name ) {
- $message = __( 'Could not add Custom Data Field, because the name contained illegal characters.', WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- }
- if ( isset( $table['custom_fields'][$name] ) ) {
- $message = __( 'Could not add Custom Data Field, because a Field with that name already exists.', WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- }
- $table['custom_fields'][$name] = '';
- uksort( $table['custom_fields'], 'strnatcasecmp' ); // sort the keys naturally
- $this->save_table( $table );
- $message = __( 'Custom Data Field added successfully.', WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- default:
- $this->do_action_list();
- return;
- }
- $this->helper->print_header_message( $message );
- if ( 'save_back' == $subaction ) {
- $this->do_action_list();
- } else {
- $table_id = $table['id'];
- $this->load_view( 'edit', compact( 'table_id' ) );
- }
- } elseif ( isset( $_GET['table_id'] ) && $this->table_exists( $_GET['table_id'] ) ) {
- $table_id = $_GET['table_id'];
- $this->load_view( 'edit', compact( 'table_id' ) );
- } else {
- $this->do_action_list();
- }
- }
- /**
- * "Bulk Edit" action handler
- */
- function do_action_bulk_edit() {
- if ( isset( $_POST['submit'] ) ) {
- check_admin_referer( $this->get_nonce( 'bulk_edit' ) );
- if ( isset( $_POST['tables'] ) ) {
- $subactions = array_keys( $_POST['submit'] );
- $subaction = $subactions[0];
- switch( $subaction ) {
- case 'copy': // see do_action_copy for explanations
- foreach ( $_POST['tables'] as $table_id ) {
- $table_to_copy = $this->load_table( $table_id );
- $new_table = $table_to_copy;
- $new_table['id'] = $this->get_new_table_id();
- $new_table['name'] = __( 'Copy of', WP_TABLE_RELOADED_TEXTDOMAIN ) . ' ' . $table_to_copy['name'];
- unset( $table_to_copy );
- $this->save_table( $new_table );
- }
- $message = _n( 'Table copied successfully.', 'Tables copied successfully.', count( $_POST['tables'] ), WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- case 'delete': // see do_action_delete for explanations
- foreach ( $_POST['tables'] as $table_id ) {
- $this->delete_table( $table_id );
- }
- $message = _n( 'Table deleted successfully.', 'Tables deleted successfully.', count( $_POST['tables'] ), WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- case 'wp_table_import': // see do_action_import for explanations
- $this->import_instance = $this->create_class_instance( 'WP_Table_Reloaded_Import', 'import.class.php' );
- $this->import_instance->import_format = 'wp_table';
- foreach ( $_POST['tables'] as $table_id ) {
- $this->import_instance->wp_table_id = $table_id;
- $this->import_instance->import_table();
- $imported_table = $this->import_instance->imported_table;
- $table = array_merge( $this->default_table, $imported_table );
-
- $rows = count( $table['data'] );
- $cols = (0 < $rows) ? count( $table['data'][0] ) : 0;
- $rows = ( 0 < $rows ) ? $rows : 1;
- $cols = ( 0 < $cols ) ? $cols : 1;
- $table['visibility']['rows'] = array_fill( 0, $rows, false );
- $table['visibility']['columns'] = array_fill( 0, $cols, false );
-
- $table['id'] = $this->get_new_table_id();
- $this->save_table( $table );
- }
- $message = _n( 'Table imported successfully.', 'Tables imported successfully.', count( $_POST['tables'] ), WP_TABLE_RELOADED_TEXTDOMAIN );
- break;
- default:
- break;
- }
- } else {
- $message = __( 'You did not select any tables!', WP_TABLE_RELOADED_TEXTDOMAIN );
- }
- $this->helper->print_header_message( $message );
- }
- $this->do_action_list();
- }
- /**
- * "Copy" action handler
- */
- function do_action_copy() {
- if ( isset( $_GET['table_id'] ) ) {
- check_admin_referer( $this->get_nonce( 'copy' ) );
- $table_to_copy = $this->load_table( $_GET['table_id'] );
- $new_table = $table_to_copy;
- $new_table['id'] = $this->get_new_table_id();
- $new_table['name'] = __( 'Copy of', WP_TABLE_RELOADED_TEXTDOMAIN ) . ' ' . $table_to_copy['name'];
- unset( $table_to_copy );
- $this->save_table( $new_table );
- $this->helper->print_header_message( sprintf( __( 'Table "%s" copied successfully.', WP_TABLE_RELOADED_TEXTDOMAIN ), $this->helper->safe_output( $new_table['name'] ) ) );
- }
- $this->do_action_list();
- }
- /**
- * "Delete" action handler, for tables and custom fields
- */
- function do_action_delete() {
- if ( isset( $_GET['table_id'] ) && isset( $_GET['item'] ) ) {
- check_admin_referer( $this->get_nonce( 'delete', $_GET['item'] ) );
- $table_id = $_GET['table_id'];
- $table = $this->load_table( $table_id );
- switch( $_GET['item'] ) {
- case 'table':
- $this->delete_table( $table_id );
- $this->helper->print_header_message( sprintf( __( 'Table "%s" deleted successfully.', WP_TABLE_RELOADED_TEXTDOMAIN ), $this->helper->safe_output( $table['name'] ) ) );
- $this->do_action_list();
- break;
- case 'custom_field':
- $name = ( isset( $_GET['element_id'] ) ) ? $_GET['element_id'] : '';
- if ( !empty( $name ) && isset( $table['custom_fields'][$name] ) ) {
- unset( $table['custom_fields'][$name] );
- $this->save_table( $table );
- $message = __( 'Custom Data Field deleted successfully.', WP_TABLE_RELOADED_TEXTDOMAIN );
- } else {
- $message = __( 'Custom Data Field could not be deleted.', WP_TABLE_RELOADED_TEXTDOMAIN );
- }
- $this->helper->print_header_message( $message );
- $this->load_view( 'edit', compact( 'table_id' ) );
- break;
- default:
- $this->helper->print_header_message( __( 'Delete failed.', WP_TABLE_RELOADED_TEXTDOMAIN ) );
- $this->do_action_list();
- }
- } else {
- $this->do_action_list();
- }
- }
- /**
- * "Import" action handler, for single tables and a Dump File
- */
- function do_action_import() {
- $this->import_instance = $this->create_class_instance( 'WP_Table_Reloaded_Import', 'import.class.php' );
- if ( isset( $_POST['submit'] ) && isset( $_POST['import_from'] ) ) {
- check_admin_referer( $this->get_nonce( 'import' ) );
- $import_error = false;
- switch( $_POST['import_from'] ) {
- case 'file-upload':
- …
Large files files are truncated, but you can click here to view the full file