<?php
/*
Plugin Name: TablePress Extension: DataTables ColRejigger
Plugin URI: https://code.studioinfinity.org/glen/tablepress-datatables-colrejigger
Description: Extension for TablePress to add ColReorder and ColResize to DataTables
Version: 0.2
Author: Glen Whitney (with thanks to Tobias Bäthge)
Author URI: https://studioinfinity.org/
*/

/* Copyright (C) 2018-2019 Glen Whitney

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
Street, Fifth Floor, Boston, MA 02110-1301 , USA.

*/

/*
 * See also http://datatables.net/extensions/colreorder/
 * and https://github.com/smasala/ColResize
 */

/* Shortcode:
 * [table id=1 datatables_colreorder=true /]
 * Make the columns of the table re-orderable by the page visitor (by dragging the headers)
 * with the default options. If any of the more specific reordering options are specified,
 * there is no need for this parameter.
 * [.. datatables_colreorder_realtime=false ..]
 * Suppress the interactive update of the columns during the drag; only reorder the columns
 * once the drag is complete.
 * [.. datatables_colreorder_fixleft=1 ..]
 * Prevent the first column on the left from being moved (or displaced by the motion of
 * another column) in visitor-initiated column reordering
 * [.. datatables_colreorder_fixright=2 ..]
 * Prevent the rightmost two columns from being moved or displaced in column dragging.
 * [table id=1 datatables_colresize=true /]
 * Allow a page visior to change the column widths on the fly by dragging an imaginary handle
 * (indicated by the cursor changing shape) at the right side of each column. Can be combined
 * or not with datatables_colreorder. If any of the more specific resizing options below are
 * specified, there is no need for this parameter.
 * [.. datatables_colresize_minwidth=50 ..]
 * Don't allow any column to become narrower than 50 pixels when resizing.
 * [.. datatables_colresize_scrolly=300 ..]
 * Limit the height of the column-resizable table to 300 pixels, adding a vertical scrollbar
 * so that the visitor can see all of the available rows.
 * [.. datatables_colresize_resizetable=true ..]
 * Grow or shrink the table horizontally to accommodate resized columns. (By default, the
 * overall width of the table remains constant, and width is removed from or added to
 * neighboring columns to accommodate the change in a resized column.)
 */

// Prohibit direct script loading.
defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );

// Init TablePress_DataTables_ColRejigger.
add_action( 'tablepress_run', array( 'TablePress_DataTables_ColRejigger', 'init' ) );
// TablePress_DataTables_ColRejigger::init_update_checker();

/**
 * TablePress Extension: DataTables ColRejigger
 * @author Glen Whitney
 * @since 0.1
 */
class TablePress_DataTables_ColRejigger {

	/**
	 * Plugin slug.
	 *
	 * @var string
	 * @since 0.1
	 */
	protected static $slug = 'tablepress-datatables-colrejigger';

	/**
	 * Plugin version.
	 *
	 * @var string
	 * @since 0.1
	 */
	protected static $version = '0.1';

//	/**
//	 * Instance of the Plugin Update Checker class.
//	 *
//	 * @var PluginUpdateChecker
//	 * @since 0.0.0
//	 */
//	protected static $plugin_update_checker;

	/**
	 * Initialize the plugin by registering necessary plugin filters and actions.
	 *
	 * @since 0.1
	 */
	public static function init() {
		add_filter( 'tablepress_shortcode_table_default_shortcode_atts', array( __CLASS__, 'shortcode_table_default_shortcode_atts' ) );
		add_filter( 'tablepress_table_js_options', array( __CLASS__, 'table_js_options' ), 10, 3 );
		add_filter( 'tablepress_datatables_parameters', array( __CLASS__, 'datatables_parameters' ), 10, 4 );
	}

//	/**
//	 * Load and initialize the plugin update checker.
//	 *
//	 * @since 0.0.0
//	 */
//	public static function init_update_checker() {
//		require_once dirname( __FILE__ ) . '/libraries/plugin-update-checker.php';
//		self::$plugin_update_checker = PucFactory::buildUpdateChecker(
//			'https://tablepress.org/downloads/extensions/update-check/' . self::$slug . '.json',
//			__FILE__,
//			self::$slug
//		);
//	}

