CTX Feed – WooCommerce Product Feed Manager Plugin - Version 3.7.4

Version Description

(2020-08-22) = * Fixed: FIle missing issue fixed.

Download this release

Release Info

Developer wahid0003
Plugin Icon 128x128 CTX Feed – WooCommerce Product Feed Manager Plugin
Version 3.7.4
Comparing to
See all releases

Code changes from version 3.7.3 to 3.7.4

README.txt CHANGED
@@ -5,7 +5,7 @@ Tags:product feed,woocommerce product feed,google shopping feed,google shopping,
5
  Requires at least: 3.6
6
  Tested Up To: 5.5
7
  Requires PHP: 5.6
8
- Stable tag: 3.7.3
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -308,6 +308,9 @@ Using pro version:
308
 
309
  == Changelog ==
310
 
 
 
 
311
  = 3.7.3 (2020-08-22) =
312
  * Added: Category mapping feature added. Option to map store category with merchant category
313
 
5
  Requires at least: 3.6
6
  Tested Up To: 5.5
7
  Requires PHP: 5.6
8
+ Stable tag: 3.7.4
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
308
 
309
  == Changelog ==
310
 
311
+ = 3.7.4 (2020-08-22) =
312
+ * Fixed: FIle missing issue fixed.
313
+
314
  = 3.7.3 (2020-08-22) =
315
  * Added: Category mapping feature added. Option to map store category with merchant category
316
 
