%1$d', $pending ) : ''; add_menu_page( __( 'PraiseBloom Reviews', 'praisebloom' ), __( 'Reviews', 'praisebloom' ) . $bubble, 'praisebloom_manage', 'praisebloom', array( __CLASS__, 'page_dashboard' ), 'dashicons-star-filled', 26 ); add_submenu_page( 'praisebloom', __( 'Dashboard', 'praisebloom' ), __( 'Dashboard', 'praisebloom' ), 'praisebloom_manage', 'praisebloom', array( __CLASS__, 'page_dashboard' ) ); add_submenu_page( 'praisebloom', __( 'All Reviews', 'praisebloom' ), __( 'All Reviews', 'praisebloom' ) . $bubble, 'praisebloom_manage', 'praisebloom-reviews', array( __CLASS__, 'page_reviews' ) ); add_submenu_page( 'praisebloom', __( 'Add New Review', 'praisebloom' ), __( 'Add New', 'praisebloom' ), 'praisebloom_manage', 'praisebloom-add', array( __CLASS__, 'page_add' ) ); add_submenu_page( 'praisebloom', __( 'Shortcode Builder', 'praisebloom' ), __( 'Shortcode Builder', 'praisebloom' ), 'praisebloom_manage', 'praisebloom-builder', array( __CLASS__, 'page_builder' ) ); add_submenu_page( 'praisebloom', __( 'Import / Export', 'praisebloom' ), __( 'Import / Export', 'praisebloom' ), 'praisebloom_manage', 'praisebloom-tools', array( __CLASS__, 'page_tools' ) ); add_submenu_page( 'praisebloom', __( 'PraiseBloom Settings', 'praisebloom' ), __( 'Settings', 'praisebloom' ), 'manage_options', 'praisebloom-settings', array( __CLASS__, 'page_settings' ) ); } /** * Enqueue admin assets on PraiseBloom pages only. * * @param string $hook Current admin page hook. */ public static function assets( $hook ) { if ( false === strpos( $hook, 'praisebloom' ) ) { return; } wp_enqueue_style( 'praisebloom-admin', PRAISEBLOOM_URL . 'admin/css/praisebloom-admin.css', array(), praisebloom_asset_ver( 'admin/css/praisebloom-admin.css' ) ); // Local QR generator (MIT, bundled) for the share dropdown. wp_enqueue_script( 'praisebloom-qrcode', PRAISEBLOOM_URL . 'admin/js/qrcode.js', array(), praisebloom_asset_ver( 'admin/js/qrcode.js' ), true ); wp_enqueue_script( 'praisebloom-admin', PRAISEBLOOM_URL . 'admin/js/praisebloom-admin.js', array( 'praisebloom-qrcode' ), praisebloom_asset_ver( 'admin/js/praisebloom-admin.js' ), true ); if ( false !== strpos( $hook, 'praisebloom-settings' ) || false !== strpos( $hook, 'praisebloom-add' ) ) { wp_enqueue_media(); } wp_localize_script( 'praisebloom-admin', 'praisebloomAdmin', array( 'confirmDelete' => __( 'Delete this review permanently?', 'praisebloom' ), 'copied' => __( 'Copied!', 'praisebloom' ), 'shareUrl' => praisebloom_collection_url(), 'chooseLogo' => __( 'Choose a platform logo', 'praisebloom' ), 'useLogo' => __( 'Use this logo', 'praisebloom' ), 'chooseHeadshot' => __( 'Choose a reviewer photo', 'praisebloom' ), 'useHeadshot' => __( 'Use this photo', 'praisebloom' ), ) ); } // Settings. /** * Register the settings option. */ public static function register_settings() { register_setting( 'praisebloom_settings_group', 'praisebloom_settings', array( 'type' => 'array', 'sanitize_callback' => array( __CLASS__, 'sanitize_settings' ), ) ); } /** * Sanitize the settings array. * * @param array $input Raw input. * @return array */ public static function sanitize_settings( $input ) { $input = is_array( $input ) ? $input : array(); $out = array(); $out['threshold'] = isset( $input['threshold'] ) ? max( 1, min( 5, absint( $input['threshold'] ) ) ) : 4; $out['thankyou_message'] = isset( $input['thankyou_message'] ) ? sanitize_textarea_field( $input['thankyou_message'] ) : ''; $out['success_message'] = isset( $input['success_message'] ) ? sanitize_textarea_field( $input['success_message'] ) : ''; $out['share_prompt'] = isset( $input['share_prompt'] ) ? sanitize_text_field( $input['share_prompt'] ) : ''; $out['share_all'] = empty( $input['share_all'] ) ? 0 : 1; $out['collection_page_id'] = isset( $input['collection_page_id'] ) ? absint( $input['collection_page_id'] ) : 0; $out['consent_text'] = isset( $input['consent_text'] ) ? sanitize_text_field( $input['consent_text'] ) : ''; $out['auto_approve'] = empty( $input['auto_approve'] ) ? 0 : 1; $out['notify_on_review'] = empty( $input['notify_on_review'] ) ? 0 : 1; $out['notify_email'] = isset( $input['notify_email'] ) ? sanitize_email( $input['notify_email'] ) : ''; $out['accent_color'] = isset( $input['accent_color'] ) && sanitize_hex_color( $input['accent_color'] ) ? sanitize_hex_color( $input['accent_color'] ) : '#6C5CE7'; $out['star_color'] = isset( $input['star_color'] ) && sanitize_hex_color( $input['star_color'] ) ? sanitize_hex_color( $input['star_color'] ) : '#F5B301'; $out['card_radius'] = isset( $input['card_radius'] ) ? max( 0, min( 40, absint( $input['card_radius'] ) ) ) : 12; $out['default_template'] = ( isset( $input['default_template'] ) && in_array( $input['default_template'], PraiseBloom_Display::templates(), true ) ) ? $input['default_template'] : 'classic'; $out['schema'] = empty( $input['schema'] ) ? 0 : 1; $out['delete_data'] = empty( $input['delete_data'] ) ? 0 : 1; $out['platforms'] = array(); if ( ! empty( $input['platforms'] ) && is_array( $input['platforms'] ) ) { foreach ( $input['platforms'] as $row ) { if ( ! is_array( $row ) ) { continue; } $name = isset( $row['name'] ) ? sanitize_text_field( $row['name'] ) : ''; if ( '' === $name ) { continue; } $icon = isset( $row['icon'] ) ? sanitize_text_field( $row['icon'] ) : 'letter'; if ( 0 === strpos( $icon, 'brand:' ) ) { $slug = substr( $icon, 6 ); $icon = PraiseBloom_Icons::get( $slug ) ? 'brand:' . $slug : 'letter'; } elseif ( 0 === strpos( $icon, 'media:' ) ) { $icon = 'media:' . absint( substr( $icon, 6 ) ); } else { $icon = 'letter'; } $id = isset( $row['id'] ) ? sanitize_key( $row['id'] ) : ''; if ( '' === $id ) { $id = sanitize_key( str_replace( ' ', '-', strtolower( $name ) ) ); } $out['platforms'][] = array( 'id' => $id, 'name' => $name, 'icon' => $icon, 'url' => isset( $row['url'] ) ? esc_url_raw( $row['url'] ) : '', 'enabled' => empty( $row['enabled'] ) ? 0 : 1, ); } } if ( empty( $out['platforms'] ) ) { $out['platforms'] = praisebloom_default_platforms(); } return $out; } // Dashboard. /** * The dashboard range in days from the URL (30, 90 or 365). * * @return int */ protected static function current_range() { $range = isset( $_GET['range'] ) ? absint( $_GET['range'] ) : 30; // phpcs:ignore WordPress.Security.NonceVerification.Recommended return in_array( $range, array( 30, 90, 365 ), true ) ? $range : 30; } /** * Initials for an avatar circle. * * @param string $name Full name. * @return string */ protected static function initials( $name ) { $words = preg_split( '/\s+/', trim( (string) $name, " \n\r\t\v\0" ) ); $initials = ''; foreach ( array_slice( (array) $words, 0, 2 ) as $word ) { if ( '' !== $word ) { $initials .= mb_strtoupper( mb_substr( $word, 0, 1 ) ); } } return $initials ? $initials : '?'; } /** * Avatar background from a stable palette. * * @param int $seed Any integer (review id). * @return string Hex color. */ protected static function avatar_color( $seed ) { $palette = array( '#6C5CE7', '#12836B', '#B45309', '#0E7490', '#6D28D9', '#475569' ); return $palette[ abs( (int) $seed ) % count( $palette ) ]; } /** * Inline SVG line chart of reviews over time. * * @param array $series date => count, oldest first. * @return string SVG markup (escaped internally). */ protected static function chart_svg( $series ) { $values = array_values( $series ); $keys = array_keys( $series ); $count = count( $values ); // Keep at most ~30 points: bucket longer ranges. $bucket = (int) ceil( $count / 30 ); if ( $bucket > 1 ) { $bucketed_values = array(); $bucketed_keys = array(); for ( $i = 0; $i < $count; $i += $bucket ) { $slice = array_slice( $values, $i, $bucket ); $bucketed_values[] = array_sum( $slice ); $bucketed_keys[] = $keys[ min( $i + $bucket - 1, $count - 1 ) ]; } $values = $bucketed_values; $keys = $bucketed_keys; $count = count( $values ); } if ( $count < 2 ) { return '