	/**
	 * Add "datatables_colreorder" and "datatables_colresize" and related
     * parameters to the [table /] Shortcode.
	 *
	 * @since 0.1
	 *
	 * @param array $default_atts Default attributes for the TablePress [table /] Shortcode.
	 * @return array Extended attributes for the Shortcode.
	 */
	public static function shortcode_table_default_shortcode_atts( $default_atts ) {
		$default_atts['datatables_colreorder'] = '';
        $default_atts['datatables_colreorder_realtime'] = '';
        $default_atts['datatables_colreorder_fixleft'] = -1;
        $default_atts['datatables_colreorder_fixright'] = -1;
        $default_atts['datatables_colresize'] = '';
        $default_atts['datatables_colresize_minwidth'] = -1;
        $default_atts['datatables_colresize_scrolly'] = -1;
        $default_atts['datatables_colresize_resizetable'] = '';
		return $default_atts;
	}

	/**
	 * Pass configuration from Shortcode parameters to JavaScript arguments.
	 *
	 * @since 0.1
	 *
	 * @param array  $js_options     Current JS options.
	 * @param string $table_id       Table ID.
	 * @param array  $render_options Render Options.
	 * @return array Modified JS options.
	 */
	public static function table_js_options( $js_options, $table_id, $render_options ) {
		$js_options['datatables_colreorder'] = strtolower( $render_options['datatables_colreorder'] );
        $js_options['datatables_colreorder_realtime'] = strtolower($render_options['datatables_colreorder_realtime']);
        $js_options['datatables_colreorder_fixleft'] = intval($render_options['datatables_colreorder_fixleft']);
        $js_options['datatables_colreorder_fixright'] = intval($render_options['datatables_colreorder_fixright']);

        $js_options['datatables_colresize'] = strtolower($render_options['datatables_colresize']);
        $js_options['datatables_colresize_minwidth'] = intval($render_options['datatables_colresize_minwidth']);
        $js_options['datatables_colresize_scrolly'] = intval($render_options['datatables_colresize_scrolly']);
        $js_options['datatables_colresize_resizetable'] = strtolower($render_options['datatables_colresize_resizetable']);
        
        $needJS = FALSE;

		// Change parameters and register files if colreorder is requested.
		if ( $js_options['datatables_colreorder'] != ''
             || $js_options['datatables_colreorder_realtime'] != ''
             || $js_options['datatables_colreorder_fixleft'] > 0
             || $js_options['datatables_colreorder_fixright'] > 0
        ) {
			// Register the JS files.
			$url = plugins_url( "js/dataTables.colReorder.js", __FILE__ );
			wp_enqueue_script( 'tablepress-datatables-colreorder', $url, array( 'tablepress-datatables' ), self::$version, true );

            $needJS = TRUE;
        }
        if ( $js_options['datatables_colresize'] != ''
             || $js_options['datatables_colresize_minwidth'] > 0
             || $js_options['datatables_colresize_scrolly'] > 0
             || $js_options['datatables_colresize_resizetable'] != ''
        ) {
            // Register the JS files.
			$url = plugins_url( "js/dataTables.colResize.js", __FILE__ );
			wp_enqueue_script( 'tablepress-datatables-colresize', $url, array( 'tablepress-datatables' ), self::$version, true );

            $needJS = TRUE;
        }
			// Add the common filter that adds JS for all calls on the page.
        if ( $needJS && ! has_filter( 'tablepress_all_datatables_commands', array( __CLASS__, 'all_datatables_commands' ) )
        ) {
				add_filter( 'tablepress_all_datatables_commands', array( __CLASS__, 'all_datatables_commands' ) );
			}

		return $js_options;
	}

