)->find(), 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 ); add_filter( 'tablepress_admin_view_actions', 'playground_add_export_pod_action'); add_filter( 'tablepress_load_file_full_path', 'playground_exportpods_path', 10, 3); add_filter( 'tablepress_view_data', 'playground_exportpods_data', 10, 2); add_action( 'admin_post_tablepress_exportpods', 'playground_handle_exportpods'); function playground_add_shortcode_parameter_pods( $default_atts ) { $default_atts['pod_name'] = ''; $default_atts['pod_dump'] = ''; $default_atts['pod_where'] = ''; 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; } function playground_exportpods_path( $fullpath, $filename, $directory ) { if ($filename !== 'view-exportpods.php') return $fullpath; return plugin_dir_path( __FILE__ ) . $filename; } function playground_exportpods_data( $data, $act ) { if ($act !== 'exportpods') return $data; // 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' ); $data['zip_support_available'] = false; $data['export_formats'] = $exporter->export_formats; $data['export_format'] = ( ! empty( $_GET['export_format'] ) ) ? $_GET['export_format'] : false; $data['csv_delimiters'] = $exporter->csv_delimiters; $data['csv_delimiter'] = ( ! empty( $_GET['csv_delimiter'] ) ) ? $_GET['csv_delimiter'] : _x( ',', 'Default CSV delimiter in the translated language (";", ",", or "tab")', 'tablepress' ); $data['pods'] = pods_api()->load_pods(); $data['pod_name'] = ( ! empty( $_GET['pod_name'] ) ) ? $_GET['pod_name'] : false; return $data; } function playground_expand_pod( $table, $render_options) { if (empty($render_options['pod_name'])) return $table; $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; } function playground_handle_exportpods () { TablePress::check_nonce( 'exportpods' ); 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'] ); } $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 ); } __halt_compiler(); $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; } */