<?php
/**
* Table Model
*
* @package TablePress
* @subpackage Models
* @author Tobias Bäthge
* @since 1.0.0
*/
// Prohibit direct script loading
defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
/**
* Table Model class
* @package TablePress
* @subpackage Models
* @author Tobias Bäthge
* @since 1.0.0
*/
class TablePress_Table_Model extends TablePress_Model {
/**
* Instance of the Post Type Model
*
* @since 1.0.0
*
* @var object
*/
protected $model_post;
/**
* Name of the Post Meta Field for table options
*
* @since 1.0.0
*
* @var string
*/
protected $table_options_field_name = '_tablepress_table_options';
/**
* Name of the Post Meta Field for table visibility
*
* @since 1.0.0
*
* @var string
*/
protected $table_visibility_field_name = '_tablepress_table_visibility';
/**
* Default set of tables
*
* Array fields:
* - last_id: last table ID that was given to a new table
* - table_post: array of connections between table ID and post ID (key: table ID, value: post ID)
*
* @since 1.0.0
*
* @var array
*/
protected $default_tables = array(
'last_id' => 0,
'table_post' => array()
);
/**
* Instance of WP_Option class for the list of tables
*
* @since 1.0.0
*
* @var object
*/
protected $tables;
/**
* Init the Table model by instantiating a Post model and loading the list of tables option
*
* @since 1.0.0
*/
public function __construct() {
parent::__construct();
$this->model_post = TablePress::load_model( 'post' );
$params = array(
'option_name' => 'tablepress_tables',
'default_value' => $this->default_tables
);
$this->tables = TablePress::load_class( 'TablePress_WP_Option', 'class-wp_option.php', 'classes', $params );
}
/**
* Get the tables option, which holds the connection between table ID and post ID
*
* @since 1.0.0
*
* @return array Current set of tables
*/
public function _debug_get_tables() {
return $this->tables->get();
}
/**
* Update the tables option, which holds the connection between table ID and post ID
*
* @since 1.0.0
*
* @param array $tables New set of tables
*/
public function _debug_update_tables( $tables ) {
$this->tables->update( $tables );
}
/**
* Convert a table to a post, which can be stored in the database
*
* @since 1.0.0
*
* @param array $table Table
* @param int $post_id Post ID
* @return array Post
*/
protected function _table_to_post( $table, $post_id ) {
// Sanitize each cell, if the user is not allowed to work with unfiltered HTML
// table name and description are sanitized by WordPress directly, but the JSON would break if we don't do it ourselves
if ( ! current_user_can( 'unfiltered_html' ) ) {
foreach ( $table['data'] as $row_idx => $row ) {
foreach ( $row as $column_idx => $cell_content ) {
$table['data'][ $row_idx ][ $column_idx ] = wp_kses_post( $cell_content ); // equals wp_filter_post_kses(), but without the unncessary slashes handling
}
}
}
$post = array(
'ID' => $post_id,
'post_title' => $table['name'],
// 'post_author' => $table['author'],
'post_excerpt' => $table['description'],
'post_content' => json_encode( $table['data'] )
);
return $post;
}
/**
* Convert a post (from the database) to a table
*
* @since 1.0.0
*
* @param WP_Post $post Post
* @param string $table_id Table ID
* @return array Table
*/
protected function _post_to_table( $post, $table_id ) {
$table = array(
'id' => $table_id,
'name' => $post->post_title,
'description' => $post->post_excerpt,
'author' => $post->post_author,
// 'created' => $post->post_date,
'last_modified' => $post->post_modified,
'data' => json_decode( $post->post_content, true )
);
// Check if JSON could be decoded
if ( is_null( $table['data'] ) ) {
// set a single cell as the default
$table['data'] = array( array( 'The internal data of this table is corrupted!' ) );
// mark table as broken
$table['name'] = '[ERROR] ' . $table['name'];
// if possible, try to find out what error prevented the JSON from being decoded
$json_error = '';
if ( function_exists( 'json_last_error' ) ) {
// Constant JSON_ERROR_UTF8 is only available as of PHP 5.3.3
if ( ! defined( 'JSON_ERROR_UTF8' ) )
define( 'JSON_ERROR_UTF8', 5 );
switch ( json_last_error() ) {
case JSON_ERROR_NONE:
$json_error = 'JSON_ERROR_NONE'; // should never happen here, as this is only called in case of an error
break;
case JSON_ERROR_DEPTH:
$json_error = 'JSON_ERROR_DEPTH';
break;
case JSON_ERROR_STATE_MISMATCH:
$json_error = 'JSON_ERROR_STATE_MISMATCH';
break;
case JSON_ERROR_CTRL_CHAR:
$json_error = 'JSON_ERROR_CTRL_CHAR';
break;
case JSON_ERROR_SYNTAX:
$json_error = 'JSON_ERROR_SYNTAX';
break;
case JSON_ERROR_UTF8:
$json_error = 'JSON_ERROR_UTF8';
break;
default:
$json_error = 'UNKNOWN ERROR';
break;
}
$json_error = " ({$json_error})";
}
$table['description'] = "[ERROR] TABLE IS CORRUPTED{$json_error}! DO NOT EDIT THIS TABLE NOW!\nInstead, please ask for support at http://wordpress.org/support/plugin/tablepress\n-\n" . $table['description'];
}
return $table;
}
/**
* Load a table
*
* @since 1.0.0
*
* @param string $table_id Table ID
* @return array|bool Table as an array on success, false on error
*/
public function load( $table_id ) {
if ( empty( $table_id ) )
return false;
$post_id = $this->_get_post_id( $table_id );
if ( false === $post_id )
return false;
$post = $this->model_post->get( $post_id );
if ( false === $post )
return false;
$table = $this->_post_to_table( $post, $table_id );
$table['options'] = $this->_get_table_options( $post_id );
$table['visibility'] = $this->_get_table_visibility( $post_id );
return $table;
}
/**
* Load all tables
*
* @since 1.0.0
*
* @return array Array of Tables, but each without table data!
*/
public function load_all() {
$tables = array();
$table_post = $this->tables->get( 'table_post' );
if ( empty( $table_post ) )
return array();
// load all table posts with one query, to prime the cache
$this->model_post->load_posts( array_values( $table_post ) );
// this loop now uses the WP cache
foreach ( $table_post as $table_id => $post_id ) {
$table_id = (string)$table_id;
$tables[ $table_id ] = $this->load( $table_id );
unset( $tables[ $table_id ]['data'] ); // remove table data, to save memory
}
return $tables;
}
/**
* Save a table
*
* @since 1.0.0
*
* @param array $table Table (needs to have $table['id']!)
* @return mixed False on error, string table ID on success
*/
public function save( $table ) {
if ( empty( $table['id'] ) )
return false;
$post_id = $this->_get_post_id( $table['id'] );
if ( false === $post_id )
return false;
$post = $this->_table_to_post( $table, $post_id );
$new_post_id = $this->model_post->update( $post );
if ( 0 === $new_post_id || $post_id !== $new_post_id )
return false;
$options_saved = $this->_update_table_options( $new_post_id, $table['options'] );
if ( ! $options_saved )
return false;
$visibility_saved = $this->_update_table_visibility( $new_post_id, $table['visibility'] );
if ( ! $visibility_saved )
return false;
// at this point, post was successfully added
// invalidate table output caches that belong to this table
$this->_invalidate_table_output_cache( $table['id'] );
// Flush caching plugins' caches
$this->_flush_caching_plugins_caches();
return $table['id'];
}
/**
* Add a new table
*
* @since 1.0.0
*
* @param array $table Table ($table['id'] is not necessary)
* @return mixed False on error, string table ID of the new table on success
*/
public function add( $table ) {
$post_id = false; // to insert table
$post = $this->_table_to_post( $table, $post_id );
$new_post_id = $this->model_post->insert( $post );
if ( 0 === $new_post_id )
return false;
$options_saved = $this->_add_table_options( $new_post_id, $table['options'] );
if ( ! $options_saved )
return false;
$visibility_saved = $this->_add_table_visibility( $new_post_id, $table['visibility'] );
if ( ! $visibility_saved )
return false;
// at this point, post was successfully added, now get an unused table ID
$table_id = $this->_get_new_table_id();
$this->_update_post_id( $table_id, $new_post_id );
return $table_id;
}
/**
* Create a copy of a table and add it
*
* @since 1.0.0
*
* @param string $table_id ID of the table to be copied
* @return mixed False on error, string table ID of the new table on success
*/
public function copy( $table_id ) {
$table = $this->load( $table_id );
if ( false === $table )
return false;
// Adjust name of copied table
if ( '' == trim( $table['name'] ) )
$table['name'] = __( '(no name)', 'tablepress' );
$table['name'] = sprintf( __( 'Copy of %s', 'tablepress' ), $table['name'] );
// Set Last Editor to user who copied
$table['options']['last_editor'] = get_current_user_id();
// Merge this data into an empty table template
$table = $this->prepare_table( $this->get_table_template(), $table, false );
if ( false === $table )
return false;
// Add the copied table
return $this->add( $table );
}
/**
* Delete a table (and its options)
*
* @since 1.0.0
*
* @param string $table_id ID of the table to be deleted
* @return bool False on error, true on success
*/
public function delete( $table_id ) {
if ( ! $this->table_exists( $table_id ) )
return false;
$post_id = $this->_get_post_id( $table_id ); // no !false check necessary, as this is covered by table_exists() check above
$deleted = $this->model_post->delete( $post_id ); // Post Meta fields will be deleted automatically by that function
if ( false === $deleted )
return false;
// if post was deleted successfully, remove the table ID from the list of tables
$this->_remove_post_id( $table_id );
// invalidate table output caches that belong to this table
$this->_invalidate_table_output_cache( $table_id );
// Flush caching plugins' caches
$this->_flush_caching_plugins_caches();
return true;
}
/**
* Delete all tables
*
* @since 1.0.0
*/
public function delete_all() {
$tables = $this->tables->get();
if ( empty( $tables['table_post'] ) )
return;
foreach ( $tables['table_post'] as $table_id => $post_id ) {
$table_id = (string)$table_id;
$this->model_post->delete( $post_id ); // Post Meta fields will be deleted automatically by that function
unset( $tables['table_post'][ $table_id ] );
$this->_invalidate_table_output_cache( $table_id ); // invalidate table output caches that belong to this table
}
$this->tables->update( $tables );
$this->_flush_caching_plugins_caches(); // Flush caching plugins' caches
}
/**
* Check if a table ID exists in the list of tables (this does not guarantee that the post with the table data exists!)
*
* @since 1.0.0
*
* @param string $table_id Table ID
* @return bool Whether the table ID exists
*/
public function table_exists( $table_id ) {
$table_post = $this->tables->get( 'table_post' );
return isset( $table_post[ $table_id ] );
}
/**
* Count the number of tables from either just the list, or by also counting the posts in the database
*
* @since 1.0.0
*
* @param bool $single_value (optional) Whether to return just the number of tables from the list, or also count in the database
* @return bool int|array Number of Tables (if $single_value), or array of Numbers from list/DB (if ! $single_value)
*/
public function count_tables( $single_value = true ) {
$count_list = count( $this->tables->get( 'table_post' ) );
if ( $single_value )
return $count_list;
$count_db = $this->model_post->count_posts();
return array( 'list' => $count_list, 'db' => $count_db );
}
/**
* Delete all transients used for output caching of a table (e.g. when the table is updated or deleted)
*
* @since 1.0.0
*
* @param string $table_id Table ID
*/
protected function _invalidate_table_output_cache( $table_id ) {
$caches_list_transient_name = 'tablepress_c_' . md5( $table_id );
$caches_list = get_transient( $caches_list_transient_name );
if ( false !== $caches_list ) {
$caches_list = json_decode( $caches_list, true );
foreach ( $caches_list as $cache_transient_name ) {
delete_transient( $cache_transient_name );
}
}
delete_transient( $caches_list_transient_name );
}
/**
* Flush the caches of the plugins W3 Total Cache, WP Supercache, and Cachify
*
* @since 1.0.0
*/
public function _flush_caching_plugins_caches() {
if ( ! apply_filters( 'tablepress_flush_caching_plugins_caches', true ) )
return;
// W3 Total Cache
if ( function_exists( 'w3tc_pgcache_flush' ) )
w3tc_pgcache_flush();
// WP Super Cache
if ( function_exists( 'wp_cache_clear_cache' ) )
wp_cache_clear_cache();
// Cachify
do_action( 'cachify_flush_cache' );
}
/**
* Get the post ID of a given table ID (if the table ID exists)
*
* @since 1.0.0
*
* @param string $table_id Table ID
* @return int Post ID on success, false on error
*/
protected function _get_post_id( $table_id ) {
$table_post = $this->tables->get( 'table_post' );
if ( isset( $table_post[ $table_id ] ) )
return $table_post[ $table_id ];
else
return false;
}
/**
* Update/Add a post ID for a given table ID, and sort the list of tables by their key in natural sort order
*
* @since 1.0.0
*
* @param string $table_id Table ID
* @param int $post_id Post ID
*/
protected function _update_post_id( $table_id, $post_id ) {
$tables = $this->tables->get();
$tables['table_post'][ $table_id ] = $post_id;
uksort( $tables['table_post'], 'strnatcasecmp' );
$this->tables->update( $tables );
}
/**
* Remove a table ID / post ID connection from the list of tables
*
* @since 1.0.0
*
* @param string $table_id Table ID
*/
protected function _remove_post_id( $table_id ) {
$tables = $this->tables->get();
unset( $tables['table_post'][ $table_id ] );
$this->tables->update( $tables );
}
/**
* Change the table ID of a table
*
* @since 1.0.0
*
* @param string $old_id Old table ID
* @param string $new_id New table ID
* @return bool True on success, false on error
*/
public function change_table_id( $old_id, $new_id ) {
$post_id = $this->_get_post_id( $old_id );
if ( false === $post_id )
return false;
// Check new ID for correct format (string from letters, numbers, -, and _ only, except the '0' string)
if ( empty( $new_id ) || 0 !== preg_match( '/[^a-zA-Z0-9_-]/', $new_id ) )
return false;
if ( $this->table_exists( $new_id ) )
return false;
$this->_update_post_id( $new_id, $post_id );
$this->_remove_post_id( $old_id );
return true;
}
/**
* Get an unused table ID (e.g. for a new table)
*
* @since 1.0.0
*
* @return string Unused table ID (e.g. for a new table)
*/
protected function _get_new_table_id() {
$tables = $this->tables->get();
// need to check new ID candidate in a loop, because a higher ID might already be in use, if a table ID was changed manually
do {
$tables['last_id'] ++;
} while ( $this->table_exists( $tables['last_id'] ) );
$this->tables->update( $tables );
return (string) $tables['last_id'];
}
/**
* Get the template for an empty table
*
* Important: This scheme is versioned via TablePress::table_scheme_version; changes likely need a version update!
*
* @since 1.0.0
*
* @return array Empty table
*/
public function get_table_template() {
// Attention: Array keys have to be lowercase, to make it possible to match them with Shortcode attributes!
$table = array(
'id' => false,
'name' => '',
'description' => '',
'data' => array( array( '' ) ), // one empty cell
// 'created' => current_time( 'mysql' ),
'last_modified' => current_time( 'mysql' ),
'author' => get_current_user_id(),
'options' => array(
'last_editor' => get_current_user_id(),
'table_head' => true,
'table_foot' => false,
'alternating_row_colors' => true,
'row_hover' => true,
'print_name' => false,
'print_name_position' => 'above',
'print_description' => false,
'print_description_position' => 'below',
'extra_css_classes' => '',
// DataTables JavaScript library
'use_datatables' => true,
'datatables_sort' => true,
'datatables_filter' => true,
'datatables_paginate' => true,
'datatables_lengthchange' => true,
'datatables_paginate_entries' => 10,
'datatables_info' => true,
'datatables_scrollx' => false,
'datatables_custom_commands' => ''
),
'visibility' => array(
'rows' => array( 1 ), // one visbile row
'columns' => array( 1 ) // one visible column
)
);
return apply_filters( 'tablepress_table_template', $table );
}
/**
* Combine two tables (e.g. an existing one with the updated data, or an empty one with new data)
* Performs consistency checks on data and visibility settings
*
* @since 1.0.0
*
* @param array $table Table to merge into
* @param array $new_table Table to merge
* @param bool $table_size_check (optional) Whether to check the number of rows and columns (e.g. not necessary for added or copied tables)
* @param bool $extended_visibility_check (optional) Whether to check the counts of hidden rows and columns (only possible for Admin_AJAX controller as of now)
* @return array|bool Merged table on success, false on error
*/
public function prepare_table( $table, $new_table, $table_size_check = true, $extended_visibility_check = false ) {
// Table ID must be the same (if there was an ID already)
if ( false !== $table['id'] ) {
if ( $table['id'] !== $new_table['id'] )
return false;
}
// Name, description, and data array need to exist, data must not be empty, the others could be ''
if ( ! isset( $new_table['name'] )
|| ! isset( $new_table['description'] )
|| empty( $new_table['data'] )
|| empty( $new_table['data'][0] ) )
return false;
// Visibility needs to exist
if ( ! isset( $new_table['visibility'] )
|| ! isset( $new_table['visibility']['rows'] )
|| ! isset( $new_table['visibility']['columns'] ) )
return false;
$new_table['visibility']['rows'] = array_map( 'intval', $new_table['visibility']['rows'] );
$new_table['visibility']['columns'] = array_map( 'intval', $new_table['visibility']['columns'] );
// Check dimensions of table data array (not done for newly added, copied, or imported tables)
if ( $table_size_check ) {
if ( empty( $new_table['number'] )
|| ! isset( $new_table['number']['rows'] )
|| ! isset( $new_table['number']['columns'] ) )
return false;
// Table data needs to be ok, and have the correct number of rows and columns
$new_table['number']['rows'] = intval( $new_table['number']['rows'] );
$new_table['number']['columns'] = intval( $new_table['number']['columns'] );
if ( 0 === $new_table['number']['rows']
|| 0 === $new_table['number']['columns']
|| $new_table['number']['rows'] !== count( $new_table['data'] )
|| $new_table['number']['columns'] !== count( $new_table['data'][0] ) )
return false;
// Visibility also needs to have correct dimensions
if ( $new_table['number']['rows'] !== count( $new_table['visibility']['rows'] )
|| $new_table['number']['columns'] !== count( $new_table['visibility']['columns'] ) )
return false;
if ( $extended_visibility_check ) { // only for Admin_AJAX controller
if ( ! isset( $new_table['number']['hidden_rows'] )
|| ! isset( $new_table['number']['hidden_columns'] ) )
return false;
$new_table['number']['hidden_rows'] = intval( $new_table['number']['hidden_rows'] );
$new_table['number']['hidden_columns'] = intval( $new_table['number']['hidden_columns'] );
// count hidden and visible rows
$num_visible_rows = count( array_keys( $new_table['visibility']['rows'], 1 ) );
$num_hidden_rows = count( array_keys( $new_table['visibility']['rows'], 0 ) );
// Check number of hidden and visible rows
if ( $new_table['number']['hidden_rows'] !== $num_hidden_rows
|| ( $new_table['number']['rows'] - $new_table['number']['hidden_rows'] ) !== $num_visible_rows )
return false;
// count hidden and visible columns
$num_visible_columns = count( array_keys( $new_table['visibility']['columns'], 1 ) );
$num_hidden_columns = count( array_keys( $new_table['visibility']['columns'], 0 ) );
// Check number of hidden and visible columns
if ( $new_table['number']['hidden_columns'] !== $num_hidden_columns
|| ( $new_table['number']['columns'] - $new_table['number']['hidden_columns'] ) !== $num_visible_columns )
return false;
}
}
// All checks were successful, replace original values with new ones
// $table['id'] is either false (and remains false) or already equal to $new_table['id']
$table['new_id'] = isset( $new_table['new_id'] ) ? $new_table['new_id'] : $table['id'];
$table['name'] = $new_table['name'];
$table['description'] = $new_table['description'];
$table['data'] = $new_table['data'];
// $table['author'] = get_current_user_id(); // we don't want this, as it would override the original author
// $table['created'] = current_time( 'mysql' ); // we don't want this, as it would override the original datetime
$table['last_modified'] = current_time( 'mysql' );
$table['options']['last_editor'] = get_current_user_id();
// Table Options
if ( isset( $new_table['options'] ) ) { // is for example not set for newly added tables
// specials check for certain options
if ( isset( $new_table['options']['extra_css_classes'] ) ) {
$new_table['options']['extra_css_classes'] = explode( ' ', $new_table['options']['extra_css_classes'] );
$new_table['options']['extra_css_classes'] = array_map( 'sanitize_html_class', $new_table['options']['extra_css_classes'] );
$new_table['options']['extra_css_classes'] = array_unique( $new_table['options']['extra_css_classes'] );
$new_table['options']['extra_css_classes'] = trim( implode( ' ', $new_table['options']['extra_css_classes'] ) );
}
if ( isset( $new_table['options']['datatables_paginate_entries'] ) ) {
$new_table['options']['datatables_paginate_entries'] = intval( $new_table['options']['datatables_paginate_entries'] );
if ( $new_table['options']['datatables_paginate_entries'] < 1 )
$new_table['options']['datatables_paginate_entries'] = 10; // default value
}
// merge new options
$default_table = $this->get_table_template();
$table['options'] = array_intersect_key( $table['options'], $default_table['options'] );
$new_table['options'] = array_intersect_key( $new_table['options'], $default_table['options'] );
$table['options'] = array_merge( $table['options'], $new_table['options'] );
}
// Table Visibility
$table['visibility']['rows'] = $new_table['visibility']['rows'];
$table['visibility']['columns'] = $new_table['visibility']['columns'];
return $table;
}
/**
* Save the table options of a table (in a post meta field of the table's post)
*
* @since 1.0.0
*
* @param int $post_id Post ID
* @param array $options Table options
* @return bool True on success, false on error
*/
protected function _add_table_options( $post_id, $options ) {
$options = json_encode( $options );
$success = $this->model_post->add_meta_field( $post_id, $this->table_options_field_name, $options );
return $success;
}
/**
* Update the table options of a table (in a post meta field in the table's post)
*
* @since 1.0.0
*
* @param int $post_id Post ID
* @param array $options Table options
* @return bool True on success, false on error
*/
protected function _update_table_options( $post_id, $options ) {
$options = json_encode( $options );
// we need to pass the previous value to make sure that an update takes place, to really get a successful (true) return result from the WP API
$prev_options = json_encode( $this->_get_table_options( $post_id ) );
$success = $this->model_post->update_meta_field( $post_id, $this->table_options_field_name, $options, $prev_options );
return $success;
}
/**
* Get the table options of a table (from a post meta field of the table's post)
*
* @since 1.0.0
*
* @param int $post_id Post ID
* @return array Table options on success, empty array on error
*/
protected function _get_table_options( $post_id ) {
$options = $this->model_post->get_meta_field( $post_id, $this->table_options_field_name );
if ( empty( $options ) )
return array();
$options = json_decode( $options, true );
return $options;
}
/**
* Save the table visibility of a table (in a post meta field of the table's post)
*
* @since 1.0.0
*
* @param int $post_id Post ID
* @param array $visibility Table visibility
* @return bool True on success, false on error
*/
protected function _add_table_visibility( $post_id, $visibility ) {
$visibility = json_encode( $visibility );
$success = $this->model_post->add_meta_field( $post_id, $this->table_visibility_field_name, $visibility );
return $success;
}
/**
* Update the table visibility of a table (in a post meta field in the table's post)
*
* @since 1.0.0
*
* @param int $post_id Post ID
* @param array $visibility Table visibility
* @return bool True on success, false on error
*/
protected function _update_table_visibility( $post_id, $visibility ) {
$visibility = json_encode( $visibility );
// we need to pass the previous value to make sure that an update takes place, to really get a successful (true) return result from the WP API
$prev_visibility = json_encode( $this->_get_table_visibility( $post_id ) );
$success = $this->model_post->update_meta_field( $post_id, $this->table_visibility_field_name, $visibility, $prev_visibility );
return $success;
}
/**
* Get the table visibility of a table (from a post meta field of the table's post)
*
* @since 1.0.0
*
* @param int $post_id Post ID
* @return array Table visibility on success, empty array on error
*/
protected function _get_table_visibility( $post_id ) {
$visibility = $this->model_post->get_meta_field( $post_id, $this->table_visibility_field_name );
if ( empty( $visibility ) )
return array();
$visibility = json_decode( $visibility, true );
return $visibility;
}
/**
* Merge existing Table Options with default Table Options,
* remove (no longer) existing options, after a table scheme change,
* for all tables
*
* @since 1.0.0
*/
public function merge_table_options_defaults() {
$table_post = $this->tables->get( 'table_post' );
if ( empty( $table_post ) )
return;
// load all table posts with one query, to prime the cache
$this->model_post->load_posts( array_values( $table_post ) );
// get default Table with default Table Options
$default_table = $this->get_table_template();
// go through all tables (this loop now uses the WP cache)
foreach ( $table_post as $table_id => $post_id ) {
$table_options = $this->_get_table_options( $post_id );
// remove old (i.e. no longer existing) Table Options:
$table_options = array_intersect_key( $table_options, $default_table['options'] );
// merge into new Table Options:
$table_options = array_merge( $default_table['options'], $table_options );
$this->_update_table_options( $post_id, $table_options );
}
}
/**
* Merge changes made for TablePress 0.6-beta:
* Table Name/Table Description
*
* @since 0.6-beta
*/
public function merge_table_options_tp06() {
$table_post = $this->tables->get( 'table_post' );
if ( empty( $table_post ) )
return;
// go through all tables
foreach ( $table_post as $table_id => $post_id ) {
$table_options = $this->_get_table_options( $post_id );
// Move "Print Name" to new format
$print_name = in_array( $table_options['print_name'], array( 'above', 'below' ), true );
if ( $print_name )
$table_options['print_name_position'] = $table_options['print_name'];
$table_options['print_name'] = $print_name;
// Move "Print Description" to new format
$print_description = in_array( $table_options['print_description'], array( 'above', 'below' ), true );
if ( $print_description )
$table_options['print_description_position'] = $table_options['print_description'];
$table_options['print_description'] = $print_description;
$this->_update_table_options( $post_id, $table_options );
}
}
/**
* Merge changes made for TablePress 0.8-beta:
* Conversion of parameter "datatables_scrollX" to "datatables_scrollx"
* Fixes a bug that affects about the first 600 downloaders of 0.8-beta
*
* @since 0.8-beta
*/
public function merge_table_options_tp08() {
$table_post = $this->tables->get( 'table_post' );
if ( empty( $table_post ) )
return;
// go through all tables
foreach ( $table_post as $table_id => $post_id ) {
$table_options = $this->_get_table_options( $post_id );
// Convert parameter "datatables_scrollX" to "datatables_scrollx"
if ( isset( $table_options['datatables_scrollX'] ) && ! isset( $table_options['datatables_scrollx'] ) )
$table_options['datatables_scrollx'] = $table_options['datatables_scrollX'];
$this->_update_table_options( $post_id, $table_options );
}
}
/**
* Invalidate all table output caches, e.g. after a plugin update
* For TablePress 0.9-RC and onwards.
*
* @since 0.9-RC
*/
public function invalidate_table_output_caches() {
$table_post = $this->tables->get( 'table_post' );
if ( empty( $table_post ) )
return;
// go through all tables
foreach ( $table_post as $table_id => $post_id ) {
$this->_invalidate_table_output_cache( $table_id );
}
}
/**
* Invalidate all table output caches, e.g. after a plugin update
* For TablePress pre-0.9-RC updates
*
* @since 0.9-RC
*/
public function invalidate_table_output_caches_tp09() {
$table_post = $this->tables->get( 'table_post' );
if ( empty( $table_post ) )
return;
// go through all tables
foreach ( $table_post as $table_id => $post_id ) {
$caches_list_transient_name = 'tablepress_c_' . md5( $table_id );
$caches_list = get_transient( $caches_list_transient_name );
if ( is_array( $caches_list ) ) {
foreach ( $caches_list as $cache_transient_name => $dummy_value ) {
delete_transient( $cache_transient_name );
}
}
delete_transient( $caches_list_transient_name );
}
}
/**
* Delete the WP_Option of the model
*
* @since 1.0.0
*/
public function destroy() {
$this->tables->delete();
}
} // class TablePress_Table_Model