' . esc_html__( 'Not enough data yet.', 'praisebloom' ) . '

'; } $width = 560; $height = 150; $max = max( 1, max( $values ) ); $points = array(); foreach ( $values as $i => $value ) { $x = round( $i / ( $count - 1 ) * $width, 1 ); $y = round( $height - 10 - ( $value / $max ) * ( $height - 30 ), 1 ); $points[] = $x . ',' . $y; } $line = implode( ' ', $points ); $area = 'M' . str_replace( ' ', ' L', $line ) . ' L' . $width . ',' . $height . ' L0,' . $height . ' Z'; $labels = array(); $label_count = 5; for ( $i = 0; $i < $label_count; $i++ ) { $idx = (int) round( $i / ( $label_count - 1 ) * ( $count - 1 ) ); $labels[] = date_i18n( 'M j', strtotime( $keys[ $idx ] ) ); } $svg = ''; $svg .= ''; $svg .= ''; $svg .= ''; $svg .= ''; $svg .= ''; $svg .= '
'; foreach ( $labels as $label ) { $svg .= '' . esc_html( $label ) . ''; } $svg .= '
'; return $svg; } /** * Dashboard page. */ public static function page_dashboard() { $range = self::current_range(); $stats = PraiseBloom_DB::get_stats(); $in_range = PraiseBloom_DB::count_in_range( $range ); $series = PraiseBloom_DB::series( $range ); $sources = PraiseBloom_DB::sources( $range ); $share_url = praisebloom_collection_url(); $ref_url = static function ( $ref ) use ( $share_url ) { return add_query_arg( 'pb_ref', $ref, $share_url ); }; $email_url = $ref_url( 'email' ); $qr_url = $ref_url( 'qr' ); $latest = PraiseBloom_DB::get_reviews( array( 'status' => 'all', 'limit' => 5, 'orderby' => 'created', 'order' => 'DESC', ) ); $max_dist = max( 1, max( $stats['distribution'] ) ); $range_labels = array( 30 => __( 'Last 30 days', 'praisebloom' ), 90 => __( 'Last 90 days', 'praisebloom' ), 365 => __( 'Last 12 months', 'praisebloom' ), ); $mail_subject = rawurlencode( __( 'Would you leave us a quick review?', 'praisebloom' ) ); $mail_body = rawurlencode( sprintf( /* translators: %s: review page link */ __( "Hi!\n\nWe'd love to hear how we did. It only takes a minute:\n%s\n\nThank you!", 'praisebloom' ), $email_url ) ); $ask_text = __( "Hi! We'd love your feedback — could you leave us a quick review?", 'praisebloom' ); // Share channels: each link carries its own pb_ref so Top sources shows where reviews came from. $share_items = array( array( 'icon' => 'whatsapp', 'label' => __( 'WhatsApp', 'praisebloom' ), 'href' => 'https://wa.me/?text=' . rawurlencode( $ask_text . ' ' . $ref_url( 'whatsapp' ) ), ), array( 'icon' => 'facebook', 'label' => __( 'Facebook', 'praisebloom' ), 'href' => 'https://www.facebook.com/sharer/sharer.php?u=' . rawurlencode( $ref_url( 'facebook' ) ), ), array( 'icon' => 'x', 'label' => __( 'X (Twitter)', 'praisebloom' ), 'href' => 'https://x.com/intent/post?text=' . rawurlencode( $ask_text ) . '&url=' . rawurlencode( $ref_url( 'x' ) ), ), array( 'icon' => 'linkedin', 'label' => __( 'LinkedIn', 'praisebloom' ), 'href' => 'https://www.linkedin.com/sharing/share-offsite/?url=' . rawurlencode( $ref_url( 'linkedin' ) ), ), ); ?>