admin/class-woo-feed-category-list.php ADDED
@@ -0,0 +1,498 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php ob_start();
2
+
3
+ /**
4
+ * Category List
5
+ *
6
+ * @link https://webappick.com/
7
+ * @since 1.0.0
8
+ *
9
+ * @package Woo_Feed_List_Table
10
+ * @author Ohidul Islam <wahid@webappick.com>
11
+ */
12
+ class Woo_Feed_Category_list extends Woo_Feed_List_Table {
13
+
14
+ /** ************************************************************************
15
+ * Normally we would be querying data from a database and manipulating that
16
+ * for use in your list table. For this example, we're going to simplify it
17
+ * slightly and create a pre-built array. Think of this as the data that might
18
+ * be returned by $wpdb->query()
19
+ *
20
+ * In a real-world scenario, you would make your own custom query inside
21
+ * this class' prepare_items() method.
22
+ *
23
+ * @var array
24
+ **************************************************************************/
25
+
26
+
27
+ /** ************************************************************************
28
+ * REQUIRED. Set up a constructor that references the parent constructor. We
29
+ * use the parent reference to set some default configs.
30
+ ***************************************************************************/
31
+ function __construct() {
32
+ // Set parent defaults
33
+ parent::__construct(
34
+ array(
35
+ 'singular' => __( 'mapping', 'woo-feed' ), // singular name of the listed records
36
+ 'plural' => __( 'mappings', 'woo-feed' ), // plural name of the listed records
37
+ 'ajax' => false, // does this table support ajax?
38
+ )
39
+ );
40
+
41
+ }
42
+
43
+
44
+ /** ************************************************************************
45
+ * Recommended. This method is called when the parent class can't find a method
46
+ * specifically build for a given column. Generally, it's recommended to include
47
+ * one method for each column you want to render, keeping your package class
48
+ * neat and organized. For example, if the class needs to process a column
49
+ * named 'title', it would first see if a method named $this->column_title()
50
+ * exists - if it does, that method will be used. If it doesn't, this one will
51
+ * be used. Generally, you should try to use custom column methods as much as
52
+ * possible.
53
+ *
54
+ * Since we have defined a column_title() method later on, this method doesn't
55
+ * need to concern itself with any column with a name of 'title'. Instead, it
56
+ * needs to handle everything else.
57
+ *
58
+ * For more detailed insight into how columns are handled, take a look at
59
+ * WP_List_Table::single_row_columns()
60
+ *
61
+ * @param array $item A singular item (one full row's worth of data)
62
+ * @param array $column_name The name/slug of the column to be processed
63
+ *
64
+ * @return string Text or HTML to be placed inside the column <td>
65
+ **************************************************************************/
66
+ function column_default( $item, $column_name ) {
67
+ // return $item[$column_name];
68
+ $getItem = $item['option_name'];
69
+ $itemInfo = maybe_unserialize( get_option( $getItem ) );
70
+ global $plugin_page;
71
+ switch ( $column_name ) {
72
+ case 'option_name':
73
+ return $itemInfo['mappingname'];
74
+ case 'provider':
75
+ return $itemInfo['mappingprovider'];
76
+ case 'view':
77
+ $edit_nonce = wp_create_nonce( 'wf_edit_mapping' );
78
+ $delete_nonce = wp_create_nonce( 'wf_delete_mapping' );
79
+
80
+ return sprintf(
81
+ '<a class="button button-primary" href="?page=%s&action=%s&cmapping=%s&_wpnonce=%s">' . __( 'Edit', 'woo-feed' ) . '</a>',
82
+ esc_attr( $plugin_page ),
83
+ 'edit-mapping',
84
+ $item['option_name'],
85
+ $edit_nonce
86
+ ) . '&nbsp;' .
87
+ sprintf(
88
+ '<a val="?page=%s&action=%s&cmapping=%s&_wpnonce=%s" class="button single-category-delete" style="cursor: pointer;">' . __( 'Delete', 'woo-feed' ) . '</a>',
89
+ esc_attr( $plugin_page ),
90
+ 'delete-mapping',
91
+ absint( $item['option_id'] ),
92
+ $delete_nonce
93
+ );
94
+ default:
95
+ return false;
96
+ }
97
+ }
98
+
99
+
100
+ /** ************************************************************************
101
+ * Recommended. This is a custom column method and is responsible for what
102
+ * is rendered in any column with a name/slug of 'title'. Every time the class
103
+ * needs to render a column, it first looks for a method named
104
+ * column_{$column_title} - if it exists, that method is run. If it doesn't
105
+ * exist, column_default() is called instead.
106
+ *
107
+ * This example also illustrates how to implement rollover actions. Actions
108
+ * should be an associative array formatted as 'slug'=>'link html' - and you
109
+ * will need to generate the URLs yourself. You could even ensure the links
110
+ *
111
+ *
112
+ * @param array $item A singular item (one full row's worth of data)
113
+ *
114
+ * @return string Text to be placed inside the column <td> (movie title only)
115
+ * *************************************************************************@see WP_List_Table::::single_row_columns()
116
+ */
117
+ function column_option_name( $item ) {
118
+ global $plugin_page;
119
+ $edit_nonce = wp_create_nonce( 'wf_edit_mapping' );
120
+ $delete_nonce = wp_create_nonce( 'wf_delete_mapping' );
121
+ $actions = array(
122
+ 'edit' => sprintf( '<a href="?page=%s&action=%s&cmapping=%s&_wpnonce=%s">' . __( 'Edit',
123
+ 'woo-feed' ) . '</a>',
124
+ esc_attr( $plugin_page ),
125
+ 'edit-mapping',
126
+ $item['option_name'],
127
+ $edit_nonce ),
128
+ 'delete' => sprintf( '<a val="?page=%s&action=%s&cmapping=%s&_wpnonce=%s" class="single-category-delete" style="cursor: pointer;">' . __( 'Delete',
129
+ 'woo-feed' ) . '</a>',
130
+ esc_attr( $plugin_page ),
131
+ 'delete-mapping',
132
+ absint( $item['option_id'] ),
133
+ $delete_nonce ),
134
+ );
135
+
136
+
137
+ // Return the title contents
138
+ $getItem = $item['option_name'];
139
+ $itemInfo = maybe_unserialize( get_option( $getItem ) );
140
+ $title = $itemInfo['mappingname'];
141
+
142
+ return sprintf( '%1$s <span style="color:silver">(id:%2$s)</span>%3$s',
143
+ /*$1%s*/
144
+ $title,
145
+ /*$2%s*/
146
+ $item['option_id'],
147
+ /*$3%s*/
148
+ $this->row_actions( $actions )
149
+ );
150
+ }
151
+
152
+ public static function get_mappings() {
153
+ global $wpdb;
154
+ // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
155
+ $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->options WHERE option_name LIKE %s;", 'wf_cmapping_%' ), 'ARRAY_A' );
156
+
157
+ return $result;
158
+ }
159
+
160
+ /**
161
+ * Delete a contact record.
162
+ *
163
+ * @param int $id customer ID
164
+ *
165
+ * @return false|int
166
+ */
167
+ public static function delete_mapping( $id ) {
168
+ global $wpdb;
169
+ // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
170
+ return $wpdb->delete( "{$wpdb->prefix}options", array( 'option_id' => $id ), array( '%d' ) );
171
+ }
172
+
173
+ /**
174
+ * Returns the count of records in the database.
175
+ *
176
+ * @return null|string
177
+ */
178
+ public static function record_count() {
179
+ global $wpdb;
180
+ // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
181
+ return $wpdb->get_var( $wpdb->prepare( "SELECT * FROM $wpdb->options WHERE option_name like %s", 'woo_cmapping_%' ) );
182
+ }
183
+
184
+ /** Text displayed when no contact data is available */
185
+ public function no_items() {
186
+ _e( 'No mapping available.', 'woo-feed' );
187
+ }
188
+
189
+
190
+ /** ************************************************************************
191
+ * REQUIRED if displaying checkboxes or using bulk actions! The 'cb' column
192
+ * is given special treatment when columns are processed. It ALWAYS needs to
193
+ * have it's own method.
194
+ *
195
+ * @param array $item A singular item (one full row's worth of data)
196
+ *
197
+ * @return string Text to be placed inside the column <td> (movie title only)
198
+ * *************************************************************************@see WP_List_Table::::single_row_columns()
199
+ */
200
+ function column_cb( $item ) {
201
+ return sprintf(
202
+ '<input type="checkbox" name="%1$s[]" value="%2$s" />',
203
+ /*$1%s*/
204
+ $this->_args['singular'], // Let's simply repurpose the table's singular label ("movie")
205
+ /*$2%s*/
206
+ $item['option_id'] // The value of the checkbox should be the record's id
207
+ );
208
+ }
209
+
210
+
211
+ function column_name( $item ) {
212
+ global $plugin_page;
213
+ $edit_nonce = wp_create_nonce( 'wf_edit_mapping' );
214
+ $delete_nonce = wp_create_nonce( 'wf_delete_mapping' );
215
+ $title = '<strong>' . $item['option_name'] . '</strong>';
216
+ $actions = array(
217
+ 'edit' => sprintf( '<a href="?page=%s&action=%s&cmapping=%s&_wpnonce=%s">' . __( 'Edit', 'woo-feed' ) . '</a>',
218
+ esc_attr( $plugin_page ),
219
+ 'edit-mapping',
220
+ absint( $item['option_id'] ),
221
+ $edit_nonce ),
222
+ 'delete' => sprintf( '<a val="?page=%s&action=%s&cmapping=%s&_wpnonce=%s" class="single-category-delete" style="cursor: pointer;">' . __( 'Delete', 'woo-feed' ) . '</a>',
223
+ esc_attr( $plugin_page ),
224
+ 'delete-mapping',
225
+ absint( $item['option_id'] ),
226
+ $delete_nonce ),
227
+ );
228
+
229
+ return $title . $this->row_actions( $actions );
230
+ }
231
+
232
+ /** ************************************************************************
233
+ * REQUIRED! This method dictates the table's columns and titles. This should
234
+ * return an array where the key is the column slug (and class) and the value
235
+ * is the column's title text. If you need a checkbox for bulk actions, refer
236
+ * to the $columns array below.
237
+ *
238
+ * The 'cb' column is treated differently than the rest. If including a checkbox
239
+ * column in your table you must create a column_cb() method. If you don't need
240
+ * bulk actions or checkboxes, simply leave the 'cb' entry out of your array.
241
+ *
242
+ * @return array An associative array containing column information: 'slugs'=>'Visible Titles'
243
+ * *************************************************************************@see WP_List_Table::::single_row_columns()
244
+ */
245
+ function get_columns() {
246
+ $columns = array(
247
+ 'cb' => '<input type="checkbox" />', // Render a checkbox instead of text
248
+ 'option_name' => __( 'Category Name', 'woo-feed' ),
249
+ 'provider' => __( 'Category Type', 'woo-feed' ),
250
+ 'view' => __( 'Action', 'woo-feed' ),
251
+ );
252
+
253
+ return $columns;
254
+ }
255
+
256
+
257
+ /** ************************************************************************
258
+ * Optional. If you want one or more columns to be sortable (ASC/DESC toggle),
259
+ * you will need to register it here. This should return an array where the
260
+ * key is the column that needs to be sortable, and the value is db column to
261
+ * sort by. Often, the key and value will be the same, but this is not always
262
+ * the case (as the value is a column name from the database, not the list table).
263
+ *
264
+ * This method merely defines which columns should be sortable and makes them
265
+ * clickable - it does not handle the actual sorting. You still need to detect
266
+ * the ORDERBY and ORDER querystring variables within prepare_items() and sort
267
+ * your data accordingly (usually by modifying your query).
268
+ *
269
+ * @return array An associative array containing all the columns that should be sortable: 'slugs'=>array('data_values',bool)
270
+ **************************************************************************/
271
+ function get_sortable_columns() {
272
+ $sortable_columns = array(
273
+ 'option_name' => array( 'option_name', false ),
274
+ );
275
+
276
+ return $sortable_columns;
277
+ }
278
+
279
+
280
+ /** ************************************************************************
281
+ * Optional. If you need to include bulk actions in your list table, this is
282
+ * the place to define them. Bulk actions are an associative array in the format
283
+ * 'slug'=>'Visible Title'
284
+ *
285
+ * If this method returns an empty value, no bulk action will be rendered. If
286
+ * you specify any bulk actions, the bulk actions box will be rendered with
287
+ * the table automatically on display().
288
+ *
289
+ * Also note that list tables are not automatically wrapped in <form> elements,
290
+ * so you will need to create those manually in order for bulk actions to function.
291
+ *
292
+ * @return array An associative array containing all the bulk actions: 'slugs'=>'Visible Titles'
293
+ **************************************************************************/
294
+ function get_bulk_actions() {
295
+ $actions = array(
296
+ 'bulk-delete' => __( 'Delete', 'woo-feed' ),
297
+ );
298
+ return $actions;
299
+ }
300
+
301
+
302
+ /** ************************************************************************
303
+ * Optional. You can handle your bulk actions anywhere or anyhow you prefer.
304
+ * For this example package, we will handle it in the class to keep things
305
+ * clean and organized.
306
+ *
307
+ * @see $this->prepare_items()
308
+ **************************************************************************/
309
+ public function process_bulk_action() {
310
+ $nonce = isset( $_REQUEST['_wpnonce'] ) && ! empty( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( $_REQUEST['_wpnonce'] ) : '';
311
+ // Detect when a bulk action is being triggered...
312
+ if ( 'delete-mapping' === $this->current_action() ) {
313
+ // In our file that handles the request, verify the nonce.
314
+ if ( ! wp_verify_nonce( $nonce, 'wf_delete_mapping' ) ) {
315
+ // die(_e('You do not have sufficient permission to delete!'));
316
+ update_option( 'wpf_message', esc_html__( 'Failed To Delete Mapping. You do not have sufficient permission to delete.', 'woo-feed' ), false );
317
+ wp_safe_redirect( admin_url( 'admin.php?page=webappick-feed-category-mapping&wpf_message=error' ) );
318
+ die();
319
+ } else {
320
+ if ( isset( $_GET['cmapping'] ) && self::delete_mapping( absint( $_GET['cmapping'] ) ) ) {
321
+ update_option( 'wpf_message', esc_html__( 'Mapping Deleted Successfully', 'woo-feed' ), false );
322
+ wp_safe_redirect( admin_url( 'admin.php?page=webappick-feed-category-mapping&wpf_message=success' ) );
323
+ die();
324
+ } else {
325
+ update_option( 'wpf_message', esc_html__( 'Failed To Delete Mapping', 'woo-feed' ), false );
326
+ wp_safe_redirect( admin_url( 'admin.php?page=webappick-feed-category-mapping&wpf_message=error' ) );
327
+ die();
328
+ }
329
+ }
330
+ }
331
+ // Detect when a bulk action is being triggered...
332
+ if ( 'edit-mapping' === $this->current_action() ) {
333
+ // In our file that handles the request, verify the nonce.
334
+ if ( ! wp_verify_nonce( $nonce, 'wf_edit_mapping' ) ) {
335
+ wp_die( esc_html__( 'You do not have sufficient permission to delete!', 'woo-feed' ), 403 );
336
+ }
337
+ }
338
+
339
+ // If the delete bulk action is triggered
340
+ if ( ( isset( $_POST['mapping'] ) ) && ( isset( $_POST['action'] ) && 'bulk-delete' == $_POST['action'] ) || ( isset( $_POST['action2'] ) && 'bulk-delete' == $_POST['action2'] ) ) {
341
+ if ( 'bulk-delete' === $this->current_action() ) {
342
+ if ( ! wp_verify_nonce( $nonce, 'bulk-' . $this->_args['plural'] ) ) {
343
+ update_option( 'wpf_message', esc_html__( 'Failed To Delete Mapping. You do not have sufficient permission to delete.', 'woo-feed' ), false );
344
+ wp_safe_redirect( admin_url( 'admin.php?page=webappick-feed-category-mapping&wpf_message=error' ) );
345
+ die();
346
+ } else {
347
+ $delete_ids = array_map( 'absint', $_POST['mapping'] );
348
+ $delete_ids = array_filter( $delete_ids );
349
+ // loop over the array of record IDs and delete them
350
+ if ( ! empty( $delete_ids ) ) {
351
+ $count = count( $delete_ids );
352
+ foreach ( $delete_ids as $id ) {
353
+ self::delete_mapping( $id );
354
+ }
355
+ $message = sprintf(
356
+ /* translators: 1: number of item deleted. */
357
+ esc_html( _n( '%d Mapping Successfully Deleted.',
358
+ '%d Mappings Successfully Deleted.',
359
+ $count,
360
+ 'woo-feed' ) ),
361
+ $count
362
+ );
363
+ update_option( 'wpf_message', $message, false );
364
+ wp_safe_redirect( admin_url( 'admin.php?page=webappick-feed-category-mapping&wpf_message=success' ) );
365
+ die();
366
+ }
367
+ }
368
+ }
369
+ }
370
+ }
371
+
372
+
373
+ /** ************************************************************************
374
+ * REQUIRED! This is where you prepare your data for display. This method will
375
+ * usually be used to query the database, sort and filter the data, and generally
376
+ * get it ready to be displayed. At a minimum, we should set $this->items and
377
+ * $this->set_pagination_args(), although the following properties and methods
378
+ * are frequently interacted with here...
379
+ *
380
+ * @global WPDB $wpdb
381
+ * @uses $this->_column_headers
382
+ * @uses $this->items
383
+ * @uses $this->get_columns()
384
+ * @uses $this->get_sortable_columns()
385
+ * @uses $this->get_pagenum()
386
+ * @uses $this->set_pagination_args()
387
+ **************************************************************************/
388
+ function prepare_items() {
389
+ /**
390
+ * First, lets decide how many records per page to show
391
+ */
392
+ $per_page = 10;
393
+
394
+
395
+ /**
396
+ * REQUIRED. Now we need to define our column headers. This includes a complete
397
+ * array of columns to be displayed (slugs & titles), a list of columns
398
+ * to keep hidden, and a list of columns that are sortable. Each of these
399
+ * can be defined in another method (as we've done here) before being
400
+ * used to build the value for our _column_headers property.
401
+ */
402
+ $columns = $this->get_columns();
403
+ $hidden = array();
404
+ $sortable = $this->get_sortable_columns();
405
+
406
+
407
+ /**
408
+ * REQUIRED. Finally, we build an array to be used by the class for column
409
+ * headers. The $this->_column_headers property takes an array which contains
410
+ * 3 other arrays. One for all columns, one for hidden columns, and one
411
+ * for sortable columns.
412
+ */
413
+ $this->_column_headers = array( $columns, $hidden, $sortable );
414
+
415
+
416
+ /**
417
+ * Optional. You can handle your bulk actions however you see fit. In this
418
+ * case, we'll handle them within our package just to keep things clean.
419
+ */
420
+ $this->process_bulk_action();
421
+
422
+
423
+ /**
424
+ * Instead of querying a database, we're going to fetch the example data
425
+ * property we created for use in this plugin. This makes this example
426
+ * package slightly different than one you might build on your own. In
427
+ * this example, we'll be using array manipulation to sort and paginate
428
+ * our data. In a real-world implementation, you will probably want to
429
+ * use sort and pagination data to build a custom query instead, as you'll
430
+ * be able to use your precisely-queried data immediately.
431
+ */
432
+ $data = $this->get_mappings();
433
+
434
+ usort( $data, 'woo_feed_usort_reorder' );
435
+
436
+
437
+ /***********************************************************************
438
+ * ---------------------------------------------------------------------
439
+ *
440
+ * In a real-world situation, this is where you would place your query.
441
+ *
442
+ * For information on making queries in WordPress, see this Codex entry:
443
+ * http://codex.wordpress.org/Class_Reference/wpdb
444
+ *
445
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
446
+ * ---------------------------------------------------------------------
447
+ */
448
+
449
+
450
+ /**
451
+ * REQUIRED for pagination. Let's figure out what page the user is currently
452
+ * looking at. We'll need this later, so you should always include it in
453
+ * your own package classes.
454
+ */
455
+ $current_page = $this->get_pagenum();
456
+
457
+ /**
458
+ * REQUIRED for pagination. Let's check how many items are in our data array.
459
+ * In real-world use, this would be the total number of items in your database,
460
+ * without filtering. We'll need this later, so you should always include it
461
+ * in your own package classes.
462
+ */
463
+ $total_items = count( $data );
464
+
465
+
466
+ /**
467
+ * The WP_List_Table class does not handle pagination for us, so we need
468
+ * to ensure that the data is trimmed to only the current page. We can use
469
+ * array_slice() to
470
+ */
471
+ $data = array_slice( $data, ( ( $current_page - 1 ) * $per_page ), $per_page );
472
+
473
+ /**
474
+ * REQUIRED. We also have to register our pagination options & calculations.
475
+ */
476
+ $this->set_pagination_args(
477
+ array(
478
+ 'total_items' => $total_items,
479
+ // WE have to calculate the total number of items.
480
+ 'per_page' => $per_page,
481
+ // WE have to determine how many items to show on a page.
482
+ 'total_pages' => ceil( $total_items / $per_page ),
483
+ // WE have to calculate the total number of pages.
484
+ )
485
+ );
486
+
487
+ // $this->set_pagination_args( array(
488
+ // 'total_items' => $total_items, //WE have to calculate the total number of items
489
+ // 'per_page' => $per_page //WE have to determine how many items to show on a page
490
+ // ) );
491
+
492
+ /**
493
+ * REQUIRED. Now we can add our *sorted* data to the items property, where
494
+ * it can be used by the rest of the class.
495
+ */
496
+ $this->items = $data;
497
+ }
498
+ }
admin/partials/woo-feed-category-mapping-list.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Category Mapping List View
4
+ *
5
+ * @link https://webappick.com/
6
+ * @since 1.0.0
7
+ *
8
+ * @package Woo_Feed
9
+ * @subpackage Woo_Feed/admin/partial
10
+ * @author Ohidul Islam <wahid@webappick.com>
11
+ */
12
+
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ die();
15
+ }
16
+ global $plugin_page;
17
+ $myListTable = new Woo_Feed_Category_list();
18
+ $myListTable->prepare_items();
19
+ ?>
20
+ <div class="wrap">
21
+ <h2><?php esc_html_e( 'Category Mapping List', 'woo-feed' ); ?><a href="<?php echo esc_url( admin_url( 'admin.php?page=webappick-feed-category-mapping&action=add-mapping' ) ); ?>" class="page-title-action"><?php esc_html_e( 'Add New Mapping', 'woo-feed' ); ?></a></h2>
22
+ <?php WPFFWMessage()->displayMessages(); ?>
23
+ <form id="contact-filter" method="post">
24
+ <!-- For plugins, we also need to ensure that the form posts back to our current page -->
25
+ <input type="hidden" name="page" value="<?php echo esc_attr( $plugin_page ); ?>">
26
+ <!-- Now we can render the completed list table -->
27
+ <?php $myListTable->display(); ?>
28
+ </form>
29
+ </div>
30
+ <script type="text/javascript">
31
+ (function ($) {
32
+ "use strict";
33
+ $(document).ready(function () {
34
+ $('body').find(".single-category-delete").click(function () {
35
+ if (confirm('<?php esc_html_e( 'Are You Sure to Delete?', 'woo-feed' ); ?>')) {
36
+ window.location.href = jQuery(this).attr('val');
37
+ }
38
+ });
39
+
40
+ $('#doaction').click(function () {
41
+ return confirm('<?php esc_html_e( 'Are You Sure to Delete?', 'woo-feed' ); ?>');
42
+ });
43
+
44
+ $('#doaction2').click(function () {
45
+ return confirm('<?php esc_html_e( 'Are You Sure to Delete?', 'woo-feed' ); ?>');
46
+ });
47
+ });
48
+ })(jQuery);
49
+ </script>
admin/partials/woo-feed-category-mapping.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Add New Category Mapping View
4
+ *
5
+ * @link https://webappick.com/
6
+ * @since 1.0.0
7
+ *
8
+ * @package Woo_Feed
9
+ * @subpackage Woo_Feed/admin/partial
10
+ * @author Ohidul Islam <wahid@webappick.com>
11
+ */
12
+
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ die();
15
+ }
16
+
17
+ $wooFeedDropDown = new Woo_Feed_Dropdown();
18
+ $value = array();
19
+ if ( isset( $_GET['action'], $_GET['cmapping'] ) ) { // phpcs:ignore
20
+ $option = get_option( sanitize_text_field( $_GET['cmapping'] ) ); // phpcs:ignore
21
+ $value = maybe_unserialize( $option );
22
+ }
23
+ ?>
24
+ <div class="wrap">
25
+ <h2><?php esc_html_e( 'Category Mapping', 'woo-feed' ); ?></h2>
26
+ <?php WPFFWMessage()->displayMessages(); ?>
27
+ <form action="" name="feed" id="category-mapping-form" method="post" autocomplete="off">
28
+ <?php wp_nonce_field( 'category-mapping' ); ?>
29
+ <table class=" widefat fixed" id="cmTable">
30
+ <tbody>
31
+ <tr>
32
+ <td width="30%">
33
+ <label for="providers"><b><?php esc_html_e( 'Merchant', 'woo-feed' ); ?> <span class="requiredIn">*</span></b></label>
34
+ </td>
35
+ <td>
36
+ <select name="mappingprovider" id="providers" class="generalInput" required>
37
+ <?php
38
+ // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
39
+ echo $wooFeedDropDown->merchantsDropdown( isset( $value['mappingprovider'] ) ? $value['mappingprovider'] : '' );
40
+ ?>
41
+ </select>
42
+ </td>
43
+ </tr>
44
+ <tr>
45
+ <td><b><?php esc_html_e( 'Mapping Name', 'woo-feed' ); ?><span class="requiredIn">*</span></b></td>
46
+ <td>
47
+ <input required value="<?php echo isset( $value['mappingname'] ) ? esc_attr( $value['mappingname'] ) : ''; ?>" name="mappingname" wftitle="<?php esc_attr_e( 'Mapping Name should be unique and don\'t use space. Otherwise it will override the existing Category Mapping. Example: myMappingName or my_mapping_name', 'woo-feed' ); ?>" type="text" class="generalInput wfmasterTooltip">
48
+ </td>
49
+ </tr>
50
+ </tbody>
51
+ </table>
52
+ <br/>
53
+ <table class="table tree widefat fixed ">
54
+ <thead>
55
+ <tr>
56
+ <th><?php esc_html_e( 'Local Category', 'woo-feed' ); ?></th>
57
+ <th><?php esc_html_e( 'Merchant Category', 'woo-feed' ); ?></th>
58
+ </tr>
59
+ </thead>
60
+ <tbody>
61
+ <?php woo_feed_render_categories( 0, '', $value ); ?>
62
+ </tbody>
63
+ <tfoot>
64
+ <tr>
65
+ <td colspan="2">
66
+ <button name="<?php echo isset( $_GET['action'] ) ? esc_attr( sanitize_text_field( $_GET['action'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended ?>" type="submit" class="button button-large button-primary"><?php esc_html_e( 'Save Mapping', 'woo-feed' ); ?></button>
67
+ </td>
68
+ </tr>
69
+ </tfoot>
70
+ </table>
71
+ </form>
72
+ </div>
woo-feed.php CHANGED
@@ -11,7 +11,7 @@
11
  * Plugin URI: https://webappick.com/
