PluginProbe
Posts Table with Search & Sort / 1.0
Posts Table with Search & Sort v1.0
trunk 1.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2 1.3 1.3.1 1.3.1-v2 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 All 39 releases
posts-data-table / posts-data-table.php

posts-data-table.php in Posts Table with Search & Sort 1.0, at posts-data-table.php

318 lines 13.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Posts Data Table plugin.
4 *
5 * @package Recent_Comments_By_Language
6 * @author Andrew Keith <andy@barn2.co.uk>
7 * @license GPL-2.0+
8 * @link http://barn2.co.uk
9 * @copyright 2015 Barn2 Media
10 *
11 * @wordpress-plugin
12 * Plugin Name: Posts Data Table
13 * Description: This plugin provides a shortcode to show a list of your site's posts in a searchable and sortable data table.
14 * Version: 1.0
15 * Author: Barn2 Media
16 * Author URI: http://barn2.co.uk
17 * Text Domain: posts-data-table
18 * Domain Path: /languages
19 * License: GPL-2.0+
20 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
21 */
22
23 // Prevent direct file access
24 if ( ! defined ( 'ABSPATH' ) ) {
25 exit;
26 }
27
28 class Posts_Data_Table_Plugin {
29
30 private $shortcode = 'posts_data_table';
31
32 private $shortcode_defaults = array(
33 'columns' => 'title,content,date,author,category',
34 'rows_per_page' => 20,
35 'sort_by' => 'date',
36 'sort_order' => '',
37 'search_on_click' => true,
38 'wrap' => false,
39 'content_length' => 20,
40 'scroll_offset' => 15
41 );
42
43 private $table_count = 1;
44
45 public function __construct() {
46
47 // Load the text domain - should go on 'plugins_loaded' hook
48 add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
49
50 // Register shortcode
51 add_shortcode( $this->shortcode, array( $this, 'shortcode' ) );
52
53 // Register styles and scripts
54 add_action( 'wp_enqueue_scripts', array( $this, 'register_styles' ) );
55 add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ) );
56 }
57
58 public function load_textdomain() {
59 load_plugin_textdomain( 'posts-data-table', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
60 }
61
62 public function register_styles() {
63 wp_enqueue_style( 'pdt-style', plugins_url( 'assets/css/posts-data-table.min.css', __FILE__ ) );
64 //wp_enqueue_style( 'pdt-plugin-style', plugins_url( 'assets/css/datatables.css', __FILE__ ) );
65 //wp_enqueue_style( 'pdt-style', plugins_url( 'assets/css/posts-data-table.css', __FILE__ ), array( 'pdt-plugin-style' ) );
66 }
67
68 public function register_scripts() {
69 wp_enqueue_script( 'pdt-script', plugins_url( 'assets/js/posts-data-table.min.js', __FILE__ ), array( 'jquery' ), false, true );
70 //wp_enqueue_script( 'pdt-plugin-script', plugins_url( 'assets/js/datatables.js', __FILE__ ), array( 'jquery' ), false, true );
71 //wp_enqueue_script( 'pdt-script', plugins_url( 'assets/js/posts-data-table.js', __FILE__ ), array( 'pdt-plugin-script' ), false, true );
72
73 $locale = get_locale();
74 $supported_locales = $this->get_supported_locales();
75
76 // Add language file to script if locale is supported (English file is not added as this is the default language)
77 if ( array_key_exists( $locale, $supported_locales ) ) {
78 wp_localize_script( 'pdt-script', 'posts_data_table', array(
79 'langurl' => $supported_locales[$locale]
80 ) );
81 }
82 }
83
84 public function shortcode( $atts, $content = '' ) {
85 return $this->get_data_table( shortcode_atts( $this->shortcode_defaults, $atts, $this->shortcode ) );
86 }
87
88 private function get_supported_locales() {
89 $lang_file_base_url = plugins_url( 'languages/data-tables/', __FILE__ );
90
91 return array(
92 'es_ES' => $lang_file_base_url . 'Spanish.json',
93 'fr_FR' => $lang_file_base_url . 'French.json',
94 'de_DE' => $lang_file_base_url . 'German.json',
95 );
96 }
97
98 private function get_data_table( $args ) {
99
100 if ( empty( $args['columns'] ) ) {
101 $args['columns'] = $this->shortcode_defaults['columns'];
102 }
103
104 $args['rows_per_page'] = filter_var( $args['rows_per_page'], FILTER_VALIDATE_INT );
105 if ( ($args['rows_per_page'] < 1) || !$args['rows_per_page'] ) {
106 $args['rows_per_page'] = false;
107 }
108
109 if ( !in_array( $args['sort_by'], array('id', 'title', 'category', 'date', 'author', 'content') ) ) {
110 $args['sort_by'] = $this->shortcode_defaults['sort_by'];
111 }
112
113 if ( !in_array( $args['sort_order'], array('asc', 'desc') ) ) {
114 $args['sort_order'] = $this->shortcode_defaults['sort_order'];
115 }
116
117 // Set default sort direction
118 if ( !$args['sort_order'] ) {
119 if ( $args['sort_by'] === 'date' ) {
120 $args['sort_order'] = 'desc';
121 } else {
122 $args['sort_order'] = 'asc';
123 }
124 }
125
126 $args['search_on_click'] = filter_var( $args['search_on_click'], FILTER_VALIDATE_BOOLEAN );
127 $args['wrap'] = filter_var( $args['wrap'], FILTER_VALIDATE_BOOLEAN );
128 $args['content_length'] = filter_var( $args['content_length'], FILTER_VALIDATE_INT );
129 $args['scroll_offset'] = filter_var( $args['scroll_offset'], FILTER_VALIDATE_INT );
130
131 $date_format = 'Y/m/d';
132 $output = $table_head = $table_body = $body_row_fmt = '';
133
134 // Get all published posts in the current language
135 $all_posts_curr_lang = get_posts( array(
136 'post_type' => 'post',
137 'posts_per_page' => -1,
138 'post_status' => 'publish',
139 'suppress_filters' => false // Ensure WPML filters run on this query
140 ) );
141
142 if ( is_array( $all_posts_curr_lang ) && $all_posts_curr_lang ) { // if we have posts
143
144 // Start table header
145
146 /* Define an array of all possible columns.
147 * Priority values are used to determine visiblity at small screen sizes (1 = highest priority, 6 = lowest priority).
148 * Column widths are automatically calculated by DataTables, but can be overridden by applying a filter to this array.
149 */
150 $all_columns = apply_filters( 'posts_data_table_column_defaults', array(
151 'id' => array(
152 'heading' => __('ID', 'posts-data-table'),
153 'priority' => 3,
154 'width' => ''
155 ),
156 'title' => array(
157 'heading' => __('Title', 'posts-data-table'),
158 'priority' => 1,
159 'width' => ''
160 ),
161 'category' => array(
162 'heading' => __('Categories', 'posts-data-table'),
163 'priority' => 6,
164 'width' => ''
165 ),
166 'date' => array(
167 'heading' => __('Date', 'posts-data-table'),
168 'priority' => 2,
169 'width' => ''
170 ),
171 'author' => array(
172 'heading' => __('Author', 'posts-data-table'),
173 'priority' => 4,
174 'width' => ''
175 ),
176 'content' => array(
177 'heading' => __('Content', 'posts-data-table'),
178 'priority' => 5,
179 'width' => ''
180 ),
181 ) );
182
183 $all_column_keys = array_keys( $all_columns );
184
185 // Get the columns to be used in this table
186 $columns = array_map( 'trim', explode( ',', strtolower( $args['columns'] ) ) );
187
188 // If none of the user-specfied columns are valid, use the default columns instead
189 if ( !array_intersect($all_column_keys, $columns) ) {
190 $columns = explode( ',', $this->shortcode_defaults['columns'] );
191 }
192
193 $heading_fmt = '<th data-name="%1$s" data-priority="%2$u" data-width="%3$s">%4$s</th>';
194 $cell_fmt = '<td>%s</td>';
195
196 foreach( $columns as $column ) {
197 if ( in_array($column, $all_column_keys) ) { // Double-check column name is valid
198
199 // Add heading to table
200 $table_head .= sprintf( $heading_fmt, $column, $all_columns[$column]['priority'], $all_columns[$column]['width'], $all_columns[$column]['heading'] );
201
202 // Add placeholder to table body format string so that content for this column is included in table
203 $body_row_fmt .= sprintf($cell_fmt, $column);
204 }
205 }
206
207 $sort_column = $args['sort_by'];
208 $sort_index = array_search( $sort_column, $columns );
209
210 if ( $sort_index === false ) {
211 // Sort column is not in list of displayed columns so we'll add it as a hidden column at end of table
212 $table_head .= sprintf( '<th data-name="%1$s" data-visible="false">%2$s</th>', $sort_column, $all_columns[$sort_column]['heading'] );
213
214 // Make sure data for this column is included in table content
215 $body_row_fmt .= sprintf($cell_fmt, $sort_column);
216
217 // Set the sort column index to be this hidden column
218 $sort_index = count($columns);
219 }
220
221 $table_head = sprintf( '<thead><tr>%s</tr></thead>', $table_head );
222 // end table header
223
224 // Start table body
225 $body_row_fmt = '<tr>' . $body_row_fmt . '</tr>';
226
227 // Loop through posts and add a row for each
228 foreach ( (array) $all_posts_curr_lang as $_post ) {
229 setup_postdata( $_post );
230
231 // Format title
232 $title = sprintf( '<a href="%1$s">%2$s</a>', get_permalink($_post), get_the_title( $_post ) );
233
234 // Format author
235 $author = sprintf(
236 '<a href="%1$s" title="%2$s" rel="author">%3$s</a>',
237 esc_url( get_author_posts_url( $_post->post_author ) ),
238 esc_attr( sprintf( __( 'Posts by %s' ), get_the_author() ) ),
239 get_the_author()
240 );
241
242 $all_post_data = array(
243 'id' => $_post->ID,
244 'title' => $title,
245 'category' => get_the_category_list( ', ', '', $_post->ID ),
246 'date' => get_the_date( $date_format, $_post ),
247 'author' => $author,
248 'content' => $this->get_post_content( $args['content_length'] )
249 );
250 $table_body .= str_replace( $all_column_keys, $all_post_data, $body_row_fmt );
251
252 } // foreach post
253
254 wp_reset_postdata();
255
256 $table_body = sprintf( '<tbody>%s</tbody>', $table_body );
257 // end table body
258
259 $paging_attr = 'false';
260 if ( ( $args['rows_per_page'] > 1 ) && ( $args['rows_per_page'] < count($all_posts_curr_lang) ) ) {
261 $paging_attr = 'true';
262 }
263
264 $order_attr = sprintf( '[[%u, "%s"]]', $sort_index, $args['sort_order'] );
265 $offset_attr = ( $args['scroll_offset'] === false ) ? 'false' : $args['scroll_offset'];
266
267 $table_class = 'posts-data-table';
268 if ( !$args['wrap'] ) {
269 $table_class .= ' nowrap';
270 }
271
272 $output = sprintf(
273 '<table '
274 . 'id="posts-table-%1$u" '
275 . 'class="%2$s" '
276 . 'data-page-length="%3$u" '
277 . 'data-paging="%4$s" '
278 . 'data-order=\'%5$s\' '
279 . 'data-click-filter="%6$s" '
280 . 'data-scroll-offset="%7$s" '
281 . 'cellspacing="0" width="100%%">'
282 . '%8$s%9$s' .
283 '</table>',
284 $this->table_count,
285 esc_attr( $table_class ),
286 esc_attr( $args['rows_per_page'] ),
287 esc_attr( $paging_attr ),
288 esc_attr( $order_attr ),
289 ( $args['search_on_click'] ? 'true' : 'false' ),
290 esc_attr( $offset_attr ),
291 $table_head,
292 $table_body
293 );
294
295 $this->table_count++;
296 } // if posts found
297
298 return $output;
299 } // get_comments_list
300
301 /**
302 * Retrieve the post content, truncated to the number of words specified by $num_words.
303 *
304 * Must be called with the Loop or a secondary loop after a call to setup_postdata().
305 *
306 * @param int $num_words The number of words to trim the content to
307 * @return string The (truncated) post content
308 */
309 private function get_post_content( $num_words = 15 ) {
310 $text = get_the_content('');
311 $text = strip_shortcodes( $text );
312 $text = apply_filters( 'the_content', $text );
313 $text = wp_trim_words( $text, $num_words, ' &hellip;' );
314 return $text;
315 }
316
317 } // end class
318 $posts_data_table = new Posts_Data_Table_Plugin();