★

$count ) : ?>

[praisebloom_form]

[praisebloom layout="grid" template="classic" columns="3"]

name ) ); ?>
name ); ?> rating ), praisebloom_allowed_html() ); ?> status ) ); ?> created_at ), strtotime( current_time( 'mysql' ) ) ) ) ); ?>

content, 28 ) ); ?>

status ) : ?>
$status, 'search' => $search, 'orderby' => 'date', 'order' => 'DESC', 'limit' => $per_page, 'offset' => ( $paged - 1 ) * $per_page, ) ); $counts = array( 'all' => PraiseBloom_DB::count_reviews( 'all' ), 'pending' => PraiseBloom_DB::count_reviews( 'pending' ), 'approved' => PraiseBloom_DB::count_reviews( 'approved' ), 'rejected' => PraiseBloom_DB::count_reviews( 'rejected' ), ); $total_for_status = isset( $counts[ $status ] ) ? $counts[ $status ] : $counts['all']; $total_pages = max( 1, (int) ceil( $total_for_status / $per_page ) ); ?>


name ); ?> featured ) : ?> ★
email ); ?>
rating ), praisebloom_allowed_html() ); ?> title ) : ?> title ); ?>
content, 24 ) ); ?>
service ? $review->service : '—' ); ?> source ) ); ?> review_date ) ); ?> status ) ); ?>
1 ) : ?>
esc_url_raw( add_query_arg( 'paged', '%#%' ) ), 'format' => '', 'current' => $paged, 'total' => $total_pages, ) ) ); ?>
$field ) ? $review->$field : $fallback; }; $rating = $editing ? (int) $review->rating : 5; ?>