12
  * Description: Easily generate woocommerce product feed for any marketing channel like Google Shopping(Merchant), Facebook Remarketing, Bing, eBay & more. Support 100+ Merchants.
13
  *
14
- * Version: 3.7.3
15
  * Author: WebAppick
16
  * Author URI: https://webappick.com/
17
  * License: GPL v2
@@ -39,7 +39,7 @@ if ( ! defined( 'WOO_FEED_FREE_VERSION' ) ) {
39
  * @var string
40
  * @since 3.1.6
41
  */
42
- define( 'WOO_FEED_FREE_VERSION', '3.7.3' );
43
  }
44
 
45
  if ( ! defined( 'WOO_FEED_FREE_FILE' ) ) {
11
  * Plugin URI: https://webappick.com/
12
  * Description: Easily generate woocommerce product feed for any marketing channel like Google Shopping(Merchant), Facebook Remarketing, Bing, eBay & more. Support 100+ Merchants.
13
  *
14
+ * Version: 3.7.4
15
  * Author: WebAppick
16
  * Author URI: https://webappick.com/
17
  * License: GPL v2
39
  * @var string
40
  * @since 3.1.6
41
  */
42
+ define( 'WOO_FEED_FREE_VERSION', '3.7.4' );
43
  }
44
 
45
  if ( ! defined( 'WOO_FEED_FREE_FILE' ) ) {