	/**
	 * Evaluate JS parameters and convert them to DataTables parameters.
	 *
	 * @since 0.1
	 *
	 * @param array  $parameters DataTables parameters.
	 * @param string $table_id   Table ID.
	 * @param string $html_id    HTML ID of the table.
	 * @param array  $js_options JS options for DataTables.
	 * @return array Extended DataTables parameters.
	 */
	public static function datatables_parameters( $parameters, $table_id, $html_id, $js_options ) {
		// Construct the DataTables ColReorder config parameter.
		$parameters['colReorder'] = array();
        if ($js_options['datatables_colreorder_realtime'] != '') {
            $parameters['colReorder'][] = "\"realtime\":{$js_options['datatables_colreorder_realtime']}";
        }
        if ($js_options['datatables_colreorder_fixleft'] > 0) {
            $parameters['colReorder'][] = "\"fixedColumnsLeft\":{$js_options['datatables_colreorder_fixleft']}";
        }
        if ($js_options['datatables_colreorder_fixright'] > 0) {
            $parameters['colReorder'][] = "\"fixedColumnsRight\":{$js_options['datatables_colreorder_fixright']}";
        }
        if (empty($parameters['colReorder'])) {
            if ($js_options['datatables_colreorder'] != ''
                && $js_options['datatables_colreorder'] != 'false')
            {
                $parameters['colReorder'] = '"colReorder":true';
            } else {
                unset($parameters['colReorder']);
            }
        } else {
            $parameters['colReorder'] = '"colReorder":{' . implode(',', $parameters['colReorder']) . '}';
        }
        // Construct the DataTables ColResize config parameter.
        $parameters['colResize'] = array();
        if ($js_options['datatables_colresize_minwidth'] > 0) {
            $parameters['colResize'][] = "\"minColumnWidth\":{$js_options['datatables_colresize_minwidth']}";
        }
        if ($js_options['datatables_colresize_scrolly'] > 0) {
            $parameters['colResize'][] = "\"scrollY\":{$js_options['datatables_colresize_scrolly']}";
        }
        if ($js_options['datatables_colresize_resizetable'] != '') {
            if ($js_options['datatables_colresize_resizetable'] != 'false') {
                $parameters['colResize'][] = "\"resizeTable\":true";
            } else {
                $parameters['colResize'][] = "\"resizeTable\":false";
            }
        }
        if (empty($parameters['colResize'])) {
            if ($js_options['datatables_colresize'] != ''
                && ($js_options['datatables_colresize'] != 'false'))
            {
                $parameters['colResize'] = '"colResize":true';
            } else {
                unset($parameters['colResize']);
            }
        } else {
            $parameters['colResize'] = '"colResize":{' . implode(',', $parameters['colResize']) . '}';
        }
        if (isset($parameters['colResize'])) {
            $parameters['autoWidth'] = '"autoWidth":false';
            $parameters['scrollX'] = '"scrollX":false';
        }
		return $parameters;
	}

	/**
	 * Add jQuery code that adds the necessary CSS for the Extension, instead of  loading that CSS from a file on all pages.
	 *
	 * @since 0.1
	 *
	 * @param array $commands The JS commands for the DataTables JS library.
	 * @return array Modified JS commands for the DataTables JS library.
	 */
	public static function all_datatables_commands( $commands ) {
        // First the ColReorder CSS
		$commands = "$('head').append('<style>table.DTCR_clonedTable.dataTable {position: absolute !important; background-color: rgba(255, 255, 255, 0.7); z-index: 202; } div.DTCR_pointer { width: 1px; background-color: #0259C4; z-index: 201;}</style>');\n" . $commands;

        // Now the ColResize CSS
        $commands = "$('head').append('<style>.dt-colresizable-table-wrapper {overflow: auto; width: 100%; position: relative;} .dt-colresizable {height: 0; position: relative; top: 0; z-index: 999;} .dt-colresizable .dt-colresizable-col {display: block; position: absolute; box-sizing: border-box; width: 5px; cursor: ew-resize; z-index: 1000;} .dt-colresizable-table-wrapper.dt-colresizable-with-scroller {overflow-x: auto; overflow-y: hidden;} .dt-colresizable-scroller-wrapper {position: absolute; overflow-y: auto; overflow-x: hidden; width: 100%; right: 0;} .dt-colresizable-scroller-content-wrapper {width: 100%;} .dt-colresizable-scroller-content {width: 100%;} .dt-colresizable-with-scroller table thead,.dt-colresizable-with-scroller table tbody tr {display: table; table-layout: fixed; width: 100%;} .dt-colresizable-with-scroller table tbody {overflow-y: auto; display: block;} .dt-colresizable-table-wrapper table {table-layout: fixed; margin: 0;} .dt-colresizable-table-wrapper table,.dt-colresizable-table-wrapper table th,.dt-colresizable-table-wrapper table {box-sizing: border-box;} .dt-colresizable-table-wrapper table thead th,.dt-colresizable-table-wrapper table tbody td,.dt-colresizable-table-wrapper table tfoot td,.dt-colresizable-table-wrapper table tfoot th {overflow: hidden;}<style>');\n" . $commands;

		return $commands;
	}

} // class TablePress_DataTables_ColRejigger