[praisebloom layout="grid" template="classic" columns="3" limit="9"]

$platform ) : ?>

__( 'Website', 'praisebloom' ), 'email' => __( 'Email', 'praisebloom' ), 'whatsapp' => __( 'WhatsApp', 'praisebloom' ), 'facebook' => __( 'Facebook', 'praisebloom' ), 'x' => __( 'X (Twitter)', 'praisebloom' ), 'linkedin' => __( 'LinkedIn', 'praisebloom' ), 'link' => __( 'Copied link', 'praisebloom' ), 'qr' => __( 'QR code', 'praisebloom' ), 'phone' => __( 'Phone', 'praisebloom' ), 'in_person' => __( 'In person', 'praisebloom' ), 'other' => __( 'Other', 'praisebloom' ), ); } /** * Human label for a source key; unknown custom pb_ref values are prettified. * * @param string $source Source key. * @return string */ public static function source_label( $source ) { $labels = self::source_labels(); return isset( $labels[ $source ] ) ? $labels[ $source ] : ucfirst( str_replace( '_', ' ', $source ) ); } /** * Build a nonce-protected single review action URL. * * @param string $action Action slug. * @param int $id Review id. * @param string $status Status to return to. * @return string */ protected static function action_url( $action, $id, $status = 'all' ) { return wp_nonce_url( admin_url( 'admin-post.php?action=praisebloom_review_action&do=' . $action . '&review=' . (int) $id . '&status_back=' . $status ), 'praisebloom_review_' . $id ); } /** * Handle a single review action. */ public static function handle_review_action() { if ( ! current_user_can( 'praisebloom_manage' ) ) { wp_die( esc_html__( 'You are not allowed to do that.', 'praisebloom' ) ); } $id = isset( $_GET['review'] ) ? absint( $_GET['review'] ) : 0; check_admin_referer( 'praisebloom_review_' . $id ); $do = isset( $_GET['do'] ) ? sanitize_key( wp_unslash( $_GET['do'] ) ) : ''; $back = isset( $_GET['status_back'] ) ? sanitize_key( wp_unslash( $_GET['status_back'] ) ) : 'all'; $msg = 'updated'; switch ( $do ) { case 'approve': PraiseBloom_DB::update_review( $id, array( 'status' => 'approved' ) ); $msg = 'approved'; break; case 'reject': PraiseBloom_DB::update_review( $id, array( 'status' => 'rejected' ) ); $msg = 'rejected'; break; case 'pending': PraiseBloom_DB::update_review( $id, array( 'status' => 'pending' ) ); break; case 'feature': PraiseBloom_DB::update_review( $id, array( 'featured' => 1 ) ); break; case 'unfeature': PraiseBloom_DB::update_review( $id, array( 'featured' => 0 ) ); break; case 'delete': PraiseBloom_DB::delete_review( $id ); $msg = 'deleted'; break; } wp_safe_redirect( admin_url( 'admin.php?page=praisebloom-reviews&status=' . $back . '&praisebloom_msg=' . $msg ) ); exit; } /** * Handle bulk actions. */ public static function handle_bulk() { if ( ! current_user_can( 'praisebloom_manage' ) ) { wp_die( esc_html__( 'You are not allowed to do that.', 'praisebloom' ) ); } check_admin_referer( 'praisebloom_bulk' ); $action = isset( $_POST['bulk_action'] ) ? sanitize_key( wp_unslash( $_POST['bulk_action'] ) ) : ''; $ids = isset( $_POST['review_ids'] ) ? array_map( 'absint', (array) wp_unslash( $_POST['review_ids'] ) ) : array(); $back = isset( $_POST['status_back'] ) ? sanitize_key( wp_unslash( $_POST['status_back'] ) ) : 'all'; foreach ( $ids as $id ) { if ( 'approve' === $action ) { PraiseBloom_DB::update_review( $id, array( 'status' => 'approved' ) ); } elseif ( 'reject' === $action ) { PraiseBloom_DB::update_review( $id, array( 'status' => 'rejected' ) ); } elseif ( 'delete' === $action ) { PraiseBloom_DB::delete_review( $id ); } } wp_safe_redirect( admin_url( 'admin.php?page=praisebloom-reviews&status=' . $back . '&praisebloom_msg=updated' ) ); exit; } /** * Handle the Add / Edit review form. */ public static function handle_add_review() { if ( ! current_user_can( 'praisebloom_manage' ) ) { wp_die( esc_html__( 'You are not allowed to do that.', 'praisebloom' ) ); } check_admin_referer( 'praisebloom_add_review' ); $review_id = isset( $_POST['review_id'] ) ? absint( $_POST['review_id'] ) : 0; $editing = $review_id && PraiseBloom_DB::get_review( $review_id ); $rating = isset( $_POST['rating'] ) ? max( 1, min( 5, absint( $_POST['rating'] ) ) ) : 5; $name = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : ''; $content = isset( $_POST['content'] ) ? sanitize_textarea_field( wp_unslash( $_POST['content'] ) ) : ''; if ( '' === $name || '' === $content ) { wp_die( esc_html__( 'Name and review text are required.', 'praisebloom' ) ); } if ( ! $editing && empty( $_POST['consent'] ) ) { wp_die( esc_html__( 'Please confirm the customer\'s permission to publish.', 'praisebloom' ) ); } $date = isset( $_POST['review_date'] ) ? sanitize_text_field( wp_unslash( $_POST['review_date'] ) ) : ''; $date = ( $date && preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date ) ) ? $date . ' 12:00:00' : ''; $data = array( 'rating' => $rating, 'title' => isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : '', 'content' => $content, 'name' => $name, 'designation' => isset( $_POST['designation'] ) ? sanitize_text_field( wp_unslash( $_POST['designation'] ) ) : '', 'company' => isset( $_POST['company'] ) ? sanitize_text_field( wp_unslash( $_POST['company'] ) ) : '', 'location' => isset( $_POST['location'] ) ? sanitize_text_field( wp_unslash( $_POST['location'] ) ) : '', 'email' => isset( $_POST['email'] ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : '', 'service' => isset( $_POST['service'] ) ? sanitize_text_field( wp_unslash( $_POST['service'] ) ) : '', 'source' => isset( $_POST['source'] ) ? sanitize_key( wp_unslash( $_POST['source'] ) ) : 'other', 'avatar_id' => isset( $_POST['avatar_id'] ) ? absint( $_POST['avatar_id'] ) : 0, 'featured' => empty( $_POST['featured'] ) ? 0 : 1, 'verified' => empty( $_POST['verified'] ) ? 0 : 1, 'owner_reply' => isset( $_POST['owner_reply'] ) ? sanitize_textarea_field( wp_unslash( $_POST['owner_reply'] ) ) : null, ); if ( $editing ) { $status = isset( $_POST['status'] ) ? sanitize_key( wp_unslash( $_POST['status'] ) ) : 'approved'; $data['status'] = in_array( $status, array( 'approved', 'pending', 'rejected' ), true ) ? $status : 'approved'; if ( $date ) { $data['review_date'] = $date; } PraiseBloom_DB::update_review( $review_id, $data ); $msg = 'saved'; } else { $data['status'] = 'approved'; $data['added_by'] = get_current_user_id(); $data['review_date'] = $date ? $date : current_time( 'mysql' ); PraiseBloom_DB::insert_review( $data ); $msg = 'added'; } wp_safe_redirect( admin_url( 'admin.php?page=praisebloom-reviews&praisebloom_msg=' . $msg ) ); exit; } /** * Export all reviews to CSV. */ public static function handle_export() { if ( ! current_user_can( 'praisebloom_manage' ) ) { wp_die( esc_html__( 'You are not allowed to do that.', 'praisebloom' ) ); } check_admin_referer( 'praisebloom_export' ); $all = array(); $offset = 0; do { $reviews = PraiseBloom_DB::get_reviews( array( 'status' => 'all', 'limit' => 100, 'offset' => $offset, ) ); $all = array_merge( $all, $reviews ); $offset += 100; } while ( ! empty( $reviews ) ); header( 'Content-Type: text/csv; charset=utf-8' ); header( 'Content-Disposition: attachment; filename=praisebloom-reviews-' . gmdate( 'Y-m-d' ) . '.csv' ); $out = fopen( 'php://output', 'w' ); $columns = array( 'name', 'rating', 'title', 'content', 'email', 'designation', 'company', 'location', 'service', 'source', 'status', 'featured', 'verified', 'owner_reply', 'review_date' ); fputcsv( $out, $columns, ',', '"', '' ); foreach ( $all as $review ) { $row = array(); foreach ( $columns as $col ) { $row[] = isset( $review->$col ) ? $review->$col : ''; } fputcsv( $out, $row, ',', '"', '' ); } fclose( $out ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose exit; } /** * Import reviews from CSV. */ public static function handle_import() { if ( ! current_user_can( 'praisebloom_manage' ) ) { wp_die( esc_html__( 'You are not allowed to do that.', 'praisebloom' ) ); } check_admin_referer( 'praisebloom_import' ); if ( empty( $_POST['import_consent'] ) || empty( $_FILES['praisebloom_csv']['tmp_name'] ) ) { wp_die( esc_html__( 'Please choose a CSV file and confirm permission.', 'praisebloom' ) ); } $tmp = $_FILES['praisebloom_csv']['tmp_name']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- tmp path from PHP upload, read below. $handle = fopen( $tmp, 'r' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen if ( ! $handle ) { wp_die( esc_html__( 'Could not read the uploaded file.', 'praisebloom' ) ); } $header = fgetcsv( $handle, 0, ',', '"', '' ); if ( ! $header ) { fclose( $handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose wp_die( esc_html__( 'The CSV file is empty.', 'praisebloom' ) ); } $header = array_map( 'strtolower', array_map( 'trim', $header ) ); $rows = array(); $line = fgetcsv( $handle, 0, ',', '"', '' ); while ( false !== $line ) { $rows[] = $line; $line = fgetcsv( $handle, 0, ',', '"', '' ); } fclose( $handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose foreach ( $rows as $row ) { $data = array(); foreach ( $header as $i => $col ) { $data[ $col ] = isset( $row[ $i ] ) ? $row[ $i ] : ''; } $name = isset( $data['name'] ) ? sanitize_text_field( $data['name'] ) : ''; $content = isset( $data['content'] ) ? sanitize_textarea_field( $data['content'] ) : ''; $rating = isset( $data['rating'] ) ? max( 1, min( 5, absint( $data['rating'] ) ) ) : 0; if ( '' === $name || '' === $content || ! $rating ) { continue; } $status = isset( $data['status'] ) && in_array( $data['status'], array( 'approved', 'pending', 'rejected' ), true ) ? $data['status'] : 'approved'; $date = ( isset( $data['review_date'] ) && preg_match( '/^\d{4}-\d{2}-\d{2}/', $data['review_date'] ) ) ? substr( $data['review_date'], 0, 10 ) . ' 12:00:00' : current_time( 'mysql' ); PraiseBloom_DB::insert_review( array( 'rating' => $rating, 'title' => isset( $data['title'] ) ? sanitize_text_field( $data['title'] ) : '', 'content' => $content, 'name' => $name, 'designation' => isset( $data['designation'] ) ? sanitize_text_field( $data['designation'] ) : '', 'company' => isset( $data['company'] ) ? sanitize_text_field( $data['company'] ) : '', 'location' => isset( $data['location'] ) ? sanitize_text_field( $data['location'] ) : '', 'email' => isset( $data['email'] ) ? sanitize_email( $data['email'] ) : '', 'service' => isset( $data['service'] ) ? sanitize_text_field( $data['service'] ) : '', 'source' => isset( $data['source'] ) ? sanitize_key( $data['source'] ) : 'import', 'status' => $status, 'added_by' => get_current_user_id(), 'review_date' => $date, ) ); } wp_safe_redirect( admin_url( 'admin.php?page=praisebloom-tools&praisebloom_msg=imported' ) ); exit; } // Helpers. /** * Human label for a status. * * @param string $status Status slug. * @return string */ protected static function status_label( $status ) { $labels = array( 'pending' => __( 'Pending', 'praisebloom' ), 'approved' => __( 'Approved', 'praisebloom' ), 'rejected' => __( 'Rejected', 'praisebloom' ), ); return isset( $labels[ $status ] ) ? $labels[ $status ] : $status; } /** * Notice text for redirect messages. * * @param string $key Message key. * @return string */ protected static function message_text( $key ) { $messages = array( 'approved' => __( 'Review approved.', 'praisebloom' ), 'rejected' => __( 'Review rejected.', 'praisebloom' ), 'deleted' => __( 'Review deleted.', 'praisebloom' ), 'updated' => __( 'Reviews updated.', 'praisebloom' ), 'added' => __( 'Review added.', 'praisebloom' ), 'saved' => __( 'Review updated.', 'praisebloom' ), 'imported' => __( 'Import finished.', 'praisebloom' ), ); return isset( $messages[ $key ] ) ? $messages[ $key ] : __( 'Done.', 'praisebloom' ); } }