Compare commits

...

5 Commits
v0.2 ... main

Author SHA1 Message Date
Glen Whitney 3f29c9ea65 fix(README): Link syntax 2022-03-28 23:11:09 +00:00
Glen Whitney 2e4d61b4ac feat: Allow shortcodes in attribute values (#11)
Since wordpress also doesn't allow brackets in attribute values, first
replace `((` and `))` by `[` and `]` before expanding the shortcodes.

Expands the README to full documentation, and renames internal functions
to make more sense.

Resolves #10.

Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Reviewed-on: #11
2022-03-28 23:08:13 +00:00
Glen Whitney 29daaf7da0 doc: Add ezolboo's hint for tables that won't update 2021-08-20 14:53:58 -07:00
Glen Whitney 6811af5970 Add an "Export Pods Table" action to the TablePress menu (#6)
Resolves #1.
Resolves #5.

Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Reviewed-on: #6
Co-Authored-By: Glen Whitney <glen@nobody@nowhere.net>
Co-Committed-By: Glen Whitney <glen@nobody@nowhere.net>
2021-02-09 01:46:00 +00:00
Glen Whitney c18048cb1a Add comments suggeted by Steve Lane to the README file 2020-09-14 04:34:18 +00:00
4 changed files with 355 additions and 19 deletions

View File

@ -12,14 +12,19 @@ This project also assumes that you have installed the Pods plug-in (see https://
The tablepress-pods extension allows you to extract and display in Tablepress tables information from the content in Pods custom post types and taxonomies. If you use Pods and would like to produce tables from the information you've stored in them, this extension is potentially very useful.
##### Installation
##### Installation/Upgrade
Download a release from https://code.studioinfinity.org/glen/tablepress-pods/releases (as a zip file) and install and activate in your WordPress site like any other extension in zip format. (Namely, from your Dashboard, select Plugins, click on add new, and then browse to the downloaded zip file on your disk.)
Download a release from https://code.studioinfinity.org/glen/tablepress-pods/releases (as a zip file) and install and activate in your WordPress site like any other extension in zip format. Namely, from your Dashboard, you can:
1. Select Plugins from the left-hand menu bar.
1. Click on "Add New" and then "Upload Plugin."
1. Browse to the downloaded zip file on your local disk, and click "Install Now."
1. If this is an upgrade, it will show you the currently installed version and the new version and ask you to
confirm the replacement.
##### Usage
This extension operates by adding additional parameters to the [table id=NN /] shortcode. For a list of the provided parameters and their meanings, see the source file tablepress-pods.php. For it to be useful, you then need to go to the
table definition (in the Tablepress tabs from the Dashboard) of the corresponding table and use Pods "magic tags" within that table.
This extension operates by adding additional parameters to the [table id=NN /] shortcode. (See below for a list of the provided parameters and their meanings.) For this extension to be useful, you then need to go to the table definition (in the Tablepress tabs from the Dashboard) of the corresponding table and use Pods "magic tags" within that table.
Here's a brief example:
@ -34,6 +39,49 @@ together with a definition of table 2 in Tablepress that looks like
will produce a two-column table that lists the number and title of each "problem" in the Pod, with the title being a link to the problem.
Note that the {}-expressions allowed in the entries of the table definition include arbitrary Pods "magic tags" syntax. So for example in my installation, which categorizes articles from a periodical, I have such expressions as `{@issue.issue_number}` and `{@section.permalink}`. You can also use the custom postprocessing argument, e.g. `{@source, list_of_links_to_terms}` (where "list_of_links_to_terms" is defined in the functions.php of my theme).
Note that the expansion can also 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]` shortcode parameters supported
- pod_name=NAME
The name of the pod from which records will be extracted.
- pod_where=SPECIFICATION
The SPECIFICATION is passed as the "where" parameter of the `pods()` call that extracts the data, so that it can filter the data returned. For example, `pod_where="t.id = 27"` would return only the record with id 27, whereas if you have a custom field "account" and your POD uses meta-data storage, `pod_where="account.meta_value = 'Sales'"` would return all records where the "account" field has value "Sales".
An example that puts this all together:
`[table id=2 pod_name="budget" pod_where="account.meta_value = 'Sales'"]`
would present the TablePress table with id 2 but with any row in which magic tags appeared into a sequence of rows with those tags expanded, for each record returned by `pods('budget', [ 'where' => "account.meta_value = 'Sales'" ])`
See the [pods() documentation](https://docs.pods.io/code/pods/) for more on possible values for the where parameter.
- pod_dump=true
If this attribute is specified, the shortcode will **ignore** the the contents of the Tablepress table altogether, and replace it with a simple dump of the ID, date, title, author, permalink, and all custom Pods fields for each record in the Pod specified by the pod_name attribute and filtered by the pod_where attribute. Note that the taxonomies, if any, of the post type will not be shown. Useful mainly for debugging and seeing what is present in your Pod; for any presentation tables you will most not want to specify the pod_dump attribute.
##### Further shortcodes in attribute values
It might happen that you would like either the Pod name or some portion of the filter specified by pod_where to be generated by another short code. However, it's not possible to specify brackets as part of the attribute value of a shortcode (due to the way Wordpress parses shortcodes). Thus, to assist with this, this extension will first replace `((` with `[` and `))` with `]` in the attribute values, and then run Wordpress `do_shortcode()` on the result. Therefore, you can write for example
`[table id=2 pod_name="budget" pod_where="account.meta_value = '((current_account))'"]`
to show the records from the "budget" Pod with "account" value equal to whatever the shortcode `[current_account]` expands to.
##### Troubleshooting
If you experience the symptom that the displayed table in your page won't update if you change the data in the Pod that it is reading from, unless you visit the table in Tablepress and re-save it, try adding `cache_table_output=false` to the shortcode that is displaying your table. (Thanks to ezolboo for this information.)
##### Building
To produce an installable zip file, change directories into a git clone of this repository, and simply execute the command in mkplugin.sh (for example, via `bash mkplugin.sh`). Note that currently you must update the version number in the mkplugin.sh command.
To produce an installable zip file, assuming you have cloned this repository:
1. Make sure that you have committed your changes with an update to the Version parameter in tablepress-pods.php.
1. Make sure the current git head is on the commit you want to build.
1. From the top-level directory of the repository, execute `bash mkplugin.sh`.

View File

@ -1 +1,5 @@
git archive HEAD --prefix=tablepress-pods/ --format=zip -o tablepress-pods-0.2.zip
verline=$(grep Version tablepress-pods.php)
cvline=${verline//[$'\t\r\n']}
destfile="tablepress-pods-${cvline#V*: }.zip"
echo "Writing $destfile..."
git archive HEAD --prefix=tablepress-pods/ --format=zip -o $destfile

View File

@ -3,9 +3,9 @@
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
Version: 0.2
Version: 0.4.1
Author: Glen Whitney
Author URI: http ://studioinfinity.org/
Author URI: http://studioinfinity.org/
*/
/* Copyright (C) 2018-2019 Glen Whitney
@ -44,6 +44,11 @@ Street, Fifth Floor, Boston, MA 02110-1301 , USA.
* designation, even though it contains magic tags; hence, the
* magic tags will appear in the result.
*
* Note that in the pod_name and pod_where parameters, `((` and `))` are
* replaced by `[` and `]` respectively and do_shortcode() is run on the
* result, to facilitate the use of shortcodes to specify the values of these
* parameters.
*
* [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
@ -56,24 +61,73 @@ Street, Fifth Floor, Boston, MA 02110-1301 , USA.
*/
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 );
'tbp_pods_add_shortcode_parameter_pods' );
add_filter( 'tablepress_table_raw_render_data', 'tbp_pods_expand_pod', 10, 2 );
add_filter( 'tablepress_admin_view_actions', 'tbp_pods_add_export_pod_action');
add_filter( 'tablepress_load_file_full_path', 'tbp_pods_exportpods_path', 10, 3);
add_filter( 'tablepress_view_data', 'tbp_pods_exportpods_data', 10, 2);
add_action( 'admin_post_tablepress_exportpods', 'tbp_pods_handle_exportpods');
function playground_add_shortcode_parameter_pods( $default_atts ) {
$default_atts['pod_name'] = '';
function tbp_pods_add_shortcode_parameter_pods( $default_atts ) {
$default_atts['pod_name'] = '';
$default_atts['pod_dump'] = '';
$default_atts['pod_where'] = '';
return $default_atts;
return $default_atts;
}
function playground_expand_pod( $table, $render_options) {
if (empty($render_options['pod_name'])) return $table;
function tbp_pods_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 tbp_pods_exportpods_path( $fullpath, $filename, $directory ) {
if ($filename !== 'view-exportpods.php') return $fullpath;
return plugin_dir_path( __FILE__ ) . $filename;
}
function tbp_pods_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 tbp_pods_maybe_shortcodes($value) {
$bracketed = str_replace(array('((', '))'), array('[', ']'), $value);
return do_shortcode($bracketed);
}
function tbp_pods_expand_pod( $table, $render_options) {
if (empty($render_options['pod_name'])) return $table;
$final_pod_name = tbp_pods_maybe_shortcodes($render_options['pod_name']);
$pod_params = array('limit'=>-1);
if (!empty($render_options['pod_where'])) {
$pod_params['where'] = $render_options['pod_where'];
$pod_params['where'] =
tbp_pods_maybe_shortcodes($render_options['pod_where']);
}
$pod = pods($render_options['pod_name'], $pod_params);
$ndata = array();
$pod = pods($final_pod_name, $pod_params);
$ndata = array();
$rvis = array();
$cvis = array();
if (empty($render_options['pod_dump'])) {
@ -128,7 +182,7 @@ function playground_expand_pod( $table, $render_options) {
while ($pod->fetch()) {
$nrow = array();
$nrow[] = $pod->field('id');
$nrow[] = $pod->field('post_date');
$nrow[] = $pod->display('post_date');
$nrow[] = $pod->field('title');
$nrow[] = get_the_author_meta('display_name', $pod->field('author'));
$nrow[] = $pod->field('permalink');
@ -145,3 +199,37 @@ function playground_expand_pod( $table, $render_options) {
$table['visibility']['columns'] = $cvis;
return $table;
}
function tbp_pods_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'] );
}
/* Reset the nonce for forwarding the action */
$_REQUEST['_wpnonce'] = wp_create_nonce( TablePress::nonce( 'export' ) );
/* Set up the filter using the pod params */
$r_opts = array('pod_name' => $export['pod_name'],
'pod_where' => $export['pod_where']
);
if ( isset( $export['pod_dump'] ) ) {
$r_opts['pod_dump'] = true;
}
$filter = function( $data, $tab, $fmt, $delim ) use ($r_opts) {
$newtab = tbp_pods_expand_pod($tab, $r_opts);
$exporter = TablePress::load_class( 'TablePress_Export', 'class-export.php', 'classes' );
return $exporter->export_table( $newtab, $fmt, $delim );
};
/* Temporarily set a filter on exporting */
add_filter( 'tablepress_export_data', $filter, 10, 4);
do_action( 'admin_post_tablepress_export' );
remove_filter( 'tablepress_export_data', $filter, 10 );
}

196
view-exportpods.php Normal file
View File

@ -0,0 +1,196 @@
<?php
/**
* Export Pods Table View
*
* @package tablepress-pods
* @author Tobias Bäthge
* @author Glen Whitney
* @since 0.2.6
*/
// Prohibit direct script loading.
defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
/**
* Export Pods Table View class
* @package tablepress-pods
* @author Tobias Bäthge
* @author Glen Whitney
* @since 0.2.6
*/
class TablePress_ExportPods_View extends TablePress_View {
/**
* Set up the view with data and do things that are specific for this view.
*
* @since 0.2.6
*
* @param string $action Action for this view.
* @param array $data Data for this view.
*/
public function setup( $action, array $data ) {
parent::setup( $action, $data );
$this->process_action_messages( array(
'error_export' => __( 'Error: The export failed.', 'tablepress' ),
'error_load_table' => __( 'Error: This table could not be loaded!', 'tablepress' ),
'error_table_corrupted' => __( 'Error: The internal data of this table is corrupted!', 'tablepress' ),
) );
$this->add_text_box( 'head', array( $this, 'textbox_head' ), 'normal' );
if ( 0 === $data['tables_count'] ) {
$this->add_meta_box( 'no-tables', __( 'Export Tables', 'tablepress' ), array( $this, 'postbox_no_tables' ), 'normal' );
} else {
$this->admin_page->enqueue_script( 'export', array( 'jquery' ) );
$this->add_meta_box( 'export-form', __( 'Export Pods Tables', 'tablepress' ), array( $this, 'postbox_export_form' ), 'normal' );
$this->data['submit_button_caption'] = _x( 'Download Pods Export File', 'button', 'tablepress' );
$this->add_text_box( 'submit', array( $this, 'textbox_submit_button' ), 'submit' );
}
}
/**
* Print the screen head text.
*
* @since 0.2.6
*
* @param array $data Data for this screen.
* @param array $box Information about the text box.
*/
public function textbox_head( array $data, array $box ) {
?>
<p>
<?php _e( 'Exporting a PODS table allows you to use it in other programs, like spreadsheets applications.', 'tablepress' ); ?>
<?php _e( 'Regularly exporting tables is also recommended as a backup of your data.', 'tablepress' ); ?>
</p>
<p>
<?php _e( 'To export, select the table, the PODS parameters, and the desired export format.', 'tablepress' ); ?>
<br />
<?php _e( 'Be aware that for the CSV and HTML formats only the table data, but no table options are exported!', 'tablepress' ); ?>
<?php _e( 'For the JSON format, the table data and the table options are exported.', 'tablepress' ); ?>
</p>
<?php
}
/**
* Print the content of the "No tables found" post meta box.
*
* @since 0.2.6
*
* @param array $data Data for this screen.
* @param array $box Information about the meta box.
*/
public function postbox_no_tables( array $data, array $box ) {
$add_url = TablePress::url( array( 'action' => 'add' ) );
$import_url = TablePress::url( array( 'action' => 'import' ) );
?>
<p><?php _e( 'No tables found.', 'tablepress' ); ?></p>
<p><?php printf( __( 'You should <a href="%1$s">add</a> or <a href="%2$s">import</a> a table to get started!', 'tablepress' ), $add_url, $import_url ); ?></p>
<?php
}
/**
* Print the content of the "Export Tables" post meta box.
*
* @since 0.2.6
*
* @param array $data Data for this screen.
* @param array $box Information about the meta box.
*/
public function postbox_export_form( array $data, array $box ) {
?>
<table class="tablepress-postbox-table fixed">
<tbody>
<tr>
<th class="column-1 top-align" scope="row">
<label for="tables-export"><?php _e( 'Table to Export', 'tablepress' ); ?>:</label>
</th>
<td class="column-2">
<input type="hidden" name="export[tables_list]" id="tables-export-list" value="" />
<?php
$select_size = $data['tables_count'] + 1; // to show at least one empty row in the select
$select_size = max( $select_size, 3 );
$select_size = min( $select_size, 12 );
?>
<select id="tables-export" name="export[tables][]"<?php echo $size_multiple; ?>>
<?php
foreach ( $data['table_ids'] as $table_id ) {
// Load table, without table data, options, and visibility settings.
$table = TablePress::$model_table->load( $table_id, false, false );
if ( ! current_user_can( 'tablepress_export_table', $table['id'] ) ) {
continue;
}
if ( '' === trim( $table['name'] ) ) {
$table['name'] = __( '(no name)', 'tablepress' );
}
$text = esc_html( sprintf( __( 'ID %1$s: %2$s', 'tablepress' ), $table['id'], $table['name'] ) );
$selected = selected( true, in_array( $table['id'], $data['export_ids'], true ), false );
echo "<option{$selected} value=\"{$table['id']}\">{$text}</option>";
}
?>
</select>
</td>
</tr>
<tr>
<th class="column-1" scope="row"><label for="tables-export-format"><?php _e( 'Export Format', 'tablepress' ); ?>:</label></th>
<td class="column-2">
<select id="tables-export-format" name="export[format]">
<?php
foreach ( $data['export_formats'] as $format => $name ) {
$selected = selected( $format, $data['export_format'], false );
echo "<option{$selected} value=\"{$format}\">{$name}</option>";
}
?>
</select>
</td>
</tr>
<tr>
<th class="column-1" scope="row"><label for="tables-export-csv-delimiter"><?php _e( 'CSV Delimiter', 'tablepress' ); ?>:</label></th>
<td class="column-2">
<select id="tables-export-csv-delimiter" name="export[csv_delimiter]">
<?php
foreach ( $data['csv_delimiters'] as $delimiter => $name ) {
$selected = selected( $delimiter, $data['csv_delimiter'], false );
echo "<option{$selected} value=\"{$delimiter}\">{$name}</option>";
}
?>
</select> <span id="tables-export-csv-delimiter-description" class="description hide-if-js"><?php _e( '(Only needed for CSV export.)', 'tablepress' ); ?></span>
</td>
</tr>
<tr>
<th class="column-1" scope="row"><label for="tables-export-pod-name"><?php _e( 'Pod name', 'tablepress'); ?>:</label></th>
<td class="column-2">
<select id="tables-export-pod-name" name="export[pod_name]">
<?php
foreach ( $data['pods'] as $pod) {
$pod_name = $pod['name'];
$selected = selected( $pod_name, $data['pod_name'], false );
echo "<option{$selected} value=\"{$pod_name}\">{$pod_name}</option>";
}
?>
</select>
</td>
</tr>
<tr>
<th class="column-1" scope="row"><label for="tables-export-pod-where"><?php _e( 'Pod "where" clause', 'tablepress'); ?>:</label></th>
<td class="column-2">
<input id="tables-export-pod-where" name="export[pod_where]" value="" />
<span id="tables-export-pod-where-description" class="description">
<?php _e( '(Optional Pod "where" parameter to filter results.)', 'tablepress' ); ?>
</span>
</td>
</tr>
<tr>
<th class="column-1" scope="row"><label for="tables-export-pod-dump"><?php _e( 'Dump Pod?', 'tablepress'); ?></label></th>
<td class="column-2">
<input type="checkbox" id="tables-export-pod-dump" name="export[pod_dump]" />
<span id="tables-export-pod-dump-description" class="description">
<?php _e( '(If checked, ignores the table and dumps all Pod fields.)', 'tablepress' ); ?>
</span>
</td>
</tr>
</tbody>
</table>
<?php
}
} // class TablePress_ExportPods_View