PluginProbe ʕ •ᴥ•ʔ
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments / 4.6.0
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments v4.6.0
4.6.2 4.6.1 4.6.0 4.5.1 4.5.0 4.4.2 4.4.1 4.4.0 4.3.3 4.3.2 4.3.1 4.3.0 4.2.3 4.2.2 4.2.1 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.11.0 1.11.1 1.11.2 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.9.0 1.9.1 1.9.2 1.9.3 1.9.4 1.9.5 2.0.0 2.0.1 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.10.0 2.10.1 2.11.0 2.11.1 2.11.2 2.11.3 2.11.4 2.12.0 2.13.0 2.14.0 2.14.1 2.15.0 2.15.1 2.16.0 2.16.1 2.16.2 2.16.3 2.17.0 2.17.1 2.17.2 2.18.0 2.19.0 2.19.2 2.19.3 2.19.4 2.2.0 2.2.1 2.20.0 2.20.1 2.20.2 2.20.3 2.20.4 2.20.5 2.20.6 2.21.0 2.22.0 2.22.1 2.23.0 2.24.0 2.25.0 2.25.1 2.25.2 2.26.0 2.27.0 2.27.1 2.28.0 2.29.0 2.29.1 2.29.2 2.29.3 2.29.4 2.3.0 2.3.1 2.30.0 2.31.0 2.31.1 2.31.2 2.31.3 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.40.0 2.40.1 2.5.0 2.5.1 2.5.2 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.9.0 3.0.0 3.0.0-RC1 3.0.0-RC2 3.0.0-beta1 3.0.0-beta2 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.10.0 3.10.1 3.11.0 3.12.0 3.13.0 3.13.1 3.13.2 3.13.3 3.13.4 3.14.0 3.15.0 3.15.1 3.15.2 3.15.3 3.15.4 3.15.5 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.16.6 3.16.7 3.16.8 3.17.0 3.17.1 3.17.2 3.17.3 3.17.4 3.17.5 3.17.6 3.18.0 3.19.0 3.19.1 3.19.2 3.2.0 3.2.1 3.2.2 3.20.0 3.20.1 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 4.0.0 4.0.1 4.0.2 4.0.3 trunk 4.1.0 0.2.19.1 4.1.1 1.0.0 4.2.0 1.0.1 1.0.2
surecart / app / src / Controllers / Admin / Reviews / ReviewsListTable.php
surecart / app / src / Controllers / Admin / Reviews Last commit date
ReviewsController.php 1 week ago ReviewsListTable.php 2 months ago ReviewsScriptsController.php 1 week ago
ReviewsListTable.php
423 lines
1 <?php
2
3 namespace SureCart\Controllers\Admin\Reviews;
4
5 use SureCart\Controllers\Admin\Tables\ListTable;
6 use SureCart\Models\Review;
7 use WP_Error;
8
9 /**
10 * Create a new table class that will extend the WP_List_Table
11 */
12 class ReviewsListTable extends ListTable {
13 /**
14 * The checkbox.
15 *
16 * @var bool
17 */
18 public $checkbox = false;
19
20 /**
21 * The error message.
22 *
23 * @var string
24 */
25 public $error = '';
26
27 /**
28 * The list of pages.
29 *
30 * @var array
31 */
32 public $pages = array();
33
34 /**
35 * Prepare the items for the table to process.
36 *
37 * @return void
38 */
39 public function prepare_items() {
40 $columns = $this->get_columns();
41 $hidden = $this->get_hidden_columns();
42 $sortable = $this->get_sortable_columns();
43
44 $this->_column_headers = array( $columns, $hidden, $sortable );
45
46 $query = $this->table_data();
47
48 if ( is_wp_error( $query ) ) {
49 $this->error = $query->get_error_message();
50 $this->items = array();
51 return;
52 }
53
54 $this->set_pagination_args(
55 array(
56 'total_items' => $query->pagination->count,
57 'per_page' => $this->get_items_per_page( 'reviews' ),
58 )
59 );
60
61 $this->items = $query->data;
62 }
63
64 /**
65 * Get views for the list table status links.
66 *
67 * @global int $post_id
68 * @global string $comment_status
69 * @global string $comment_type
70 */
71 protected function get_views() {
72 $allowed_statuses = array( 'all', 'published', 'in_review', 'unpublished' );
73 $requested_status = ! empty( $_GET['status'] ) && in_array( $_GET['status'], $allowed_statuses, true ) ? sanitize_text_field( wp_unslash( $_GET['status'] ) ) : 'all'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
74
75 foreach ( $this->getStatuses() as $status => $label ) {
76 $link = admin_url( 'admin.php?page=sc-reviews' );
77 $current_link_attributes = '';
78
79 if ( ! empty( $requested_status ) ) {
80 if ( $status === $requested_status ) {
81 $current_link_attributes = ' class="current" aria-current="page"';
82 }
83 } elseif ( 'all' === $status ) {
84 $current_link_attributes = ' class="current" aria-current="page"';
85 }
86
87 $link = add_query_arg( 'status', $status, $link );
88
89 $link = esc_url( $link ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
90
91 // translators: %s: The number of reviews for a specific status.
92 $status_links[ $status ] = sprintf( '<a href="%s"%s>%s</a>', esc_url( $link ), $current_link_attributes, esc_html( $label ) );
93 }
94
95 /**
96 * Filters the comment status links.
97 *
98 * @since 2.5.0
99 * @since 5.1.0 The 'Mine' link was added.
100 *
101 * @param string[] $status_links An associative array of fully-formed comment status links. Includes 'All', 'Mine',
102 * 'Pending', 'Approved', 'Spam', and 'Trash'.
103 */
104 return apply_filters( 'comment_status_links', $status_links );
105 }
106
107 /**
108 * Override the parent columns method. Defines the columns to use in your listing table.
109 *
110 * @return array
111 */
112 public function get_columns() {
113 return array_merge(
114 [
115 'review' => __( 'Review', 'surecart' ),
116 'stars' => __( 'Rating', 'surecart' ),
117 'customer' => __( 'Customer', 'surecart' ),
118 'product' => __( 'Product', 'surecart' ),
119 'status' => __( 'Status', 'surecart' ),
120 'date' => __( 'Submitted on', 'surecart' ),
121 ],
122 parent::get_columns()
123 );
124 }
125
126 /**
127 * Define which columns are sortable.
128 *
129 * @return array
130 */
131 public function get_sortable_columns() {
132 return array(
133 'stars' => array( 'stars', false ),
134 'date' => array( 'created_at', false ),
135 );
136 }
137
138 /**
139 * Define which columns are hidden.
140 *
141 * @return array
142 */
143 public function get_hidden_columns() {
144 return array();
145 }
146
147 /**
148 * Get the table data.
149 *
150 * @return object|WP_Error
151 */
152 private function table_data() {
153 $args = array(
154 'status[]' => $this->getFilteredStatus(),
155 'query' => $this->get_search_query(),
156 );
157
158 // Add sorting.
159 $orderby = $this->get_orderby();
160 $order = $this->get_order();
161
162 if ( $orderby && in_array( $orderby, [ 'stars', 'created_at', 'updated_at' ], true ) ) {
163 $args['sort'] = $orderby . ':' . $order;
164 }
165
166 $review_query = Review::where( $args )->with( [ 'customer', 'product' ] );
167
168 // Check if there is any sc_product.
169 if ( ! empty( $_GET['sc_product'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
170 $review_query->where(
171 array(
172 'product_ids' => array( sanitize_text_field( wp_unslash( $_GET['sc_product'] ) ) ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended
173 )
174 );
175 }
176
177 return $review_query->paginate(
178 array(
179 'per_page' => $this->get_items_per_page( 'reviews' ),
180 'page' => $this->get_pagenum(),
181 )
182 );
183 }
184
185 /**
186 * Nothing found.
187 *
188 * @return void
189 */
190 public function no_items() {
191 if ( $this->error ) {
192 echo esc_html( $this->error );
193 return;
194 }
195 echo esc_html_e( 'No reviews found.', 'surecart' );
196 }
197
198 /**
199 * Status column.
200 *
201 * @param Review $review Review model.
202 *
203 * @return string
204 */
205 public function column_status( $review ) {
206 ob_start();
207 ?>
208 <sc-tag type="<?php echo esc_attr( $review->status_type ); ?>">
209 <?php echo esc_html( $review->status_display ); ?>
210 </sc-tag>
211 <?php
212 return ob_get_clean();
213 }
214
215 /**
216 * Stars column.
217 *
218 * @param Review $review Review model.
219 *
220 * @return string
221 */
222 public function column_stars( $review ) {
223 ob_start();
224 ?>
225 <div style="display: flex; gap: 0.25em;">
226 <sc-review-stars rating="<?php echo esc_attr( $review->stars ); ?>" color="#fbbf24"></sc-review-stars>
227 <span style="color: var(--sc-color-gray-500);">(<?php echo esc_html( $review->stars ); ?>)</span>
228 </div>
229 <?php
230 return ob_get_clean();
231 }
232
233 /**
234 * Customer column.
235 *
236 * @param Review $review Review model.
237 *
238 * @return string
239 */
240 public function column_customer( $review ) {
241 if ( empty( $review->customer ) ) {
242 return '-';
243 }
244 $customer_name = $review->customer->name ?? $review->customer->email ?? '-';
245 return '<a href="' . esc_url( \SureCart::getUrl()->edit( 'customer', $review->customer->id ?? '' ) ) . '">' . esc_html( $customer_name ) . '</a>';
246 }
247
248 /**
249 * Product column.
250 *
251 * @param Review $review Review model.
252 *
253 * @return string
254 */
255 public function column_product( $review ) {
256 if ( empty( $review->product ) ) {
257 return '-';
258 }
259 return '<a href="' . esc_url( admin_url( '/admin.php?page=sc-reviews&sc_product=' . $review->product->id ) ) . '">' . esc_html( $review->product->name ) . '</a>';
260 }
261
262 /**
263 * Review column.
264 *
265 * @param Review $review Review model.
266 *
267 * @return string
268 */
269 public function column_review( $review ) {
270 ob_start();
271 ?>
272 <div>
273 <strong>
274 <a class="row-title" aria-label="<?php esc_attr_e( 'Edit Review', 'surecart' ); ?>" href="<?php echo esc_url( \SureCart::getUrl()->edit( 'review', $review->id ) ); ?>">
275 <?php echo esc_html( $review->title ); ?>
276 </a>
277 <?php if ( ! empty( $review->verified ) ) : ?>
278 <sc-tooltip text="<?php esc_attr_e( 'Verified Buyer', 'surecart' ); ?>" type="text" style="display: inline-flex; align-items: center; margin-left: 4px;">
279 <sc-icon name="verified" style="font-size: 18px; color: var(--sc-color-success-500); vertical-align: middle;"></sc-icon>
280 </sc-tooltip>
281 <?php endif; ?>
282 </strong>
283 <?php if ( ! empty( $review->body ) ) : ?>
284 <div style="margin-top: 0.25em; color: #6b7280; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.4;">
285 <?php echo esc_html( $review->body ); ?>
286 </div>
287 <?php endif; ?>
288 <?php echo $this->row_actions( $this->getRowActions( $review ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
289 </div>
290 <?php
291 return ob_get_clean();
292 }
293
294 /**
295 * Define what data to show on each column of the table.
296 *
297 * @param Review $review Review model.
298 * @param string $column_name Current column name.
299 *
300 * @return mixed
301 */
302 public function column_default( $review, $column_name ) {
303 // Call the parent method to handle custom columns.
304 parent::column_default( $review, $column_name );
305
306 return esc_html( $review->$column_name ?? '' );
307 }
308
309 /**
310 * Get row actions.
311 *
312 * @param Review $review Review model.
313 *
314 * @return array
315 */
316 protected function getRowActions( $review ) {
317 $actions = [
318 'edit' => '<a href="' . esc_url( \SureCart::getUrl()->edit( 'review', $review->id ) ) . '" aria-label="' . esc_attr__( 'Edit Review', 'surecart' ) . '">' . esc_html__( 'Edit', 'surecart' ) . '</a>',
319 ];
320
321 if ( in_array( $review->status, [ 'in_review', 'unpublished' ], true ) ) {
322 $actions['publish'] = '<a href="' . esc_url(
323 add_query_arg(
324 [
325 'action' => 'publish',
326 'nonce' => wp_create_nonce( 'publish_review' ),
327 'id' => $review->id,
328 ],
329 admin_url( 'admin.php?page=sc-reviews' )
330 )
331 ) . '" aria-label="' . esc_attr__( 'Approve Review', 'surecart' ) . '">' . esc_html__( 'Approve', 'surecart' ) . '</a>';
332 }
333
334 if ( in_array( $review->status, [ 'in_review', 'published' ], true ) ) {
335 $actions['unpublish'] = '<a href="' . esc_url(
336 add_query_arg(
337 [
338 'action' => 'unpublish',
339 'nonce' => wp_create_nonce( 'unpublish_review' ),
340 'id' => $review->id,
341 ],
342 admin_url( 'admin.php?page=sc-reviews' )
343 )
344 ) . '" aria-label="' . esc_attr__( 'Reject Review', 'surecart' ) . '">' . esc_html__( 'Reject', 'surecart' ) . '</a>';
345 }
346
347 $actions['delete'] = sprintf(
348 /* translators: 1: Confirmation message, 2: URL, 3: aria-label, 4: link text. */
349 '<a class="submitdelete" onclick="return confirm(\'%1$s\')" href="%2$s" aria-label="%3$s">%4$s</a>',
350 esc_attr__( 'Are you sure? This cannot be undone.', 'surecart' ),
351 esc_url(
352 add_query_arg(
353 [
354 'action' => 'delete',
355 'nonce' => wp_create_nonce( 'delete_review' ),
356 'id' => $review->id,
357 ],
358 admin_url( 'admin.php?page=sc-reviews' )
359 )
360 ),
361 esc_attr__( 'Delete Review', 'surecart' ),
362 esc_html__( 'Delete', 'surecart' )
363 );
364
365 return $actions;
366 }
367
368 /**
369 * Displays extra table navigation.
370 *
371 * @param string $which Top or bottom placement.
372 */
373 protected function extra_tablenav( $which ) {
374 $status = ! empty( $_GET['status'] ) ? sanitize_text_field( wp_unslash( $_GET['status'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
375 $order_by = ! empty( $_GET['orderby'] ) ? sanitize_text_field( wp_unslash( $_GET['orderby'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
376 $order = ! empty( $_GET['order'] ) ? sanitize_text_field( wp_unslash( $_GET['order'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
377 ?>
378 <input type="hidden" name="page" value="sc-reviews" />
379
380 <?php if ( ! empty( $status ) ) : ?>
381 <input type="hidden" name="status" value="<?php echo esc_attr( $status ); ?>" />
382 <?php endif; ?>
383
384 <?php if ( ! empty( $order_by ) ) : ?>
385 <input type="hidden" name="orderby" value="<?php echo esc_attr( $order_by ); ?>" />
386 <?php endif; ?>
387
388 <?php if ( ! empty( $order ) ) : ?>
389 <input type="hidden" name="order" value="<?php echo esc_attr( $order ); ?>" />
390 <?php endif; ?>
391
392 <?php
393 /**
394 * Fires immediately following the closing "actions" div in the tablenav
395 * for the reviews list table.
396 *
397 * @param string $which The location of the extra table nav markup: 'top' or 'bottom'.
398 */
399 do_action( 'manage_reviews_extra_tablenav', $which );
400 }
401
402 /**
403 * Get filtered status / default status.
404 *
405 * @return string|null
406 */
407 private function getFilteredStatus() {
408 return ! empty( $_GET['status'] ) && 'all' !== $_GET['status'] ? sanitize_text_field( wp_unslash( $_GET['status'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
409 }
410
411 /**
412 * Get all review statuses.
413 *
414 * @return array
415 */
416 public function getStatuses(): array {
417 return array_merge(
418 [ 'all' => __( 'All', 'surecart' ) ],
419 ( new Review() )->getStatuses()
420 );
421 }
422 }
423