2019-09-14 15:42:34 +00:00
< ? php
/*
Plugin Name : TablePress Extension : Pods tables
Plugin URI : https :// code . studioinfinity . org / glen / tablepress - pods
Description : Custom Extension for TablePress to incorporate Pods information in tables
2021-02-08 22:14:13 +00:00
Version : 0.2 . 13
2019-09-14 15:42:34 +00:00
Author : Glen Whitney
2021-02-08 20:33:53 +00:00
Author URI : http :// studioinfinity . org /
2019-09-14 15:42:34 +00:00
*/
/* 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 .
*/
/*
* Usage and possible parameters :
* [ table id = 1 pod_name = " mypod " pod_where = " t.myfield = 'important' " / ]
*
* Each row of the table which contains a Pods " magic tag " anywhere is expanded
* into one row for each of the pod records returned by
* pods ( < pod_name > ) -> find ( < pod_where > ), with all of the magic tags in the row
* expanded for the corresponding record .
*
* The expansion can be controlled by the following " pseudo-shortcodes " which
* must occur at the beginning of the first column of the row ( you may want to
* dedicate a hidden column just for this purpose if you are making use of these )
* [ once ] -- this row expands only into a single row ( corresponding to the
* first record returned by the find () call ), with magic
* tags expanded
* [ literal ] -- do not expand this row , except for removing the [ literal ]
* designation , even though it contains magic tags ; hence , the
* magic tags will appear in the result .
*
* [ table id = 1 pod_name = " mypod " pod_dump = true pod_where = " t.myfield = 3 " / ]
*
* * Ignores * the contents of the table altogether , and replaces it with a
* simple dump of the ID , date , title , author , permalink , and all custom
* Pods fields for each record in a Pods custom post type . Note that the
* taxonomies , if any , of the post type will not be shown . Useful mainly for
* seeing what is present in your Pod ; for any presentation tables you will
* most likely want to use the first form .
*
*/
add_filter ( 'tablepress_shortcode_table_default_shortcode_atts' ,
'playground_add_shortcode_parameter_pods' );
add_filter ( 'tablepress_table_raw_render_data' , 'playground_expand_pod' , 10 , 2 );
2021-02-08 18:34:03 +00:00
add_filter ( 'tablepress_admin_view_actions' , 'playground_add_export_pod_action' );
2021-02-08 18:51:28 +00:00
add_filter ( 'tablepress_load_file_full_path' , 'playground_exportpods_path' , 10 , 3 );
2021-02-08 20:06:36 +00:00
add_filter ( 'tablepress_view_data' , 'playground_exportpods_data' , 10 , 2 );
2021-02-08 20:33:53 +00:00
add_action ( 'admin_post_tablepress_exportpods' , 'playground_handle_exportpods' );
2019-09-14 15:42:34 +00:00
function playground_add_shortcode_parameter_pods ( $default_atts ) {
2021-02-08 17:36:52 +00:00
$default_atts [ 'pod_name' ] = '' ;
2019-09-14 15:42:34 +00:00
$default_atts [ 'pod_dump' ] = '' ;
$default_atts [ 'pod_where' ] = '' ;
2021-02-08 17:36:52 +00:00
return $default_atts ;
}
function playground_add_export_pod_action ( $view_actions ) {
$view_actions [ 'exportpods' ] = array (
'show_entry' => true ,
'page_title' => __ ( 'Export Pods Table' , 'tablepress' ),
'admin_menu_title' => __ ( 'Export Pods Table' , 'tablepress' ),
'nav_tab_title' => _x ( 'Export Pods' , 'navigation bar' , 'tablepress' ),
'required_cap' => 'tablepress_export_tables' ,
);
return $view_actions ;
2019-09-14 15:42:34 +00:00
}
2021-02-08 18:34:03 +00:00
function playground_exportpods_path ( $fullpath , $filename , $directory ) {
if ( $filename !== 'view-exportpods.php' ) return $fullpath ;
return plugin_dir_path ( __FILE__ ) . $filename ;
}
2021-02-08 20:06:36 +00:00
function playground_exportpods_data ( $data , $act ) {
2021-02-08 20:33:53 +00:00
if ( $act !== 'exportpods' ) return $data ;
2021-02-08 20:06:36 +00:00
// Load all table IDs without priming the post meta cache, as table options/visibility are not needed.
$data [ 'table_ids' ] = TablePress :: $model_table -> load_all ( false );
$data [ 'tables_count' ] = TablePress :: $model_table -> count_tables ();
if ( ! empty ( $_GET [ 'table_id' ] ) ) {
$data [ 'export_ids' ] = explode ( ',' , $_GET [ 'table_id' ] );
} else {
// Just show empty export form.
$data [ 'export_ids' ] = array ();
}
$exporter = TablePress :: load_class ( 'TablePress_Export' , 'class-export.php' , 'classes' );
2021-02-08 21:07:30 +00:00
$data [ 'zip_support_available' ] = false ;
2021-02-08 20:06:36 +00:00
$data [ 'export_formats' ] = $exporter -> export_formats ;
$data [ 'export_format' ] = ( ! empty ( $_GET [ 'export_format' ] ) ) ? $_GET [ 'export_format' ] : false ;
2021-02-08 21:07:30 +00:00
$data [ 'csv_delimiters' ] = $exporter -> csv_delimiters ;
2021-02-08 20:06:36 +00:00
$data [ 'csv_delimiter' ] = ( ! empty ( $_GET [ 'csv_delimiter' ] ) ) ? $_GET [ 'csv_delimiter' ] : _x ( ',' , 'Default CSV delimiter in the translated language (";", ",", or "tab")' , 'tablepress' );
2021-02-08 21:11:47 +00:00
$data [ 'pods' ] = pods_api () -> load_pods ();
2021-02-08 21:07:30 +00:00
$data [ 'pod_name' ] = ( ! empty ( $_GET [ 'pod_name' ] ) ) ? $_GET [ 'pod_name' ] : false ;
2021-02-08 20:06:36 +00:00
return $data ;
}
2019-09-14 15:42:34 +00:00
function playground_expand_pod ( $table , $render_options ) {
2021-02-08 18:34:03 +00:00
if ( empty ( $render_options [ 'pod_name' ])) return $table ;
2019-09-14 15:42:34 +00:00
$pod_params = array ( 'limit' =>- 1 );
if ( ! empty ( $render_options [ 'pod_where' ])) {
$pod_params [ 'where' ] = $render_options [ 'pod_where' ];
}
$pod = pods ( $render_options [ 'pod_name' ], $pod_params );
$ndata = array ();
$rvis = array ();
$cvis = array ();
if ( empty ( $render_options [ 'pod_dump' ])) {
# Standard case: expand rows with magic tags into multiple rows,
# one for each record in $pod, controlled by the pseudo-shortcodes
$cvis = $table [ 'visibility' ][ 'columns' ];
$orig_rvis = $table [ 'visibility' ][ 'rows' ];
foreach ( $table [ 'data' ] as $row_idx => $row ) {
# First, check for the [literal] code since nothing much to do then
if ( 0 === strpos ( $row [ 0 ], '[literal]' )) {
$row [ 0 ] = substr ( $row [ 0 ], 9 );
$ndata [] = $row ;
$rvis [] = $orig_rvis [ $row_idx ];
continue ;
}
# Similarly, if no magic tags, just copy the row.
$wholerow = implode ( '' , $row );
if ( ! preg_match ( '/{@.*}/' , $wholerow )) {
$ndata [] = $row ;
$rvis [] = $orig_rvis [ $row_idx ];
continue ;
}
# OK, we need to expand magic tags in the row. First check for
# the [once] pseudo-shortcode:
$one_timer = FALSE ;
if ( 0 === strpos ( $row [ 0 ], '[once]' )) {
$row [ 0 ] = substr ( $row [ 0 ], 6 );
$one_timer = TRUE ;
}
# Here's the expansion loop
$pod -> reset ();
while ( $pod -> fetch ()) {
$ndata [] = array_map ( function ( $c ) use ( $pod ) {
return $pod -> do_magic_tags ( $c );
}, $row );
$rvis [] = $orig_rvis [ $row_idx ];
if ( $one_timer ) { break ; }
}
} # for each row of the original table
} else { # pod_dump is specified.
$flds = $pod -> fields ();
$hrow = array ( 'ID' , 'Date' , 'Title' , 'Author' , 'Permalink' );
$cvis = array ( TRUE , TRUE , TRUE , TRUE , TRUE );
$frow = array ();
foreach ( $flds as $fkey => $finfo ) {
$hrow [] = $finfo [ 'label' ];
$cvis [] = TRUE ;
$frow [] = $fkey ;
}
$ndata [] = $hrow ;
$rvis = array ( TRUE );
while ( $pod -> fetch ()) {
$nrow = array ();
$nrow [] = $pod -> field ( 'id' );
$nrow [] = $pod -> field ( 'post_date' );
$nrow [] = $pod -> field ( 'title' );
$nrow [] = get_the_author_meta ( 'display_name' , $pod -> field ( 'author' ));
$nrow [] = $pod -> field ( 'permalink' );
foreach ( $frow as $field_slug ) {
$nrow [] = $pod -> display ( $field_slug );
}
$ndata [] = $nrow ;
$rvis [] = TRUE ;
}
} # do a pod dump
# OK, install the new table information
$table [ 'data' ] = $ndata ;
$table [ 'visibility' ][ 'rows' ] = $rvis ;
$table [ 'visibility' ][ 'columns' ] = $cvis ;
return $table ;
}
2021-02-08 20:33:53 +00:00
function playground_handle_exportpods () {
2021-02-08 21:34:46 +00:00
TablePress :: check_nonce ( 'exportpods' );
2021-02-08 20:33:53 +00:00
if ( ! current_user_can ( 'tablepress_export_tables' ) ) {
wp_die ( __ ( 'Sorry, you are not allowed to access this page.' , 'default' ), 403 );
}
if ( empty ( $_POST [ 'export' ] ) || ! is_array ( $_POST [ 'export' ] ) ) {
TablePress :: redirect ( array ( 'action' => 'export' , 'message' => 'error_export' ) );
} else {
$export = wp_unslash ( $_POST [ 'export' ] );
}
2021-02-08 22:14:13 +00:00
$real_export = TablePress :: url ( array ( 'action' => 'export' , 'export' => $export ), false , 'admin-post.php' );
$nonced_export = add_query_arg ( '_wpnonce' , wp_create_nonce ( TablePress :: nonce ( 'export' ) ), $real_export );
wp_redirect ( $nonced_export );
2021-02-08 21:34:46 +00:00
}
2021-02-08 21:54:50 +00:00
__halt_compiler ();
2021-02-08 20:33:53 +00:00
$exporter = TablePress :: load_class ( 'TablePress_Export' , 'class-export.php' , 'classes' );
if ( empty ( $export [ 'tables' ] ) ) {
TablePress :: redirect ( array ( 'action' => 'export' , 'message' => 'error_export' ) );
}
if ( empty ( $export [ 'format' ] ) || ! isset ( $exporter -> export_formats [ $export [ 'format' ] ] ) ) {
TablePress :: redirect ( array ( 'action' => 'export' , 'message' => 'error_export' ) );
}
if ( empty ( $export [ 'csv_delimiter' ] ) ) {
// Set a value, so that the variable exists.
$export [ 'csv_delimiter' ] = '' ;
}
if ( 'csv' === $export [ 'format' ] && ! isset ( $exporter -> csv_delimiters [ $export [ 'csv_delimiter' ] ] ) ) {
TablePress :: redirect ( array ( 'action' => 'export' , 'message' => 'error_export' ) );
}
// Use list of tables from concatenated field if available (as that's hopefully not truncated by Suhosin, which is possible for $export['tables']).
$tables = ( ! empty ( $export [ 'tables_list' ] ) ) ? explode ( ',' , $export [ 'tables_list' ] ) : $export [ 'tables' ];
// Determine if ZIP file support is available.
if ( $exporter -> zip_support_available
&& ( ( isset ( $export [ 'zip_file' ] ) && 'true' === $export [ 'zip_file' ] ) || count ( $tables ) > 1 ) ) {
// Export to ZIP only if ZIP is desired or if more than one table were selected (mandatory then).
$export_to_zip = true ;
} else {
$export_to_zip = false ;
}
if ( ! $export_to_zip ) {
// This is only possible for one table, so take the first one.
if ( ! current_user_can ( 'tablepress_export_table' , $tables [ 0 ] ) ) {
wp_die ( __ ( 'Sorry, you are not allowed to access this page.' , 'default' ), 403 );
}
// Load table, with table data, options, and visibility settings.
$table = TablePress :: $model_table -> load ( $tables [ 0 ], true , true );
if ( is_wp_error ( $table ) ) {
TablePress :: redirect ( array ( 'action' => 'export' , 'message' => 'error_load_table' , 'export_format' => $export [ 'format' ], 'csv_delimiter' => $export [ 'csv_delimiter' ] ) );
}
if ( isset ( $table [ 'is_corrupted' ] ) && $table [ 'is_corrupted' ] ) {
TablePress :: redirect ( array ( 'action' => 'export' , 'message' => 'error_table_corrupted' , 'export_format' => $export [ 'format' ], 'csv_delimiter' => $export [ 'csv_delimiter' ] ) );
}
$download_filename = sprintf ( '%1$s-%2$s-%3$s.%4$s' , $table [ 'id' ], $table [ 'name' ], date ( 'Y-m-d' ), $export [ 'format' ] );
$download_filename = sanitize_file_name ( $download_filename );
// Export the table.
$export_data = $exporter -> export_table ( $table , $export [ 'format' ], $export [ 'csv_delimiter' ] );
/**
* Filter the exported table data .
*
* @ since 1.6 . 0
*
* @ param string $export_data The exported table data .
* @ param array $table Table to be exported .
* @ param string $export_format Format for the export ( 'csv' , 'html' , 'json' ) .
* @ param string $csv_delimiter Delimiter for CSV export .
*/
$export_data = apply_filters ( 'tablepress_export_data' , $export_data , $table , $export [ 'format' ], $export [ 'csv_delimiter' ] );
$download_data = $export_data ;
} else {
// Zipping can use a lot of memory and execution time, but not this much hopefully.
/** This filter is documented in the WordPress file wp-admin/admin.php */
@ ini_set ( 'memory_limit' , apply_filters ( 'admin_memory_limit' , WP_MAX_MEMORY_LIMIT ) );
@ set_time_limit ( 300 );
$zip_file = new ZipArchive ();
$download_filename = sprintf ( 'tablepress-export-%1$s-%2$s.zip' , date_i18n ( 'Y-m-d-H-i-s' ), $export [ 'format' ] );
$download_filename = sanitize_file_name ( $download_filename );
$full_filename = wp_tempnam ( $download_filename );
if ( true !== $zip_file -> open ( $full_filename , ZIPARCHIVE :: OVERWRITE ) ) {
@ unlink ( $full_filename );
TablePress :: redirect ( array ( 'action' => 'export' , 'message' => 'error_create_zip_file' , 'export_format' => $export [ 'format' ], 'csv_delimiter' => $export [ 'csv_delimiter' ] ) );
}
foreach ( $tables as $table_id ) {
// Don't export tables for which the user doesn't have the necessary export rights.
if ( ! current_user_can ( 'tablepress_export_table' , $table_id ) ) {
continue ;
}
// Load table, with table data, options, and visibility settings.
$table = TablePress :: $model_table -> load ( $table_id , true , true );
// Don't export if the table could not be loaded.
if ( is_wp_error ( $table ) ) {
continue ;
}
// Don't export if the table is corrupted.
if ( isset ( $table [ 'is_corrupted' ] ) && $table [ 'is_corrupted' ] ) {
continue ;
}
$export_data = $exporter -> export_table ( $table , $export [ 'format' ], $export [ 'csv_delimiter' ] );
/** This filter is documented in controllers/controller-admin.php */
$export_data = apply_filters ( 'tablepress_export_data' , $export_data , $table , $export [ 'format' ], $export [ 'csv_delimiter' ] );
$export_filename = sprintf ( '%1$s-%2$s-%3$s.%4$s' , $table [ 'id' ], $table [ 'name' ], date ( 'Y-m-d' ), $export [ 'format' ] );
$export_filename = sanitize_file_name ( $export_filename );
$zip_file -> addFromString ( $export_filename , $export_data );
}
// If something went wrong, or no files were added to the ZIP file, bail out.
if ( ! ZIPARCHIVE :: ER_OK === $zip_file -> status || 0 === $zip_file -> numFiles ) {
$zip_file -> close ();
@ unlink ( $full_filename );
TablePress :: redirect ( array ( 'action' => 'export' , 'message' => 'error_create_zip_file' , 'export_format' => $export [ 'format' ], 'csv_delimiter' => $export [ 'csv_delimiter' ] ) );
}
$zip_file -> close ();
// Load contents of the ZIP file, to send it as a download.
$download_data = file_get_contents ( $full_filename );
@ unlink ( $full_filename );
}
// Send download headers for export file.
header ( 'Content-Description: File Transfer' );
header ( 'Content-Type: application/octet-stream' );
header ( " Content-Disposition: attachment; filename= \" { $download_filename } \" " );
header ( 'Content-Transfer-Encoding: binary' );
header ( 'Expires: 0' );
header ( 'Cache-Control: must-revalidate' );
header ( 'Pragma: public' );
header ( 'Content-Length: ' . strlen ( $download_data ) );
// $filetype = text/csv, text/html, application/json
// header( 'Content-Type: ' . $filetype. '; charset=' . get_option( 'blog_charset' ) );
@ ob_end_clean ();
flush ();
echo $download_data ;
exit ;
2021-02-08 21:34:46 +00:00
}
*/