Файловый менеджер - Редактировать - /home/tuudkjt/globeasy/wp-includes/ID3/app.tar
Назад
Services/CategoryService.php 0000777 00000003125 15251220643 0012146 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Apiz\Http\Response; use Rvx\WPDrill\Response as drillResponse; use Rvx\Api\CategoryApi; use Rvx\Utilities\Helper; class CategoryService extends \Rvx\Services\Service { /** * */ public function __construct() { // add_action('save_post', [$this, 'saveProduct'], 10, 1); } /** * @return Response */ public function selectable() { return (new CategoryApi())->selectable(); } /** * @return Response */ public function getCategory() { return (new CategoryApi())->getCategory(); } /** * @return Response */ public function getCategoryAll() : drillResponse { $product_categories = get_terms(array('taxonomy' => 'product_cat', 'hide_empty' => \false)); $response = array(); foreach ($product_categories as $parent_category) { $subcategory_array = array(); $subcategories = get_terms(array('taxonomy' => 'product_cat', 'hide_empty' => \false, 'parent' => $parent_category->term_id)); foreach ($subcategories as $subcategory) { $subcategory_array[] = array('name' => $subcategory->name, 'id' => $subcategory->term_id); } $response[] = array('parent' => array('name' => $parent_category->name, 'id' => $parent_category->term_id), 'subcategories' => $subcategory_array); } return Helper::rest($response)->success("All category list"); } public function storeCategory($data) { return (new CategoryApi())->create($data); } } Services/ProductService.php 0000777 00000000447 15251220643 0012015 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Apiz\Http\Response; use Rvx\Api\ProductApi; class ProductService extends \Rvx\Services\Service { /** * @return Response */ public function getSelectProduct($data) { return (new ProductApi())->getProductSelect($data); } } Services/PingService.php 0000777 00000011770 15251220643 0011273 0 ustar 00 <?php namespace Rvx\Services; class PingService extends \Rvx\Services\Service { public function __construct() { } /** * Ping the WP to check the status of the plugin and server. * * @return array */ public function ping() { global $wpdb, $wp_version; // Get migration status $migration_status = \get_option('_rvx_db_upgrade_216', '0'); $rollback_status = \get_option('_rvx_current_rollback', '0'); return ['environment' => ['php' => ['version' => \PHP_VERSION, 'memory_limit' => \ini_get('memory_limit'), 'max_execution_time' => \ini_get('max_execution_time'), 'extensions' => \get_loaded_extensions(), 'opcache_enabled' => \extension_loaded('opcache') && \opcache_get_status()['opcache_enabled'], 'apcu_enabled' => \extension_loaded('apcu') && \ini_get('apc.enabled')], 'server' => ['software' => $_SERVER['SERVER_SOFTWARE'] ?? 'N/A', 'protocol' => $_SERVER['SERVER_PROTOCOL'] ?? 'N/A', 'https' => is_ssl(), 'db_version' => $wpdb->db_version(), 'fs_method' => \defined('FS_METHOD') ? FS_METHOD : 'direct']], 'wordpress' => ['version' => $wp_version, 'locale' => get_locale(), 'multisite' => is_multisite(), 'debug' => ['wp_debug' => WP_DEBUG, 'wp_debug_log' => WP_DEBUG_LOG, 'wp_debug_display' => WP_DEBUG_DISPLAY, 'script_debug' => SCRIPT_DEBUG], 'memory' => ['wp_memory_limit' => WP_MEMORY_LIMIT, 'wp_max_memory_limit' => WP_MAX_MEMORY_LIMIT, 'current_usage' => \round(\memory_get_usage() / 1024 / 1024, 2) . 'M'], 'cron' => ['jobs_count' => \count(_get_cron_array()), 'alternate_wp_cron' => \defined('ALTERNATE_WP_CRON') && ALTERNATE_WP_CRON], 'cache' => $this->get_cache_status()], 'reviewx' => ['version' => RVX_VERSION, 'migration' => ['status' => (bool) $migration_status], 'rollback' => ['status' => (bool) $rollback_status], 'paths' => ['dir_name' => RVX_DIR_NAME, 'dir_path' => RVX_DIR_PATH, 'dir_url' => RVX_URL]], 'plugins' => $this->get_plugins_status(), 'theme' => $this->get_theme_details()]; } private function get_cache_status() { return ['wp_cache' => \defined('WP_CACHE') && WP_CACHE, 'object_cache' => \file_exists(WP_CONTENT_DIR . '/object-cache.php'), 'browser_cache' => (bool) \get_option('gzipcompression', 0), 'plugins' => $this->detect_caching_plugins(), 'server_side' => $this->detect_server_caching()]; } private function detect_caching_plugins() { $caching_plugins = []; $active_plugins = \get_option('active_plugins', []); $known_caching_plugins = ['w3-total-cache' => 'w3-total-cache/w3-total-cache.php', 'wp-super-cache' => 'wp-super-cache/wp-cache.php', 'wp-rocket' => 'wp-rocket/wp-rocket.php', 'litespeed-cache' => 'litespeed-cache/litespeed-cache.php', 'autoptimize' => 'autoptimize/autoptimize.php']; foreach ($known_caching_plugins as $name => $plugin_path) { if (\in_array($plugin_path, $active_plugins)) { $caching_plugins[$name] = \true; } } return $caching_plugins; } private function detect_server_caching() { $headers = \headers_list(); $server_software = $_SERVER['SERVER_SOFTWARE'] ?? ''; return ['varnish' => isset($_SERVER['HTTP_X_VARNISH']), 'nginx_cache' => \strpos($server_software, 'nginx') !== \false, 'cloudflare' => isset($_SERVER['HTTP_CF_RAY']), 'opcache' => \extension_loaded('opcache') && \opcache_get_status()['opcache_enabled'], 'redis' => \defined('WP_REDIS_HOST'), 'memcached' => \defined('WP_MEMCACHED_HOST')]; } private function test_rest_api() { $response = wp_remote_get(rest_url('wp/v2/types/post')); return ['status' => !\is_wp_error($response), 'response_code' => wp_remote_retrieve_response_code($response), 'error' => \is_wp_error($response) ? $response->get_error_message() : null]; } private function get_theme_details() { $theme = wp_get_theme(); return ['name' => $theme->get('Name'), 'version' => $theme->get('Version'), 'parent_theme' => $theme->parent() ? $theme->parent()->get('Name') : null, 'theme_uri' => $theme->get('ThemeURI'), 'author' => $theme->get('Author'), 'template_dir' => $theme->get_template_directory(), 'stylesheet_dir' => $theme->get_stylesheet_directory()]; } private function get_plugins_status() { if (!\function_exists('Rvx\\get_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $plugins = []; foreach (get_plugins() as $path => $plugin) { if (is_plugin_active($path)) { $plugins[$plugin['TextDomain'] ?? $path] = ['version' => $plugin['Version'], 'network_active' => is_plugin_active_for_network($path), 'author' => $plugin['Author'], 'update_available' => $this->check_plugin_update($path, $plugin)]; } } return $plugins; } private function check_plugin_update($plugin_path, $plugin_data) { $updates = \get_transient('update_plugins'); return isset($updates->response[$plugin_path]) ? $updates->response[$plugin_path]->new_version : \false; } } Services/ProductSyncService.php 0000777 00000024766 15251220643 0012664 0 ustar 00 <?php namespace Rvx\Services; use Exception; use Rvx\Utilities\Helper; use Rvx\WPDrill\Facades\DB; use Rvx\Services\CategorySyncService; class ProductSyncService extends \Rvx\Services\Service { protected $postMetaPriceRelation; protected $productCount = 0; protected $postMetaAverageRatingRelation; protected $postMetaRatingCountPercentageRelation; protected $postMetaReviewsCountRelation; protected $postMetaSalePriceRelation; protected $postMetaThumbnaiRelation; protected $postMetaAttachmentsRelation; protected $postMetaStarCountsRelation; protected $productids; protected $postAttachmentRelation; protected CategorySyncService $syncedCategories; protected $postTermRelation; public function __construct() { $this->syncedCategories = new CategorySyncService(); $this->postTermRelation = $this->syncedCategories->getPostTermRelation(); } public function processProductForSync($file, $post_type) : int { $this->syncProductsMeta($post_type); return $this->syncProducts($file, $post_type); } public function getProductAttachementRalation() { return $this->postAttachmentRelation; } public function syncProductsMeta($post_type) { // Base meta keys $dbTableKeys = ['rvx_avg_rating', 'rating', '_thumbnail_id', 'rvx_total_reviews', 'rvx_star_count_1', 'rvx_star_count_2', 'rvx_star_count_3', 'rvx_star_count_4', 'rvx_star_count_5']; // Add product-specific keys if ($post_type === 'product') { $dbTableKeys = \array_merge($dbTableKeys, ['_price', '_sale_price', '_wc_review_count', '_wc_average_rating', '_wc_rating_count']); } // Define relation targets by meta key $relationMap = ['_price' => 'postMetaPriceRelation', '_sale_price' => 'postMetaSalePriceRelation', '_wc_review_count' => 'postMetaReviewsCountRelation', '_wc_rating_count' => 'postMetaRatingCountPercentageRelation', '_thumbnail_id' => 'postMetaThumbnaiRelation', 'rvx_total_reviews' => 'postMetaReviewsCountRelation']; try { DB::table('postmeta')->whereIn('meta_key', $dbTableKeys)->chunk(100, function ($allPostMeta) use($relationMap) { foreach ($allPostMeta as $meta) { $key = $meta->meta_key; $pid = $meta->post_id; $value = $meta->meta_value; // Direct assignment using map if (isset($relationMap[$key])) { $this->{$relationMap[$key]}[$pid] = $value; continue; } // Collect Star Counts for CPT if (\strpos($key, 'rvx_star_count_') === 0) { $starIndex = \str_replace('rvx_star_count_', '', $key); // 1, 2, 3... $this->postMetaStarCountsRelation[$pid][$starIndex] = $value; continue; } // --- Rating Prioritization Logic --- // Priority: _wc_average_rating > rvx_avg_rating > rating if ($key === '_wc_average_rating' || $key === 'rvx_avg_rating' || $key === 'rating') { // Assign only if not already assigned by a higher-priority field if (!isset($this->postMetaAverageRatingRelation[$pid])) { $this->postMetaAverageRatingRelation[$pid] = $value; } } } }); } catch (Exception $e) { throw new Exception($e->getMessage()); } } public function syncProducts($file, $post_type) { $productCount = 0; $attachmentRelation = []; $this->postMetaAttachmentsRelation = []; DB::table('posts')->select(['ID', 'post_type', 'post_title', 'post_name', 'post_excerpt', 'post_status', 'guid', 'post_modified', 'comment_count'])->orderBy('ID')->whereIn('post_type', [$post_type])->chunk(100, function ($products) use(&$attachmentRelation, &$file, &$productCount) { foreach ($products as $product) { $this->productids[] = $product->ID; $productImage = get_the_post_thumbnail_url($product->ID, 'full') ? get_the_post_thumbnail_url($product->ID, 'full') : null; if ($product->post_type !== 'product') { $this->postMetaReviewsCountRelation[$product->ID] = $product->comment_count; } $formatedProduct = $this->processProduct($product, $productImage); if ($formatedProduct['post_type'] !== 'attachment') { Helper::appendToJsonl($file, $formatedProduct); $productCount++; } } }); $this->setPostAttachemtRelation($attachmentRelation); Helper::rvxLog($productCount, "Product Done"); return $productCount; } public function setPostAttachemtRelation($attachmentRelation) : void { $this->postAttachmentRelation = $attachmentRelation; } public function processProduct($product, $productImage) : array { $reviewsCount = isset($this->postMetaReviewsCountRelation[$product->ID]) ? (int) $this->postMetaReviewsCountRelation[$product->ID] : 0; $ratingCount = $this->postMetaRatingCountPercentageRelation[$product->ID] ?? []; // Handle CPT Star Counts (from rvx_ meta) if ($product->post_type !== 'product') { // Self-Healing: If star data is missing, calculate it NOW. if (!isset($this->postMetaStarCountsRelation[$product->ID])) { \Rvx\CPT\CptAverageRating::update_average_rating($product->ID); // Fetch fresh data immediately $freshStars = []; for ($i = 1; $i <= 5; $i++) { $freshStars[$i] = (int) \get_post_meta($product->ID, "rvx_star_count_{$i}", \true); } $this->postMetaStarCountsRelation[$product->ID] = $freshStars; $freshTotal = (int) \get_post_meta($product->ID, 'rvx_total_reviews', \true); $this->postMetaReviewsCountRelation[$product->ID] = $freshTotal; $freshAvg = (float) \get_post_meta($product->ID, 'rvx_avg_rating', \true); $this->postMetaAverageRatingRelation[$product->ID] = $freshAvg; } $cptStars = $this->postMetaStarCountsRelation[$product->ID]; // Format to match what ratingCountsConverter expects or construct directly $ratingCounts = ["one" => (int) ($cptStars[1] ?? 0), "two" => (int) ($cptStars[2] ?? 0), "three" => (int) ($cptStars[3] ?? 0), "four" => (int) ($cptStars[4] ?? 0), "five" => (int) ($cptStars[5] ?? 0)]; // Refresh total reviews count from relation if it was updated $reviewsCount = isset($this->postMetaReviewsCountRelation[$product->ID]) ? (int) $this->postMetaReviewsCountRelation[$product->ID] : $reviewsCount; } else { // Default WooCommerce logic // Ensure WooCommerce serialized rating count is converted to array if (\is_string($ratingCount)) { $decoded = @\unserialize($ratingCount); $ratingCount = \is_array($decoded) ? $decoded : []; } $ratingCounts = $this->ratingCountsConverter($ratingCount); } return ['rid' => 'rid://Product/' . (int) $product->ID, "post_type" => $product->post_type ?? null, "wp_id" => (int) ($product->ID ?? 0), "title" => isset($product->post_title) ? \htmlspecialchars($product->post_title, \ENT_QUOTES, 'UTF-8') : null, "url" => $product->guid ?? '', "description" => $product->post_excerpt ?? null, "price" => isset($this->postMetaPriceRelation[$product->ID]) ? Helper::formatToTwoDecimalPlaces($this->postMetaPriceRelation[$product->ID]) : 0, "discounted_price" => isset($this->postMetaSalePriceRelation[$product->ID]) ? Helper::formatToTwoDecimalPlaces($this->postMetaSalePriceRelation[$product->ID]) : 0, "slug" => $product->post_name ?? '', "status" => $this->productStatus($product->post_status ?? ''), "total_reviews" => $reviewsCount, "avg_rating" => isset($this->postMetaAverageRatingRelation[$product->ID]) ? Helper::formatToTwoDecimalPlaces($this->postMetaAverageRatingRelation[$product->ID]) : 0, "stars" => ["one" => $ratingCounts["one"], "two" => $ratingCounts["two"], "three" => $ratingCounts["three"], "four" => $ratingCounts["four"], "five" => $ratingCounts["five"]], "one_stars" => $ratingCounts["one"], "two_stars" => $ratingCounts["two"], "three_stars" => $ratingCounts["three"], "four_stars" => $ratingCounts["four"], "five_stars" => $ratingCounts["five"], "modified_date" => Helper::validateReturnDate($product->post_modified) ?? null, "image" => $productImage, "category_ids" => isset($this->postTermRelation[(int) $product->ID]) && \is_array($this->postTermRelation[(int) $product->ID]) ? \array_map('intval', $this->postTermRelation[(int) $product->ID]) : []]; } private function ratingCountsConverter(array $ratingCount) : array { // Final output initialized to 0 $stars = ["one" => 0, "two" => 0, "three" => 0, "four" => 0, "five" => 0]; // Empty OR invalid input → return default immediately if (empty($ratingCount)) { return $stars; } foreach ($ratingCount as $rawKey => $value) { // Convert numeric strings $value = \is_numeric($value) ? (float) $value : 0; // Convert key to float (handles "3.5", 5, "4", etc.) $key = \is_numeric($rawKey) ? (float) $rawKey : null; if ($key === null) { continue; } // Round decimals down (3.5 => 3) $bucket = (int) \floor($key); switch ($bucket) { case 1: $stars["one"] += $value; break; case 2: $stars["two"] += $value; break; case 3: $stars["three"] += $value; break; case 4: $stars["four"] += $value; break; case 5: $stars["five"] += $value; break; } } return $stars; } public function productStatus($status) : int { switch ($status) { case 'publish': return 1; case 'private': return 2; default: return 3; } } } Services/OrderItemSyncService.php 0000777 00000015744 15251220643 0013132 0 ustar 00 <?php namespace Rvx\Services; use DateTime; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Rvx\WPDrill\Facades\DB; class OrderItemSyncService extends \Rvx\Services\Service { protected $orderFullfillmentStatusRelation; protected $validOrderIds = []; protected $validOrdersMetaIds = []; protected $orderItems = []; protected $orderItemCount = 0; protected $orderFullfillmentAtRelation; protected $orderItemOrderRelation = []; protected $orderItemProductRelation = []; protected $orderItemQtyRelation = []; protected $orderItemPriceRelation = []; public function syncOrder($file) : int { $orderCount = 0; $this->orderStat(); $startDate = (new DateTime())->modify('-60 days')->format('Y-m-d H:i:s'); $endDate = (new DateTime())->format('Y-m-d H:i:s'); DB::table('wc_orders')->select(['id', 'customer_id', 'total_amount', 'tax_amount', 'status', 'date_created_gmt', 'date_updated_gmt'])->whereBetween('date_created_gmt', $startDate, $endDate)->chunk(100, function ($orders) use($file, &$orderCount) { foreach ($orders as $order) { $this->validOrderIds[] = (int) $order->id; $order->fulfillment_status = $this->orderFullfillmentStatusRelation[(int) $order->id] ?? null; $order->fulfilled_at = $this->orderFullfillmentAtRelation[(int) $order->id] ?? null; $formattedOrder = $this->formatOrderData($order); Helper::appendToJsonl($file, $formattedOrder); $orderCount++; } }); Helper::rvxLog($orderCount, "Order Done"); return $orderCount; } public function formatOrderData($order) : array { $paid_at = !empty($order->fulfilled_at) && \strtotime($order->fulfilled_at) ? \wp_date('Y-m-d H:i:s', \strtotime($order->fulfilled_at)) : null; return ['rid' => 'rid://Order/' . (int) $order->id, 'wp_id' => (int) $order->id, 'customer_wp_unique_id' => $order->customer_id ? Client::getUid() . '-' . $order->customer_id : null, 'subtotal' => Helper::formatToTwoDecimalPlaces($order->total_amount ?? 0.0), 'tax' => Helper::formatToTwoDecimalPlaces($order->tax_amount ?? 0.0), 'total' => Helper::formatToTwoDecimalPlaces($order->total_amount ?? 0.0), 'status' => isset($order->status) ? Helper::orderStatus(Helper::rvxGetOrderStatus($order->status)) : null, 'review_request_email_sent_at' => null, 'review_reminder_email_sent_at' => null, 'photo_review_email_sent_at' => null, 'paid_at' => $paid_at, 'created_at' => !empty($order->date_created_gmt) ? Helper::validateReturnDate($order->date_created_gmt) : null, 'updated_at' => !empty($order->date_updated_gmt) ? Helper::validateReturnDate($order->date_updated_gmt) : null]; } public function orderStat() { $startDate = (new DateTime())->modify('-60 days')->format('Y-m-d H:i:s'); $endDate = (new DateTime())->format('Y-m-d H:i:s'); DB::table('wc_order_stats')->whereBetween('date_created', $startDate, $endDate)->chunk(100, function ($orderStats) { foreach ($orderStats as $orderStat) { $this->orderFullfillmentStatusRelation[(int) $orderStat->order_id] = Helper::orderItemStatus(Helper::rvxGetOrderStatus($orderStat->status)); $this->orderFullfillmentAtRelation[(int) $orderStat->order_id] = $orderStat->date_completed ?? $orderStat->date_paid ?? null; } }); } public function syncOrderItem($file) : int { $orderItemCount = 0; // Early exit if no valid orders to process if (empty($this->validOrderIds)) { // Helper::rvxLog(0, "No valid orders found, skipping order item sync"); return 0; } // Step 1: Collect valid order items and their IDs $this->validOrdersMetaIds = []; $this->orderItems = []; // Store full order item objects keyed by order_item_id DB::table('woocommerce_order_items')->whereNotIn('order_item_type', ['shipping'])->whereIn('order_id', $this->validOrderIds)->chunk(500, function ($orderItems) { foreach ($orderItems as $orderItem) { $this->validOrdersMetaIds[] = $orderItem->order_item_id; $this->orderItems[$orderItem->order_item_id] = $orderItem; } }); // Early exit if no valid order items found if (empty($this->validOrdersMetaIds)) { // Helper::rvxLog(0, "No valid order items found, skipping meta sync"); return 0; } // Step 2: Fetch associated meta data for the collected order items $this->getOrderItemMeta(); // Step 3: Format and write each order item to the file foreach ($this->orderItems as $orderItemId => $orderItem) { $orderItem->product_id = $this->orderItemProductRelation[$orderItemId] ?? 0; $orderItem->quantity = $this->orderItemQtyRelation[$orderItemId] ?? 0; $orderItem->price = $this->orderItemPriceRelation[$orderItemId] ?? 0.0; $formattedOrderItem = $this->formatOrderItem($orderItem); Helper::appendToJsonl($file, $formattedOrderItem); $orderItemCount++; } Helper::rvxLog($orderItemCount, "Order Item Done"); return $orderItemCount; } public function formatOrderItem($orderItem) : array { $productId = (int) ($orderItem->product_id ?? 0); return ['rid' => 'rid://LineItem/' . (int) $orderItem->order_item_id, 'wp_id' => (int) $orderItem->order_item_id, "wp_unique_id" => Client::getUid() . '-' . (int) $orderItem->order_item_id, 'order_id' => (int) $orderItem->order_id, 'product_wp_unique_id' => Client::getUid() . '-' . $productId, 'name' => $orderItem->order_item_name ?? null, 'quantity' => (int) ($orderItem->quantity ?? 0), 'price' => Helper::formatToTwoDecimalPlaces($orderItem->price ?? 0.0), 'review_id' => null, 'site_id' => Client::getSiteId(), 'fulfillment_status' => $this->orderFullfillmentStatusRelation[(int) $orderItem->order_id] ?? null, 'fulfilled_at' => !empty($this->orderFullfillmentAtRelation[(int) $orderItem->order_id]) ? Helper::validateReturnDate($this->orderFullfillmentAtRelation[(int) $orderItem->order_id]) : null, 'reviewed_at' => null]; } public function getOrderItemMeta() : void { DB::table('woocommerce_order_itemmeta')->whereIn('order_item_id', $this->validOrdersMetaIds)->whereIn('meta_key', ['_product_id', '_qty', '_line_total'])->chunk(100, function ($orderItemMeta) { foreach ($orderItemMeta as $item) { if ($item->meta_key === '_product_id') { $this->orderItemProductRelation[$item->order_item_id] = $item->meta_value; } if ($item->meta_key === '_qty') { $this->orderItemQtyRelation[$item->order_item_id] = $item->meta_value; } if ($item->meta_key === '_line_total') { $this->orderItemPriceRelation[$item->order_item_id] = $item->meta_value; } } }); } } Services/UserServices.php 0000777 00000002002 15251220643 0011463 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Apiz\Http\Response; use Rvx\Utilities\Helper; class UserServices extends \Rvx\Services\Service { /** * @return Response */ public function getUser() { $customer_ids = get_users(array('role' => 'customer', 'fields' => 'ID')); $customer_data_array = array(); foreach ($customer_ids as $customer_id) { $user_data = get_userdata($customer_id); $customer_first_name = \get_user_meta($customer_id, 'first_name', \true); $customer_last_name = \get_user_meta($customer_id, 'last_name', \true); $current_customer_data = array('customer_id' => $customer_id, 'customer_email' => $user_data->user_email, 'customer_username' => $user_data->user_login, 'customer_first_name' => $customer_first_name, 'customer_last_name' => $customer_last_name); $customer_data_array[] = $current_customer_data; } return Helper::rest($customer_data_array)->success("All Customer list"); } } Services/Api/LoginService.php 0000777 00000002755 15251220643 0012162 0 ustar 00 <?php namespace Rvx\Services\Api; use Rvx\Api\AuthApi; use Rvx\Services\Service; class LoginService extends Service { public function resetPostMeta() { global $wpdb; $insight_key = '_rvx_latest_reviews_insight'; $review_key = '_rvx_latest_reviews'; $post_ids = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s OR meta_key = %s", $insight_key, $review_key)); if (!empty($post_ids)) { $post_ids_placeholders = \implode(',', \array_fill(0, \count($post_ids), '%d')); $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE (meta_key = %s OR meta_key = %s) AND post_id IN ({$post_ids_placeholders})", \array_merge([$insight_key, $review_key], $post_ids))); } } public function resetProductWisePostMeta($product_id) { global $wpdb; $review_key = '_rvx_latest_reviews'; // Validate the product ID if (empty($product_id) || !\is_numeric($product_id)) { return; // Exit if the product ID is invalid } // Prepare and execute the deletion query $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE meta_key = %s AND post_id = %d", $review_key, $product_id)); } public function forgetPassword($data) { return (new AuthApi())->forgetPassword($data); } public function resetPassword($data) { return (new AuthApi())->resetPassword($data); } } Services/ImportExportServices.php 0000777 00000033631 15251220643 0013235 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Api\ReviewImportAndExportApi; use Rvx\CPT\CptHelper; use Rvx\Services\Api\LoginService; use Rvx\Api\AuthApi; use Rvx\Utilities\Helper; use Exception; class ImportExportServices extends \Rvx\Services\Service { private \Rvx\Services\DataSyncService $dataSyncService; private \Rvx\Services\CacheServices $cacheServices; private LoginService $loginService; public function __construct() { $this->dataSyncService = new \Rvx\Services\DataSyncService(); $this->cacheServices = new \Rvx\Services\CacheServices(); $this->loginService = new LoginService(); } public function importSupportedAppStore($data) { return (new ReviewImportAndExportApi())->importSupportedAppStore($data); } public function importStore($request) { $files = $request->get_file_params(); $data = $request->get_params(); // Direct WP DB import $response = $this->importReviewStore($files, $data); global $wpdb; // Initialize tables and reset sync flag (new \Rvx\Handlers\RvxInit\LoadReviewxCreateSiteTable())->init(); \set_transient('rvx_reset_sync_flag', \true, 300); // 5 mins TTL $rvxSites = $wpdb->prefix . 'rvx_sites'; $uid = $wpdb->get_var("SELECT uid FROM {$rvxSites} ORDER BY id DESC LIMIT 1"); if ($uid) { // Mark as not synced initially $wpdb->update($rvxSites, ['is_saas_sync' => 0], ['uid' => $uid], ['%d'], ['%s']); // Start initial sync for all enabled post types $enabled_post_types = (new CptHelper())->usedCPTOnSync('used'); foreach ($enabled_post_types as $post_type) { $this->dataSyncService->dataSync('default', $post_type); } } // Always clean cache and redirect, even if UID or API failed $this->cacheServices->removeCache(); $this->loginService->resetPostMeta(); // Invalidate aggregation transient so next /reviews call fetches fresh data \delete_transient('rvx_admin_aggregation'); return ['status' => 'success', 'message' => 'WordPress import success! Initiating synchronization with ReviewX Cloud...', 'data' => $response]; } public function importReviewStore($files, $data) { // Prevent timeout for large files \set_time_limit(0); $request = $data; $reviews = []; $totalProcessed = 0; $successCount = 0; $file = $files['file']['tmp_name']; $wpReviewIds = []; if (($handle = \fopen($file, 'r')) !== \FALSE) { // Get the header row $header = \fgetcsv($handle); if (!$header) { \fclose($handle); return ['total' => 0, 'success' => 0, 'failed' => 0]; } $map = $request['map'] ?? []; $productIdColumn = $map['product_id'] ?? null; $chunkSize = 50; $currentChunk = []; while (($row = \fgetcsv($handle)) !== \FALSE) { // Combine header with row data if (\count($header) === \count($row)) { $reviewData = \array_combine($header, $row); // Basic validation if ($productIdColumn && !empty($reviewData[$productIdColumn])) { $currentChunk[] = $reviewData; } } // Process chunk if (\count($currentChunk) >= $chunkSize) { $results = $this->processReviewBatch($currentChunk, $request); $totalProcessed += $results['total']; $successCount += $results['success']; $wpReviewIds = \array_merge($wpReviewIds, $results['ids']); $currentChunk = []; // Optional: distinct cleanups if needed per chunk } } // Process remaining if (!empty($currentChunk)) { $results = $this->processReviewBatch($currentChunk, $request); $totalProcessed += $results['total']; $successCount += $results['success']; $wpReviewIds = \array_merge($wpReviewIds, $results['ids']); } \fclose($handle); } $response = ['total' => $totalProcessed, 'success' => $successCount, 'failed' => $totalProcessed - $successCount]; // Log history to SaaS try { (new \Rvx\Api\ReviewImportAndExportApi())->logImportHistory(['name' => \basename($files['file']['name']), 'map' => $request['map'] ?? [], 'wp_review_ids' => $wpReviewIds, 'stats' => ['total_reviews' => $totalProcessed, 'success_reviews' => $successCount, 'failed_reviews' => $totalProcessed - $successCount]]); } catch (\Exception $e) { \error_log("Failed to log import history to SaaS: " . $e->getMessage()); } return $response; } private function processReviewBatch(array $reviews, array $request) : array { $ids = []; $map = $request['map'] ?? []; $productIdColumn = $map['product_id'] ?? null; $total = 0; $success = 0; foreach ($reviews as $reviewData) { $total++; $wpProductId = $productIdColumn && isset($reviewData[$productIdColumn]) ? (int) $reviewData[$productIdColumn] : 0; if (!$wpProductId) { continue; } $postType = $reviewData['Post_Type'] ?? 'product'; try { // We can optimize transient deletion to happen once per product per batch if needed, // but for now keeping it safe. \delete_transient("rvx_{$wpProductId}_latest_reviews"); \delete_transient("rvx_{$wpProductId}_latest_reviews_insight"); $commentId = $this->insertReview($wpProductId, $reviewData, $request, $postType); if ($commentId) { $ids[] = $commentId; $success++; } } catch (Exception $e) { \error_log("Failed to insert review: " . $e->getMessage()); } } return ['total' => $total, 'success' => $success, 'ids' => $ids]; } public function insertReview($reviews_id, $review_data, $request, $post_type) { $mediaArray = []; $map = $request['map'] ?? []; $attachmentKey = $map['attachment'] ?? null; if ($attachmentKey && isset($review_data[$attachmentKey]) && !empty($review_data[$attachmentKey])) { $mediaArray = \explode(',', $review_data[$attachmentKey]); } $comment_type = 'review'; if (!empty($post_type) && \strtolower($post_type) != 'product') { $comment_type = 'comment'; } $customerNameKey = $request['map']['customer_name'] ?? null; $customerEmailKey = $request['map']['customer_email'] ?? null; $feedbackKey = $request['map']['feedback'] ?? null; $createdAtKey = $request['map']['created_at'] ?? null; $comment_data = ['comment_post_ID' => $reviews_id, 'comment_author' => $customerNameKey && isset($review_data[$customerNameKey]) ? $review_data[$customerNameKey] : 'Anonymous', 'comment_author_email' => $customerEmailKey && isset($review_data[$customerEmailKey]) ? $review_data[$customerEmailKey] : '', 'comment_content' => $feedbackKey && isset($review_data[$feedbackKey]) ? $review_data[$feedbackKey] : '', 'comment_date' => $createdAtKey && !empty($review_data[$createdAtKey]) && \strtotime($review_data[$createdAtKey]) !== \false ? \wp_date('Y-m-d H:i:s', \strtotime($review_data[$createdAtKey])) : \wp_date('Y-m-d H:i:s'), 'comment_approved' => Helper::arrayGet($request, 'status'), 'comment_type' => $comment_type]; $comment_id = \wp_insert_comment($comment_data); if ($comment_id && !\is_wp_error($comment_id)) { $titleKey = $request['map']['review_title'] ?? null; $titleValue = $titleKey && isset($review_data[$titleKey]) ? $review_data[$titleKey] : null; \update_comment_meta($comment_id, 'reviewx_title', $titleValue); $ratingColumn = $request['map']['rating'] ?? null; $rating = $ratingColumn && isset($review_data[$ratingColumn]) ? (int) $review_data[$ratingColumn] : 5; if ($rating > 5) { $rating = 5; } elseif ($rating < 1) { $rating = 1; } \update_comment_meta($comment_id, 'rating', $rating); $processedMedia = []; foreach ($mediaArray as $url) { $processedMedia[] = $this->sideloadAttachment(\trim($url)); } \update_comment_meta($comment_id, 'reviewx_attachments', $processedMedia); \update_comment_meta($comment_id, 'verified', Helper::arrayGet($request, 'verified')); \update_comment_meta($comment_id, 'rvx_review_version', 'v2'); // Explicitly trigger aggregation if approved if ($comment_data['comment_approved'] == 1) { \Rvx\CPT\CptAverageRating::update_average_rating($reviews_id); } // Handle Review Reply $replyContentColumn = $request['map']['review_reply'] ?? null; if ($replyContentColumn && isset($review_data[$replyContentColumn]) && !empty($review_data[$replyContentColumn]) && $comment_id) { $repliedAtColumn = $request['map']['replied_at'] ?? null; $repliedAt = $repliedAtColumn && isset($review_data[$repliedAtColumn]) && !empty($review_data[$repliedAtColumn]) ? \strtotime($review_data[$repliedAtColumn]) : \time(); $currentUser = Helper::getWpCurrentUser(); $replyData = ['comment_post_ID' => $reviews_id, 'comment_author' => $currentUser ? $currentUser->display_name : 'Shop Owner', 'comment_author_email' => $currentUser ? $currentUser->user_email : \get_option('admin_email'), 'comment_content' => $review_data[$replyContentColumn], 'comment_type' => 'comment', 'comment_parent' => $comment_id, 'comment_approved' => 1, 'comment_date' => \wp_date('Y-m-d H:i:s', $repliedAt)]; \wp_insert_comment($replyData); } } return $comment_id; } /** * @throws Exception */ public function importRollback($data) { return (new ReviewImportAndExportApi())->importRollback($data); } public function rollbackImportByIds($data) { $wpReviewIds = $data['wp_review_ids'] ?? []; if (empty($wpReviewIds)) { return ['status' => 'error', 'message' => 'Missing wp_review_ids']; } $count = 0; $affectedPosts = []; foreach ($wpReviewIds as $commentId) { $comment = \Rvx\get_comment($commentId); if ($comment) { $affectedPosts[] = $comment->comment_post_ID; if (\Rvx\wp_delete_comment($commentId, \true)) { $count++; } } } // Clear caches for affected products foreach (\array_unique($affectedPosts) as $postId) { (new \Rvx\Services\CacheServices())->removeProductCache($postId); \Rvx\CPT\CptAverageRating::update_average_rating($postId); } (new \Rvx\Services\CacheServices())->removeCache(); return ['status' => 'success', 'message' => "Successfully deleted {$count} reviews", 'deleted_count' => $count]; } /** * @throws Exception */ public function importRestore($data) { return (new ReviewImportAndExportApi())->importRestore($data); } public function exportCsv($data) { return (new ReviewImportAndExportApi())->exportCsv($data); } public function exportHistory() { return (new ReviewImportAndExportApi())->exportHistory(); } public function importHistory() { return (new ReviewImportAndExportApi())->importHistory(); } /** * Sideload an attachment from a URL to the local media library. * * @param string $url * @return string */ protected function sideloadAttachment($url) { if (empty($url) || !\filter_var($url, \FILTER_VALIDATE_URL)) { return $url; } // 1. Same-Domain Check $homeUrl = \Rvx\home_url(); $parsedHome = \parse_url($homeUrl); $parsedUrl = \parse_url($url); if (isset($parsedUrl['host'], $parsedHome['host']) && $parsedUrl['host'] === $parsedHome['host']) { return $url; } // 2. Duplicate Prevention (check by source URL) $args = ['post_type' => 'attachment', 'post_status' => 'inherit', 'meta_query' => [['key' => '_rvx_source_url', 'value' => $url]], 'posts_per_page' => 1, 'fields' => 'ids']; $existing = \Rvx\get_posts($args); if (!empty($existing)) { return \Rvx\wp_get_attachment_url($existing[0]); } // 3. Sideloading Process if (!\function_exists('Rvx\\download_url')) { require_once \ABSPATH . 'wp-admin/includes/file.php'; } if (!\function_exists('Rvx\\media_handle_sideload')) { require_once \ABSPATH . 'wp-admin/includes/media.php'; require_once \ABSPATH . 'wp-admin/includes/image.php'; } $tmp = \Rvx\download_url($url); if (\is_wp_error($tmp)) { \error_log("RVX Import: Failed to download attachment ({$url}): " . $tmp->get_error_message()); return $url; } $file_array = ['name' => \basename($url), 'tmp_name' => $tmp]; // Sideload keeping the file $id = \Rvx\media_handle_sideload($file_array, 0); if (\is_wp_error($id)) { @\unlink($tmp); \error_log("RVX Import: Failed to sideload attachment ({$url}): " . $id->get_error_message()); return $url; } // Store original source URL as metadata \update_post_meta($id, '_rvx_source_url', $url); return \Rvx\wp_get_attachment_url($id); } } Services/Service.php 0000777 00000000062 15251220643 0010445 0 ustar 00 <?php namespace Rvx\Services; class Service { } Services/ReviewService.php 0000777 00000131362 15251220643 0011637 0 ustar 00 <?php namespace Rvx\Services; use Exception; use Rvx\Api\ReviewsApi; use Rvx\Enum\ReviewStatusEnum; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Rvx\Utilities\TransactionManager; use Rvx\WPDrill\Response; class ReviewService extends \Rvx\Services\Service { protected ReviewsApi $reviewApi; public function __construct() { $this->reviewApi = new ReviewsApi(); } public function getReviews($data) { $query = \http_build_query($data); return (new ReviewsApi())->getReviews($query); } public function reviewList($data) { $query = \http_build_query($data); return (new ReviewsApi())->reviewList($query); } public function createReview($request) { return TransactionManager::run(function () use($request) { $wpCommentData = $this->prepareWpCommentData($request); $commentId = $this->storeReviewMeta($request, $wpCommentData); return $commentId; }, function ($commentId) use($request) { $appReviewData = $this->prepareAppReviewData($request->get_params(), $commentId); // Ensure SaaS payload rating equals the exact value stored in WP DB $storedRating = \get_comment_meta($commentId, 'rating', \true); $appReviewData['rating'] = \is_numeric($storedRating) ? (float) \round($storedRating, 2) : (float) 0.0; return $this->reviewApi->create($appReviewData); }); } /** * Store review metadata. * * @param array $request The request data. * @param array $wpCommentData The prepared WordPress comment data. * @return int The inserted comment ID. */ public function storeReviewMeta($data, array $wpCommentData) : int { try { $files = $data->get_file_params(); $max_file_size = 100 * 1024 * 1024; $attachments = []; $uploaded_images = isset($files['attachments']) ? $files['attachments'] : []; if ($uploaded_images) { foreach ($uploaded_images['size'] as $size) { if ($size > $max_file_size) { throw new Exception('File size exceeds 100MB limit'); } } $attachments = $this->fileUpload($uploaded_images); } else { $attachments = $data->get_params()['attachments'] ? $data->get_params()['attachments'] : []; } $criterias = isset($data->get_params()['criterias']) ? $data->get_params()['criterias'] : null; $isAllowedMultiCriteria = (new \Rvx\Services\SettingService())->getReviewSettings(get_post_type($data->get_params()['wp_post_id']))['reviews']['multicriteria']['enable'] ?? \false; // Calculate the average rating if ($criterias !== null && $isAllowedMultiCriteria === \true) { $wcAverageRating = $this->calculateAverageRating($criterias); } else { $wcAverageRating = (float) \round($data->get_params()['rating'], 2); } $wpCommentData['comment_meta'] = ['reviewx_title' => \strip_tags(\array_key_exists('title', $data->get_params()) ? $data->get_params()['title'] : null), 'is_recommended' => \array_key_exists('is_recommended', $data->get_params()) && $data->get_params()['is_recommended'] === "true" ? 1 : 0, 'verified' => \array_key_exists('verified', $data->get_params()) && $data->get_params()['verified'], 'is_anonymous' => \array_key_exists('is_anonymous', $data->get_params()) && $data->get_params()['is_anonymous'] === "true" ? 1 : 0, 'rvx_criterias' => $criterias, 'rating' => $wcAverageRating, 'reviewx_attachments' => $attachments, 'rvx_review_version' => 'v2']; $commentId = \wp_insert_comment($wpCommentData); if (!\is_wp_error($commentId) && $commentId > 0) { \Rvx\CPT\CptAverageRating::update_average_rating($wpCommentData['comment_post_ID']); return $commentId; } return 0; } catch (Exception $e) { throw new Exception("Review Save field" . $e->getMessage()); } } public function storeReviewMetaFormWidget($data, array $wpCommentData, $file = []) { try { $attachments = !empty($file) ? $file : []; $criterias = isset($data->get_params()['criterias']) ? $data->get_params()['criterias'] : null; // Calculate the average rating $isAllowedMultiCriteria = (new \Rvx\Services\SettingService())->getReviewSettings(get_post_type($data->get_params()['wp_post_id']))['reviews']['multicriteria']['enable'] ?? \false; if ($criterias !== null && $isAllowedMultiCriteria === \true) { $wcAverageRating = $this->calculateAverageRating($criterias); } else { $wcAverageRating = \round($data->get_params()['rating'], 2); } $wpCommentData['comment_meta'] = ['reviewx_title' => \strip_tags(\array_key_exists('title', $data->get_params()) ? $data->get_params()['title'] : null), 'is_recommended' => \array_key_exists('is_recommended', $data->get_params()) && $data->get_params()['is_recommended'] === "true" ? 1 : 0, 'verified' => \array_key_exists('verified', $data->get_params()) && $data->get_params()['verified'], 'is_anonymous' => \array_key_exists('is_anonymous', $data->get_params()) && $data->get_params()['is_anonymous'] === "true" ? 1 : 0, 'rvx_criterias' => $criterias, 'rating' => $wcAverageRating, 'reviewx_attachments' => $attachments, 'rvx_review_version' => 'v2']; $commentId = \wp_insert_comment($wpCommentData); if (!\is_wp_error($commentId) && $commentId > 0) { \Rvx\CPT\CptAverageRating::update_average_rating($wpCommentData['comment_post_ID']); return (int) $commentId; } return 0; } catch (Exception $e) { \error_log($e->getMessage()); } } public function prepareWpCommentData($request) : array { $data = (array) (new \Rvx\Services\SettingService())->getReviewSettings(get_post_type($request['wp_post_id'])); $review_type = 'review'; if (get_post_type($request['wp_post_id']) !== 'product') { $review_type = 'comment'; } $status = Helper::arrayGet($request->get_params(), 'status') ?? $data['reviews']['auto_approve_reviews']; if (!$status || $status === 'false' || $status === '0') { $status = 0; } else { $status = 1; } return ['comment_post_ID' => absint($request['wp_post_id']), 'comment_content' => \strip_tags(\trim($request['feedback'], '"') ?? null), 'comment_author' => sanitize_text_field($request['reviewer_name']), 'comment_author_email' => sanitize_text_field($request['reviewer_email']), 'comment_type' => $review_type, 'comment_approved' => $status, 'comment_agent' => $_SERVER['HTTP_USER_AGENT'], 'comment_author_IP' => $_SERVER['REMOTE_ADDR'], 'comment_date_gmt' => current_time('mysql', 1), 'user_id' => sanitize_text_field($request['user_id']) ?? 0, 'comment_date' => current_time('mysql', \true)]; } /** * Prepare application review data. * * @param array $request The request data. * @param int $commentId The comment ID. * @return array The prepared application review data. */ public function prepareAppReviewData(array $payloadData, int $commentId) : array { $data = ['wp_id' => $commentId, 'product_wp_unique_id' => Client::getUid() . '-' . $payloadData['wp_post_id'] ?? null, 'wp_post_id' => $payloadData['wp_post_id'] ?? null, 'reviewer_email' => sanitize_text_field($payloadData['reviewer_email'] ?? null), 'reviewer_name' => sanitize_text_field($payloadData['reviewer_name'] ?? null), 'rating' => (float) sanitize_text_field(\round($payloadData['rating'], 2) ?? 0.0), 'feedback' => \strip_tags($payloadData['feedback'] ?? null), 'is_verified' => Helper::arrayGet($payloadData, 'verified'), 'auto_publish' => Helper::arrayGet($payloadData, 'status'), 'created_at' => current_time('mysql', \true), 'title' => \strip_tags($payloadData['title'] ?? null), 'attachments' => isset($payloadData['attachments']) ? $payloadData['attachments'] : []]; $data = \array_merge($data, $payloadData); $criterias = Helper::arrayGet($data, 'criterias'); if ($criterias) { $data['criterias'] = \array_map('intval', $criterias); } return $data; } public function aiReviewCount() { return $this->reviewApi->aiReviewCount(); } public function fileUpload($uploaded_images) { if (!isset($uploaded_images['name'])) { return; } $uploaded_urls = []; foreach ($uploaded_images['name'] as $key => $image_name) { $file = ['name' => $uploaded_images['name'][$key], 'type' => $uploaded_images['type'][$key], 'tmp_name' => $uploaded_images['tmp_name'][$key], 'error' => $uploaded_images['error'][$key], 'size' => $uploaded_images['size'][$key]]; $upload = wp_handle_upload($file, ['test_form' => \false]); if (isset($upload['url'])) { $attachment_id = wp_insert_attachment(['guid' => $upload['url'], 'post_mime_type' => $upload['type'], 'post_title' => sanitize_file_name($file['name']), 'post_content' => '', 'post_status' => 'publish'], $upload['file']); $attachment_data = wp_generate_attachment_metadata($attachment_id, $upload['file']); wp_update_attachment_metadata($attachment_id, $attachment_data); $uploaded_urls[] = wp_get_attachment_url($attachment_id); } } return $uploaded_urls; } public function deleteReview($request) { $wpUniqueId = sanitize_text_field($request->get_param('wpUniqueId')); $this->reviewDelete($request->get_params()); $delete_rev = (new ReviewsApi())->deleteReviewData($wpUniqueId); if ($delete_rev) { return Helper::rest($delete_rev)->success(); } return Helper::rest(null)->fails(__("Review Delete Fails", "reviewx")); } public function reviewDelete($data) { $parts = \explode('-', $data['wpUniqueId']); $last_part = \end($parts); wp_delete_comment($last_part, \true); } public function restoreReview($request) { $wpUniqueId = sanitize_text_field($request->get_param('wpUniqueId')); return TransactionManager::run(function () use($wpUniqueId) { $this->restoreTrashToPublish($wpUniqueId); return \true; }, function () use($wpUniqueId) { return $this->reviewApi->restoreReview($wpUniqueId); }); } public function restoreTrashToPublish($review_unique_id) { $id = $this->getLastSegment($review_unique_id); $status = \get_comment_meta($id, '_wp_trash_meta_status', \true); if ($status) { wp_set_comment_status($id, 'approve'); } else { wp_set_comment_status($id, 'hold'); } } public function getReview($request) { $wpUniqueId = sanitize_text_field($request->get_param('wpUniqueId')); return (new ReviewsApi())->getReview($wpUniqueId); } public function restoreTrashItem($data) { //Bulk trash restore $response = (new ReviewsApi())->restoreTrashItem($data); if ((int) $response->getStatusCode() === 200) { $this->bulkRestoreTrashItem($data); } return $response; } public function bulkRestoreTrashItem($data) { foreach ($data['wp_id'] as $id) { $status = \get_comment_meta($id, '_wp_trash_meta_status', \true); if ($status == 'approve' || $status == ReviewStatusEnum::APPROVED) { wp_set_comment_status($id, 'approve'); } elseif ($status == 'hold' || $status == ReviewStatusEnum::PENDING) { wp_set_comment_status($id, 'hold'); } elseif ($status == 'unapproved' || $status == ReviewStatusEnum::UNPUBLISHED) { wp_set_comment_status($id, 'hold'); } elseif ($status == 'spam' || $status == ReviewStatusEnum::SPAM) { wp_set_comment_status($id, 'spam'); } else { wp_set_comment_status($id, 'approve'); } } } public function isVerify($request) { $wpUniqueId = $request['wpUniqueId']; $status = $request->get_param('status'); $verifyData = (new ReviewsApi())->verifyReview($status, $wpUniqueId); if ($verifyData) { return Helper::rest($verifyData()->from('data')->toArray())->success(); } return Helper::rest(null)->fails(__('Verify Fail', 'reviewx')); } public function isvisibility($request) { return TransactionManager::run(function () use($request) { return $this->visibilitySpam($request->get_params()); }, function () use($request) { $wpUniqueId = $request['wpUniqueId']; $statusData = ['status' => $request->get_param('status')]; return $this->reviewApi->visibilityReviewData($statusData, $wpUniqueId); }); } public function visibilitySpam($data) { if (ReviewStatusEnum::SPAM === $data['status']) { wp_spam_comment($data['wp_id']); } if (ReviewStatusEnum::APPROVED === $data['status']) { wp_set_comment_status($data['wp_id'], 'approve'); } if (ReviewStatusEnum::PENDING === $data['status']) { wp_set_comment_status($data['wp_id'], 'hold'); } if (ReviewStatusEnum::TRASH === $data['status']) { wp_trash_comment($data['wp_id']); } return \true; } public function updateReqEmail($request) { $data = []; $wpUniqueId = $request['wpUniqueId']; $verifyData = (new ReviewsApi())->sendUpdateReviewRequestEmail($data, $wpUniqueId); if ($verifyData) { return Helper::rest($verifyData()->from('data')->toArray())->success(__("Verify", "reviewx")); } return Helper::rest(null)->fails(__('Fail', 'reviewx')); } public function reviewReplies($request) { $wpUniqueId = $request['wpUniqueId']; $replies = ['reply' => $request['reply'], 'wp_id' => $this->getLastSegment($wpUniqueId)]; $commentReply = (new ReviewsApi())->commentReply($replies, $wpUniqueId); if ($commentReply) { $this->reviewRepliesForWp($replies); $this->reviewCacheDelete($this->getLastSegment($wpUniqueId)); return Helper::rvxApi(['success' => null])->success('Reply submitted sucesfully.', 200); } return Helper::rest(null)->fails(__('Replies Fail', 'reviewx')); } public function reviewCacheDelete($review_id) { $post_id = get_comment($review_id)->comment_post_ID ?? null; \delete_transient("rvx_{$post_id}_latest_reviews"); \delete_transient("rvx_{$post_id}_latest_reviews_insight"); } public function reviewRepliesForWp($replies) { $parentReviewId = $replies['wp_id']; $parent_comment = get_comment($parentReviewId); if (!$parent_comment) { return \false; } $replyData = $this->prepareDataForReply($parent_comment, $replies, $parentReviewId); if ($parent_comment->comment_parent == 0) { $replayId = \wp_insert_comment($replyData); return \true; } } public function prepareDataForReply($parent_comment, $replies, $parentReviewId) { return ['comment_post_ID' => $parent_comment->comment_post_ID, 'comment_author' => $parent_comment->comment_author, 'comment_author_email' => $parent_comment->comment_author_email, 'comment_author_url' => '', 'comment_content' => $replies['reply'], 'comment_type' => $parent_comment->comment_type, 'comment_parent' => $parentReviewId, 'user_id' => get_current_user_id(), 'comment_approved' => 1, 'comment_date' => current_time('mysql'), 'comment_date_gmt' => current_time('mysql', 1)]; } private function getLastSegment($string) { $lastHyphenPos = \strrpos($string, '-'); if ($lastHyphenPos === \false) { return $string; } return \substr($string, $lastHyphenPos + 1); } public function reviewRepliesUpdate($request) { $wpUniqueId = $request['wpUniqueId']; $repliesUpdate = ['reply' => $request['reply']]; $commentReply = (new ReviewsApi())->updateCommentReply($repliesUpdate, $wpUniqueId); if ($commentReply) { $this->reviewRepliesUpdateForWp($wpUniqueId, $repliesUpdate); $this->reviewCacheDelete($wpUniqueId); return Helper::rest($commentReply()->from('data')->toArray())->success(); } return Helper::rest(null)->fails(__('Update Fail', 'reviewx')); } private function reviewRepliesUpdateForWp($wpUniqueId, $repliesUpdate) { $parentReviewId = $this->getLastSegment($wpUniqueId); $comment_data = array('comment_ID' => $parentReviewId, 'comment_content' => $repliesUpdate['reply'], 'comment_date' => current_time('mysql'), 'comment_date_gmt' => current_time('mysql', 1)); wp_update_comment($comment_data); } public function reviewRepliesDelete($request) { $wpUniqueId = $request['wpUniqueId']; $commentReply = (new ReviewsApi())->deleteCommentReply($wpUniqueId); if ($commentReply) { return Helper::rest($commentReply()->from('data')->toArray())->success(); } return Helper::rest(null)->fails(__('Delete Fail', 'reviewx')); } public function aiReview($request) { global $wpdb; $wpdb->query('START TRANSACTION'); try { $comment_id = \wp_insert_comment($this->aiReviewWp($request)); $reviApp = $this->aiReviewApp($request, $comment_id); $reviewApi = new ReviewsApi(); $res = $reviewApi->aiReview($reviApp); $resReviewData = $res->getApiData(); wp_update_comment($comment_id, $resReviewData); $wpdb->query('COMMIT'); return $res; } catch (Exception $e) { $wpdb->query('ROLLBACK'); } } public function aggregationMeta($request) { try { foreach ($request->get_params() as $data) { $productId = Helper::arrayGet($data, 'product_wp_id'); if (!$productId) { continue; } $aggregation_data = \json_encode(wp_slash(Helper::arrayGet($data, "meta")), \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES); \set_transient("rvx_{$productId}_latest_reviews_insight", $aggregation_data, 604800); // Expires in 7 days } return Helper::rest()->success("Success"); } catch (Exception $e) { return Helper::rest($e->getMessage())->fails("Fails"); } } public function aiReviewApp($request, $comment_id) { return ["wp_id" => $comment_id, "product_wp_unique_id" => $request['product_wp_unique_id'], "wp_post_id" => $request['wp_post_id'], "max_reviews" => $request['max_reviews'], "status" => $request['status'], "verified" => $request['verified'], "region" => $request['region'], "religious" => $request['religious'], "gender" => $request['gender']]; } public function aiReviewWp($request) { $review_type = 'review'; if (get_post_type($request['wp_post_id']) !== 'product') { $review_type = 'comment'; } return ['comment_post_ID' => absint($request['product_id']), 'comment_content' => sanitize_text_field($request['feedback'] ?? ''), 'comment_author' => sanitize_text_field(get_userdata(get_current_user_id())->display_name), 'comment_author_email' => sanitize_text_field(get_userdata(get_current_user_id())->user_email), 'comment_type' => $review_type, 'comment_approved' => sanitize_text_field($request['status'] ?? ''), 'comment_agent' => $_SERVER['HTTP_USER_AGENT'], 'comment_author_IP' => $_SERVER['REMOTE_ADDR'], 'comment_date_gmt' => current_time('mysql', 1), 'comment_date' => current_time('mysql', \true)]; } public function updateWooReview($updatedData, $wpUpdatedData) { $wpUniqueId = $updatedData['wp_unique_id']; try { $reviewApi = new ReviewsApi(); $res = $reviewApi->updateWooReviewData($updatedData, $wpUniqueId); if ($res->getStatusCode() !== Response::HTTP_OK) { return ['error' => $res->getStatusCode()]; } return $res; } catch (Exception $e) { return ["error" => "Review Not updated"]; } } public function updateReview($request) { $reviewId = $request->get_param('wp_id'); $wpUniqueId = $request->get_param('wpUniqueId'); return TransactionManager::run(function () use($request, $reviewId) { $existingReview = get_comment($reviewId); if (!$existingReview) { return \false; } $wpCommentData = $this->prepareUpdateWpComment($request, $existingReview); wp_update_comment(['comment_ID' => $reviewId, 'comment_content' => \strip_tags($wpCommentData['comment_content']), 'comment_approved' => sanitize_text_field($wpCommentData['comment_approved']), 'comment_author_email' => sanitize_text_field($wpCommentData['comment_author_email']), 'comment_author' => sanitize_text_field($wpCommentData['comment_author'])]); $this->reviewCacheDelete($reviewId); $this->updateReviewMeta($reviewId, $request); // Update average rating for the post \Rvx\CPT\CptAverageRating::update_average_rating($existingReview->comment_post_ID); return \true; }, function () use($request, $wpUniqueId) { $appReviewData = $this->prepareUpdateAppReview($request->get_params(), $request->get_file_params()); $response = $this->reviewApi->updateReviewData($appReviewData, $wpUniqueId); if (!\is_object($response)) { return \false; } return $response; }); } public function updateReviewMeta($reviewId, $data) { $params = $data->get_params(); // 1. Title if (isset($params['title'])) { \update_comment_meta($reviewId, 'reviewx_title', sanitize_text_field($params['title'])); } // 2. Rating & Criterias $criterias = $params['criterias'] ?? null; if ($criterias !== null) { \update_comment_meta($reviewId, 'rvx_criterias', $criterias); $wp_post_id = $params['wp_post_id'] ?? get_comment($reviewId)->comment_post_ID; $isAllowedMultiCriteria = (new \Rvx\Services\SettingService())->getReviewSettings(get_post_type($wp_post_id))['reviews']['multicriteria']['enable'] ?? \false; if ($isAllowedMultiCriteria) { $wcAverageRating = $this->calculateAverageRating($criterias); \update_comment_meta($reviewId, 'rating', $wcAverageRating); \update_comment_meta($reviewId, 'reviewx_rating', $wcAverageRating); } } elseif (isset($params['rating'])) { $rating = (float) \round($params['rating'], 2); \update_comment_meta($reviewId, 'rating', $rating); \update_comment_meta($reviewId, 'reviewx_rating', $rating); } // 3. Flags (Safe updates using filter_var for string booleans) if (isset($params['verified'])) { \update_comment_meta($reviewId, 'verified', \filter_var($params['verified'], \FILTER_VALIDATE_BOOLEAN)); } if (isset($params['is_recommended'])) { \update_comment_meta($reviewId, 'is_recommended', \filter_var($params['is_recommended'], \FILTER_VALIDATE_BOOLEAN) ? 1 : 0); } if (isset($params['is_anonymous'])) { \update_comment_meta($reviewId, 'is_anonymous', \filter_var($params['is_anonymous'], \FILTER_VALIDATE_BOOLEAN) ? 1 : 0); } // 4. Attachments if (isset($params['attachments'])) { \update_comment_meta($reviewId, 'reviewx_attachments', $params['attachments'] ?? []); } } /** * Prepare WordPress comment data for updating. * * @param array $request The request data. * @param WP_Comment $existingReview The existing review data. * @return array The prepared WordPress comment data. */ public function prepareUpdateWpComment($request, $existingReview) { return ['comment_content' => \strip_tags($request['feedback'] ?? $existingReview->comment_content), 'comment_approved' => sanitize_text_field($request['status'] ?? $existingReview->comment_approved), 'comment_author_email' => sanitize_text_field($request['reviewer_email'] ?? $existingReview->comment_author_email), 'comment_author' => sanitize_text_field($request['reviewer_name'] ?? $existingReview->comment_author)]; } public function prepareUpdateAppReview(array $payloadData, array $files) { $isRecommended = isset($payloadData['is_recommended']) == 1 ? \true : \false; // $uploaded_images = $files['attachments']; // $uploaded_images = isset($files['attachments']) ? $files['attachments'] : []; // $attachments = $this->fileUpload($uploaded_images); $criterias = Helper::arrayGet($payloadData, 'criterias'); $rating = Helper::arrayGet($payloadData, 'rating', null); if ($criterias) { $wp_post_id = $payloadData['wp_post_id'] ?? null; $isAllowedMultiCriteria = $wp_post_id ? (new \Rvx\Services\SettingService())->getReviewSettings(get_post_type($wp_post_id))['reviews']['multicriteria']['enable'] ?? \false : \true; if ($isAllowedMultiCriteria) { $rating = $this->calculateAverageRating($criterias); } } $payloadData['rating'] = $rating ? (float) \round($rating, 2) : (float) 0.0; $data = [ // 'rating' => (int)$payloadData['rating'], 'feedback' => \strip_tags($payloadData['feedback']), 'title' => \strip_tags($payloadData['title']), 'reviewer_name' => sanitize_text_field($payloadData['reviewer_name']), 'reviewer_email' => sanitize_text_field($payloadData['reviewer_email']), 'date' => current_time('mysql', \true), 'anonymous' => isset($payloadData['anonymous']), 'is_recommended' => $isRecommended, 'attachment_access' => isset($payloadData['attachment_access']), ]; $data = \array_merge($payloadData, $data); $criterias = Helper::arrayGet($payloadData, 'criterias'); if ($criterias) { $payloadData['criterias'] = \array_map('intval', $criterias); } return $data; } public function getWidgetReviewsForProduct($request) { return (new ReviewsApi())->getWidgetReviewsForProductApi($request); } public function getWidgetAllReviewsForSite($request, $site_id) { return (new ReviewsApi())->getWidgetAllReviewsForSiteApi($request, $site_id); } public function getWidgetReviewsListShortcode($request) { return (new ReviewsApi())->getWidgetReviewsListShortcodeApi($request); } public function settingMeta($request) { try { $settings = $request->get_params()['meta']; (new \Rvx\Services\SettingService())->updateSettingsData($settings); return Helper::rest()->success("Success"); } catch (Exception $th) { return Helper::rest()->fails("Fails"); } } public static function getSpecificReviewItem($data) { $review_ids = $data['review_ids']; $uid = Client::getUid(); $review_wp_unique_ids = \array_map(function ($id) use($uid) { return $uid . '-' . $id; }, $review_ids); $data = []; $data['review_wp_unique_ids'] = $review_wp_unique_ids; return (new ReviewsApi())->getSpecificReviewItem($uid, $data); } public function getSingleProductAllReviews($data) { return (new ReviewsApi())->getSingleProductAllReviews($data); } public function getWidgetInsight($request) { return (new ReviewsApi())->getWidgetInsight($request); } public function reviewBulkUpdate($data) { return TransactionManager::run(function () use($data) { $this->reviewBulkStatusUpdateForWp($data); return \true; }, function () use($data) { return $this->reviewApi->reviewBulkUpdate($data); }); } public function reviewBulkStatusUpdateForWp($data) { if (ReviewStatusEnum::SPAM === $data['status']) { foreach ($data['wp_id'] as $id) { wp_spam_comment($id); } } if (ReviewStatusEnum::APPROVED === $data['status']) { foreach ($data['wp_id'] as $id) { wp_set_comment_status($id, 'approve'); } } if (ReviewStatusEnum::PENDING === $data['status']) { foreach ($data['wp_id'] as $id) { wp_set_comment_status($id, 'hold'); } } if (ReviewStatusEnum::TRASH === $data['status']) { foreach ($data['wp_id'] as $id) { wp_trash_comment($id); } } } public function reviewBulkTrash($data) { return TransactionManager::run(function () use($data) { $this->bulkTrashInWp($data); return \true; }, function () use($data) { return $this->reviewApi->reviewBulkTrash($data); }); } public function bulkTrashInWp($data) { if (!\is_array($data)) { return \false; } foreach ($data['wp_id'] as $review_id) { wp_trash_comment($review_id, \true); } } public function reviewEmptyTrash($data) { return TransactionManager::run(function () use($data) { $this->emptyTrashInWp($data); return \true; }, function () use($data) { return $this->reviewApi->reviewEmptyTrash(); }); } public function emptyTrashInWp($review_ids) { if (!\is_array($review_ids)) { return \false; } foreach ($review_ids['wp_ids'] as $review_id) { wp_delete_comment($review_id, \true); } return \true; } public function reviewAggregation() { return (new ReviewsApi())->reviewAggregation(); } public function saveWidgetReviewsForProduct($request) { return TransactionManager::run(function () use($request) { return $this->dataMerge($request); }, function ($data) { return $this->reviewApi->saveWidgetReviewsForProductApi($data); }); } public function dataMerge($request) { $files = $request->get_file_params(); $max_file_size = 100 * 1024 * 1024; // 100MB in bytes $attachments = []; if (!empty($files['attachments']['name']) && \is_array($files['attachments']['size'])) { foreach ($files['attachments']['size'] as $size) { if ($size > $max_file_size) { return ['error' => 'File size exceeds 100MB limit']; } } $attachments = $this->fileUpload($files['attachments']); } $wpCommentData = $this->prepareWpCommentData($request); $commentId = $this->storeReviewMetaFormWidget($request, $wpCommentData, $attachments); $productId = $request->get_param('wp_post_id'); $siteUid = Client::getUid(); $productWpUniqueId = $siteUid . '-' . $productId; $data = \array_merge($request->get_params(), ["wp_id" => $commentId, "site_uid" => $siteUid, "product_wp_unique_id" => $productWpUniqueId, "is_anonymous" => $request['is_anonymous'] == "true" ? \true : \false, "is_verified" => $request['verified'] == "true" ? \true : \false, "is_customer_verified" => $request['is_customer_verified'] == "true" ? \true : \false, "attachments" => $attachments, 'created_at' => current_time('mysql', \true), 'is_recommended' => $request['is_recommended'] == "true" ? \true : \false]); $data['feedback'] = \strip_tags($request['feedback']); $data['title'] = \strip_tags($request['title']); $criterias = Helper::arrayGet($data, 'criterias'); $post_type = get_post_type($productId); $review_setting = (new \Rvx\Services\SettingService())->getReviewSettings($post_type); $criteria_enabled = $review_setting['reviews']['multicriteria']['enable']; if ($criterias && $criteria_enabled === \true) { $data['criterias'] = \array_map('intval', $criterias); // Rating Modified $total_rating = \array_sum($data['criterias']); $rating_count = \count($data['criterias']); // Count of valid values $data['rating'] = $rating_count > 0 ? (float) \round($total_rating / $rating_count, 2) : (float) 0.0; } else { $data['rating'] = $request['rating'] ? (float) \round($request['rating'], 2) : (float) 0.0; } return $data; } public function requestReviewEmailAttachment($request) { // Get parameters and file payload $wpUniqueId = $request->get_params(); $payload = $request->get_file_params(); // Initialize the response array $response = []; // Maximum file size in bytes (e.g., 5MB) $maxFileSize = 5 * 1024 * 1024; // 5 MB // Allowed mime types for images $allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif', 'video/mp4', 'video/webm', 'video/ogg']; // Loop through the reviews array foreach ($wpUniqueId['reviews'] as $index => $reviewData) { if (isset($reviewData['wp_unique_id'])) { $wp_unique_id = $this->getLastSegment($reviewData['wp_unique_id']); // Prepare the files array for this review $files = []; if (isset($payload['reviews']['tmp_name'][$index]['files'])) { foreach ($payload['reviews']['tmp_name'][$index]['files'] as $fileIndex => $tmpFile) { // Get the corresponding file details $file_info = ['name' => $payload['reviews']['name'][$index]['files'][$fileIndex]['file'], 'tmp_name' => $tmpFile['file'], 'type' => $payload['reviews']['type'][$index]['files'][$fileIndex]['file'], 'error' => $payload['reviews']['error'][$index]['files'][$fileIndex]['file'], 'size' => $payload['reviews']['size'][$index]['files'][$fileIndex]['file']]; // Validate file size if ($file_info['size'] > $maxFileSize) { continue; } // Validate file type (mime type) if (!\in_array($file_info['type'], $allowedMimeTypes)) { continue; } if ($file_info['error'] === \UPLOAD_ERR_OK) { // Upload the file to WordPress $upload = wp_handle_upload($file_info, ['test_form' => \false]); if (!isset($upload['error']) && isset($upload['url'])) { // Add the file URL to the files array $files[] = ['file' => $upload['url']]; } } } } $image_urls = \array_map(function ($file) { return $file['file']; }, $files); \update_comment_meta($wp_unique_id, 'reviewx_attachments', $image_urls); // Add the data for this review $response[] = ['wp_unique_id' => Client::getUid() . '-' . $wp_unique_id, 'files' => $files]; } } return $response; } public function reviewMoveToTrash($data) { return TransactionManager::run(function () use($data) { $this->trashInWp($data); return \true; }, function () use($data) { return $this->reviewApi->reviewMoveToTrash($data); }); } public function trashInWp($data) { $parts = \explode('-', $data['WpUniqueId']); $last_part = \end($parts); wp_trash_comment($last_part); } public function likeDIslikePreference($data) { return (new ReviewsApi())->likeDIslikePreference($data); } public function reviewListMultiCriteria() { return (new ReviewsApi())->reviewListMultiCriteria(); } public function highlight($data) { return (new ReviewsApi())->highlight($data); } public function bulkTenReviews($data) { return $data; } public function reviewRequestStoreItem($data) { global $wpdb; $wpdb->query('START TRANSACTION'); try { $comment_ids = $this->commentInsertableFormEmail($data); $saasData = $this->prepareAppReviewDataFormEmail($comment_ids); // return $this->reviewApi->reviewRequestStoreItem($saasData, $uid); $wpdb->query('COMMIT'); return $saasData; } catch (Exception $e) { $wpdb->query('ROLLBACK'); } } public function commentInsertableFormEmail($data) { $wpCommentData = $this->prepareWpCommentDataForEmail($data); return $this->storeReviewMetaForEmail($data, $wpCommentData); } public function prepareAppReviewDataFormEmail(array $commentIds) : array { $reviewData = ['reviews' => []]; foreach ($commentIds as $commentId) { $comment = get_comment($commentId); if (!$comment) { continue; } $data = ['wp_id' => (int) $comment->comment_ID, 'product_wp_unique_id' => Client::getUid() . '-' . $comment->comment_post_ID, 'wp_post_id' => (int) $comment->comment_post_ID, 'reviewer_email' => $comment->comment_author_email, 'reviewer_name' => $comment->comment_author, 'rating' => (float) \round(\get_comment_meta($comment->comment_ID, 'rating', \true), 2), 'feedback' => $comment->comment_content, 'created_at' => $comment->comment_date, 'title' => \get_comment_meta($comment->comment_ID, 'rvx_comment_title', \true), 'order_item_wp_unique_id' => \get_comment_meta($comment->comment_ID, 'rvx_comment_order_item', \true), 'criterias' => \get_comment_meta($comment->comment_ID, 'rvx_criterias', \true)]; $reviewData['reviews'][] = $data; } return $reviewData; } public function prepareWpCommentDataForEmail($data) : array { //Send email review only product $settingsData = (new \Rvx\Services\SettingService())->getReviewSettings('product'); $auto_approve_reviews = $settingsData['reviews']['auto_approve_reviews']; $review_type = 'review'; if (get_post_type($request['wp_post_id']) !== 'product') { $review_type = 'comment'; } $dataStore = []; foreach ($data['reviews'] as $review) { $dataWp = ['comment_post_ID' => absint($review['product_wp_id']), 'comment_content' => sanitize_text_field($review['feedback'] ?? ''), 'comment_author' => sanitize_text_field($review['reviewer_name']), 'comment_author_email' => sanitize_text_field($review['reviewer_email']), 'comment_type' => $review_type, 'comment_approved' => $auto_approve_reviews === \true ? 1 : 0, 'comment_agent' => $_SERVER['HTTP_USER_AGENT'], 'comment_author_IP' => $_SERVER['REMOTE_ADDR'], 'comment_date_gmt' => current_time('mysql', 1), 'user_id' => absint($review['user_id']) ?? 0, 'comment_date' => current_time('mysql', \true)]; $dataStore[] = $dataWp; } return $dataStore; } public function storeReviewMetaForEmail($data, array $wpCommentData) : array { try { $id = []; $isAllowedMultiCriteria = (new \Rvx\Services\SettingService())->getReviewSettings('product')['reviews']['multicriteria']['enable'] ?? \false; foreach ($wpCommentData as $index => $comment) { $criterias = $data['reviews'][$index]['criterias'] ?? null; if (!empty($criterias) && $criterias !== null && $isAllowedMultiCriteria === \true) { // Calculate the average rating $wcAverageRating = $this->calculateAverageRating($criterias); $modified_criteria = \json_encode($criterias); } else { $wcAverageRating = (float) sanitize_text_field(\round($data['reviews'][$index]['rating'], 2)) ?? 0.0; $modified_criteria = null; } $commentId = \wp_insert_comment($comment); add_comment_meta($commentId, 'rvx_comment_title', sanitize_text_field($data['reviews'][$index]['title'] ?? null)); \update_comment_meta($commentId, 'rvx_criterias', $modified_criteria); add_comment_meta($commentId, 'rating', $wcAverageRating); add_comment_meta($commentId, 'rvx_comment_order_item', sanitize_text_field($data['reviews'][$index]['order_item_wp_unique_id'])); add_comment_meta($commentId, 'verified', 1); add_comment_meta($commentId, 'is_recommended', 1); add_comment_meta($commentId, 'reviewx_attachments', []); add_comment_meta($commentId, 'rvx_review_version', 'v2'); $id[] = $commentId; } return $id; } catch (Exception $e) { throw new Exception('Something went wrong!' . $e->getMessage()); } } /** * Calculate the average rating from criteria values. * * @param array|null $criterias An array containing numeric values or key-value pairs with numeric values. * @return int The ceiling value of the average, or 1 if no valid data exists. */ public function calculateAverageRating($criterias) { // Ensure $criterias is an array; default to an empty array if it's null or not an array if (!\is_array($criterias)) { return (float) 0.0; // Fallback value } // Normalize all values to float $values = \array_map(function ($value) { return \is_numeric($value) ? (int) $value : 0; // Convert numeric values to float, default to 0.00 }, \array_values($criterias)); // Filter out any invalid (zero or negative) values $values = \array_filter($values, function ($value) { return $value > 0; // Keep only positive integers }); $total = \array_sum($values); // Sum of all valid values $count = \count($values); // Count of valid values return $count > 0 ? (float) \round($total / $count, 2) : (float) 0.0; // Calculate the average and round up } public function thanksMessage($request) { return ['message' => "Thank you for sharing your review"]; } public function setAllReviewsMetaTransient($site_id, $post_type, $latest_reviews) { $post_type = $post_type != null ? $post_type : 'all'; \set_transient("rvx_{$site_id}_{$post_type}_reviews", wp_slash($latest_reviews), 3600); // Expires in 1 hour } public function postMetaReviewInsert($id, $latest_reviews) { \set_transient("rvx_{$id}_latest_reviews", wp_slash($latest_reviews), 3600); // Expires in 1 hour } public function allReviewApproveCount() : int { global $wpdb; $query = $wpdb->prepare("SELECT COUNT(*) \n FROM {$wpdb->comments} \n WHERE comment_approved = '1' \n AND comment_parent = 0 \n AND comment_type IN ('review','comment')"); return (int) $wpdb->get_var($query); } public function allReviewPendingCount() : int { global $wpdb; $query = $wpdb->prepare("SELECT COUNT(*) \n FROM {$wpdb->comments} \n WHERE comment_approved = '0' \n AND comment_parent = 0\n AND comment_type IN ('review','comment')"); return (int) $wpdb->get_var($query); } public function saasStatusReviewCount() { $data = \get_transient('rvx_reviews_data_list'); if (\is_array($data)) { return $data['count']; } return []; } public function makeSaaSCallDecision() { $approveReviewCount = $this->allReviewApproveCount(); $pendingReviewCount = $this->allReviewPendingCount(); $saasApproveReviewCount = \array_key_exists('published', $this->saasStatusReviewCount()) ? $this->saasStatusReviewCount()['published'] : 0; $saasPendingReviewCount = \array_key_exists('pending', $this->saasStatusReviewCount()) ? $this->saasStatusReviewCount()['pending'] : 0; if ($approveReviewCount != $saasApproveReviewCount) { return \true; } if ($saasPendingReviewCount != $pendingReviewCount) { return \true; } return \false; } } Services/EmailService.php 0000777 00000004104 15251220643 0011416 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Apiz\Http\Response; use Rvx\Api\EmailApi; class EmailService extends \Rvx\Services\Service { /** * @return Response */ public function index() { return (new EmailApi())->index(); } /** * @return Response */ public function store($data) { return (new EmailApi())->create($data); } /** * @return Response */ public function update($data) { return (new EmailApi())->update($data); } /** * @return Response */ public function remove($request) { return (new EmailApi())->remove(); } public function mailRequest($data) { $query = \http_build_query($data); return (new EmailApi())->mailRequest($query); } public function content() { return (new EmailApi())->content(); } public function saveEmailRequest($data) { return (new EmailApi())->saveEmailRequest($data); } public function followup($data) { return (new EmailApi())->followup($data); } public function photoReview($data) { return (new EmailApi())->photoReview($data); } public function testMail($data) { return (new EmailApi())->testMail($data); } public function markAsComplete($data) { return (new EmailApi())->markAsComplete($data['uid']); } public function emailCancel($data) { return (new EmailApi())->emailCancel($data['uid']); } public function requestEmailSend($data) { return (new EmailApi())->requestEmailSend($data); } public function requestEmailResend($data) { return (new EmailApi())->requestEmailResend($data); } public function requestEmailUnsubscribe() { return (new EmailApi())->requestEmailUnsubscribe(); } public function reviewRequestSettings() { return (new EmailApi())->reviewRequestSettings(); } public function allReminderSettings($data) { return (new EmailApi())->allReminderSettings($data); } } Services/SettingService.php 0000777 00000030234 15251220643 0012007 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Api\SettingApi; class SettingService extends \Rvx\Services\Service { protected $settingApi; public function __construct() { // $this->settingApi = new SettingApi(); } public function getApiReviewSettings($data) { return (new SettingApi())->getApiReviewSettings($data); } public function saveApiReviewSettings($data) { return (new SettingApi())->saveApiReviewSettings($data); } public function getApiWidgetSettings() { return (new SettingApi())->getAPiWidgetSettings(); } public function saveWidgetSettings($data) { return (new SettingApi())->saveApiWidgetSettings($data); } /** * Get Settings Data * @return array */ public function getSettingsData($post_type = null) : array { $review_settings = $this->getReviewSettings($post_type); $widget_settings = $this->getWidgetSettings(); $rvx_settings = $this->formatSettings($review_settings, $widget_settings); // Ensure we always return an array even if invalid data exists return \is_array($rvx_settings) ? $rvx_settings : []; } public function getReviewSettings($post_type = null) : array { $default_cpt_name = 'product'; if ($post_type !== null) { $default_cpt_name = $post_type; } $option_name = '_rvx_settings_' . $default_cpt_name; $rvx_settings = \get_option($option_name, \false); if ($post_type === 'product' && $rvx_settings === \false) { $rvx_settings = \get_option('_rvx_settings_data'); } return $rvx_settings['setting']['review_settings'] ?? []; } public function getWidgetSettings() : array { $option_name = '_rvx_settings_widget'; $rvx_settings = \get_option($option_name, \false); if ($rvx_settings === \false) { $rvx_settings = \get_option('_rvx_settings_data'); } return $rvx_settings['setting']['widget_settings'] ?? []; } /** * Upadte Settings Data * @return array */ public function updateSettingsData(array $data, $post_type = null) : void { \update_option("_rvx_settings_data", $data); } public function updateReviewSettings(array $review_settings, $post_type = null) : void { $default_cpt_name = 'product'; if ($post_type !== null) { $default_cpt_name = $post_type; if ($post_type === 'product') { $review_settings = $review_settings['reviews']; } } $option_name = '_rvx_settings_' . $default_cpt_name; $data = ["setting" => ["review_settings" => ["reviews" => $review_settings]]]; if ($post_type !== 'product') { // Define the review submission policy $policy = ["review_submission_policy" => ["options" => ["anyone" => 1]]]; // Ensure reviews is an array and merge policy directly into it if (!\is_array($data['setting']['review_settings']['reviews'])) { $data['setting']['review_settings']['reviews'] = []; } // Merge the policy directly at the top level of "reviews" $data['setting']['review_settings']['reviews'] = \array_merge($policy, $data['setting']['review_settings']['reviews']); } \update_option($option_name, $data); } public function updateReviewSettingsOnSync(array $review_settings, $post_type = null) : void { $default_cpt_name = 'product'; if ($post_type !== null) { $default_cpt_name = $post_type; $review_settings = $review_settings['reviews']; } $option_name = '_rvx_settings_' . $default_cpt_name; $data = ["setting" => ["review_settings" => ["reviews" => $review_settings]]]; if ($post_type !== 'product') { // Define the review submission policy $policy = ["review_submission_policy" => ["options" => ["anyone" => 1]]]; // Ensure reviews is an array and merge policy directly into it if (!\is_array($data['setting']['review_settings']['reviews'])) { $data['setting']['review_settings']['reviews'] = []; } // Merge the policy directly at the top level of "reviews" $data['setting']['review_settings']['reviews'] = \array_merge($policy, $data['setting']['review_settings']['reviews']); } \update_option($option_name, $data); } public function updateWidgetSettings(array $widget_settings) : void { $data = ["setting" => ["widget_settings" => $widget_settings]]; \update_option("_rvx_settings_widget", $data); } private function formatSettings(array $review_settings, array $widget_settings) : array { $data = ["setting" => ["review_settings" => $review_settings, "widget_settings" => $widget_settings]]; return $data ?? []; } public function wooCommerceVerificationRating() : array { $value = \get_option('woocommerce_review_rating_verification_label', 'no'); return ['active' => $value === 'yes']; } public function wooVerificationRatingRequired() : array { $value = \get_option('woocommerce_review_rating_verification_required', 'no'); return ['active' => $value === 'yes']; } public function wooCommerceVerificationRatingUpdate($data) { if ($data['active'] == \true) { \update_option('woocommerce_review_rating_verification_label', 'yes'); $data = ['success' => \true, 'message' => __("Verified Owner Active")]; return $data; } if ($data['active'] == \false) { \update_option('woocommerce_review_rating_verification_label', 'no'); $data = ['success' => \true, 'message' => __("Verified Owner Deactive")]; return $data; } } public function wooVerificationRating($data) { if ($data['active'] == \true) { \update_option('woocommerce_review_rating_verification_required', 'yes'); $data = ['success' => \true, 'message' => __("Reviews can only be left by verified owners active")]; return $data; } if ($data['active'] == \false) { \update_option('woocommerce_review_rating_verification_required', 'no'); $data = ['success' => \true, 'message' => __("Reviews can only be left by verified owners deactive")]; return $data; } } public function userCurrentPlan() { return (new SettingApi())->userCurrentPlan(); } public function getApiGeneralSettings() { return (new SettingApi())->getApiGeneralSettings(); } public function saveApiGeneralSettings($data) { return (new SettingApi())->saveApiGeneralSettings($data); } public function allSettingsSave($data) { $payload_json = \json_encode($data['settings']); \update_option('rvx_all_setting_data', $payload_json); return ['message' => __('Settings saved successfully'), 'data' => $data['settings']]; } public function removeCredentials($requestData) { global $wpdb; $table_name = $wpdb->prefix . 'rvx_sites'; $sql = "TRUNCATE TABLE {$table_name}"; $result = $wpdb->query($sql); if ($wpdb->last_error) { return ['message' => 'Error: ' . $wpdb->last_error]; } return ['message' => 'Site Table deleted successfully', 'result' => $result]; } public function updateSiteData($requestHeaders) { global $wpdb; $table_name = $wpdb->prefix . 'rvx_sites'; // --- Extract headers (headers come as arrays) --- $user_email = isset($requestHeaders['x_user_email'][0]) ? sanitize_email($requestHeaders['x_user_email'][0]) : ''; $user_name = isset($requestHeaders['x_user_name'][0]) ? sanitize_text_field($requestHeaders['x_user_name'][0]) : ''; $site_uid = isset($requestHeaders['x_site_uid'][0]) ? sanitize_text_field($requestHeaders['x_site_uid'][0]) : ''; // $site_id = isset($requestHeaders['x_site_id'][0]) ? intval($requestHeaders['x_site_id'][0]) : 0; // $domain = isset($requestHeaders['x_domain'][0]) ? sanitize_text_field($requestHeaders['x_domain'][0]) : ''; // --- Validation: must provide at least one field to update --- if (empty($user_email) && empty($user_name)) { // error_log('[ReviewX] updateSiteData: Missing X-User-Email and X-User-Name in request headers.'); return ['status' => 'fail', 'message' => 'Missing X-User-Email and X-User-Name in request headers.']; } // --- Decide which identifier to use for WHERE (preferred order: uid, site_id, domain) --- $where = []; $where_fmt = []; if (!empty($site_uid)) { $where = ['uid' => $site_uid]; $where_fmt = ['%s']; } else { // No identifier provided — refuse to do a global update for safety // error_log('[ReviewX] updateSiteData: No site identifier provided (x_site_uid, x_site_id or x_domain). Aborting to avoid global update.'); return ['status' => 'fail', 'message' => 'Missing site identifier. Provide x_site_uid, x_site_id or x_domain in request headers.']; } // --- Prepare data to update --- $data = []; $format = []; if (!empty($user_email)) { $data['email'] = $user_email; $format[] = '%s'; } if (!empty($user_name)) { $data['name'] = $user_name; $format[] = '%s'; } if (empty($data)) { return ['status' => 'fail', 'message' => 'No valid update fields provided.']; } // error_log('[ReviewX] updateSiteData: Target WHERE: ' . print_r($where, true) . ' — Updating: ' . print_r($data, true)); // --- Fetch existing row to detect no-op updates and to ensure the row exists --- $where_keys = \array_keys($where); // Build a safe WHERE clause and prepare values $where_clauses = []; $where_values = []; foreach ($where as $col => $val) { $where_clauses[] = "{$col} = %s"; $where_values[] = (string) $val; } $where_sql = \implode(' AND ', $where_clauses); $select_sql = $wpdb->prepare("SELECT * FROM {$table_name} WHERE {$where_sql} LIMIT 1", $where_values); $existing = $wpdb->get_row($select_sql, ARRAY_A); if (null === $existing) { // error_log('[ReviewX] updateSiteData: No site row found for identifier: ' . print_r($where, true)); return ['status' => 'fail', 'message' => 'No site found matching provided identifier.', 'where' => $where]; } // Compare values — if identical, return success (no change needed) $is_same = \true; foreach ($data as $col => $val) { $existing_val = isset($existing[$col]) ? (string) $existing[$col] : ''; if ($existing_val !== (string) $val) { $is_same = \false; break; } } if ($is_same) { return ['status' => 'success', 'message' => 'No changes required — data already up to date.', 'data' => $data, 'where' => $where]; } // --- Perform the update using $wpdb->update (safe) --- $updated = $wpdb->update($table_name, $data, $where, $format, $where_fmt); if ($wpdb->last_error) { // error_log('[ReviewX] updateSiteData: DB error - ' . $wpdb->last_error); return ['status' => 'error', 'message' => 'Database error: ' . $wpdb->last_error]; } // $updated can be: false (error), 0 (no rows changed), >0 (rows updated) if ($updated === \false) { return ['status' => 'error', 'message' => 'Failed to update site data.']; } $rows = $wpdb->rows_affected; return ['status' => 'success', 'message' => $rows > 0 ? "Site data updated successfully ({$rows} row(s) affected)." : 'No rows were changed.', 'data' => $data, 'where' => $where]; } public function getLocalSettings($post_type) { return (new SettingApi())->getLocalSettings($post_type); } } Services/DashboardServices.php 0000777 00000002137 15251220643 0012445 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Api\DashboardApi; class DashboardServices extends \Rvx\Services\Service { public function insight() { return (new DashboardApi())->insightReviews(); } public function requestEmail() { return (new DashboardApi())->requestEmail(); } public function requestUserData() { global $wpdb; $table_name = $wpdb->prefix . 'rvx_sites'; $site_data = $wpdb->get_row("SELECT * FROM {$table_name} WHERE id = 1"); // error_log('Site Data: ' . print_r($site_data, true)); if (!$site_data) { return ['success' => \false, 'message' => 'No site data found', 'data' => null]; } return ['success' => \true, 'message' => 'Site user data fetched successfully', 'site_id' => $site_data->site_id, 'user_name' => $site_data->name, 'user_email' => $site_data->email, 'site_domain' => $site_data->domain, 'is_saas_synced' => $site_data->is_saas_sync]; } public function chart($request) { $time = $request['view']; return (new DashboardApi())->chart($time); } } Services/DataSyncService.php 0000777 00000014452 15251220643 0012104 0 ustar 00 <?php namespace Rvx\Services; use Exception; use Rvx\Api\DataSyncApi; use Rvx\Api\WebhookRequestApi; use Rvx\Handlers\DataSyncHandler; use Rvx\Services\Service; use Rvx\Services\OrderService; use Rvx\Services\OrderItemSyncService; use Rvx\Services\UserSyncService; use Rvx\Services\ProductSyncService; use Rvx\Services\ReviewSyncService; // use Rvx\Services\CategorySyncService; use Rvx\Utilities\Helper; class DataSyncService extends Service { protected DataSyncHandler $dataSyncHandler; protected UserSyncService $userSyncService; // protected CategorySyncService $categorySyncService; protected ProductSyncService $productSyncService; protected ReviewSyncService $reviewSyncService; protected OrderService $orderService; protected OrderItemSyncService $orderItemSyncService; public function __construct() { $this->dataSyncHandler = new DataSyncHandler(); $this->userSyncService = new UserSyncService(); // $this->categorySyncService = new CategorySyncService(); $this->productSyncService = new ProductSyncService(); $this->reviewSyncService = new ReviewSyncService(); $this->orderService = new OrderService(); $this->orderItemSyncService = new OrderItemSyncService(); } public function dataSync($from, $post_type = 'product') : bool { try { $reviewx_dir_exists = \is_dir(WP_CONTENT_DIR . '/uploads/reviewx'); if (!$reviewx_dir_exists) { // Create the directory if it does not exist \mkdir(WP_CONTENT_DIR . '/uploads/reviewx', 0777, \true); } // Create the file path for the sync data // Sanitize just in case: $post_type = sanitize_key($post_type); if ($post_type === 'product') { $file_name = "shop-bulk-data.jsonl"; } else { $file_name = "{$post_type}-cpt-bulk-data.jsonl"; } $file_path = WP_CONTENT_DIR . '/uploads/reviewx/' . $file_name; $file = \fopen($file_path, 'w'); $total_objects = 0; if ($post_type === 'product') { // Product Sync Data for *Login or Register* $total_objects += $this->userSyncService->syncUser($file); if (\class_exists('WooCommerce') || $this->dataSyncHandler->wc_data_exists_in_db()) { // $syncedCaterories = new CategorySyncService(); // $total_objects += $syncedCaterories->syncCategory($file); $total_objects += $this->productSyncService->processProductForSync($file, $post_type); $total_objects += $this->reviewSyncService->processReviewForSync($file, $post_type); $total_objects += $this->orderItemSyncService->syncOrder($file); $total_objects += $this->orderItemSyncService->syncOrderItem($file); } } else { // CPT Sync Data $total_objects += $this->productSyncService->processProductForSync($file, $post_type); $total_objects += $this->reviewSyncService->processReviewForSync($file, $post_type); } \fclose($file); (new WebhookRequestApi())->finishedWebhook(['total_objects' => $total_objects, 'status' => 'finished', 'from' => $from, 'post_type' => $post_type, 'resource_url' => Helper::getRestAPIurl() . '/api/v1/synced/data?post_type=' . $post_type]); return \true; } catch (Exception $e) { return \false; } } protected function dataSyncFile($file, $file_path, $from, $total_objects) { \fclose($file); $file_info = $this->prepareFileInfo($file_path); $file = $_FILES['file'] = $file_info; $fileUpload = (new DataSyncApi())->dataSync($file, $from, $total_objects); if (\file_exists($file_path)) { \unlink($file_path); } return $fileUpload; } private function prepareFileInfo($file_path) { return ['name' => \basename($file_path), 'full_path' => \realpath($file_path), 'type' => "application/json", 'tmp_name' => $file_path, 'error' => 0, 'size' => \filesize($file_path)]; } public function syncStatus() { return (new DataSyncApi())->syncStatus(); } public function dataManualSync($data) { \mkdir(WP_CONTENT_DIR . '/uploads/reviewx', 0777, \true); $file_path = WP_CONTENT_DIR . '/uploads/reviewx/manual_sync.jsonl'; $file = \fopen($file_path, 'a'); $totalLines = 0; if ("users" === $data['action']) { $totalLines = \get_option('rvx_sync_number'); $totalLines += (new UserSyncService())->syncUser($file); \update_option('rvx_sync_number', $totalLines); } if ("categories" === $data['action']) { if (\class_exists('WooCommerce') || $this->dataSyncHandler->wc_data_exists_in_db()) { // $syncedCaterories = new CategorySyncService(); // $totalLines += $syncedCaterories->syncCategory($file); $processProduct = new ProductSyncService(); $totalLines += $processProduct->processProductForSync($file, 'product'); \update_option('rvx_sync_number', $totalLines); } } if ("reviews" === $data['action']) { if (\class_exists('WooCommerce') || $this->dataSyncHandler->wc_data_exists_in_db()) { $totalLines = \get_option('rvx_sync_number'); $totalLines += (new ReviewSyncService())->processReviewForSync($file, 'product'); \update_option('rvx_sync_number', $totalLines); } } if ("order" === $data['action']) { if (\class_exists('WooCommerce') || $this->dataSyncHandler->wc_data_exists_in_db()) { $order = new OrderItemSyncService(); $totalLines = \get_option('rvx_sync_number'); $totalLines += $order->syncOrder($file); $totalLines += $order->syncOrderItem($file); \update_option('rvx_sync_number', $totalLines); } } if ("api" === $data['action']) { $totalLines = \get_option('rvx_sync_number'); return $this->dataSyncFile($file, $file_path, 'register', $totalLines); } } } Services/DiscountSyncService.php 0000777 00000015241 15251220643 0013020 0 ustar 00 <?php namespace Rvx\Services; use Exception; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Rvx\WPDrill\Facades\DB; class DiscountSyncService extends \Rvx\Services\Service { protected $discountCount = 0; protected $usedbyRelation; protected $maximumAmountRelation; protected $minimumAmountRelation; protected $freeShippingRelation; protected $dateExpiresRelation; protected $usageLimitPerUserRelation; protected $usageLimitRelation; protected $couponAmountRelation; protected $discountTypeRelation; public function processDiscountForSync($file) : int { $this->syncPostMeta(); return $this->syncPost($file); } public function syncPostMeta() { try { $this->usedbyRelation = []; $this->maximumAmountRelation = []; $this->minimumAmountRelation = []; $this->freeShippingRelation = []; $this->dateExpiresRelation = []; $this->usageLimitPerUserRelation = []; $this->usageLimitRelation = []; $this->couponAmountRelation = []; $this->discountTypeRelation = []; DB::table('postmeta')->whereIn('meta_key', ['_used_by', 'maximum_amount', 'minimum_amount', 'free_shipping', 'date_expires', 'usage_limit_per_user', 'usage_limit', 'coupon_amount', 'discount_type'])->chunk(100, function ($allPostMeta) { foreach ($allPostMeta as $postMetas) { switch ($postMetas->meta_key) { case '_used_by': $this->usedbyRelation[$postMetas->post_id] = $postMetas->meta_value; break; case 'maximum_amount': $this->maximumAmountRelation[$postMetas->post_id] = $postMetas->meta_value; break; case 'minimum_amount': $this->minimumAmountRelation[$postMetas->post_id] = $postMetas->meta_value; break; case 'free_shipping': $this->freeShippingRelation[$postMetas->post_id] = $postMetas->meta_value; break; case 'date_expires': $this->dateExpiresRelation[$postMetas->post_id] = $postMetas->meta_value; break; case 'usage_limit_per_user': $this->usageLimitPerUserRelation[$postMetas->post_id] = $postMetas->meta_value; break; case 'usage_limit': $this->usageLimitRelation[$postMetas->post_id] = $postMetas->meta_value; break; case 'coupon_amount': $this->couponAmountRelation[$postMetas->post_id] = $postMetas->meta_value; break; case 'discount_type': $this->discountTypeRelation[$postMetas->post_id] = $postMetas->meta_value; break; } } }); } catch (Exception $e) { throw new Exception($e->getMessage()); } } public function syncPost($file) { $discountCount = 0; DB::table('posts')->select(['ID', 'post_type', 'post_title', 'post_name', 'post_status', 'post_modified'])->orderBy('ID')->whereIn('post_type', ['shop_coupon'])->chunk(100, function ($discounts) use(&$file, &$discountCount) { foreach ($discounts as $discount) { $formatedDiscount = $this->processDiscount($discount); if ($formatedDiscount['single_code'] && $formatedDiscount['type']) { Helper::appendToJsonl($file, $formatedDiscount); $discountCount++; } } }); Helper::rvxLog($discountCount, "Cuopn Done"); return $discountCount; } public function processDiscount($discount) : array { $start_date = \wp_date('Y-m-d', \strtotime($discount->post_modified)) ?? null; $end_date = \wp_date('Y-m-d', $this->dateExpiresRelation[$discount->ID]) ?? null; $exper_day = $this->discountExperDay($start_date, $end_date); return ['rid' => 'rid://Discount/' . (int) $discount->ID, "request_type" => 2, "wp_id" => (int) $discount->ID, "wp_unique_id" => Client::getUid() . '-' . (int) $discount->ID, "site_id" => Client::getSiteId(), "code_type" => 1, "status" => $this->discountStatus($discount->post_status), "single_code" => !empty($discount->post_title) ? $discount->post_title : null, "title" => !empty($discount->post_title) ? $discount->post_title : null, "type" => $this->discountType($this->discountTypeRelation[$discount->ID]) ?? null, "value" => 6, "free_shipping" => $this->dataTypeConvert($this->freeShippingRelation[$discount->ID]) ?? \false, "can_be_used_with_other_coupon" => \false, "exclude_sale_items_from_discount" => \true, "minimum_amount" => Helper::formatToTwoDecimalPlaces($this->minimumAmountRelation[$discount->ID] ?? 0), "maximum_amount" => Helper::formatToTwoDecimalPlaces($this->maximumAmountRelation[$discount->ID] ?? 0), "usage_limit_per_coupon" => (int) $this->usageLimitPerUserRelation[$discount->ID] ?? 0, "usage_limit_per_user" => (int) $this->usageLimitRelation[$discount->ID] ?? 0, "start_date" => $start_date, "start_time" => \wp_date('H:i', \strtotime($discount->post_modified)) ?? null, "expires_in" => $exper_day, "end_date" => $end_date, "end_time" => \wp_date('H:i', $this->dateExpiresRelation[$discount->ID]) ?? null]; } public function discountStatus($status) : int { switch ($status) { case 'publish': return 1; case 'private': return 2; default: return 3; } } public function discountType($type) : string { switch ($type) { case 'fixed_cart': return 'fixed_amount'; case 'percent': return 'percentage'; default: return ''; } } public function dataTypeConvert($data) : bool { if ($data === 'yes') { return \true; } return \false; } public function discountExperDay($start_date, $end_date) { if ($start_date && $end_date) { $start_timestamp = \strtotime($start_date); $end_timestamp = \strtotime($end_date); $difference_in_seconds = $end_timestamp - $start_timestamp; return \floor($difference_in_seconds / (60 * 60 * 24)); } return null; } } Services/OrderService.php 0000777 00000010613 15251220643 0011444 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Api\OrderApi; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Rvx\WPDrill\Response; class OrderService extends \Rvx\Services\Service { public function __construct() { } public function updateOrder($order_id) { $order = wc_get_order($order_id); if (!$order) { return; } $payload = $this->prepareData($order); $uid = Client::getUid() . '-' . $order_id; $response = (new OrderApi())->update($payload, $uid); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log('Order Not Update' . $response->getStatusCode()); return \false; } } public function prepareData($order) { $status = $order->get_status(); $status_mapping = $this->orderStatusArray(); $date_created = $order->get_date_created(); $created_at = $date_created ? \wp_date('Y-m-d H:i:s', $date_created->getTimestamp()) : null; $date_modified = $order->get_date_modified(); $updated_at = $date_modified ? \wp_date('Y-m-d H:i:s', $date_modified->getTimestamp()) : \wp_date('Y-m-d H:i:s'); // Get the order state, ensure a fallback if 'date_paid' doesn't exist $order_state = $this->wooOrderState($order->get_id()); $paid_at = $order_state['date_paid'] ?? null; $orderData = ["wp_id" => (int) $order->get_id(), "customer_wp_unique_id" => Client::getUid() . '-' . (int) $order->get_customer_id(), "subtotal" => (float) $order->get_subtotal(), "tax" => (float) $order->get_total_tax(), "total" => (float) $order->get_total(), "status" => Helper::orderStatus($order->get_status()), "review_request_email_sent_at" => null, "review_reminder_email_sent_at" => null, "photo_review_email_sent_at" => null, "paid_at" => $paid_at, "created_at" => $created_at, "updated_at" => $updated_at]; if (isset($status_mapping[$status])) { $orderData[$status_mapping[$status]] = \wp_date('Y-m-d H:i:s'); } return ['order' => $orderData, 'order_items' => $this->orderItems($order, $orderData)]; } public function orderStatusArray() : array { return ['processing' => 'processing_at', 'pending_payment' => 'pending_payment_at', 'on_hold' => 'on_hold_at', 'completed' => 'completed_at', 'cancelled' => 'cancelled_at', 'refunded' => 'refunded_at', 'failed' => 'failed_at', 'draft' => 'draft_at']; } public function wooOrderState($order_id) { global $wpdb; $query = $wpdb->prepare("SELECT date_paid, date_completed FROM {$wpdb->prefix}wc_order_stats WHERE order_id = %d", $order_id); $results = $wpdb->get_row($query); if ($results) { return ['date_paid' => !empty($results->date_paid) && \strtotime($results->date_paid) ? \wp_date('Y-m-d H:i:s', \strtotime($results->date_paid)) : null, 'date_completed' => !empty($results->date_completed) && \strtotime($results->date_completed) ? \wp_date('Y-m-d H:i:s', \strtotime($results->date_completed)) : null]; } return ['date_paid' => null, 'date_completed' => null]; } public function orderItems($order, $orderData = []) { $date = $this->wooOrderState($order->get_id()); $items_data = []; $order_items = $order->get_items(); foreach ($order_items as $order_item) { $product = $order_item->get_product(); if ($product) { $item_data = ["wp_id" => (int) $order_item->get_id(), "wp_unique_id" => Client::getUid() . '-' . (int) $order_item->get_id(), "product_wp_unique_id" => Client::getUid() . '-' . (int) $product->get_id(), "review_id" => null, "site_id" => Client::getSiteId(), "name" => $product->get_name(), "quantity" => $order_item->get_quantity(), "price" => (float) $product->get_price(), "reviewed_at" => null, "fulfillment_status" => Helper::orderItemStatus($order->get_status())]; if ($order->get_status() !== 'completed') { $item_data['fulfilled_at'] = \wp_date('Y-m-d H:i:s'); } if ($order->get_status() == 'completed') { $item_data['fulfilled_at'] = !empty($date['date_completed']) && \strtotime($date['date_completed']) ? \wp_date('Y-m-d H:i:s', \strtotime($date['date_completed'])) : \wp_date('Y-m-d H:i:s'); } $items_data[] = $item_data; } } return $items_data; } } Services/CptService.php 0000777 00000001474 15251220643 0011124 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Apiz\Http\Response; use Rvx\Api\CptApi; use Rvx\Utilities\Auth\Client; class CptService { /** * @return Response */ public function cptGet() { return (new CptApi())->cptGet(); } public function cptStore($request) { $uid = ['wp_unique_id' => Client::getUid()]; $data = \array_merge($request, $uid); return (new CptApi())->cptStore($data); } public function cptUpdate($data) { $uid = $data['uid']; return (new CptApi())->cptUpdate($data, $uid); } public function cptDelete($data) { return (new CptApi())->cptDelete($data); } public function cptStatusChange($data) { $uid = $data['uid']; return (new CptApi())->cptStatusChange($data, $uid); } } Services/CategorySyncService.php 0000777 00000007352 15251220643 0013011 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Rvx\WPDrill\Facades\DB; use Rvx\Handlers\DataSyncHandler; class CategorySyncService extends \Rvx\Services\Service { protected $categories; protected $taxonomyRelation; protected $descriptionRelation; protected $parentRelation; protected $selectedTerms; protected $syncedCategories; protected $postTermRelation = []; protected $taxonomyTerm; protected $datSyncHandler; public function __construct() { $this->datSyncHandler = new DataSyncHandler(); } public function syncCategory($file) { $catCount = 0; $this->syncTermTaxonomy(); $this->syncTermTaxonomyRelation(); DB::table('terms')->chunk(100, function ($allTerms) use($file, &$catCount) { foreach ($allTerms as $term) { if (\in_array((int) $term->term_id, $this->selectedTerms, \true)) { $formatedTerm = $this->formatCategoryData($term); $this->setSyncCategories($formatedTerm); Helper::rvxLog($formatedTerm); Helper::appendToJsonl($file, $formatedTerm); $catCount++; } } }); Helper::rvxLog($catCount, "Category Done"); return $catCount; } public function getPostTermRelation() { return $this->postTermRelation; } public function setSyncCategories($syncedCategories) : void { $this->syncedCategories[] = $syncedCategories; } public function setPostTermRelation($postTermRelation) { return $this->postTermRelation = $postTermRelation; } public function syncTermTaxonomyRelation() : void { DB::table('term_relationships')->chunk(100, function ($allTermTaxonomyRelations) { foreach ($allTermTaxonomyRelations as $termTaxonomyRelation) { if (\array_key_exists($termTaxonomyRelation->object_id, $this->postTermRelation)) { $this->postTermRelation[$termTaxonomyRelation->object_id] = \array_merge($this->postTermRelation[$termTaxonomyRelation->object_id], [(int) $termTaxonomyRelation->term_taxonomy_id]); } else { $this->postTermRelation[$termTaxonomyRelation->object_id] = isset($this->taxonomyTerm[$termTaxonomyRelation->term_taxonomy_id]) ? [Helper::arrayGet($this->taxonomyTerm, $termTaxonomyRelation->term_taxonomy_id, [])] : []; } } }); $this->setPostTermRelation($this->postTermRelation); } public function syncTermTaxonomy() : void { DB::table('term_taxonomy')->select(['term_taxonomy_id', 'term_id', 'taxonomy', 'parent'])->whereIn('taxonomy', $this->datSyncHandler->getProductTaxonomies())->chunk(100, function ($allTermTaxonomy) { foreach ($allTermTaxonomy as $termTaxonomy) { $this->taxonomyTerm[$termTaxonomy->term_taxonomy_id] = (int) $termTaxonomy->term_id; $this->selectedTerms[] = (int) $termTaxonomy->term_id; $this->taxonomyRelation[$termTaxonomy->term_id] = $termTaxonomy->taxonomy; $this->parentRelation[$termTaxonomy->term_id] = $termTaxonomy->parent; } }); } private function formatCategoryData($category) : array { return ['rid' => 'rid://Category/' . (int) $category->term_id, 'wp_id' => (int) $category->term_id, 'title' => $category->name ?? null, 'slug' => $category->slug ?? null, 'taxonomy' => $this->taxonomyRelation[$category->term_id] ?? null, 'description' => null, 'parent_wp_unique_id' => isset($this->parentRelation[$category->term_id]) ? Client::getUid() . '-' . $this->parentRelation[$category->term_id] : '']; } } Services/GoogleReviewService.php 0000777 00000002360 15251220643 0012767 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Apiz\Http\Response; use Rvx\Api\GoogleReviewApi; class GoogleReviewService extends \Rvx\Services\Service { /** * @return Response */ public function googleReviewGet() { return (new GoogleReviewApi())->googleReviewGet(); } /** * @return Response */ public function googleReviewPlaceApi() { return (new GoogleReviewApi())->googleReviewPlaceApi(); } public function googleRecaptchaVerify($data) { $secret = (new \Rvx\Services\SettingService())->getReviewSettings()['reviews']['recaptcha']['secret_key']; $token = $data['token']; $recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify?secret=' . \urlencode($secret) . '&response=' . \urlencode($token); $response = wp_remote_get($recaptcha_url); $body = wp_remote_retrieve_body($response); $result = \json_decode($body, \true); return ['result' => $result['success']]; } public function googleReviewKey($request) { return (new GoogleReviewApi())->googleReviewKey($request); } public function googleReviewSetting($request) { return (new GoogleReviewApi())->googleReviewSetting($request); } } Services/ReviewSyncService.php 0000777 00000046650 15251220643 0012501 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Handlers\MigrationRollback\MigrationPrompt; use Rvx\Handlers\MigrationRollback\ReviewXChecker; use Rvx\Utilities\Helper; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Facades\DB; use Rvx\Services\ReviewService; class ReviewSyncService extends \Rvx\Services\Service { protected $reviewMetaTitle; protected $reviewRelationId; protected $reviewids; protected $reviewMetaRating; protected $reviewMetaVerified; protected $reviewMetaAttachmentsAll; protected $reviewMetaRecommended; protected $reviewMetaAnonymous; protected $reviewMultiCriteriasRating; protected $reviewTrashStatus; protected $reviewTrashTime; protected $reviewMetaOrder; protected $reviewMetaOrderItem; protected $orderCustomerRelation = []; protected $criteria; protected $procesedReviews; protected $commentReplyRelation; protected ReviewService $reviewService; protected MigrationPrompt $migrationData; public function __construct() { $this->reviewService = new ReviewService(); $this->migrationData = new MigrationPrompt(); if (ReviewXChecker::isReviewXExists() && !ReviewXChecker::isReviewXSaasExists()) { $this->criteria = \get_option('_rx_option_review_criteria') ?? []; } elseif (ReviewXChecker::isReviewXSaasExists()) { $this->criteria = (new \Rvx\Services\SettingService())->getReviewSettings('product')['reviews']['multicriteria']["criterias"] ?? []; } else { $this->criteria = []; } } public function getCriteria() { return $this->criteria; } public function processReviewForSync($file, $post_type) : int { $this->syncReviewMata(); return $this->syncReview($file, $post_type); } public function syncReview($file, $post_type) : int { $this->procesedReviews = []; $this->reviewids = []; $this->reviewRelationId = []; $reviewCount = 0; //Reply DB::table('comments')->join('posts', 'posts.ID', '=', 'comments.comment_post_ID')->where('posts.post_type', $post_type)->where('comment_parent', '!=', 0)->chunk(100, function ($comments) use(&$file) { foreach ($comments as $comment) { $this->commentReplyRelation[$comment->comment_parent][] = [$comment->comment_ID => $comment->comment_content]; } }); //WC Reviews / CPT Reviews $review_type = $post_type === 'product' ? ['review'] : ['comment']; DB::table('comments')->join('posts', 'posts.ID', '=', 'comments.comment_post_ID')->where('posts.post_type', $post_type)->where('comment_parent', '=', 0)->whereIn('comment_type', $review_type)->chunk(100, function ($comments) use(&$commentReplyRelation, &$file, &$reviewCount) { foreach ($comments as $comment) { $this->procesedReviews = $this->processReview($comment); Helper::appendToJsonl($file, $this->procesedReviews); $reviewCount++; } }); // Helper::rvxLog($reviewCount, "Review Done"); return $reviewCount; } public function processReview($comment) : array { $reply = null; if (!empty($this->commentReplyRelation[$comment->comment_ID]) && \is_array($this->commentReplyRelation[$comment->comment_ID])) { $replyData = $this->commentReplyRelation[$comment->comment_ID][0] ?? null; $reply = $replyData ? \reset($replyData) : null; } $trashed_at = null; if ($comment->comment_approved === 'trash') { $status = !empty($this->reviewTrashStatus[$comment->comment_ID]) && $this->reviewTrashStatus[$comment->comment_ID] === 0 ? 'pending' : 'published'; $metaTrashTime = $this->reviewTrashTime[$comment->comment_ID] ?? null; $trashed_at = $metaTrashTime ? Helper::validateReturnDate($metaTrashTime) : null; } else { $status = $this->getCommentStatus($comment); } return ['rid' => 'rid://Review/' . (int) $comment->comment_ID, 'product_id' => (int) $comment->comment_post_ID, 'wp_id' => (int) $comment->comment_ID, 'wp_post_id' => (int) $comment->comment_post_ID, 'rating' => isset($this->reviewMetaRating[$comment->comment_ID]) ? (float) \round($this->reviewMetaRating[$comment->comment_ID], 2) : (float) 0.0, 'reviewer_email' => $comment->comment_author_email ?? null, 'reviewer_name' => $comment->comment_author ?? null, 'title' => isset($this->reviewMetaTitle[$comment->comment_ID]) ? $this->reviewMetaTitle[$comment->comment_ID] : null, 'feedback' => $comment->comment_content ?? null, 'verified' => !empty($this->reviewMetaVerified[$comment->comment_ID]), 'attachments' => $this->reviewMetaAttachmentsAll[$comment->comment_ID] ?? [], 'is_recommended' => !empty($this->reviewMetaRecommended[$comment->comment_ID]), 'is_anonymous' => !empty($this->reviewMetaAnonymous[$comment->comment_ID]), 'status' => $status, 'reply' => $reply, 'trashed_at' => $trashed_at, 'created_at' => Helper::validateReturnDate($comment->comment_date_gmt) ?? null, 'customer_id' => $this->getReviewCustomerId($comment), 'order_wp_unique_id' => isset($this->reviewMetaOrder[$comment->comment_ID]) ? Client::getUid() . '-' . $this->reviewMetaOrder[$comment->comment_ID] : null, 'order_item_wp_unique_id' => $this->reviewMetaOrderItem[$comment->comment_ID] ?? null, 'ip' => $comment->comment_author_IP ?? null, 'criterias' => $this->reviewMultiCriteriasRating[$comment->comment_ID] ?? null]; } private function getReviewCustomerId($comment) : ?string { $orderId = $this->reviewMetaOrder[$comment->comment_ID] ?? null; // If we have an order ID, try to get the customer from the order relation if ($orderId && isset($this->orderCustomerRelation[(int) $orderId])) { $customerId = $this->orderCustomerRelation[(int) $orderId]; return Client::getUid() . '-' . $customerId; } // Fallback to comment user_id, but only if it's not likely to be an admin if ($comment->user_id) { // For now, we'll trust user_id if no order is linked. return Client::getUid() . '-' . $comment->user_id; } return null; } public function syncReviewMata() : void { DB::table('commentmeta')->whereIn('meta_key', ['rvx_review_version', 'reviewx_title', 'verified', 'rating', 'rvx_criterias', 'reviewx_rating', 'reviewx_attachments', 'reviewx_video_url', 'is_recommended', 'reviewx_recommended', 'is_anonymous', '_wp_trash_meta_status', '_wp_trash_meta_time', 'reviewx_order', 'rvx_comment_order_item'])->chunk(100, function ($allCommentMeta) { $orderIds = []; foreach ($allCommentMeta as $commentMeta) { $commentId = $commentMeta->comment_id; if ($commentMeta->meta_key === 'reviewx_order') { $this->reviewMetaOrder[$commentId] = $commentMeta->meta_value; $orderIds[] = (int) $commentMeta->meta_value; } if ($commentMeta->meta_key === 'rvx_comment_order_item') { $this->reviewMetaOrderItem[$commentId] = $commentMeta->meta_value; } // Process each meta_key if ($commentMeta->meta_key === 'reviewx_title') { $this->reviewMetaTitle[$commentId] = $commentMeta->meta_value; } if ($commentMeta->meta_key === 'verified') { $this->reviewMetaVerified[$commentId] = !\in_array($commentMeta->meta_value, ['', '0', 'false', 0, \false], \true); } if ($commentMeta->meta_key === 'rating') { $this->reviewMetaRating[$commentId] = $commentMeta->meta_value; if (!ReviewXChecker::isReviewXExists() && !ReviewXChecker::isReviewXSaasExists()) { $this->reviewMultiCriteriasRating[$commentId] = $this->criteriaMappingWC($commentId, $commentMeta->meta_value); } } if (ReviewXChecker::isReviewXExists() && !ReviewXChecker::isReviewXSaasExists()) { if ($commentMeta->meta_key === 'reviewx_rating') { $this->reviewMultiCriteriasRating[$commentId] = $this->criteriaMappingV1($commentId, $commentMeta->meta_value); } if (\in_array($commentMeta->meta_key, ['reviewx_attachments', 'reviewx_video_url'], \true)) { $metaData = ['reviewx_attachments' => $commentMeta->meta_key === 'reviewx_attachments' ? $commentMeta->meta_value : null, 'reviewx_video_url' => $commentMeta->meta_key === 'reviewx_video_url' ? $commentMeta->meta_value : null]; // Call attachmentsV1 once for the current $commentId $this->reviewMetaAttachmentsAll[$commentId] = $this->attachmentsV1($commentId, $metaData); } if ($commentMeta->meta_key === 'reviewx_recommended') { $this->reviewMetaRecommended[$commentId] = !\in_array($commentMeta->meta_value, ['', '0', 'false', 0, \false], \true); } if ($commentMeta->meta_key === 'reviewx_anonymous') { $this->reviewMetaAnonymous[$commentId] = !\in_array($commentMeta->meta_value, ['', '0', 'false', 0, \false], \true); } } if (ReviewXChecker::isReviewXSaasExists()) { if ($commentMeta->meta_key === 'rvx_criterias') { $this->reviewMultiCriteriasRating[$commentId] = $this->criteriaMappingV2($commentId, $commentMeta->meta_value); } if ($commentMeta->meta_key === 'reviewx_attachments') { $this->reviewMetaAttachmentsAll[$commentId] = $this->attachmentsV2($commentId, $commentMeta->meta_value); } if ($commentMeta->meta_key === 'is_recommended') { $this->reviewMetaRecommended[$commentId] = $commentMeta->meta_value; } if ($commentMeta->meta_key === 'is_anonymous') { $this->reviewMetaAnonymous[$commentId] = $commentMeta->meta_value; } } if ($commentMeta->meta_key === '_wp_trash_meta_status') { $this->reviewTrashStatus[$commentId] = $commentMeta->meta_value; } if ($commentMeta->meta_key === '_wp_trash_meta_time') { $this->reviewTrashTime[$commentId] = $commentMeta->meta_value; } } // Pre-fetch customer IDs for found orders to avoid N+1 queries if (!empty($orderIds)) { $orderStats = DB::table('wc_order_stats')->whereIn('order_id', \array_unique($orderIds))->select(['order_id', 'customer_id'])->get(); foreach ($orderStats as $stat) { $this->orderCustomerRelation[(int) $stat->order_id] = (int) $stat->customer_id; } } }); } private function getCommentStatus($comment) : ?string { switch ($comment->comment_approved) { case '1': return 'published'; case '0': return 'pending'; case 'spam': return 'spam'; default: return null; } } private function criteriaMappingWC($commentId, $metaValue) { $metaValue = maybe_unserialize($metaValue) ?? 0; // If $metaValue is not an array or scalar numeric, default to 0 if (!\is_array($metaValue) && !\is_numeric($metaValue)) { $metaValue = 0; } // If it's a scalar, treat as single rating and wrap in array for consistency if (\is_numeric($metaValue)) { $metaValue = [$metaValue]; } // Predefined keys a to j (10 keys) $keys = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; $newArray = []; $i = 0; foreach ($keys as $key) { // Always add predefined keys, with value from $metaValue or 0 $newArray[$key] = isset($metaValue[$i]) ? (int) $metaValue[$i] : 0; $i++; } if ($newArray == []) { return $newArray = null; } // Update the comment meta with the new format if (!empty($newArray)) { \update_comment_meta($commentId, 'rvx_criterias', $newArray); } return $newArray; } private function criteriaMappingV1($commentId, $metaValue) { $metaValue = maybe_unserialize($metaValue); // Example: a:3:{s:8:"ctr_h8S7";s:1:"3";s:8:"ctr_h8S8";s:1:"3";s:8:"ctr_h8S9";s:1:"3";} // Retrieve the existing criteria mapping (old criteria names) $multCritria_data = $this->getCriteria(); // Example: a:3:{s:8:"ctr_h8S7";s:7:"Quality";s:8:"ctr_h8S8";s:5:"Price";s:8:"ctr_h8S9";s:9:"Packaging";} if (empty($multCritria_data)) { return null; // If no criteria data is available, return an empty array } // Flip multCritria_data to map keys like 'ctr_h8S7' => 'a', 'ctr_h8S8' => 'b', etc. $criteriaKeys = []; $index = 0; foreach ($multCritria_data as $key => $name) { // Assign a short key (a, b, c, ...) based on order $criteriaKeys[$key] = \chr(97 + $index); // ASCII 'a' = 97 $index++; } // Initialize the new criteria array in the required format $newCriteria = []; if (!empty($metaValue)) { foreach ($metaValue as $key => $value) { if (isset($criteriaKeys[$key])) { // Use the new short key and map it to the value as an integer $newCriteria[$criteriaKeys[$key]] = (int) $value; // 'a' => 3, 'b' => 2 } } } else { foreach ($criteriaKeys as $shortKey) { // If metaValue is empty, assign default value of 0 $newCriteria[$shortKey] = 0; // 'a' => 0, 'b' => 0 } } // Update the 'rating' comment meta with the new format $ratingValue = \get_comment_meta($commentId, 'rating', \true); $currentRating = (float) \is_numeric($ratingValue) ? (float) \round($ratingValue, 2) : (float) 0.0; $averageRating = $this->reviewService->calculateAverageRating($newCriteria); $critriaAllowed = $this->migrationData->rvx_retrieve_old_plugin_options_data()['multicriteria']['enable'] ?? \false; if ($currentRating !== $averageRating && !empty($metaValue) && $critriaAllowed === \true) { \update_comment_meta($commentId, 'rating', $averageRating); } // Fill in missing keys ('a' to 'j') with default value 0 $allKeys = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; foreach ($allKeys as $key) { if (!isset($newCriteria[$key])) { $newCriteria[$key] = 0; // Default value for missing keys } } // Update the 'rvx_criterias' comment meta with the new format if (!empty($newCriteria)) { \update_comment_meta($commentId, 'rvx_criterias', $newCriteria); } return $newCriteria; } private function criteriaMappingV2($commentId, $metaValue) { // Deserialize the meta value $metaValue = maybe_unserialize($metaValue); // Ensure $metaValue is always an array if (!\is_array($metaValue)) { $metaValue = []; } // Retrieve the criteria mapping $multCritria_data = $this->getCriteria(); if (empty($multCritria_data)) { return null; // No criteria data available } // Initialize the new criteria array $newCriteria = $metaValue; // Start with existing metaValue if valid // Update the 'rating' comment meta with the new format $ratingValue = \get_comment_meta($commentId, 'rating', \true); $currentRating = (float) \is_numeric($ratingValue) ? (float) \round($ratingValue, 2) : (float) 0.0; $averageRating = $this->reviewService->calculateAverageRating($newCriteria); $critriaAllowed = $this->migrationData->rvx_retrieve_saas_plugin_options_data()['multicriteria']['enable'] ?? \false; if ($currentRating !== $averageRating && !empty($metaValue) && $critriaAllowed === \true) { \update_comment_meta($commentId, 'rating', $averageRating); } // Fill in missing keys ('a' to 'j') with default value 0 $allKeys = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; foreach ($allKeys as $key) { if (!isset($newCriteria[$key])) { $newCriteria[$key] = 0; // Default value for missing keys } else { // Ensure all existing values are integers $newCriteria[$key] = (int) $newCriteria[$key]; } } // Update the comment meta with the new format if (!empty($newCriteria)) { \update_comment_meta($commentId, 'rvx_criterias', $newCriteria); } return $newCriteria; // Ensure all keys from 'a' to 'j' are present } private function attachmentsV1($commentId, array $metaData) : array { $links = []; foreach ($metaData as $metaKey => $metaValue) { if ($metaValue === null) { continue; // Skip if no value provided for this meta key } $data = \is_string($metaValue) ? maybe_unserialize($metaValue) : $metaValue; if ($metaKey === 'reviewx_attachments' && \is_array($data) && isset($data['images'])) { // Process image attachments foreach ($data['images'] as $image_id) { $image_url = wp_get_attachment_url($image_id); if (\filter_var($image_url, \FILTER_VALIDATE_URL)) { $links[] = $image_url; } } } if ($metaKey === 'reviewx_video_url') { // Process video attachments $videoLinks = []; if (\is_array($data)) { foreach ($data as $video_url) { if (\filter_var($video_url, \FILTER_VALIDATE_URL)) { $videoLinks[] = $video_url; } } } elseif (\is_string($data) && \filter_var($data, \FILTER_VALIDATE_URL)) { $videoLinks[] = $data; } // Merge video links into links $links = \array_merge($links, $videoLinks); } } // Update the comment meta with IDs for images and URLs for videos if (!empty($links)) { \update_comment_meta($commentId, 'reviewx_attachments', $links); } return $links; // Return URLs } private function attachmentsV2($commentId, $metaValue) : array { $data = maybe_unserialize($metaValue); $links = []; if (\is_array($data)) { foreach ($data as $data_url) { if (\filter_var($data_url, \FILTER_VALIDATE_URL)) { $links[] = $data_url; } } } elseif (\is_string($data) && \filter_var($data, \FILTER_VALIDATE_URL)) { $links[] = $data; } return $links; } } Services/CacheServices.php 0000777 00000006155 15251220643 0011565 0 ustar 00 <?php namespace Rvx\Services; class CacheServices extends \Rvx\Services\Service { public function allReviewApproveCount() : int { global $wpdb; $query = $wpdb->prepare("SELECT COUNT(*) \n FROM {$wpdb->comments} \n WHERE comment_approved = '1' \n AND comment_parent = 0 \n AND comment_type IN ('review','comment')"); return (int) $wpdb->get_var($query); } public function allReviewPendingCount() : int { global $wpdb; $query = $wpdb->prepare("SELECT COUNT(*) \n FROM {$wpdb->comments} \n WHERE comment_approved = '0' \n AND comment_parent = 0\n AND comment_type IN ('review','comment')"); return (int) $wpdb->get_var($query); } public function saasStatusReviewCount() { $data = \get_transient('rvx_reviews_data_list'); if (\is_array($data)) { return $data['count']; } return []; } public function makeSaaSCallDecision() { $approveReviewCount = $this->allReviewApproveCount(); $pendingReviewCount = $this->allReviewPendingCount(); $saasApproveReviewCount = \array_key_exists('published', $this->saasStatusReviewCount()) ? $this->saasStatusReviewCount()['published'] : 0; $saasPendingReviewCount = \array_key_exists('pending', $this->saasStatusReviewCount()) ? $this->saasStatusReviewCount()['pending'] : 0; if ($approveReviewCount != $saasApproveReviewCount) { return \true; } if ($saasPendingReviewCount != $pendingReviewCount) { return \true; } return \false; } public function removeCache() { \delete_transient('rvx_reviews_data_list'); \delete_transient('rvx_review_approve_data'); \delete_transient('rvx_review_pending_data'); \delete_transient('rvx_review_spam_data'); \delete_transient('rvx_review_trash_data'); \delete_transient('rvx_admin_aggregation'); \delete_transient('rvx_review_shortcode'); \delete_transient('rvx_shortcode_transient'); \delete_transient('rvx_shortcode_all_reviews'); } public function clearShortcodesCache($arrayFirst, $arraySecond) { if (empty($arrayFirst)) { return \false; } $firstData = maybe_unserialize($arrayFirst); if (!\is_array($firstData) || !\is_array($arraySecond)) { return \false; } \ksort($firstData); \ksort($arraySecond); $firstHash = \md5(\json_encode($firstData)); $secondHash = \md5(\json_encode($arraySecond)); if ($firstHash === $secondHash) { return \true; } return \false; } /** * Clear product-specific transients for reviews and insight data. * @param int $productId The WP Post ID of the product. */ public function removeProductCache($productId) : void { if (!$productId) { return; } \delete_transient("rvx_{$productId}_latest_reviews"); \delete_transient("rvx_{$productId}_latest_reviews_insight"); } } Services/UserSyncService.php 0000777 00000002051 15251220643 0012141 0 ustar 00 <?php namespace Rvx\Services; use Rvx\Utilities\Helper; use Rvx\WPDrill\Facades\DB; class UserSyncService extends \Rvx\Services\Service { protected $users; public function syncUser($file) { $userCount = 0; DB::table('users')->select(['ID', 'display_name', 'user_email', 'user_status'])->chunk(100, function ($allUsers) use($file, &$userCount) { foreach ($allUsers as $user) { $formatedUser = $this->formatUserData($user); Helper::appendToJsonl($file, $formatedUser); $userCount++; } }); Helper::rvxLog($userCount, "User Done"); return $userCount; } public function formatUserData($user) : array { return ['rid' => 'rid://Customer/' . (int) $user->ID, 'wp_id' => (int) $user->ID, 'name' => $user->display_name ?? null, 'email' => is_email($user->user_email) ? $user->user_email : '', 'avatar' => null, 'city' => null, 'phone' => null, 'address' => null, 'country' => null, 'status' => (int) $user->user_status]; } } Services/DiscountService.php 0000777 00000005446 15251220643 0012171 0 ustar 00 <?php namespace Rvx\Services; use WC_Coupon; use Exception; use Rvx\Api\DiscountApi; class DiscountService extends \Rvx\Services\Service { public function wpDiscountCreate($data) { $coupon = $this->setBasicCouponData($data); $this->setAdditionalCouponData($coupon, $data); $coupon->save(); return $coupon; } private function setBasicCouponData($data) { $coupon_data = ['code' => sanitize_text_field($data['code']), 'discount_type' => sanitize_text_field($data['discount_type']), 'amount' => sanitize_text_field($data['amount'])]; $coupon = new WC_Coupon(); $coupon->set_props($coupon_data); return $coupon; } private function setAdditionalCouponData($coupon, $data) { if (isset($data['expiry_date'])) { $coupon->set_date_expires(sanitize_text_field($data['expiry_date'])); } if (isset($data['individual_use'])) { $coupon->set_individual_use($data['individual_use'] === 'yes'); } if (isset($data['usage_limit'])) { $coupon->set_usage_limit(sanitize_text_field($data['usage_limit'])); } if (isset($data['free_shipping'])) { $coupon->set_free_shipping($data['free_shipping'] === 'yes'); } if (isset($data['usage_limit_per_user'])) { $coupon->set_usage_limit_per_user((int) $data['usage_limit_per_user']); } if (isset($data['minimum_amount'])) { $coupon->add_meta_data('minimum_amount', sanitize_text_field($data['minimum_amount']), \true); } if (isset($data['maximum_amount'])) { $coupon->add_meta_data('maximum_amount', sanitize_text_field($data['maximum_amount']), \true); } } public function deleteDiscount($couponId) { try { $coupon = new WC_Coupon($couponId); $coupon->delete(\true); // true for force delete return \true; } catch (Exception $e) { return \false; } } public function getDiscount() { return (new DiscountApi())->getDiscount(); } public function discountSetting() { return (new DiscountApi())->discountSetting(); } public function discountSettingsSave($data) { return (new DiscountApi())->discountSettingsSave($data); } public function saveDiscount($data) { return (new DiscountApi())->saveDiscount($data); } public function discountTemplateGet() { return (new DiscountApi())->discountTemplateGet(); } public function discountTemplatePost($data) { return (new DiscountApi())->discountTemplatePost($data); } public function discountMessage($data) { return (new DiscountApi())->discountMessage($data); } } Api/DashboardApi.php 0000777 00000001244 15251220643 0010317 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; use Exception; class DashboardApi extends \Rvx\Api\BaseApi { /** * @return Response * @throws Exception */ public function insightReviews() : Response { return $this->get('dashboard/insight'); } /** * @return Response * @throws Exception */ public function requestEmail() : Response { return $this->get('dashboard/review-request-email'); } /** * @param $time * @return Response * @throws Exception */ public function chart($time) : Response { return $this->get('dashboard/chart?view=' . $time); } } Api/ProductApi.php 0000777 00000003552 15251220643 0010054 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; use Exception; class ProductApi extends \Rvx\Api\BaseApi { /** * @return Response * @throws Exception */ public function getProductSelect($id) : Response { if (!empty($id['search'])) { return $this->get('products/selectable?search=' . $id['search']); } return $this->get('products/selectable'); } /** * @return Response * @throws Exception */ public function getProducts() : Response { return $this->get('products'); } /** * @return Response * @throws Exception */ public function getProductInsights() : Response { return $this->get('products/insights'); } /** * @param array $data * @return Response * @throws Exception */ public function create(array $data) : Response { return $this->withJson($data)->post('products/store'); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function update(array $data, $uid) : Response { return $this->withJson($data)->put('products/' . $uid . '/update'); } /** * @param $uid * @param $status * @return Response * @throws Exception */ public function status($uid, $status) : Response { return $this->put('products/' . $uid . '/status?status=' . $status); } /** * @param $id * @return mixed * @throws Exception */ public function remove($id) { $link = 'products/' . $id; return $this->delete($link); } /** * @param $id * @return mixed * @throws Exception */ public function trashToRestoreWpProduct($id) { $link = 'products/' . $id . '/restore'; return $this->put($link); } } Api/UserApi.php 0000777 00000002160 15251220643 0007344 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; class UserApi extends \Rvx\Api\BaseApi { /** * @return Response * @throws \Exception */ public function getUser() : Response { return $this->get('customers'); } /** * @param array $data * @return Response * @throws Exception */ public function create(array $data) : Response { return $this->withJson($data)->post('customer'); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function update(array $data, $uid) : Response { return $this->withJson($data)->put('customer/' . $uid . '/update'); } public function editAccountUpdate(array $data, $uid) : Response { return $this->withJson($data)->put('customer/' . $uid . '/update'); } /** * @param $id * @return Response * @throws Exception */ public function remove($id) : Response { $tt = 'customer/' . $id; \error_log("Delete " . $tt); return $this->delete('customer/' . $id); } } Api/CategoryApi.php 0000777 00000002100 15251220643 0010175 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; class CategoryApi extends \Rvx\Api\BaseApi { /** * @param $id * @return Response * @throws \Exception */ public function selectable() : Response { return $this->get('category/selectable'); } public function getCategory() : Response { return $this->get('categories'); } public function create(array $data) { return $this->withJson($data)->post('category'); } /** * @param $id * @return mixed * @throws \Exception */ public function remove($id) { \error_log("delete uid " . $id); return $this->delete('category/' . $id); } /** * @param array $data * @param $uid * @return Response * @throws \Exception */ public function update(array $data, $uid) : Response { return $this->withJson($data)->put('category/' . $uid . '/update'); } public function dataSync(array $data) { return $this->withJson($data)->post('sync/categories'); } } Api/GoogleReviewApi.php 0000777 00000002433 15251220643 0011027 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; use Exception; class GoogleReviewApi extends \Rvx\Api\BaseApi { /** * @return Response * @throws Exception */ public function googleReviewGet() : Response { return $this->get('reviews/google'); } /** * @return Response * @throws Exception */ public function googleReviewPlaceApi() : Response { return $this->get('settings/google-place-api/get'); } /** * @param array $data * @return Response * @throws Exception */ public function googleReviewKey(array $data) : Response { if ($data['disconnect'] == \true) { return $this->withJson($data)->post('settings/google-place-api/save?disconnect=' . $data['disconnect']); } return $this->withJson($data)->post('settings/google-place-api/save'); } /** * @param array $data * @return Response * @throws Exception */ public function googleReviewSetting(array $data) : Response { if ($data['is_default'] == \true) { return $this->withJson($data)->post('settings/google-widget/save?is_default=' . $data['is_default']); } return $this->withJson($data)->post('settings/google-widget/save'); } } Api/OrderApi.php 0000777 00000002415 15251220643 0007504 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; use Exception; class OrderApi extends \Rvx\Api\BaseApi { /** * @param array $data * @return Response * @throws Exception */ public function create(array $data) : Response { return $this->withJson($data)->post('orders/store'); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function update(array $data, $uid) : Response { return $this->withJson($data)->put('orders/' . $uid . '/update'); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function changeStatus(array $data, $uid) : Response { return $this->withJson($data)->put('orders/' . $uid . '/change/status'); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function changeBulkStatus(array $data) : Response { return $this->withJson($data)->post('orders/bulk/change/status'); } /** * @param $uid * @return Response * @throws Exception */ public function delete($uid) : Response { return $this->delete('orders/' . $uid); } } Api/WpApi.php 0000777 00000005167 15251220643 0007026 0 ustar 00 <?php namespace Rvx\Api; use Rvx\GuzzleHttp\Client; use Rvx\GuzzleHttp\Exception\RequestException; use Rvx\Utilities\Helper; class WpApi { protected string $baseUrl; protected ?string $token = null; protected Client $client; public function __construct($token = null) { // Use get_rest_url instead of hardcoding wp-json $this->baseUrl = Helper::getRestAPIurl() . '/api/v1'; $this->token = Helper::getAuthToken(); $this->client = new Client(['base_uri' => $this->baseUrl, 'timeout' => 10.0]); } /** * Make a GET request. * * @param string $route * @return mixed */ public function get(string $route) { $url = $this->prepareRoute($route); $headers = $this->prepareHeaders(); try { $response = $this->client->request('GET', $url, ['headers' => $headers]); return \json_decode((string) $response->getBody(), \true); } catch (RequestException $e) { return $e->getMessage(); } } /** * Make a POST request. * * @param string $route * @param array $payload * @return mixed */ public function post(string $route, array $payload) { $url = $this->prepareRoute($route); $headers = $this->prepareHeaders(); try { $response = $this->client->request('POST', $url, ['headers' => $headers, 'json' => $payload]); return \json_decode((string) $response->getBody(), \true); } catch (RequestException $e) { return $e->getMessage(); } } /** * Prepare the full route URL. * * @param string $route * @return string */ public function prepareRoute(string $route) : string { return \rtrim($this->baseUrl, '/') . '/' . \ltrim($route, '/'); } /** * Prepare the authorization headers. * * @return array */ protected function prepareHeaders() : array { $headers = ['Content-Type' => 'application/json']; if ($this->token) { $headers['Authorization'] = 'Bearer ' . $this->token; $headers['X-url'] = home_url(); } return $headers; } /** * Set the authorization token for the API. * * @param string $token * @return void */ public function setToken(string $token) : void { $this->token = $token; } /** * Set the base URL for the API. * * @param string $baseUrl * @return void */ public function setBaseUrl(string $baseUrl) : void { $this->baseUrl = \rtrim($baseUrl, '/'); } } Api/ReviewsApi.php 0000777 00000027720 15251220643 0010063 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; use Exception; use Rvx\Models\Post; use Rvx\Utilities\Auth\Client; class ReviewsApi extends \Rvx\Api\BaseApi { public function getReviews($data) : Response { if (!empty($data)) { \parse_str($data, $query_params); if (isset($query_params['product']) && \is_numeric($query_params['product'])) { $query_params['product'] = Client::getUid() . '-' . $query_params['product']; } return $this->get('reviews?' . \http_build_query($query_params)); } return $this->get('reviews'); } public function reviewList($data) : Response { if (!empty($data)) { \parse_str($data, $query_params); if (isset($query_params['product']) && \is_numeric($query_params['product'])) { $query_params['product'] = Client::getUid() . '-' . $query_params['product']; } return $this->get('reviews/list?' . \http_build_query($query_params)); } return $this->get('reviews/list'); } /** * @param $id * @return Response * @throws Exception */ public function getReview($wpUniqueId) : Response { return $this->get('reviews/' . $wpUniqueId); } /** * @param array $data * @return Response * @throws Exception */ public function create(array $data) : Response { return $this->withJson($data)->post('reviews/create/manual'); } /** * @param array $data * @param $wpUniqueId * @return Response * @throws Exception */ public function updateReviewData(array $data, $wpUniqueId) : Response { return $this->withJson($data)->put('reviews/' . $wpUniqueId . '/update'); } public function updateWooReviewData(array $data, $wpUniqueId) : Response { return $this->withJson($data)->put('reviews/' . $wpUniqueId . '/update?woocommerce_update=true'); } /** * @param $uid * @return Response * @throws Exception */ public function deleteReviewData($wpUniqueId) : Response { return $this->delete('reviews/' . $wpUniqueId . '/delete'); } /** * @param $uid * @return Response * @throws Exception */ public function restoreReview($wpUniqueId, $status = null) : Response { $route = 'reviews/' . $wpUniqueId . '/restore'; if ($status) { $route .= '?status=' . $status; } return $this->put($route); } /** * @param $data * @param $wpUniqueId * @return Response * @throws Exception */ public function verifyReview($data, $wpUniqueId) : Response { return $this->put('reviews/' . $wpUniqueId . '/verify?status=' . $data); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function visibilityReviewData(array $data, $wpUniqueId) : Response { if ($data['status']) { return $this->put('reviews/' . $wpUniqueId . '/visibility?status=' . $data['status']); } return $this->put('reviews/' . $wpUniqueId . '/visibility'); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function sendUpdateReviewRequestEmail(array $data, $wpUniqueId) : Response { return $this->withJson($data)->put('reviews/' . $wpUniqueId . '/send/update/request-email'); } /** * @return Response * @throws Exception */ public function reviewAggregation() : Response { return $this->get('reviews/get-aggregation'); } /** * @return Response * @throws Exception */ public function getSpecificReviewItem($uid, $data) : Response { return $this->withJson($data)->post('storefront/' . $uid . '/widgets/short/code/reviews'); } /** * @param array $data * @return Response * @throws Exception */ public function bulkStatusUpdateReviewData(array $data) : Response { return $this->withJson($data)->put('reviews/bulk/status/update'); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function replayCommentReviewData(array $data, $uid) : Response { return $this->withJson($data)->post('reviews/{$uid}/comments'); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function updateReplayCommentReviewData(array $data, $uid) : Response { return $this->withJson($data)->post('reviews/{$uid}/update/comments'); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function deleteReplayCommentReviewData(array $data, $uid) : Response { return $this->withJson($data)->post('reviews/{$uid}/delete/{$id}/comments'); } //replies /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function commentReply(array $data, $wpUniqueId) : Response { return $this->withJson($data)->post('reviews/' . $wpUniqueId . '/replies'); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function updateCommentReply(array $data, $uid) : Response { return $this->withJson($data)->put('reviews/' . $uid . '/update/replies'); } /** * @param $uid * @return Response * @throws Exception */ public function deleteCommentReply($wpUniqueId) : Response { return $this->delete('reviews/' . $wpUniqueId . '/delete/reply'); } /** * @param array $data * @return Response * @throws Exception */ public function aiReview(array $data) : Response { return $this->withJson($data)->post('reviews/create/ai'); } /** * @param array $data * @return Response * @throws Exception */ public function aiReviewCount() : Response { return $this->get('reviews/ai/count'); } /** * @param $request * @return Response * @throws Exception */ public function getWidgetReviewsForProductApi($request) : Response { $query_string = \http_build_query($request->get_params()); \parse_str($query_string, $query_params); unset($query_params['product_id']); $productId = $request->get_param('product_id'); $siteUid = Client::getUid(); $post = Post::find($productId); $productWpUniqueId = $siteUid . '-' . $post->ID; $new_query_string = \http_build_query($query_params); $callableRoute = "/storefront/{$siteUid}/widgets/products/{$productWpUniqueId}/reviews"; if (!empty($new_query_string)) { $callableRoute .= '?' . $new_query_string; } return $this->get($callableRoute); } /** * @param $request * @return Response * @throws Exception */ public function getWidgetAllReviewsForSiteApi($request, $site_id) : Response { $query_params = $request->get_params(); unset($query_params['site_id']); $callableRoute = "/storefront/{$site_id}/all/reviews/shortcode"; $query_string = \http_build_query($query_params); if ($query_string) { $callableRoute .= '?' . $query_string; } return $this->get($callableRoute); } /** * @param $request * @return Response * @throws Exception */ public function getWidgetReviewsListShortcodeApi($request) : Response { $query_params = $request->get_params(); unset($query_params['product_id']); $productId = $request->get_param('product_id'); $siteUid = Client::getUid(); $post = Post::find($productId); $productWpUniqueId = $siteUid . '-' . $post->ID; $query_string = \http_build_query($query_params); $callableRoute = "/storefront/{$siteUid}/widgets/products/{$productWpUniqueId}/reviews/shortcode"; if ($query_string) { $callableRoute .= '?' . $query_string; } return $this->get($callableRoute); } public function getSingleProductAllReviews($productId) : Response { $siteUid = Client::getUid(); $post = Post::find($productId); $productWpUniqueId = $siteUid . '-' . $post->ID; $callableRoute = "/storefront/{$siteUid}/widgets/products/{$productWpUniqueId}/reviews"; return $this->get($callableRoute); } /** * @param $request * @return Response * @throws Exception */ public function getWidgetInsight($request) : Response { $query_string = \http_build_query($request->get_params()); \parse_str($query_string, $query_params); unset($query_params['product_id']); $productId = $request->get_param('product_id'); $siteUid = Client::getUid(); $post = Post::find($productId); $productWpUniqueId = $siteUid . '-' . $post->ID; $new_query_string = \http_build_query($query_params); $callableRoute = "/storefront/{$siteUid}/widgets/products/{$productWpUniqueId}/insight"; if (!empty($new_query_string)) { $callableRoute .= '?' . $new_query_string; } return $this->get($callableRoute); } public function reviewBulkUpdate($data) { return $this->withJson($data)->post('/reviews/bulk/status/update'); } public function restoreTrashItem($data) { return $this->withJson($data)->post('reviews/bulk/restore/trash'); } public function reviewBulkTrash($data) { return $this->withJson($data)->post('/reviews/bulk/trash'); } public function reviewEmptyTrash() { return $this->delete('reviews/empty/trash'); } /** * @param $request * @return Response * @throws Exception */ public function saveWidgetReviewsForProductApi($data) : Response { $callableRoute = "/storefront/reviews"; return $this->withJson($data)->post($callableRoute); } /** * @param $request * @return Response * @throws Exception */ public function reviewMoveToTrash($data) : Response { $callableRoute = "reviews/" . $data['WpUniqueId'] . "/trash"; return $this->put($callableRoute); } /** * @param $request * @return Response * @throws Exception */ public function likeDIslikePreference($data) : Response { $callableRoute = 'storefront/reviews/' . $data['uniq_id'] . '/preference'; return $this->withJson($data)->post($callableRoute); } /** * @param $request * @return Response * @throws Exception */ public function reviewListMultiCriteria() : Response { return $this->get('reviews/list/multi-criteria'); } /** * @param $request * @return Response * @throws Exception */ public function getProductReviewFormId($data) : Response { if ($data['product'] != null) { $siteUid = Client::getUid(); $post = Post::find($data['product']); $productWpUniqueId = $siteUid . '-' . $post->ID; $callableRoute = "/storefront/{$siteUid}/widgets/products/{$productWpUniqueId}/reviews"; return $this->get($callableRoute); } return $this->get('reviews'); } /** * @param $request * @return Response * @throws Exception */ public function highlight($data) : Response { $callableRoute = 'reviews/' . $data['wpUniqueId'] . '/highlight'; return $this->withJson($data)->put($callableRoute); } /** * @param array $data * @return Response * @throws Exception */ public function reviewRequestStoreItem(array $data, $uid) : Response { return $this->withJson($data)->post('storefront/request-review/email/' . $uid . '/store/items'); } } Api/AuthApi.php 0000777 00000002721 15251220643 0007332 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; use Exception; class AuthApi extends \Rvx\Api\BaseApi { /** * @param array $data * @return Response * @throws Exception */ public function login(array $data) : Response { return $this->withJson($data)->post('login'); } /** * @param array $data * @return Response * @throws Exception */ public function register(array $data) : Response { if ($data['domain'] === 'localhost') { $ip = (new \Rvx\Api\BaseApi())->getIp(); $data['url'] = $ip; } return $this->withJson($data)->post('register'); } /** * @param array $data * @return Response * @throws Exception */ public function licenseLogin(array $data) : Response { return $this->withJson($data)->post('/login/key'); } /** * @param array $data * @return Response * @throws Exception */ public function forgetPassword(array $data) : Response { return $this->withJson($data)->post('forget-password'); } /** * @param array $data * @return Response * @throws Exception */ public function resetPassword(array $data) : Response { return $this->withJson($data)->post('reset-password'); } public function changePluginStatus(array $data) : Response { return $this->withJson($data)->post('/plugin/change-status'); } } Api/ReviewImportAndExportApi.php 0000777 00000004510 15251220643 0012710 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; use Exception; use Rvx\Utilities\Auth\Client; class ReviewImportAndExportApi extends \Rvx\Api\BaseApi { /** * @param array $data * @return Response * @throws Exception */ public function importSupportedAppStore(array $data) : Response { return $this->withJson($data)->post('admin/import/supported/app/store'); } /** * @param array $data * @param array $files * @return Response * @throws Exception */ public function importStore(array $data, array $files) : Response { $file = $files['file']['tmp_name']; $res = $this->withFormData($data)->withFile('file', $file, $files['file']['name'])->post('/reviews/import/store'); return $res; } /** * @param array $data * @return Response * @throws Exception */ public function exportCsv(array $data) : Response { $new_product_ids = []; foreach ($data['product_ids'] as $product_id) { $new_product_ids[] = Client::getUid() . '-' . $product_id; } unset($data['product_ids']); $data['product_wp_unique_ids'] = $new_product_ids; return $this->withJson($data)->post('reviews/exports/generate/csv'); } /** * @return Response * @throws Exception */ public function exportHistory() : Response { return $this->get('reviews/exports/history'); } /** * @return Response * @throws Exception */ public function importHistory() : Response { return $this->get('reviews/import/history'); } /** * @param array $data * @return Response * @throws Exception */ public function importRollback(array $data) : Response { return $this->delete('reviews/import/rollback/' . $data['uid']); } /** * @param array $data * @return Response * @throws Exception */ public function importRestore(array $data) : Response { return $this->withJson($data)->put('admin/import/restore/7kAN-uGTkdlmo-4BAP'); } /** * @param array $data * @return Response * @throws Exception */ public function logImportHistory(array $data) : Response { return $this->withJson($data)->post('reviews/import/log-history'); } } Api/EmailApi.php 0000777 00000011074 15251220643 0007461 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; use Exception; class EmailApi extends \Rvx\Api\BaseApi { /** * @return Response * @throws Exception */ public function index() : Response { return $this->get('email-templates'); } /** * @return Response * @throws Exception */ public function show($id) : Response { return $this->get('email-templates' . $id); } /** * @param array $data * @return Response * @throws Exception */ public function create(array $data) : Response { return $this->withJson($data)->post('email-templates'); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function update(array $data, $uid) : Response { return $this->withJson($data)->put('email-templates/' . $uid); } /** * @param $uid * @return Response * @throws Exception */ public function remove($uid) : Response { return $this->delete('email-templates/' . $uid); } /** * @param $uid * @return Response * @throws Exception */ public function reviewRequest($uid) : Response { return $this->get('review/request/emails' . $uid); } /** * @param $uid * @return Response * @throws Exception */ public function mailRequest($data) : Response { if (!empty($data)) { $callableRoute = 'review/request/emails'; $callableRoute .= '?' . $data; return $this->get($callableRoute); } return $this->get('review/request/emails'); } /** * @return Response * @throws Exception */ public function content() : Response { return $this->get('review/email/contents'); } /** * @param array $data * @return Response * @throws Exception */ public function saveEmailRequest(array $data) : Response { return $this->withJson($data)->post('review/email/request/contents'); } /** * @param array $data * @return Response * @throws Exception */ public function followup(array $data) : Response { return $this->withJson($data)->post('review/email/followup/contents'); } /** * @param array $data * @return Response * @throws Exception */ public function photoReview(array $data) : Response { return $this->withJson($data)->post('review/email/photo/contents'); } /** * @param array $data * @return Response * @throws Exception */ public function testMail(array $data) : Response { return $this->withJson($data)->post('review/email/send-test'); } /** * @param string $uid * @return Response * @throws Exception */ public function emailCancel($uid) : Response { return $this->withJson()->put('/review-request/email/cancel/' . $uid); } /** * @param string $uid * @return Response * @throws Exception */ public function requestEmailSend($data) : Response { $callableRoute = '/review-request/email/send/' . $data['uid']; return $this->withJson($data)->put($callableRoute); } /** * @param string $uid * @return Response * @throws Exception */ public function requestEmailResend($data) : Response { $callableRoute = 'review-request/email/resend/' . $data['uid']; return $this->withJson($data)->put($callableRoute); } /** * @param string $uid * @return Response * @throws Exception */ public function requestEmailUnsubscribe() : Response { return $this->withJson()->put('review-request/unsubscribe/'); } /** * @param string $uid * @return Response * @throws Exception */ public function markAsComplete($uid) : Response { return $this->withJson()->put('/review-request/email/mark-as-done/' . $uid); } /** * @return Response * @throws Exception */ public function reviewRequestSettings() : Response { return $this->get('review/request/settings'); } /** * @param array $data * @return Response * @throws Exception */ public function allReminderSettings(array $data) : Response { if ($data['is_default'] == \true) { return $this->withJson($data)->post('review/request/settings/?' . $data['is_default']); } return $this->withJson($data)->post('review/request/settings'); } } Api/DataSyncApi.php 0000777 00000001214 15251220643 0010133 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; class DataSyncApi extends \Rvx\Api\BaseApi { /** * @param array $files * @param string $from * @param int $total_objects * @return Response * @throws \Exception */ public function dataSync(array $files, string $from = 'register', int $total_objects = 0) : Response { $fileName = $files['tmp_name']; return $this->withFile('file', $fileName, $files['full_path'])->post('sync?from=' . $from . '&total_objects=' . $total_objects); } public function syncStatus() : Response { return $this->get('/get/sync/status'); } } Api/DiscountApi.php 0000777 00000002167 15251220643 0010225 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; class DiscountApi extends \Rvx\Api\BaseApi { /** * @return Response * @throws \Exception */ public function getDiscount() : Response { return $this->get('discount'); } /** * @return Response * @throws \Exception */ public function discountSetting() : Response { return $this->get('discount/settings'); } /** * @return Response * @throws \Exception */ public function discountSettingsSave($data) : Response { return $this->withJson($data)->post('discount/settings'); } public function saveDiscount($data) : Response { return $this->withJson($data)->post('discount'); } public function discountTemplateGet() : Response { return $this->get('discount/template'); } public function discountTemplatePost($data) : Response { return $this->withJson($data)->post('discount/template'); } public function discountMessage($data) : Response { return $this->withJson($data)->post('discount/message'); } } Api/BaseApi.php 0000777 00000002367 15251220643 0007311 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\AbstractApi; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; class BaseApi extends AbstractApi { protected $response = \Rvx\Api\ApiResponse::class; protected array $config = ['http_errors' => \false]; /** * @return string */ public function getBaseUrl() : string { if (Helper::plugin()->isProduction()) { return "https://api.reviewx.io"; } return "https://api-dev.reviewx.io"; } public function getIp() : string { return '192.168.68.119:10013'; } /** * @return string */ public function getPrefix() : string { return '/admin/api/v1'; } /** * @return array */ public function getDefaultHeaders() : array { return ['Accept' => 'application/json', 'Authorization' => 'Bearer ' . Helper::getAuthToken(), 'X-url' => home_url(), 'X-Domain' => Helper::getWpDomainNameOnly(), 'X-Theme' => wp_get_theme()->get('Name'), 'X-Site-Locale' => get_locale(), 'X-Request-Id' => \sha1(\time() . Client::getUid()), 'X-Wp-Version' => get_bloginfo("version"), 'X-Reviewx-Version' => RVX_VERSION, 'X-Environment' => Helper::plugin()->isProduction() ? 'production' : 'development']; } } Api/SettingApi.php 0000777 00000003627 15251220643 0010054 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; use Rvx\Utilities\Auth\Client; class SettingApi extends \Rvx\Api\BaseApi { public function getApiReviewSettings($data) : Response { $url = 'reviews/settings/get'; if (isset($data['cpt_type'])) { return $this->get($url . '?cpt_type=' . $data['cpt_type']); } return $this->get($url); } public function getApiWidgetSettings() : Response { return $this->get('settings/widget/get'); } public function userCurrentPlan() : Response { return $this->get('user/current/plan'); } public function getLocalSettings($post_type = null) : Response { $uid = Client::getUid(); if ($post_type === null) { $post_type = 'product'; } return $this->get('storefront/' . $uid . '/widgets/settings?cpt_type=' . $post_type); } public function getApiGeneralSettings() : Response { return $this->get('settings/general/get'); } public function saveApiGeneralSettings($data) : Response { $url = 'settings/general/save'; if (isset($data['is_default'])) { return $this->withJson($data)->post($url . '?is_default=' . $data['is_default']); } return $this->withJson($data)->post($url); } public function saveApiReviewSettings($data) { $url = 'reviews/settings/save'; if (isset($data['is_default'])) { return $this->withJson($data)->post($url . '?is_default=' . $data['is_default']); } return $this->withJson($data)->post($url); } public function saveApiWidgetSettings($data) : Response { $url = 'settings/widget/save'; if (isset($data['is_default'])) { return $this->withJson($data)->post($url . '?is_default=' . $data['is_default']); } return $this->withJson($data)->post($url); } } Api/CptApi.php 0000777 00000002423 15251220643 0007156 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; use Exception; class CptApi extends \Rvx\Api\BaseApi { /** * @param $id * @return Response * @throws Exception */ public function cptGet() : Response { return $this->get('custom-post-type'); } /** * @param array $data * @return Response * @throws Exception */ public function cptStore(array $data) : Response { return $this->withJson($data)->post('custom-post-type/store'); } /** * @param $id * @return mixed * @throws Exception */ public function cptDelete($id) { return $this->delete('custom-post-type/' . $id['uid']); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function cptUpdate(array $data, $uid) : Response { $url = 'custom-post-type/' . $uid . '/update'; return $this->withJson($data)->put($url); } /** * @param array $data * @param $uid * @return Response * @throws Exception */ public function cptStatusChange(array $data, $uid) : Response { $url = 'custom-post-type/' . $uid . '/status-change'; return $this->withJson($data)->put($url); } } Api/WebhookRequestApi.php 0000777 00000000501 15251220643 0011372 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; class WebhookRequestApi extends \Rvx\Api\BaseApi { /** * @param array $data * @return Response */ public function finishedWebhook(array $data) : Response { return $this->withJson($data)->post('webhooks/datasync/finished'); } } Api/ApiResponse.php 0000777 00000000534 15251220643 0010227 0 ustar 00 <?php namespace Rvx\Api; use Rvx\Apiz\Http\Response; class ApiResponse extends Response { /** * @return array */ public function getApiData() : array { $response = $this->autoParse(); return $response['data'] ?? []; } public function statusCode() { return $this->getStatusCode(); } } Builder/BaseBuilder.php 0000777 00000002026 15251220643 0011033 0 ustar 00 <?php namespace Rvx\Builder; abstract class BaseBuilder { /** * Prepare classes for a given segment. * * @param string $segment * @return array */ public function prepareClasses(string $segment) : array { $uniqueClasses = $this->getUniqueClasses($segment); $modifiedClasses = []; foreach ($uniqueClasses as $item) { $transformed = $this->transformClass($item); $modifiedClasses[] = $transformed; } return $modifiedClasses; } /** * Retrieve unique classes for a given segment. * * This method must be implemented by subclasses. * * @param string $segment * @return array */ public abstract function getUniqueClasses(string $segment) : array; /** * Transform a class item into the required format. * * This method must be implemented by subclasses. * * @param array $item * @return array */ public abstract function transformClass(array $item) : array; } Elementor/Classes/Starter.php 0000777 00000003650 15251220643 0012243 0 ustar 00 <?php namespace Rvx\Elementor\Classes; use Rvx\Elementor\Traits\Addons; use Rvx\Elementor\Traits\Library; if (!\defined('ABSPATH')) { exit; } // Exit if accessed directly /** * Class Starter * @package Rvx\Elementor\Classes */ class Starter { use Addons, Library; // instance container private static $instance = null; // registered elements container public $registered_elements; // registered extensions container public $registered_extensions; // additional settings public $additional_settings; /** * Singleton instance * * @since 3.0.0 */ public static function instance() { if (self::$instance == null) { self::$instance = new self(); } return self::$instance; } /** * Constructor of plugin class * * @since 3.0.0 */ private function __construct() { // elements classmap $this->registered_elements = ['rxcall-to-review' => ['class' => 'Rvx\\Elementor\\Elements\\Data_Tabs'], 'rxcall-to-review-widget' => ['class' => 'Rvx\\Elementor\\Elements\\Review_Widget']]; // extensions classmap // $this->registered_extensions = apply_filters('rx/registered_extensions', Helper::arrayGet(config('settings'), 'rxextensions')); // // // additional settings $this->additional_settings = apply_filters('rx/additional_settings', ['quick_tools' => \true]); // register hooks $this->register_hooks(); } /** * Register Hooks * * @return void */ protected function register_hooks() { // Elements add_action('elementor/elements/categories_registered', array($this, 'register_widget_categories')); add_action('elementor/widgets/widgets_registered', array($this, 'register_elements')); add_action('elementor/widgets/register', array($this, 'cpt_register_element')); } } Elementor/Elements/Cpt_Widget.php 0000777 00000061030 15251220643 0013023 0 ustar 00 <?php namespace Rvx; // namespace ReviewX\Elementor\Elements; // If this file is called directly, abort. if (!\defined('ABSPATH')) { exit; } use Elementor\Controls_Manager; use Elementor\Group_Control_Border; use Elementor\Group_Control_Box_Shadow; use Elementor\Group_Control_Typography; use Elementor\Plugin; use Elementor\Utils; use Elementor\Widget_Base; use ReviewX\Constants\Reviewx; /** * Class Review * @package ReviewX\Elementor\Elements */ class Cpt_Widgets extends Widget_Base { /** * @return string */ public function get_name() { return 'rx-cpt-widget'; } /** * @return string|void */ public function get_title() { return __('ReviewX CPT Review', 'reviewx'); } /** * @return string */ public function get_icon() { return 'eicon-review'; } /** * @return array|string[] */ public function get_categories() { return ['rx-addons-elementor']; } /** * @return array */ public function get_keywords() { return ['reviewx', 'cpt review', 'cpt', 'comment', 'review', 'addons', 'ea', 'essential addons']; } /** * @return string */ public function get_custom_help_url() { return esc_url('https://reviewx.io/docs'); } /** * @param $styles * @param bool $group * @return array|array[]|mixed */ private function get_options_by_groups($styles, $group = \false) { $groups = ['line' => ['label' => __('Line', 'reviewx'), 'options' => ['solid' => __('Solid', 'reviewx'), 'double' => __('Double', 'reviewx'), 'dotted' => __('Dotted', 'reviewx'), 'dashed' => __('Dashed', 'reviewx')]]]; if (!empty($styles)) { foreach ($styles as $key => $style) { if (!isset($groups[$style['group']])) { $groups[$style['group']] = ['label' => \ucwords(\str_replace('_', '', $style['group'])), 'options' => []]; } $groups[$style['group']]['options'][$key] = $style['label']; } } if ($group && isset($groups[$group])) { return $groups[$group]; } return $groups; } /** * @param $array * @param $key * @param $value * @return array */ private function filter_styles_by($array, $key, $value) { return \array_filter($array, function ($style) use($key, $value) { return $value === $style[$key]; }); } /** * Register Controls * @return void */ protected function register_controls() { $styles = ''; $this->graph(); $this->reviewItem(); $this->form(); $this->frontSize(); $this->filterOptions(); } public function graph() { $this->start_controls_section('rx_section_graph_style', ['label' => __('Graph of Review Criteria', 'reviewx')]); $this->start_controls_tabs('graph_style'); $this->add_control('rx_summary_progress_bar_box_border_color', ['label' => __('Rating Out Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => [' #rvx-storefront-widget .rvx-rating-out-of' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_rating_color', ['label' => __('Rating Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6C7075', 'selectors' => [' #rvx-storefront-widget .rvx-rating' => 'color: {{VALUE}} !important']]); $this->add_control('rx_template_badge_color', ['label' => __('Badge Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#5FC65F', 'selectors' => [' #rvx-storefront-widget .rvx-rating-badge' => 'background-color: {{VALUE}} !important']]); $this->add_control('rx_template_text_color', ['label' => __('Badge Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FFFFFF', 'selectors' => [' #rvx-storefront-widget .rvx-rating-badge__text' => 'color: {{VALUE}} !important']]); $this->add_control('rx_template_summary_star_color', ['label' => __('Summary Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FBD045', 'selectors' => [' #rvx-storefront-widget .rvx-aggregation__rating .rvx-aggregation__rating-icon path' => 'fill: {{VALUE}} !important']]); $this->add_control('rx_template_summary_criteria_star_color', ['label' => __('Summary Criteria Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FBD045', 'selectors' => [' #rvx-storefront-widget .rvx-aggregation-multicriteria__total .rvx-aggregation-multicriteria__start-icon path' => 'fill: {{VALUE}} !important']]); $this->add_control('rx_template_aggeregation_criteria_progressbar_color', ['label' => __('Aggregation Multicriteria Bar', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FBD045', 'selectors' => [' #rvx-storefront-widget .rvx-aggregation__progressbar .rvx-aggregation__progressbar-active' => 'background: {{VALUE}} !important']]); $this->add_control('rx_template_progressbar_active_color', ['label' => __('Progressbar Active Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FBD045', 'selectors' => [' #rvx-storefront-widget .rvx-aggregation__progressbar .rvx-aggregation__progressbar-active' => 'background: {{VALUE}} !important']]); $this->add_control('rx_template_total_review_color', ['label' => __('Total Reviews Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#717C71', 'selectors' => [' #rvx-storefront-widget .rvx-total-review' => 'color: {{VALUE}} !important']]); $this->add_control('rx_template_critriya_color', ['label' => __('Total Criteria Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6d6d6d', 'selectors' => [' #rvx-storefront-widget .rvx-aggregation-multicriteria__name' => 'color: {{VALUE}} !important']]); $this->end_controls_tabs(); $this->end_controls_section(); } public function reviewItem() { $this->start_controls_section('rx_template_one_section_review_style', ['label' => __('Review Item', 'reviewx')]); $this->start_controls_tabs('template_one_review_style'); $this->add_control('rx_template_one_author_block_style', ['type' => Controls_Manager::HEADING, 'label' => __('Reviewer Information', 'reviewx'), 'separator' => 'after']); $this->add_control('rx_template_one_author_color', ['label' => __('Reviewer Name Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#373747', 'selectors' => [' .rvx-review-user .rvx-review-user__name' => 'color: {{VALUE}} !important']]); $this->add_control('rx_template_one_main_content_block_style', ['type' => Controls_Manager::HEADING, 'label' => __('Main Content', 'reviewx'), 'separator' => 'before']); $this->add_control('rx_template_one_title_color', ['label' => __('Review Title Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#373747', 'selectors' => [' .rvx-review-info .rvx-review-info__title' => 'color: {{VALUE}} !important']]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_template_one_title_typography', 'label' => __('Review Title Typography', 'reviewx'), 'selector' => ' .rvx-review-info .rvx-review-info__title']); $this->add_control('rx_template_one_text_color', ['label' => __('Review Comments Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#9B9B9B', 'selectors' => [' .rvx-review-info .rvx-review-info__feedback' => 'color: {{VALUE}} !important']]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_template_one_text_typography', 'label' => __('Review Comments Typography', 'reviewx'), 'selector' => ' .rvx-review-info .rvx-review-info__feedback']); /********************************* * Review Comments End * *********************************/ $this->add_control('rx_template_one_text_block_style', ['type' => Controls_Manager::HEADING, 'label' => __('Meta Information', 'reviewx'), 'separator' => 'before']); $this->add_control('rvx_write_review_bg', ['label' => __('Write Review', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#387CF7', 'selectors' => [' #rvx-storefront-widget .rvx-review-write__button' => 'background-color : {{VALUE}} !important']]); $this->add_control('rvx_write_review_text', ['label' => __('Write Review Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FFFFFF', 'selectors' => [' #rvx-storefront-widget .rvx-review-write__button' => 'color : {{VALUE}} !important']]); $this->add_control('rx_template_one_date_icon_color', ['label' => __('Reviewed Date Icon Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#707070', 'selectors' => [' .rvx-review-info .rvx-review-info__date' => 'color: {{VALUE}} !important']]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_template_one_date_typography', 'label' => __('Reviewed Date Typography', 'reviewx'), 'selector' => ' .rvx-review-info .rvx-review-info__date']); $this->add_control('rvx_was_his_helpful_color', ['label' => __('Was this helpful', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#333', 'selectors' => [' #rvx-storefront-widget .rvx-review-footer .rvx-review-footer__text' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_like', ['label' => __('Review Item Like', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#E0E0E0', 'selectors' => [' #rvx-storefront-widget .rvx-review-footer__thumbs--like-icon path' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_dislike', ['label' => __('Review Item Disike', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#E0E0E0', 'selectors' => [' #rvx-storefront-widget .rvx-review-footer__thumbs--dislike-icon path' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_username', ['label' => __('User Name Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FFFFFF', 'selectors' => [' #rvx-storefront-widget .rvx-review-user .rvx-review-user__avatar' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_username_feedback', ['label' => __('User Name Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FFFFFF', 'selectors' => [' #rvx-storefront-widget .rvx-review-user .rvx-review-user__avatar-fallback' => 'color: {{VALUE}} !important']]); $this->end_controls_tabs(); $this->end_controls_section(); } public function form() { $this->start_controls_section('rx_template_one_section_form_style', ['label' => __('Review Form', 'reviewx')]); $this->add_control('rvx_form_background_color', ['label' => __('Form Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => [' #rvx-review-form__wrapper' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_criteria_star_color', ['label' => __('Criteria star color active', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#ECBD3F', 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__star-active' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_criteria_inactive_star_color', ['label' => __('Criteria star color inactive', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#808080', 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__star-inactive' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_criteria_star_half_color_active', ['label' => __('Criteria star color inactive', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#808080', 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__star-active-half stop:first-child' => 'stop-color: {{VALUE}} !important']]); $this->add_control('rvx_criteria_half_star_color_inactive', ['label' => __('Criteria star color inactive', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#808080', 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__star-active-half stop:last-child' => 'stop-color: {{VALUE}} !important']]); $this->add_control('rvx_placeholder_text_color', ['label' => __('Placeholder text color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#BDBDBD', 'selectors' => [' #rvx-review-form__wrapper input::placeholder' => 'color: {{VALUE}} !important', ' #rvx-review-form__wrapper textarea::placeholder' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_product_image_radius', ['label' => __('Product image radius', 'reviewx'), 'type' => Controls_Manager::IMAGE_DIMENSIONS, 'default' => ['width' => '', 'height' => '', 'unit' => 'px'], 'size_units' => ['px', 'em', '%'], 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__product img' => 'width: {{WIDTH}}{{UNIT}} !important; height: {{HEIGHT}}{{UNIT}} !important;']]); $this->add_control('rvx_placeholder_text_color_one', ['label' => __('Hide product image', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => [' #rvx-review-form__wrapper' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_placeholder_text_color_two', ['label' => __('Product image radius', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => [' #rvx-review-form__wrapper' => 'background: {{VALUE}} !important']]); $this->add_control('rx_product_title_color', ['label' => __('Product Title Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#1a1a1a', 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__product--title' => 'color: {{VALUE}} !important']]); $this->add_control('rx_template_one_form_separator_one', ['type' => Controls_Manager::DIVIDER]); $this->add_control('rvx_review_form__title_namemulti', ['label' => __('Criteria Title Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#1a1a1a', 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__multicriteria--name' => 'color: {{VALUE}} !important']]); //rvx-review-form__title--name $this->add_control('rvx_review_form__title_name', ['label' => __('Review Input Title Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#3797FF', 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__title--name' => 'color: {{VALUE}} !important']]); $this->add_control('rx_template_one_form_separator_two', ['type' => Controls_Manager::DIVIDER]); $this->add_control('rvx_review_form__description', ['label' => __('Review Description Title', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6d6d6d', 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__description .rvx-review-form__title--name' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_review_form__attachments', ['label' => __('Review Attachment Title', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6d6d6d', 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--name' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_review_form__recommended', ['label' => __('Review Recommended Title', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6d6d6d', 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__recommended .rvx-review-form__recommended--name' => 'color: {{VALUE}} !important']]); $this->add_control('rx_template_one_form_separator_three', ['type' => Controls_Manager::DIVIDER]); $this->add_control('rx_template_one_form_submit_button_text_color', ['label' => __('Submit Button Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"], #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:focus ' => 'color: {{VALUE}} !important']]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_template_one_form_submit_button_text_typography', 'label' => __('Submit Button Text Typography', 'reviewx'), 'selector' => ' #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"], #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:focus']); $this->add_control('rx_template_one_form_submit_button_bg_color', ['label' => __('Submit Button Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#2f4fff', 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"], #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:focus' => 'background-color: {{VALUE}} !important']]); $this->add_control('rx_template_one_form_submit_button_border_radius', ['label' => __('Submit Button Border Radius', 'reviewx'), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => ['px', '%'], 'selectors' => [' #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}} !important;']]); $this->add_control('rx_anonymous_submit_text_color', ['label' => __('Anonymous Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6D6D6D', 'selectors' => [' #rvx-storefront-widget .rvx-review-form__mark-anonymous' => 'color: {{VALUE}} !important;']]); $this->end_controls_tabs(); $this->end_controls_section(); } public function frontSize() { $this->start_controls_section('rx_template_font_section', ['label' => __('Front size', 'reviewx')]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_template_front_size_text_typography', 'label' => __('Review Criteria Typography', 'reviewx'), 'selector' => ' .rvx-review-form__multicriteria--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_criteria_label_typography', 'label' => __('Criteria Label Typography', 'reviewx'), 'selector' => ' .rvx-review-form__multicriteria--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_criteria_value_typography', 'label' => __('Criteria Value Typography', 'reviewx'), 'selector' => ' .rvx-aggregation-multicriteria__row-inner .rvx-review-form__multicriteria--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_title_lable_typography', 'label' => __('Title lable', 'reviewx'), 'selector' => ' #rvx-review-form__wrapper .rvx-review-form__title--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_title_value_typography', 'label' => __('Title Value', 'reviewx'), 'selector' => ' .rvx-review-info .rvx-review-info__title']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_description_label_typography', 'label' => __('Description label', 'reviewx'), 'selector' => ' .rvx-review-form__description .rvx-review-form__title--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_description_value_typography', 'label' => __('Description Value', 'reviewx'), 'selector' => ' .rvx-review-info .rvx-review-info__feedback']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_attachments_typography', 'label' => __('Attachment', 'reviewx'), 'selector' => ' .rvx-review-form__attachment--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_recommended_typography', 'label' => __('Recommended', 'reviewx'), 'selector' => ' .rvx-review-form__recommended--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rx_anonymous_typography', 'label' => __('Mark as Anonymous', 'reviewx'), 'selector' => ' .rvx-review-form__mark-anonymousk']); $this->end_controls_tabs(); $this->end_controls_section(); } public function filterOptions() { $this->start_controls_section('rx_template_filter_section', ['label' => __('Filter Options', 'reviewx')]); $this->add_control('rvx_filter_text_color', ['label' => __('Filter Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#000000', 'selectors' => [' #rvx-storefront-widget .rvx-review-filter__button' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_filter_text_button_background_color', ['label' => __('Filter Button Background color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => [' #rvx-storefront-widget .rvx-review-filter__button' => 'background: {{VALUE}} !important']]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_filter_button_font_size', 'label' => __('Filter Button Font Size', 'reviewx'), 'selector' => ' #rvx-storefront-widget .rvx-review-filter__button', 'fields_options' => ['font_size' => ['default' => ['unit' => 'px', 'size' => 16]]]]); $this->add_control('rvx_filter_by_text_color', ['label' => __('Filter By Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6B707A', 'selectors' => [' #rvx-storefront-widget .rvx-review-filter-wrapper__title' => 'color: {{VALUE}} !important']]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_filter_by_font_size', 'label' => __('Filter By Font Size', 'reviewx'), 'selector' => ' #rvx-storefront-widget .rvx-review-filter-wrapper__title', 'fields_options' => ['font_size' => ['default' => ['unit' => 'px', 'size' => 16]]]]); $this->add_control('rvx_filter_dropdown_background_color', ['label' => __('Dropdown Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FFFFFF', 'selectors' => [' .rvx-review-filter-wrapper' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_filter_reset_filters_text_color', ['label' => __('Reset Filters Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#383239', 'selectors' => [' .rvx-review-filter-wrapper__footer button' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_filter_filter_button_background', ['label' => __('Filter Button Background', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => [' .rvx-review-filter-wrapper__footer button' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_filter_button_border_radius', ['label' => __('Button Border Radius', 'reviewx'), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => ['px', '%'], 'selectors' => [' .rvx-review-filter-wrapper__footer button' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}} !important;']]); $this->add_control('rvx_filter_dropdown_text_color', ['label' => __('Filter Dropdown Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => [' .rvx-review-filter-wrapper' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_filter_main_short_dropdown_text_color', ['label' => __('Short By Dropdown Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#000000', 'selectors' => [' .rvx-review-filter-wrapper__outer' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_filter_main_short_background_color', ['label' => __('Short By Dropdown BG Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => [' .rvx-review-filter-wrapper__outer' => 'background: {{VALUE}} !important']]); $this->end_controls_tabs(); $this->end_controls_section(); } /** * Render * @return void */ protected function render() { global $post; $post = get_post(); if ($post->post_type == 'product') { echo '<h3>' . __('This widget only works for the post page. In order to achieve, follow the steps: this Dashboard > Template > Theme Builder > Add New > Choose Template Type \'Single Post\' > Create Template', 'reviewx') . '</h3>'; return; } $rx_template_type = $this->get_settings_for_display(); setup_postdata($post->ID); \call_user_func('comments_template', 'reviews'); } /** * */ public function render_plain_content() { } } /** * Class Review * @package ReviewX\Elementor\Elements */ \class_alias('Rvx\\Cpt_Widgets', 'Cpt_Widgets', \false); Elementor/Elements/Review_Widget.php 0000777 00000153716 15251220643 0013553 0 ustar 00 <?php namespace Rvx\Elementor\Elements; // If this file is called directly, abort. if (!\defined('ABSPATH')) { exit; } use Elementor\Controls_Manager; use Elementor\Group_Control_Border; use Elementor\Group_Control_Box_Shadow; use Elementor\Group_Control_Typography; use Elementor\Plugin; use Elementor\Utils; use Elementor\Widget_Base; /** * Class Review * @package ReviewX\Elementor\Elements */ class Review_Widget extends Widget_Base { /** * @return string */ public function get_name() { return 'rx-review-widget'; } /** * @return string|void */ public function get_title() { return __('ReviewX Woo Review', 'reviewx'); } /** * @return string */ public function get_icon() { return 'eicon-review'; } /** * @return array|string[] */ public function get_categories() { return ['rx-addons-elementor']; } /** * @return array */ public function get_keywords() { return ['reviewx', 'woo review', 'woo', 'woocommerce', 'comment', 'review', 'addons', 'ea', 'essential addons']; } /** * @return string */ public function get_custom_help_url() { return esc_url('https://reviewx.io/docs'); } /** * @param $styles * @param bool $group * @return array|array[]|mixed */ private function get_options_by_groups($styles, $group = \false) { $groups = ['line' => ['label' => __('Line', 'reviewx'), 'options' => ['solid' => __('Solid', 'reviewx'), 'double' => __('Double', 'reviewx'), 'dotted' => __('Dotted', 'reviewx'), 'dashed' => __('Dashed', 'reviewx')]]]; if (!empty($styles)) { foreach ($styles as $key => $style) { if (!isset($groups[$style['group']])) { $groups[$style['group']] = ['label' => \ucwords(\str_replace('_', '', $style['group'])), 'options' => []]; } $groups[$style['group']]['options'][$key] = $style['label']; } } if ($group && isset($groups[$group])) { return $groups[$group]; } return $groups; } /** * @param $array * @param $key * @param $value * @return array */ private function filter_styles_by($array, $key, $value) { return \array_filter($array, function ($style) use($key, $value) { return $value === $style[$key]; }); } /** * Register Controls * @return void */ protected function register_controls() { $styles = ''; $this->start_controls_section('rvx_section_review_tabs_style', ['label' => __('Tabs', 'reviewx'), 'tab' => Controls_Manager::TAB_STYLE]); $this->add_control('rvx_wc_style_warning', ['type' => Controls_Manager::RAW_HTML, 'raw' => __('The style of this widget is often affected by your theme and plugins. If you experience any such issue, try to switch to a basic theme and deactivate related plugins.', 'reviewx'), 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info']); $this->start_controls_tabs('tabs_style'); $this->start_controls_tab('normal_tabs_style', ['label' => __('Normal', 'reviewx')]); $this->add_control('rvx_tab_text_color', ['label' => __('Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li a' => 'color: {{VALUE}}']]); $this->add_control('rvx_tab_bg_color', ['label' => __('Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'alpha' => \false, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li' => 'background-color: {{VALUE}}']]); $this->add_control('rvx_tabs_border_color', ['label' => __('Border Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel' => 'border-color: {{VALUE}}', '.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li' => 'border-color: {{VALUE}}']]); $this->end_controls_tab(); $this->start_controls_tab('active_tabs_style', ['label' => __('Active', 'reviewx')]); $this->add_control('rvx_active_tab_text_color', ['label' => __('Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li.active a' => 'color: {{VALUE}}']]); $this->add_control('rvx_active_tab_bg_color', ['label' => __('Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'alpha' => \false, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel, .woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li.active' => 'background-color: {{VALUE}}', '.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li.active' => 'border-bottom-color: {{VALUE}}']]); $this->add_control('rvx_active_tabs_border_color', ['label' => __('Border Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel' => 'border-color: {{VALUE}}', '.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li.active' => 'border-color: {{VALUE}} {{VALUE}} {{active_tab_bg_color.VALUE}} {{VALUE}}', '.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li:not(.active)' => 'border-bottom-color: {{VALUE}}']]); $this->end_controls_tab(); $this->end_controls_tabs(); $this->add_control('rvx_separator_tabs_style', ['type' => Controls_Manager::DIVIDER]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_tab_typography', 'label' => __('Typography', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li a']); $this->add_control('rvx_tab_border_radius', ['label' => __('Border Radius', 'reviewx'), 'type' => Controls_Manager::SLIDER, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li' => 'border-radius: {{SIZE}}{{UNIT}} {{SIZE}}{{UNIT}} 0 0']]); $this->end_controls_section(); $this->start_controls_section('rvx_section_product_panel_style', ['label' => __('Panel', 'reviewx'), 'tab' => Controls_Manager::TAB_STYLE]); $this->add_control('rvx_text_color', ['label' => __('Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel' => 'color: {{VALUE}}']]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_content_typography', 'label' => __('Typography', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel']); $this->add_control('rvx_heading_panel_heading_style', ['type' => Controls_Manager::HEADING, 'label' => __('Heading', 'reviewx'), 'separator' => 'before']); $this->add_control('rvx_heading_color', ['label' => __('Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'selectors' => ['.woocommerce {{WRAPPER}} h2' => 'color: {{VALUE}}']]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_content_heading_typography', 'label' => __('Typography', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-tabs h2']); $this->add_control('rvx_separator_panel_style', ['type' => Controls_Manager::DIVIDER]); $this->add_control('rvx_panel_border_width', ['label' => __('Border Width', 'reviewx'), 'type' => Controls_Manager::DIMENSIONS, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel' => 'border-width: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}}; margin-top: -{{TOP}}{{UNIT}}']]); $this->add_control('rvx_panel_border_radius', ['label' => __('Border Radius', 'reviewx'), 'type' => Controls_Manager::DIMENSIONS, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}}', '.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs' => 'margin-left: {{TOP}}{{UNIT}}; margin-right: {{RIGHT}}{{UNIT}}']]); $this->add_group_control(Group_Control_Box_Shadow::get_type(), ['name' => 'rvx_panel_box_shadow', 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel']); $this->end_controls_section(); $this->graph(); $this->reviewCard(); $this->reviewForm(); // $this->frontSize(); $this->filterOptions(); } public function graph() { $this->start_controls_section('rvx_section_summary_style', ['label' => __('Review Summary', 'reviewx')]); $this->start_controls_tabs('graph_style'); $this->add_control('rvx_template_average_rating_color', ['label' => __('Average Rating Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['{{WRAPPER}} #rvx-storefront-widget .rvx-average-rating' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_max_rating_color', ['label' => __('Max Rating Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#BDBDBD', 'selectors' => ['{{WRAPPER}} #rvx-storefront-widget .rvx-max-rating' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_badge_color', ['label' => __('Badge Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#4CAF50', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget .rvx-rating-badge' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_budge_text_color', ['label' => __('Badge Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FFFFFF', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget .rvx-rating-badge__text' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_average_rating_star_active_color', ['label' => __('Average Rating Star Active Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FCCE08', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-aggregation-summary__star-active' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-review__aggregation__summary__star-active-half-star' => 'stop-color: {{VALUE}} !important']]); $this->add_control('rvx_template_average_rating_star_inactive_color', ['label' => __('Average Rating Star inactive Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => 'gray', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-review-form__star-inactive' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-review__aggregation__summary__star-inactive-half-star' => 'stop-color: {{VALUE}} !important']]); $this->add_control('rvx_template_total_review_count_color', ['label' => __('Total Review Count Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#BDBDBD', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-total-review' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_summary_star_color', ['label' => __('Summary Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FCCE08', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-aggregation__row .rvx-aggregation__rating-icon path' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_summary_progress_bar_active_color', ['label' => __('Summary Progress Bar Active Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => 'rgb(0, 67, 221)', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-aggregation__row .rvx-aggregation__progressbar .rvx-aggregation__progressbar-active' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_summary_progress_bar_inactive_color', ['label' => __('Summary Progress Bar Inactive Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#D9D9D9', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-aggregation__row .rvx-aggregation__progressbar .rvx-aggregation__progressbar-inactive' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_multi_criteria_title_color', ['label' => __('Multi Criteria Title Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#D9D9D9', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget .rvx-aggregation-multicriteria .rvx-aggregation-multicriteria__name span' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_multi_criteria_progressbar_active_color', ['label' => __('Multi Criteria Progress Bar Active Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => 'rgb(0, 67, 221)', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget .rvx-aggregation-multicriteria .rvx-aggregation__progressbar .rvx-aggregation__progressbar-active' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_multi_criteria_progressbar_inactive_color', ['label' => __('Multi Criteria Progress Bar Inactive Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#D9D9D9', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget .rvx-aggregation-multicriteria .rvx-aggregation__progressbar .rvx-aggregation__progressbar-inactive' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_multi_criteria_star_color', ['label' => __('Multi Criteria Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FCCE08', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget .rvx-aggregation-multicriteria .rvx-aggregation-multicriteria__total .rvx-aggregation__rating-icon path' => 'fill: {{VALUE}} !important']]); $this->end_controls_tabs(); $this->end_controls_section(); } public function reviewCard() { $this->start_controls_section('rvx_template_section_review_card_style', ['label' => __('Review Card', 'reviewx')]); $this->start_controls_tabs('rvx_template_tabs_review_card_style'); $this->add_control('rvx_template_one_author_block_style', ['type' => Controls_Manager::HEADING, 'label' => __('Reviewer Information', 'reviewx'), 'separator' => 'after']); $this->add_control('rvx_template_reviewer_info_author_avatar_size', ['label' => __('Avatar Size', 'reviewx'), 'show_label' => \true, 'type' => Controls_Manager::IMAGE_DIMENSIONS, 'default' => ['width' => '50', 'height' => '50', 'unit' => 'px'], 'size_units' => ['px', 'em', '%'], 'selectors' => ['.woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-review-user__avatar' => 'width: {{WIDTH}}{{UNIT}} !important; height: {{HEIGHT}}{{UNIT}} !important;', ' .woocommerce {{WRAPPER}} #rvx-review-details .rvx-review-user__avatar' => 'width: {{WIDTH}}{{UNIT}} !important; height: {{HEIGHT}}{{UNIT}} !important;']]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_template_reviewer_info_author_avatar_fallback_typography', 'label' => __('Avatar Fallback Typography', 'reviewx'), 'selector' => ' .woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-review-user__avatar .rvx-review-user__avatar-fallback span, .woocommerce {{WRAPPER}} #rvx-review-details .rvx-review-user__avatar .rvx-review-user__avatar-fallback span ', 'fields_options' => ['font_size' => ['default' => ['unit' => 'px', 'size' => 16]]]]); $this->add_control('rvx_template_reviewer_info_author_avatar_text_color', ['label' => __('Avatar Fallback Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#BDBDBD', 'selectors' => ['.woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-review-user__avatar .rvx-review-user__avatar-fallback span' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-review-details .rvx-review-user__avatar .rvx-review-user__avatar-fallback span' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_reviewer_card_background_color_for_review', ['label' => __('Review Card Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget .rvx-review-wrapper .rvx-review-card' => 'background-color: {{VALUE}} !important;']]); $this->add_control('rvx_template_reviewer_info_author_name_text_color', ['label' => __('Name Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#373747', 'selectors' => ['.woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-review-user .rvx-review-user__name' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-review-details .rvx-review-user .rvx-review-user__name' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_reviewer_info_rating_star_active_color', ['label' => __('Rating Star Active Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#ECBD3F', 'selectors' => ['.woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-reviewer__star-active' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-reviewer__star-half.rvx-reviewer__star-active-half-star' => 'stop-color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-review-details .rvx-reviewer__star-active' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-review-details .rvx-reviewer__star-half.rvx-reviewer__star-active-half-star' => 'stop-color: {{VALUE}} !important']]); $this->add_control('rvx_template_reviewer_info_rating_star_inactive_color', ['label' => __('Rating Star Inactive Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#ECBD3F', 'selectors' => ['.woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-reviewer__star-inactive' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-reviewer__star-half rvx-reviewer__star-inactive-half-star' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-review-details__body .rvx-reviewer__star-inactive' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-review-details__body .rvx-reviewer__star-half.rvx-reviewer__star-inactive-half-star' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_main_content_block_style', ['type' => Controls_Manager::HEADING, 'label' => __('Main Content', 'reviewx'), 'separator' => 'before']); $this->add_control('rvx_template_main_content_title_color', ['label' => __('Review Title Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#373747', 'selectors' => ['.woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__title' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-review-details .rvx-review-info .rvx-review-info__title' => 'color: {{VALUE}} !important']]); // $this->add_group_control( // Group_Control_Typography::get_type(), // [ // 'name' => 'rvx_template_main_content_review_title_typography', // 'label' => __('Review Title Typography', 'reviewx'), // 'selector' => '.woocommerce {{WRAPPER}} #rvx-storefront-widget .rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__title, .woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-details .rvx-review-info .rvx-review-info__title', // ] // ); $this->add_control('rvx_template_main_content_review_description_text_color', ['label' => __('Review Description Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#9B9B9B', 'selectors' => ['.woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__feedback' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-review-details .rvx-review-info .rvx-review-info__feedback' => 'color: {{VALUE}} !important']]); // $this->add_group_control( // Group_Control_Typography::get_type(), // [ // 'name' => 'rvx_template_main_content_review_description_text_typography', // 'label' => __('Review Description Typography', 'reviewx'), // 'selector' => '.woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__feedback,.woocommerce {{WRAPPER}} #rvx-review-details .rvx-review-info .rvx-review-info__feedback', // ] // ); $this->add_control('rvx_template_main_content_review_description_review_date', ['label' => __('Review Date Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#757575', 'selectors' => ['.woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__date' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-review-details .rvx-review-info .rvx-review-info__date' => 'color: {{VALUE}} !important']]); // $this->add_group_control( // Group_Control_Typography::get_type(), // [ // 'name' => 'rvx_template_main_content_review_description_review_date_typography', // 'label' => __('Review Date Typography', 'reviewx'), // 'selector' => '.woocommerce {{WRAPPER}} .rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__date, .woocommerce {{WRAPPER}} #rvx-review-details .rvx-review-info .rvx-review-info__date', // ] // ); $this->add_control('rvx_template_main_content_footer_action_helpful_message_text_color', ['label' => __('Was This Helpful Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#333', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget .rvx-review-card .rvx-review-footer .rvx-review-footer__text' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-details .rvx-review-footer .rvx-review-footer__text' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_main_content_footer_like', ['label' => __('Review Like Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#E0E0E0', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget .rvx-review-card .rvx-review-footer__thumbs--like-icon path' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-details .rvx-review-footer__thumbs--like-icon path' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_card_load_more', ['label' => __('Load More Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FFFFFF', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget button' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_card_load_more_text_color', ['label' => __('Load More Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget button' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_card_load_more_background_hover_color', ['label' => __('Load More Hover Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#D5D5D5', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget button:hover' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_card_load_more_hover_text_color', ['label' => __('Load More Text Hover Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget button:hover' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_main_content_footer_dislike', ['label' => __('Review Dislike', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#E0E0E0', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget .rvx-review-card .rvx-review-footer__thumbs--dislike-icon path' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-details .rvx-review-footer__thumbs--dislike-icon path' => 'fill: {{VALUE}} !important']]); /********************************* * Review Description End * *********************************/ $this->end_controls_tabs(); $this->end_controls_section(); } public function filterOptions() { $this->start_controls_section('rvx_template_filter_section', ['label' => __('Filter Options', 'reviewx')]); $this->add_control('rvx_template_write_review_action_bg_color', ['label' => __('Write Review Action Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#387CF7', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-write__button' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_write_review_action_text_color', ['label' => __('Write Review Action Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-write__button' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_text_color', ['label' => __('Filter Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__button' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_text_button_background_color', ['label' => __('Filter Button Background color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__button' => 'background: {{VALUE}} !important']]); // $this->add_group_control( // Group_Control_Typography::get_type(), // [ // 'name' => 'rvx_filter_button_font_size', // 'label' => __('Filter Button Font Size', 'reviewx'), // 'selector' => '.woocommerce {{WRAPPER}} #rvx-storefront-widget .rvx-review-filter__button', // 'fields_options' => [ // 'font_size' => [ // 'default' => [ // 'unit' => 'px', // 'size' => 16, // Default font size set to 16px // ], // ], // ], // ] // ); $this->add_control('rvx_filter_dropdown_background_color', ['label' => __('Filter Dropdown Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FFFFFF', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper, .woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper .rvx-review-filter__wrapper-inner, .woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer ' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_by_text_color', ['label' => __('Dropdown Filter By Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6B707A', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__title' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_options_text_color', ['label' => __('Dropdown Filter Options Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6B707A', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__rating .rvx-review-filter-wrapper__rating--text, .woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__rating .rvx-review-filter-wrapper__rating-wrapper .rvx-review-filter-wrapper__rating-inner .rvx-review-filter__wrapper__rating--radio-group__option-label, .woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__attachment .rvx-review-filter-wrapper__attachment--text, .woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__attachment .rvx-review-filter-wrapper__attachment-wrapper .rvx-review-filter-wrapper__attachment-inner .rvx-review-filter__wrapper__attachment--radio-group__option-label ' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_options_icon_color', ['label' => __('Dropdown Filter Option Icon Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6B707A', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__rating .rvx-review-filter-wrapper__rating-inner--icon, .woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__attachment .rvx-review-filter-wrapper__attachment-inner--icon ' => 'color: {{VALUE}} !important']]); // $this->add_group_control( // Group_Control_Typography::get_type(), // [ // 'name' => 'rvx_filter_by_font_size', // 'label' => __('Dropdown Filter By Font Size', 'reviewx'), // 'selector' => '.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper__title', // 'fields_options' => [ // 'font_size' => [ // 'default' => [ // 'unit' => 'px', // 'size' => 16, // Default font size set to 16px // ], // ], // ], // ] // ); $this->add_control('rvx_template_filter_reset_button_text_color', ['label' => __('Filter Reset Button Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#383239', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper__footer button' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_reset_button_background_color', ['label' => __('Filter Reset Button Background', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper__footer button' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_reset_button_border_radius', ['label' => __('Filter Reset Button Border Radius', 'reviewx'), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => ['px', '%'], 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper__footer button' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}} !important;']]); $this->add_control('rvx_template_sort_by_button_text_color', ['label' => __('Sort By Button Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-sort__button' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_sort_by_button_bg_color', ['label' => __('Sort By Button Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-sort__button' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_sort_by_dropdown_text_color', ['label' => __('Sort By Dropdown Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-sort-wrapper .rvx-review-sort-wrapper__outer .rvx-review-sort-wrapper__inner .rvx-review-sort__wrapper--radio-group__option-label' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_sort_by_dropdown_bg_color', ['label' => __('Sort By Dropdown Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-filter .rvx-review-sort-wrapper' => 'background: {{VALUE}} !important']]); $this->end_controls_tabs(); $this->end_controls_section(); } public function reviewForm() { $this->start_controls_section('rvx_template_review_form_section_style', ['label' => __('Review Form', 'reviewx')]); // Form Text: Write a Review $this->add_control('rvx_template_review_form_text_write_a_review', ['label' => __('Write a Review', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Write a Review', 'selectors' => ['{{WRAPPER}} .rvx-review-form__title' => 'textContent: {{VALUE}};']]); // Form Text: Rating Title (Text) $this->add_control('rvx_template_review_form_text_rating_star_title', ['label' => __('Rating (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Rating', 'selectors' => ['{{WRAPPER}} .rvx-review-form__rating--name' => 'textContent: {{VALUE}};']]); // Form Text: Review Title (Text) $this->add_control('rvx_template_review_form_text_review_title', ['label' => __('Review Title (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Review Title', 'selectors' => ['{{WRAPPER}} .rvx-review-form__title--name' => 'textContent: {{VALUE}};']]); // Form Text: Review Title (Placeholder) $this->add_control('rvx_template_review_form_placeholder_review_title', ['label' => __('Review Title (Placeholder)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Write Review Title', 'selectors' => ['{{WRAPPER}} .rvx-review-form__title--input' => 'textContent: {{VALUE}};']]); // Form Text: Review Description (Text) $this->add_control('rvx_template_review_form_text_review_description', ['label' => __('Description (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Description', 'selectors' => ['{{WRAPPER}} .rvx-review-form__description--title' => 'textContent: {{VALUE}};']]); // Form Text: Review Description (Placeholder) $this->add_control('rvx_template_review_form_placeholder_review_description', ['label' => __('Description (Placeholder)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Write your description here', 'selectors' => ['{{WRAPPER}} .rvx-review-form__title--textarea' => 'textContent: {{VALUE}};']]); // Form Text: Full Name (Text) $this->add_control('rvx_template_review_form_text_full_name', ['label' => __('Full Name (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Full Name', 'selectors' => ['{{WRAPPER}} .rvx-review-form__description--title' => 'textContent: {{VALUE}};']]); // Form Text: Full Name (Placeholder) $this->add_control('rvx_template_review_form_placeholder_full_name', ['label' => __('Full Name (Placeholder)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Full Name', 'selectors' => ['{{WRAPPER}} .rvx-review-form__title--textarea' => 'textContent: {{VALUE}};']]); // Form Text: Email Address (Text) $this->add_control('rvx_template_review_form_text_email_name', ['label' => __('Email Address (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Email Address', 'selectors' => ['{{WRAPPER}} .rvx-review-form__description--title' => 'textContent: {{VALUE}};']]); // Form Text: Email Address (Placeholder) $this->add_control('rvx_template_review_form_placeholder_email_name', ['label' => __('Email Address (Placeholder)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Email Address', 'selectors' => ['{{WRAPPER}} .rvx-review-form__title--textarea' => 'textContent: {{VALUE}};']]); // Form Text: Attachment (Text) $this->add_control('rvx_template_review_form_text_attachment_title', ['label' => __('Attachment (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Attachment', 'selectors' => ['{{WRAPPER}} .rvx-review-form__attachment--name' => 'textContent: {{VALUE}};']]); // Form Text: Upload Photo / Video (Placeholder) $this->add_control('rvx_template_review_form_placeholder_upload_photo', ['label' => __('Upload Photo / video (Placeholder)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Upload Photo / Video', 'selectors' => ['{{WRAPPER}} .rvx-review-form__attachment--upload--text' => 'textContent: {{VALUE}};']]); // Form Text: Mark as Anonymous (Text) $this->add_control('rvx_template_review_form_text_mark_as_anonymous', ['label' => __('Mark as Anonymous (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Mark as Anonymous', 'selectors' => ['{{WRAPPER}} .rvx-review-form__mark-anonymous' => 'textContent: {{VALUE}};']]); // Form Text: Recommended? (Text) $this->add_control('rvx_template_review_form_text_recommended_title', ['label' => __('Recommended? (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Recommendation?', 'selectors' => ['{{WRAPPER}} .rvx-review-form__recommended--name' => 'textContent: {{VALUE}};']]); $this->add_control('rvx_template_review_form_background_color', ['label' => __('Form Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-storefront-widget #rvx-review-form__wrapper' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_title_color', ['label' => __('Form Title Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__title' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_border_color', ['label' => __('Form Border Line Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#E0E0E0', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__line' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_product_image_size', ['label' => __('Product Image Size', 'reviewx'), 'type' => Controls_Manager::IMAGE_DIMENSIONS, 'show_label' => \true, 'default' => ['width' => '64', 'height' => '64', 'unit' => 'px'], 'size_units' => ['px', 'em', '%'], 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__product .rvx-review-form__product--image' => 'width: {{WIDTH}}{{UNIT}} !important; height: {{HEIGHT}}{{UNIT}} !important;']]); // $this->add_control( // 'rvx_hide_product_image', // [ // 'label' => __('Hide Product Image', 'reviewx'), // 'type' => Controls_Manager::HIDDEN, // 'default' => 'block', // 'selectors' => [ // '.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__inner .rvx-review-form__product .rvx-review-form__product' => 'display: {{VALUE}} !important', // ], // ] // ); // $this->add_control('rvx_template_review_form_product_title_color', ['label' => __('Product Title Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__product .rvx-review-form__product--title' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_rating_star_active_color', ['label' => __('Rating Active Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FCCE08', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__rating .rvx-review-form__star-active' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_rating_star_inactive_color', ['label' => __('Rating Inactive Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FCCE08', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__rating .rvx-review-form__star-inactive' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_multi_criteria_star_active_color', ['label' => __('Multi Criteria Active Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FCCE08', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__multicriteria .rvx-review-form__star-active' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_multi_criteria_star_inactive_color', ['label' => __('Multi Criteria Inactive Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#757575', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__multicriteria .rvx-review-form__star-inactive' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_label_color', ['label' => __('Review Form Label Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__title .rvx-review-form__title--name, .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__description .rvx-review-form__description--title, .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__rating .rvx-review-form__rating--name, .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__multicriteria .rvx-review-form__multicriteria--name, .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__user .rvx-review-form__user--name, .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__email .rvx-review-form__email--name, .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__attachment .rvx-review-form__attachment--name, .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__attachment--inner .rvx-review-form__mark-anonymous, .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__recommended .rvx-review-form__recommended--name, .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__recommended label ' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_review_title_input_placeholder_color', ['label' => __('Review Form Input Placeholder Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#BDBDBD', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper input::placeholder, .woocommerce {{WRAPPER}} #rvx-review-form__wrapper textarea::placeholder ' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_input_background_color', ['label' => __('Review Form Input Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper input, .woocommerce {{WRAPPER}} #rvx-review-form__wrapper textarea ' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form__attachments_icon_color', ['label' => __('Review Attachment Icon Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#9E9E9E', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload--icon' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form__attachments_text_color', ['label' => __('Review Attachment Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#9E9E9E', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload--count, .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload--text' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form__attachments_background_color', ['label' => __('Review Attachment Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#EEEEEE', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_submit_button_bg_color', ['label' => __('Submit Button Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#2f4fff', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"], .woocommerce {{WRAPPER}} .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:focus' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_submit_button_text_color', ['label' => __('Submit Button Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"], .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:focus ' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_submit_button_hover_background_color', ['label' => __('Submit Button Hover Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"], .woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:hover ' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_submit_button_border_radius', ['label' => __('Submit Button Border Radius', 'reviewx'), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => ['px', '%'], 'selectors' => ['.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}} !important;']]); $this->end_controls_tabs(); $this->end_controls_section(); } public function frontSize() { $this->start_controls_section('rvx_template_font_section', ['label' => __('Font size', 'reviewx')]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_template_front_size_text_typography', 'label' => __('Review Criteria Typography', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .rvx-review-form__multicriteria--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_criteria_label_typography', 'label' => __('Criteria Label Typography', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .rvx-review-form__multicriteria--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_criteria_value_typography', 'label' => __('Criteria Value Typography', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .rvx-aggregation-multicriteria__row-inner .rvx-review-form__multicriteria--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_title_lable_typography', 'label' => __('Title lable', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} #rvx-review-form__wrapper .rvx-review-form__title--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_title_value_typography', 'label' => __('Title Value', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .rvx-review-info .rvx-review-info__title']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_description_label_typography', 'label' => __('Description label', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .rvx-review-form__description .rvx-review-form__title--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_description_value_typography', 'label' => __('Description Value', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .rvx-review-info .rvx-review-info__feedback']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_attachments_typography', 'label' => __('Attachment', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .rvx-review-form__attachment--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_recommended_typography', 'label' => __('Recommended', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .rvx-review-form__recommended--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_anonymous_typography', 'label' => __('Mark as Anonymous', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .rvx-review-form__mark-anonymous']); $this->end_controls_tabs(); $this->end_controls_section(); } /** * Template One Style * @return void */ /** * Render * @return void */ protected function render() { global $builderElementorSetting; $settings = $this->get_settings_for_display(); $builderElementorSetting = []; // Define the keys to be added if they have a value $keys = ['write_a_review' => 'rvx_template_review_form_text_write_a_review', 'text_rating_star_title' => 'rvx_template_review_form_text_rating_star_title', 'text_review_title' => 'rvx_template_review_form_text_review_title', 'placeholder_review_title' => 'rvx_template_review_form_placeholder_review_title', 'text_review_description' => 'rvx_template_review_form_text_review_description', 'placeholder_review_description' => 'rvx_template_review_form_placeholder_review_description', 'text_full_name' => 'rvx_template_review_form_text_full_name', 'placeholder_full_name' => 'rvx_template_review_form_placeholder_full_name', 'text_email_name' => 'rvx_template_review_form_text_email_name', 'placeholder_email_name' => 'rvx_template_review_form_placeholder_email_name', 'text_attachment_title' => 'rvx_template_review_form_text_attachment_title', 'placeholder_upload_photo' => 'rvx_template_review_form_placeholder_upload_photo', 'text_mark_as_anonymous' => 'rvx_template_review_form_text_mark_as_anonymous', 'text_recommended_title' => 'rvx_template_review_form_text_recommended_title']; // Loop through each key and add it to the array only if it has a non-empty value foreach ($keys as $key => $settingKey) { if (!empty($settings[$settingKey])) { $builderElementorSetting[$key] = $settings[$settingKey]; } } if (\class_exists('WooCommerce')) { global $product; $product = wc_get_product(); if (empty($product)) { echo '<h3>' . __('This widget only works for the product page. In order to achieve, follow the steps: this Dashboard > Template > Theme Builder > Add New > Choose Template Type \'Single Product\' > Create Template', 'reviewx') . '</h3>'; return; } setup_postdata($product->get_id()); \call_user_func('comments_template', 'reviews'); } } /** * */ public function render_plain_content() { } } Elementor/Elements/Data_Tabs.php 0000777 00000162417 15251220643 0012627 0 ustar 00 <?php namespace Rvx\Elementor\Elements; // If this file is called directly, abort. if (!\defined('ABSPATH')) { exit; } use Elementor\Control_Base_Multiple; use Elementor\Controls_Manager; use Elementor\Group_Control_Border; use Elementor\Group_Control_Box_Shadow; use Elementor\Group_Control_Typography; use Elementor\Plugin; use Elementor\Utils; use Elementor\Widget_Base; use ReviewX\Constants\Reviewx; /** * Class Data_Tabs * @package ReviewX\Elementor\Elements */ class Data_Tabs extends Widget_Base { /** * @return string */ public function get_name() { return 'rvx-review-data-tab'; } /** * @return string|void */ public function get_title() { return __('ReviewX Product Data Tabs', 'reviewx'); } /** * @return string */ public function get_icon() { return 'eicon-review'; } /** * @return array|string[] */ public function get_categories() { return ['rvx-addons-elementor']; } /** * @return array */ public function get_keywords() { return ['reviewx', 'woo review', 'woo', 'woocommerce', 'comment', 'review', 'addons', 'ea', 'essential addons']; } /** * @return string */ public function get_custom_help_url() { return esc_url('https://reviewx.io/docs'); } /** * @param $styles * @param bool $group * @return array|array[]|mixed */ private function get_options_by_groups($styles, $group = \false) { $groups = ['line' => ['label' => __('Line', 'reviewx'), 'options' => ['solid' => __('Solid', 'reviewx'), 'double' => __('Double', 'reviewx'), 'dotted' => __('Dotted', 'reviewx'), 'dashed' => __('Dashed', 'reviewx')]]]; if (!empty($cri)) { foreach ($styles as $key => $style) { if (!isset($groups[$style['group']])) { $groups[$style['group']] = ['label' => \ucwords(\str_replace('_', '', $style['group'])), 'options' => []]; } $groups[$style['group']]['options'][$key] = $style['label']; } } if ($group && isset($groups[$group])) { return $groups[$group]; } return $groups; } /** * @param $array * @param $key * @param $value * @return array */ private function filter_styles_by($array, $key, $value) { return \array_filter($array, function ($style) use($key, $value) { return $value === $style[$key]; }); } /** * Register Controls * @return void */ protected function register_controls() { $styles = ''; $this->start_controls_section('rvx_section_review_tabs_style', ['label' => __('Tabs', 'reviewx'), 'tab' => Controls_Manager::TAB_STYLE]); $this->add_control('rvx_wc_style_warning', ['type' => Controls_Manager::RAW_HTML, 'raw' => __('The style of this widget is often affected by your theme and plugins. If you experience any such issue, try to switch to a basic theme and deactivate related plugins.', 'reviewx'), 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info']); $this->start_controls_tabs('tabs_style'); $this->start_controls_tab('normal_tabs_style', ['label' => __('Normal', 'reviewx')]); $this->add_control('rvx_tab_text_color', ['label' => __('Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li a' => 'color: {{VALUE}}']]); $this->add_control('rvx_tab_bg_color', ['label' => __('Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'alpha' => \false, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li' => 'background-color: {{VALUE}}']]); $this->add_control('rvx_tabs_border_color', ['label' => __('Border Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel' => 'border-color: {{VALUE}}', '.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li' => 'border-color: {{VALUE}}']]); $this->end_controls_tab(); $this->start_controls_tab('active_tabs_style', ['label' => __('Active', 'reviewx')]); $this->add_control('rvx_active_tab_text_color', ['label' => __('Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li.active a' => 'color: {{VALUE}}']]); $this->add_control('rvx_active_tab_bg_color', ['label' => __('Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'alpha' => \false, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel, .woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li.active' => 'background-color: {{VALUE}}', '.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li.active' => 'border-bottom-color: {{VALUE}}']]); $this->add_control('rvx_active_tabs_border_color', ['label' => __('Border Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel' => 'border-color: {{VALUE}}', '.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li.active' => 'border-color: {{VALUE}} {{VALUE}} {{active_tab_bg_color.VALUE}} {{VALUE}}', '.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li:not(.active)' => 'border-bottom-color: {{VALUE}}']]); $this->end_controls_tab(); $this->end_controls_tabs(); $this->add_control('rvx_separator_tabs_style', ['type' => Controls_Manager::DIVIDER]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_tab_typography', 'label' => __('Typography', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li a']); $this->add_control('rvx_tab_border_radius', ['label' => __('Border Radius', 'reviewx'), 'type' => Controls_Manager::SLIDER, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs li' => 'border-radius: {{SIZE}}{{UNIT}} {{SIZE}}{{UNIT}} 0 0']]); $this->end_controls_section(); $this->start_controls_section('rvx_section_product_panel_style', ['label' => __('Panel', 'reviewx'), 'tab' => Controls_Manager::TAB_STYLE]); $this->add_control('rvx_text_color', ['label' => __('Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel' => 'color: {{VALUE}}']]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_content_typography', 'label' => __('Typography', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel']); $this->add_control('rvx_heading_panel_heading_style', ['type' => Controls_Manager::HEADING, 'label' => __('Heading', 'reviewx'), 'separator' => 'before']); $this->add_control('rvx_heading_color', ['label' => __('Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel h2' => 'color: {{VALUE}}']]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_content_heading_typography', 'label' => __('Typography', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel h2']); $this->add_control('rvx_separator_panel_style', ['type' => Controls_Manager::DIVIDER]); $this->add_control('rvx_panel_border_width', ['label' => __('Border Width', 'reviewx'), 'type' => Controls_Manager::DIMENSIONS, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel' => 'border-width: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}}; margin-top: -{{TOP}}{{UNIT}}']]); $this->add_control('rvx_panel_border_radius', ['label' => __('Border Radius', 'reviewx'), 'type' => Controls_Manager::DIMENSIONS, 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}}', '.woocommerce {{WRAPPER}} .woocommerce-tabs ul.wc-tabs' => 'margin-left: {{TOP}}{{UNIT}}; margin-right: {{RIGHT}}{{UNIT}}']]); $this->add_group_control(Group_Control_Box_Shadow::get_type(), ['name' => 'rvx_panel_box_shadow', 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-tabs .woocommerce-Tabs-panel']); $this->end_controls_section(); $this->graph(); $this->reviewCard(); $this->reviewForm(); // $this->frontSize(); $this->filterOptions(); } public function graph() { $this->start_controls_section('rvx_section_summary_style', ['label' => __('Review Summary', 'reviewx')]); $this->start_controls_tabs('graph_style'); $this->add_control('rvx_template_average_rating_color', ['label' => __('Average Rating Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['{{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-average-rating' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_max_rating_color', ['label' => __('Max Rating Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#BDBDBD', 'selectors' => ['{{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-max-rating' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_badge_color', ['label' => __('Badge Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#4CAF50', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-rating-badge' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_budge_text_color', ['label' => __('Badge Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FFFFFF', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-rating-badge__text' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_average_rating_star_active_color', ['label' => __('Average Rating Star Active Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FCCE08', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-aggregation-summary__star-active' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-review__aggregation__summary__star-active-half-star' => 'stop-color: {{VALUE}} !important']]); $this->add_control('rvx_template_average_rating_star_inactive_color', ['label' => __('Average Rating Star inactive Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => 'gray', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-review-form__star-inactive' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-review__aggregation__summary__star-inactive-half-star' => 'stop-color: {{VALUE}} !important']]); $this->add_control('rvx_template_total_review_count_color', ['label' => __('Total Review Count Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#BDBDBD', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-total-review' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_summary_star_color', ['label' => __('Summary Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FCCE08', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-aggregation__row .rvx-aggregation__rating-icon path' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_summary_progress_bar_active_color', ['label' => __('Summary Progress Bar Active Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => 'rgb(0, 67, 221)', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-aggregation__row .rvx-aggregation__progressbar .rvx-aggregation__progressbar-active' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_summary_progress_bar_inactive_color', ['label' => __('Summary Progress Bar Inactive Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#D9D9D9', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-aggregation__row .rvx-aggregation__progressbar .rvx-aggregation__progressbar-inactive' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_multi_criteria_title_color', ['label' => __('Multi Criteria Title Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#D9D9D9', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-aggregation-multicriteria .rvx-aggregation-multicriteria__name span' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_multi_criteria_progressbar_active_color', ['label' => __('Multi Criteria Progress Bar Active Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => 'rgb(0, 67, 221)', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-aggregation-multicriteria .rvx-aggregation__progressbar .rvx-aggregation__progressbar-active' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_multi_criteria_progressbar_inactive_color', ['label' => __('Multi Criteria Progress Bar Inactive Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#D9D9D9', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-aggregation-multicriteria .rvx-aggregation__progressbar .rvx-aggregation__progressbar-inactive' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_multi_criteria_star_color', ['label' => __('Multi Criteria Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FCCE08', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-aggregation-multicriteria .rvx-aggregation-multicriteria__total .rvx-aggregation__rating-icon path' => 'fill: {{VALUE}} !important']]); $this->end_controls_tabs(); $this->end_controls_section(); } public function reviewCard() { $this->start_controls_section('rvx_template_section_review_card_style', ['label' => __('Review Card', 'reviewx')]); $this->start_controls_tabs('rvx_template_tabs_review_card_style'); $this->add_control('rvx_template_one_author_block_style', ['type' => Controls_Manager::HEADING, 'label' => __('Reviewer Information', 'reviewx'), 'separator' => 'after']); $this->add_control('rvx_template_reviewer_info_author_avatar_size', ['label' => __('Avatar Size', 'reviewx'), 'show_label' => \true, 'type' => Controls_Manager::IMAGE_DIMENSIONS, 'default' => ['width' => '50', 'height' => '50', 'unit' => 'px'], 'size_units' => ['px', 'em', '%'], 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-review-user__avatar' => 'width: {{WIDTH}}{{UNIT}} !important; height: {{HEIGHT}}{{UNIT}} !important;', ' .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details .rvx-review-user__avatar' => 'width: {{WIDTH}}{{UNIT}} !important; height: {{HEIGHT}}{{UNIT}} !important;']]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_template_reviewer_info_author_avatar_fallback_typography', 'label' => __('Avatar Fallback Typography', 'reviewx'), 'selector' => ' .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-review-user__avatar .rvx-review-user__avatar-fallback span, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details .rvx-review-user__avatar .rvx-review-user__avatar-fallback span ', 'fields_options' => ['font_size' => ['default' => ['unit' => 'px', 'size' => 16]]]]); $this->add_control('rvx_template_reviewer_info_author_avatar_text_color', ['label' => __('Avatar Fallback Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#BDBDBD', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-review-user__avatar .rvx-review-user__avatar-fallback span' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details .rvx-review-user__avatar .rvx-review-user__avatar-fallback span' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_reviewer_card_background_color_for_review', ['label' => __('Review Card Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-review-wrapper .rvx-review-card' => 'background-color: {{VALUE}} !important;']]); $this->add_control('rvx_template_reviewer_info_author_name_text_color', ['label' => __('Name Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#373747', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-review-user .rvx-review-user__name' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details .rvx-review-user .rvx-review-user__name' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_reviewer_info_rating_star_active_color', ['label' => __('Rating Star Active Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#ECBD3F', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-reviewer__star-active' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-reviewer__star-half.rvx-reviewer__star-active-half-star' => 'stop-color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details .rvx-reviewer__star-active' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details .rvx-reviewer__star-half.rvx-reviewer__star-active-half-star' => 'stop-color: {{VALUE}} !important']]); $this->add_control('rvx_template_reviewer_info_rating_star_inactive_color', ['label' => __('Rating Star Inactive Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#ECBD3F', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-reviewer__star-inactive' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-reviewer__star-half.rvx-reviewer__star-inactive-half-star' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details__body .rvx-reviewer__star-inactive' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details__body .rvx-reviewer__star-half.rvx-reviewer__star-inactive-half-star' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_main_content_block_style', ['type' => Controls_Manager::HEADING, 'label' => __('Main Content', 'reviewx'), 'separator' => 'before']); $this->add_control('rvx_template_main_content_title_color', ['label' => __('Review Title Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#373747', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__title' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details .rvx-review-info .rvx-review-info__title' => 'color: {{VALUE}} !important']]); // $this->add_group_control( // Group_Control_Typography::get_type(), // [ // 'name' => 'rvx_template_main_content_review_title_typography', // 'label' => __('Review Title Typography', 'reviewx'), // 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__title, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-details .rvx-review-info .rvx-review-info__title', // ] // ); $this->add_control('rvx_template_main_content_review_description_text_color', ['label' => __('Review Description Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#9B9B9B', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__feedback' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details .rvx-review-info .rvx-review-info__feedback' => 'color: {{VALUE}} !important']]); // $this->add_group_control( // Group_Control_Typography::get_type(), // [ // 'name' => 'rvx_template_main_content_review_description_text_typography', // 'label' => __('Review Description Typography', 'reviewx'), // 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__feedback,.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details .rvx-review-info .rvx-review-info__feedback', // ] // ); $this->add_control('rvx_template_main_content_review_description_review_date', ['label' => __('Review Date Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#757575', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__date' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details .rvx-review-info .rvx-review-info__date' => 'color: {{VALUE}} !important']]); // $this->add_group_control( // Group_Control_Typography::get_type(), // [ // 'name' => 'rvx_template_main_content_review_description_review_date_typography', // 'label' => __('Review Date Typography', 'reviewx'), // 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__date, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-details .rvx-review-info .rvx-review-info__date', // ] // ); $this->add_control('rvx_template_main_content_footer_action_helpful_message_text_color', ['label' => __('Was This Helpful Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#333', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-review-card .rvx-review-footer .rvx-review-footer__text' => 'color: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-details .rvx-review-footer .rvx-review-footer__text' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_main_content_footer_like', ['label' => __('Review Like Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#E0E0E0', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-review-card .rvx-review-footer__thumbs--like-icon path' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-details .rvx-review-footer__thumbs--like-icon path' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_main_content_footer_dislike', ['label' => __('Review Dislike', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#E0E0E0', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-review-card .rvx-review-footer__thumbs--dislike-icon path' => 'fill: {{VALUE}} !important', '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-details .rvx-review-footer__thumbs--dislike-icon path' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_card_load_more', ['label' => __('Load More Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FFFFFF', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget button' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_card_load_more_text_color', ['label' => __('Load More Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget button' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_card_load_more_background_hover_color', ['label' => __('Load More Hover Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#D5D5D5', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget button:hover' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_card_load_more_hover_text_color', ['label' => __('Load More Text Hover Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget button:hover' => 'color: {{VALUE}} !important']]); /********************************* * Review Description End * *********************************/ $this->end_controls_tabs(); $this->end_controls_section(); } public function filterOptions() { $this->start_controls_section('rvx_template_filter_section', ['label' => __('Filter Options', 'reviewx')]); $this->add_control('rvx_template_write_review_action_bg_color', ['label' => __('Write Review Action Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#387CF7', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-write__button' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_write_review_action_text_color', ['label' => __('Write Review Action Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-write__button' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_text_color', ['label' => __('Filter Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__button' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_text_button_background_color', ['label' => __('Filter Button Background color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__button' => 'background: {{VALUE}} !important']]); // $this->add_group_control( // Group_Control_Typography::get_type(), // [ // 'name' => 'rvx_filter_button_font_size', // 'label' => __('Filter Button Font Size', 'reviewx'), // 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget .rvx-review-filter__button', // 'fields_options' => [ // 'font_size' => [ // 'default' => [ // 'unit' => 'px', // 'size' => 16, // Default font size set to 16px // ], // ], // ], // ] // ); $this->add_control('rvx_filter_dropdown_background_color', ['label' => __('Filter Dropdown Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FFFFFF', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper .rvx-review-filter__wrapper-inner, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer ' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_by_text_color', ['label' => __('Dropdown Filter By Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6B707A', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__title' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_options_text_color', ['label' => __('Dropdown Filter Options Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6B707A', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__rating .rvx-review-filter-wrapper__rating--text, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__rating .rvx-review-filter-wrapper__rating-wrapper .rvx-review-filter-wrapper__rating-inner .rvx-review-filter__wrapper__rating--radio-group__option-label, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__attachment .rvx-review-filter-wrapper__attachment--text, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__attachment .rvx-review-filter-wrapper__attachment-wrapper .rvx-review-filter-wrapper__attachment-inner .rvx-review-filter__wrapper__attachment--radio-group__option-label ' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_options_icon_color', ['label' => __('Dropdown Filter Option Icon Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#6B707A', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__rating .rvx-review-filter-wrapper__rating-inner--icon, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__attachment .rvx-review-filter-wrapper__attachment-inner--icon ' => 'color: {{VALUE}} !important']]); // $this->add_group_control( // Group_Control_Typography::get_type(), // [ // 'name' => 'rvx_filter_by_font_size', // 'label' => __('Dropdown Filter By Font Size', 'reviewx'), // 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper__title', // 'fields_options' => [ // 'font_size' => [ // 'default' => [ // 'unit' => 'px', // 'size' => 16, // Default font size set to 16px // ], // ], // ], // ] // ); $this->add_control('rvx_template_filter_reset_button_text_color', ['label' => __('Filter Reset Button Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#383239', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper__footer button' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_reset_button_background_color', ['label' => __('Filter Reset Button Background', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper__footer button' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_filter_reset_button_border_radius', ['label' => __('Filter Reset Button Border Radius', 'reviewx'), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => ['px', '%'], 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper__footer button' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}} !important;']]); $this->add_control('rvx_template_sort_by_button_text_color', ['label' => __('Sort By Button Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-sort__button' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_sort_by_button_bg_color', ['label' => __('Sort By Button Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-sort__button' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_sort_by_dropdown_text_color', ['label' => __('Sort By Dropdown Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-sort-wrapper .rvx-review-sort-wrapper__outer .rvx-review-sort-wrapper__inner .rvx-review-sort__wrapper--radio-group__option-label' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_sort_by_dropdown_bg_color', ['label' => __('Sort By Dropdown Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-sort-wrapper' => 'background: {{VALUE}} !important']]); $this->end_controls_tabs(); $this->end_controls_section(); } public function reviewForm() { $this->start_controls_section('rvx_template_review_form_section_style', ['label' => __('Review Form', 'reviewx')]); // Form Text: Write a Review $this->add_control('rvx_template_review_form_text_write_a_review', ['label' => __('Write a Review', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Write a Review', 'selectors' => ['{{WRAPPER}} .rvx-review-form__title' => 'textContent: {{VALUE}};']]); // Form Text: Rating Title (Text) $this->add_control('rvx_template_review_form_text_rating_star_title', ['label' => __('Rating (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Rating', 'selectors' => ['{{WRAPPER}} .rvx-review-form__rating--name' => 'textContent: {{VALUE}};']]); // Form Text: Review Title (Text) $this->add_control('rvx_template_review_form_text_review_title', ['label' => __('Review Title (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Review Title', 'selectors' => ['{{WRAPPER}} .rvx-review-form__title--name' => 'textContent: {{VALUE}};']]); // Form Text: Review Title (Placeholder) $this->add_control('rvx_template_review_form_placeholder_review_title', ['label' => __('Review Title (Placeholder)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Write Review Title', 'selectors' => ['{{WRAPPER}} .rvx-review-form__title--input' => 'textContent: {{VALUE}};']]); // Form Text: Review Description (Text) $this->add_control('rvx_template_review_form_text_review_description', ['label' => __('Description (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Description', 'selectors' => ['{{WRAPPER}} .rvx-review-form__description--title' => 'textContent: {{VALUE}};']]); // Form Text: Review Description (Placeholder) $this->add_control('rvx_template_review_form_placeholder_review_description', ['label' => __('Description (Placeholder)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Write your description here', 'selectors' => ['{{WRAPPER}} .rvx-review-form__title--textarea' => 'textContent: {{VALUE}};']]); // Form Text: Full Name (Text) $this->add_control('rvx_template_review_form_text_full_name', ['label' => __('Full Name (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Full Name', 'selectors' => ['{{WRAPPER}} .rvx-review-form__description--title' => 'textContent: {{VALUE}};']]); // Form Text: Full Name (Placeholder) $this->add_control('rvx_template_review_form_placeholder_full_name', ['label' => __('Full Name (Placeholder)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Full Name', 'selectors' => ['{{WRAPPER}} .rvx-review-form__title--textarea' => 'textContent: {{VALUE}};']]); // Form Text: Email Address (Text) $this->add_control('rvx_template_review_form_text_email_name', ['label' => __('Email Address (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Email Address', 'selectors' => ['{{WRAPPER}} .rvx-review-form__description--title' => 'textContent: {{VALUE}};']]); // Form Text: Email Address (Placeholder) $this->add_control('rvx_template_review_form_placeholder_email_name', ['label' => __('Email Address (Placeholder)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Email Address', 'selectors' => ['{{WRAPPER}} .rvx-review-form__title--textarea' => 'textContent: {{VALUE}};']]); // Form Text: Attachment (Text) $this->add_control('rvx_template_review_form_text_attachment_title', ['label' => __('Attachment (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Attachment', 'selectors' => ['{{WRAPPER}} .rvx-review-form__attachment--name' => 'textContent: {{VALUE}};']]); // Form Text: Upload Photo / Video (Placeholder) $this->add_control('rvx_template_review_form_placeholder_upload_photo', ['label' => __('Upload Photo / Video (Placeholder)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Upload Photo / Video', 'selectors' => ['{{WRAPPER}} .rvx-review-form__attachment--upload--text' => 'textContent: {{VALUE}};']]); // Form Text: Mark as Anonymous (Text) $this->add_control('rvx_template_review_form_text_mark_as_anonymous', ['label' => __('Mark as Anonymous (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Mark as Anonymous', 'selectors' => ['{{WRAPPER}} .rvx-review-form__mark-anonymous' => 'textContent: {{VALUE}};']]); // Form Text: Recommended? (Text) $this->add_control('rvx_template_review_form_text_recommended_title', ['label' => __('Recommended? (Text)', 'reviewx'), 'type' => Controls_Manager::TEXT, 'default' => 'Recommendation?', 'selectors' => ['{{WRAPPER}} .rvx-review-form__recommended--name' => 'textContent: {{VALUE}};']]); $this->add_control('rvx_template_review_form_background_color', ['label' => __('Form Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#F5F5F5', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-form__wrapper' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_title_color', ['label' => __('Form Title Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__title[]' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_border_color', ['label' => __('Form Border Line Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#E0E0E0', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__line' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_product_image_size', ['label' => __('Product Image Size', 'reviewx'), 'type' => Controls_Manager::IMAGE_DIMENSIONS, 'show_label' => \true, 'default' => ['width' => '64', 'height' => '64', 'unit' => 'px'], 'size_units' => ['px', 'em', '%'], 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__product .rvx-review-form__product--image' => 'width: {{WIDTH}}{{UNIT}} !important; height: {{HEIGHT}}{{UNIT}} !important;']]); // $this->add_control( // 'rvx_hide_product_image', // [ // 'label' => __('Hide Product Image', 'reviewx'), // 'type' => Controls_Manager::HIDDEN, // 'default' => 'block', // 'selectors' => [ // '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__inner .rvx-review-form__product .rvx-review-form__product' => 'display: {{VALUE}} !important', // ], // ] // ); // $this->add_control('rvx_template_review_form_product_title_color', ['label' => __('Product Title Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__product .rvx-review-form__product--title' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_rating_star_active_color', ['label' => __('Rating Active Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FCCE08', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__rating .rvx-review-form__star-active' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_rating_star_inactive_color', ['label' => __('Rating Inactive Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FCCE08', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__rating .rvx-review-form__star-inactive' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_multi_criteria_star_active_color', ['label' => __('Multi Criteria Active Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#FCCE08', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__multicriteria .rvx-review-form__star-active' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_multi_criteria_star_inactive_color', ['label' => __('Multi Criteria Inactive Star Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#757575', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__multicriteria .rvx-review-form__star-inactive' => 'fill: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_label_color', ['label' => __('Review Form Label Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#424242', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__title .rvx-review-form__title--name, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__description .rvx-review-form__description--title, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__rating .rvx-review-form__rating--name, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__multicriteria .rvx-review-form__multicriteria--name, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__user .rvx-review-form__user--name, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__email .rvx-review-form__email--name, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__attachment .rvx-review-form__attachment--name, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__attachment--inner .rvx-review-form__mark-anonymous, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__recommended .rvx-review-form__recommended--name, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__recommended label ' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_review_title_input_placeholder_color', ['label' => __('Review Form Input Placeholder Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#BDBDBD', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper input::placeholder, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper textarea::placeholder ' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_input_background_color', ['label' => __('Review Form Input Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper input, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper textarea ' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form__attachments_icon_color', ['label' => __('Review Attachment Icon Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#9E9E9E', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload--icon' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form__attachments_text_color', ['label' => __('Review Attachment Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#9E9E9E', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload--count, .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload--text' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form__attachments_background_color', ['label' => __('Review Attachment Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#EEEEEE', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload' => 'background: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_submit_button_bg_color', ['label' => __('Submit Button Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#2f4fff', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"], .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:focus' => 'background-color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_submit_button_text_color', ['label' => __('Submit Button Text Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"], .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:focus' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_submit_button_hover_background_color', ['label' => __('Submit Button Hover Background Color', 'reviewx'), 'type' => Controls_Manager::COLOR, 'default' => '#fff', 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"], .woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:hover' => 'color: {{VALUE}} !important']]); $this->add_control('rvx_template_review_form_submit_button_border_radius', ['label' => __('Submit Button Border Radius', 'reviewx'), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => ['px', '%'], 'selectors' => ['.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}} !important;']]); $this->end_controls_tabs(); $this->end_controls_section(); } public function frontSize() { $this->start_controls_section('rvx_template_font_section', ['label' => __('Font size', 'reviewx')]); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_template_front_size_text_typography', 'label' => __('Review Criteria Typography', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-form__multicriteria--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_criteria_label_typography', 'label' => __('Criteria Label Typography', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-form__multicriteria--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_criteria_value_typography', 'label' => __('Criteria Value Typography', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-aggregation-multicriteria__row-inner .rvx-review-form__multicriteria--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_title_lable_typography', 'label' => __('Title lable', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__title--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_title_value_typography', 'label' => __('Title Value', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-info .rvx-review-info__title']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_description_label_typography', 'label' => __('Description label', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-form__description .rvx-review-form__title--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_description_value_typography', 'label' => __('Description Value', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-info .rvx-review-info__feedback']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_attachments_typography', 'label' => __('Attachment', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-form__attachment--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_recommended_typography', 'label' => __('Recommended', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-form__recommended--name']); $this->add_group_control(Group_Control_Typography::get_type(), ['name' => 'rvx_anonymous_typography', 'label' => __('Mark as Anonymous', 'reviewx'), 'selector' => '.woocommerce {{WRAPPER}} .woocommerce-Tabs-panel .rvx-review-form__mark-anonymous']); $this->end_controls_tabs(); $this->end_controls_section(); } /** * Render * @return void */ protected function render() { global $builderElementorSetting; $settings = $this->get_settings_for_display(); $builderElementorSetting = []; // Define the keys to be added if they have a value $keys = ['write_a_review' => 'rvx_template_review_form_text_write_a_review', 'text_rating_star_title' => 'rvx_template_review_form_text_rating_star_title', 'text_review_title' => 'rvx_template_review_form_text_review_title', 'placeholder_review_title' => 'rvx_template_review_form_placeholder_review_title', 'text_review_description' => 'rvx_template_review_form_text_review_description', 'placeholder_review_description' => 'rvx_template_review_form_placeholder_review_description', 'text_full_name' => 'rvx_template_review_form_text_full_name', 'placeholder_full_name' => 'rvx_template_review_form_placeholder_full_name', 'text_email_name' => 'rvx_template_review_form_text_email_name', 'placeholder_email_name' => 'rvx_template_review_form_placeholder_email_name', 'text_attachment_title' => 'rvx_template_review_form_text_attachment_title', 'placeholder_upload_photo' => 'rvx_template_review_form_placeholder_upload_photo', 'text_mark_as_anonymous' => 'rvx_template_review_form_text_mark_as_anonymous', 'text_recommended_title' => 'rvx_template_review_form_text_recommended_title']; // Loop through each key and add it to the array only if it has a non-empty value foreach ($keys as $key => $settingKey) { if (!empty($settings[$settingKey])) { $builderElementorSetting[$key] = $settings[$settingKey]; } } if (\class_exists('WooCommerce')) { global $product; $product = wc_get_product(); //$title = $settings['rvx_review_form__description_text']; //var_dump($title); if (empty($product)) { echo '<h3>' . __('This widget only works for the product page. In order to achieve, follow the steps: this Dashboard > Template > Theme Builder > Add New > Choose Template Type \'Single Product\' > Create Template', 'reviewx') . '</h3>'; return; } setup_postdata($product->get_id()); wc_get_template('single-product/tabs/tabs.php'); } // On render widget from Editor - trigger the init manually. if (wp_doing_ajax()) { ?> <script> jQuery('.wc-tabs-wrapper, .woocommerce-tabs, #rating').trigger('init'); </script> <?php } } public function render_plain_content() { } } Elementor/Traits/Addons.php 0000777 00000005600 15251220643 0011675 0 ustar 00 <?php namespace Rvx\Elementor\Traits; use Rvx\Elementor\Core\Settings\Manager as Settings_Manager; /** * Trait Addons * @package Rvx\Elementor\Traits */ trait Addons { /** * Add elementor category * * @since v1.0.0 * @param $elements_manager */ public function register_widget_categories($elements_manager) { $elements_manager->add_category('rx-addons-elementor', ['title' => __('ReviewX Addons', 'reviewx'), 'icon' => 'font'], 1); } /** * Register widgets * * @since v3.0.0 * @param $widgets_manager */ public function register_elements($widgets_manager) { $active_elements = (array) $this->get_settings(); $active_elements = ['rxcall-to-review', 'rxcall-to-review-widget', 'rx-promotion', 'quick_tools']; if (empty($active_elements)) { return; } \asort($active_elements); foreach ($active_elements as $active_element) { if (!isset($this->registered_elements[$active_element])) { continue; } if (isset($this->registered_elements[$active_element]['condition'])) { $check = \false; if (isset($this->registered_elements[$active_element]['condition'][2])) { $check = $this->registered_elements[$active_element]['condition'][2]; } if ($this->registered_elements[$active_element]['condition'][0]($this->registered_elements[$active_element]['condition'][1]) == $check) { continue; } } // $widgets_manager->register_widget_type(new $this->registered_elements[$active_element]['class']); $widgets_manager->register(new $this->registered_elements[$active_element]['class']()); } } public function cpt_register_element($widgets_manager) { $new_path = RVX_DIR_PATH . '/app/Elementor/Elements/Cpt_Widget.php'; if (\file_exists($new_path)) { require_once $new_path; $widgets_manager->register(new \Rvx\Cpt_Widgets()); } if (!\file_exists($new_path)) { \error_log("File Pathe Not found", 0); } } /** * Register extensions * * @since v3.0.0 */ public function register_extensions() { $active_elements = (array) $this->get_settings(); // set promotion extension enabled \array_push($active_elements, 'rx-promotion'); foreach ($this->registered_extensions as $key => $extension) { if (!\in_array($key, $active_elements)) { continue; } new $extension['class'](); } } /** * Register WC hooks * @return void */ public function register_wc_hooks() { if (\class_exists('WooCommerce')) { wc()->frontend_includes(); } } } Elementor/Traits/Library.php 0000777 00000002571 15251220643 0012075 0 ustar 00 <?php namespace Rvx\Elementor\Traits; if (!\defined('ABSPATH')) { exit; } // Exit if accessed directly /** * Trait Library * @package Rvx\Elementor\Traits */ trait Library { /** * Return array of registered elements. * * @todo filter output */ public function get_registered_elements() { return \array_keys($this->registered_elements); } /** * Return saved settings * * @since 3.0.0 * @param null $element * @return array|int|mixed */ public function get_settings($element = null) { // $defaults = array_fill_keys(array_keys(array_merge($this->registered_elements, $this->registered_extensions, $this->additional_settings)), true); // $elements = get_option('rx_save_settings', $defaults); $elements = ['rxcall-to-review' => \true, 'rxcall-to-review-widget' => \true, 'rx-promotion' => \true, 'quick_tools' => \true]; // $elements = array_merge($defaults, $elements); return isset($element) ? isset($elements[$element]) ? $elements[$element] : 0 : \array_keys(\array_filter($elements)); } /** * Generate safe path * * @since v3.0.0 */ public function safe_path($path) { $path = \str_replace(['//', '\\\\'], ['/', '\\'], $path); return \str_replace(['/', '\\'], \DIRECTORY_SEPARATOR, $path); } } Utilities/Helper.php 0000777 00000024103 15251220643 0010456 0 ustar 00 <?php namespace Rvx\Utilities; use Rvx\Firebase\JWT\JWT; use Rvx\Utilities\Auth\Client; use Throwable; use Rvx\WPDrill\Plugin; use Rvx\WPDrill\Response; class Helper { public static function plugin() : Plugin { return Plugin::getInstance(); } public static function rest($data = []) : Response { return new Response($data); } public static function pluginPath(string $path = "") : string { return RVX_DIR_PATH . \ltrim($path, "/"); } public static function resourcePath(string $path = "") : string { return self::pluginPath("resources/" . \ltrim($path, "/")); } public static function storagePath(string $path = "") : string { return self::pluginPath("storage/" . \ltrim($path, "/")); } public static function pluginFile() : string { return RVX_FILE; } public static function getAuthToken() : string { if (!Client::has()) { return ""; } $payload = ["iss" => $_SERVER["HTTP_HOST"], "iat" => \time(), "exp" => \time() + 300, "nbf" => \time(), "jti" => \uniqid("", \true)]; $additionalPayload = ["uid" => Client::getUid()]; // Encode the payload and return the JWT token return JWT::encode(\array_merge($payload, $additionalPayload), Client::getSecret(), "HS256"); } public static function getWpDomainNameOnly() : string { return \trim(\parse_url(home_url(), \PHP_URL_HOST), '/'); } public static function getApiResponse($response) { try { if (!\is_object($response)) { return self::rest([])->fails('Invalid response from SaaS'); } if ($response->getStatusCode() >= Response::HTTP_OK && $response->getStatusCode() < 300) { return self::rest($response->getApiData())->success($response()->message, $response->getStatusCode()); } return self::rest($response->getApiData())->fails($response()->message, $response->getStatusCode()); } catch (Throwable $th) { return self::rest([])->fails($th->getMessage()); } } public static function rvxApi($data = []) { return new Response($data); } public static function saasResponse($response) : Response { $content = $response->autoParse(); $statusCode = $response->getStatusCode(); $data = $content['data'] ?? []; $message = $content['message'] ?? ($statusCode >= 400 ? 'SaaS API Error' : 'Success'); if ($statusCode >= 200 && $statusCode < 300) { return self::rest($data)->success($message, $statusCode); } else { return self::rest($data)->fails((string) $message, $statusCode); } } public static function loggedIn() { return is_user_logged_in() ? 1 : 0; } public static function getWpCurrentUser() { $user = wp_get_current_user(); return $user->ID > 0 ? $user : null; } public static function arrayGet($data, $accessor, $default = null) { $accessorArray = \is_array($accessor) ? $accessor : \explode(".", $accessor); $value = $data[\array_shift($accessorArray)] ?? $default; foreach ($accessorArray as $key) { if (!isset($value[$key])) { return $default; } $value = $value[$key]; } return $value; } public static function verifiedCustomer($customer_id) : bool { $orders = wc_get_orders(["customer" => $customer_id, "status" => ["completed", "processing", "on-hold", "pending-payment"], "limit" => 1]); if (!empty($orders)) { return \true; } return \false; } public static function debugLog($message = "") { $logMessage = \is_array($message) ? "Output is: " . \print_r($message, \true) : "Output is: " . $message; \error_log($logMessage); return $logMessage; } public static function arrayValue($array, $key, $default = null) { if (!\is_array($array)) { return $default; } if (\is_null($key)) { return $array; } if (\array_key_exists($key, $array)) { return $array[$key]; } foreach (\explode(".", $key) as $segment) { if (\array_key_exists($segment, $array)) { $array = $array[$segment]; } else { return $default; } } return $array; } public static function retrieveReviewId($order_id, $prod_id, $user_id) { if (isset($order_id, $prod_id, $user_id)) { global $wpdb; $rx_comment = $wpdb->prefix . "comments"; $rx_commentmeta = $wpdb->prefix . "commentmeta"; $data = $wpdb->get_results($wpdb->prepare("SELECT DISTINCT {$rx_commentmeta}.comment_id FROM {$rx_commentmeta} \n INNER JOIN {$rx_comment} \n ON {$rx_commentmeta}.comment_id = {$rx_comment}.comment_ID \n WHERE {$rx_commentmeta}.meta_key = 'reviewx_order' \n AND {$rx_commentmeta}.meta_value = %d \n AND {$rx_comment}.comment_post_ID = %d \n AND {$rx_comment}.user_id = %d", $order_id, $prod_id, $user_id)); if ($data && !empty($data[0]->comment_id)) { return $data[0]->comment_id; } } return 0; } public static function getIpAddress() { $ip_address = $_SERVER["HTTP_CLIENT_IP"] ?? $_SERVER["REMOTE_ADDR"]; return \explode(":", $ip_address)[0] ?? null; } public static function loadTemplate($template_name, $data = []) { \extract($data); $template_path = RVX_DIR_PATH . "widget/components/" . $template_name . ".php"; if (\file_exists($template_path)) { include $template_path; } else { echo "Template file not found: " . $template_name; } } public static function prepareLangArray() : array { $json_file_path = RVX_DIR_PATH . "/translation.json"; $json_content = \file_get_contents($json_file_path); $translations = \json_decode($json_content, \true); $result = []; foreach ($translations as $key => $text) { $result[$key] = __($text, "reviewx"); } return $result; } public static function rvxGetOrderStatus($orderStatus) : ?string { return \str_replace('wc-', '', $orderStatus); } public static function appendToJsonl($file, $data, $jsonOptions = \JSON_UNESCAPED_UNICODE) { $json = wp_json_encode($data, $jsonOptions); if ($json === \false) { return \false; } return \fwrite($file, $json . \PHP_EOL); } public static function rvxLog($message, $context = 'debug') { $log_folder = RVX_DIR_PATH . 'log/'; if (!\is_dir($log_folder)) { return; } $log_file = $log_folder . 'log-' . \wp_date('Y-m-d') . '.log'; $formatted_message = \sprintf("[%s] [%s]: %s\n", \wp_date('Y-m-d H:i:s'), \strtoupper($context), \print_r($message, \true)); \file_put_contents($log_file, $formatted_message, \FILE_APPEND); } public static function domainSupport() { // Get the full site URL including the subdomain and subdirectory (if present) $site_url = get_site_url(); // Parse the URL to extract the components $parsed_url = \parse_url($site_url); // Rebuild the base URL (scheme + host + path) $full_domain = $parsed_url['scheme'] . '://' . $parsed_url['host']; // Add the path (subdirectory) if it exists if (isset($parsed_url['path'])) { $full_domain .= \rtrim($parsed_url['path'], '/'); } return $full_domain; } public static function getRestAPIurl() : string { // If init hasn't fired yet → don't fallback if (!did_action('init')) { // Return fallback REST API URL return site_url('/?rest_route=/reviewx'); } // init has fired, return proper REST API URL return get_rest_url(null, 'reviewx'); } public static function orderStatus($newStatus) : string { $statusMap = ['processing' => 'processing', 'pending' => 'pending', 'on-hold' => 'on_hold', 'completed' => 'completed', 'cancelled' => 'cancelled', 'refunded' => 'refunded', 'failed' => 'failed', 'checkout-draft' => 'draft', 'auto-draft' => 'auto_draft']; if (!$statusMap[$newStatus]) { return 'any'; } return $statusMap[$newStatus]; } public static function orderItemStatus($newStatus) : string { $statusMap = ['processing' => 'PROCESSING', 'pending' => 'PENDING_PAYMENT', 'on-hold' => 'ON_HOLD', 'completed' => 'COMPLETED', 'cancelled' => 'CANCELLED', 'refunded' => 'REFUNDED', 'failed' => 'FAILED', 'checkout-draft' => 'DRAFT', 'auto-draft' => 'AUTO-DRAFT']; if (!$statusMap[$newStatus]) { return 'any'; } return $statusMap[$newStatus]; } public static function validateReturnDate($dateString) { if (\is_numeric($dateString) && $dateString > 0) { $timestamp = (int) $dateString; } else { $timestamp = \strtotime($dateString); } if ($timestamp === \false || $timestamp < 0) { return null; } return \wp_date('Y-m-d H:i:s', $timestamp); } public static function formatToTwoDecimalPlaces($number) { if (empty($number)) { $number = 0; } return \number_format((float) $number, 2); } public static function getWpClientInfo() : array { $current_user = wp_get_current_user(); $first_name = $current_user->first_name ?: $current_user->user_login; $last_name = $current_user->last_name ?: ''; return ['domain' => \Rvx\Utilities\Helper::getWpDomainNameOnly(), 'url' => home_url(), 'site_locale' => get_locale(), 'first_name' => sanitize_text_field($first_name), 'last_name' => sanitize_text_field($last_name)]; } } Utilities/TransactionManager.php 0000777 00000003152 15251220643 0013020 0 ustar 00 <?php namespace Rvx\Utilities; use Exception; use Throwable; class TransactionManager { /** * Run a task with potential rollback. * * @param callable $wpCallback Should return the data needed for SaaS or true on success. * @param callable $saasCallback Receives the result of $wpCallback. * @return mixed The SaaS response or false on failure. */ public static function run(callable $wpCallback, callable $saasCallback) { global $wpdb; try { // Start WP Transaction $wpdb->query('START TRANSACTION'); // 1. Perform WP updates $wpResult = $wpCallback(); if ($wpResult === \false || \is_wp_error($wpResult)) { $wpdb->query('ROLLBACK'); return $wpResult; } // 2. Perform SaaS updates $saasResponse = $saasCallback($wpResult); // Handle SaaS Response success check $isSuccess = \false; if (\method_exists($saasResponse, 'getStatusCode')) { $status = $saasResponse->getStatusCode(); $isSuccess = $status >= 200 && $status < 300; } if (!$isSuccess) { // SaaS failed, rollback WP $wpdb->query('ROLLBACK'); return $saasResponse; } // Both succeeded $wpdb->query('COMMIT'); return $saasResponse; } catch (Throwable $e) { $wpdb->query('ROLLBACK'); \error_log("Transaction failed: " . $e->getMessage()); throw $e; } } } Utilities/Auth/WpUserManager.php 0000777 00000001264 15251220643 0012663 0 ustar 00 <?php namespace Rvx\Utilities\Auth; class WpUserManager { protected bool $isUserLoggedIn = \false; protected bool $userCan = \false; public function __construct(bool $isLoggedIn = \false, bool $userCan = \false) { $this->isUserLoggedIn = $isLoggedIn; $this->userCan = $userCan; } public function setLoggedInStatus(bool $isLoggedIn) { $this->isUserLoggedIn = $isLoggedIn; } public function setAbility(bool $userCan) { $this->userCan = $userCan; } public function isLoggedIn() : bool { return $this->isUserLoggedIn; } public function can() : bool { return $this->userCan; } } Utilities/Auth/ClientManager.php 0000777 00000003401 15251220643 0012647 0 ustar 00 <?php namespace Rvx\Utilities\Auth; class ClientManager { protected ?object $site = null; public function __construct(?object $site) { $this->set($site); } public function set(?object $client) { // dd($client); $this->site = $client; } public function has() : bool { return $this->site !== null; } public function site() : ?object { return $this->site; } public function getUid() : string { if ($this->has()) { return $this->site->uid; } return ''; } public function getSiteId() : int { if ($this->has()) { return $this->site->site_id; } return 0; } public function getName() : string { if ($this->has()) { return $this->site->name; } return ''; } public function getDomain() : string { if ($this->has()) { return $this->site->domain; } return ''; } public function getUrl() : string { if ($this->has()) { return $this->site->url; } return ''; } public function getLocale() : string { if ($this->has()) { return $this->site->locale; } return ''; } public function getEmail() : string { if ($this->has()) { return $this->site->email; } return ''; } public function getSecret() : string { if ($this->has()) { return $this->site->secret; } return ''; } public function getSync() : bool { if ($this->has()) { return (bool) $this->site->is_saas_sync; } return \false; } } Utilities/Auth/Client.php 0000777 00000001113 15251220643 0011352 0 ustar 00 <?php namespace Rvx\Utilities\Auth; use Rvx\WPDrill\Facade; /** * Class Client * * @method static bool has() * @method static object|null site() * @method static string getUid() * @method static int getSiteId() * @method static string getName() * @method static string getDomain() * @method static string getUrl() * @method static bool getSync() * @method static string getSecret() * @package Rvx\Utilities\Auth */ class Client extends Facade { public static function getFacadeAccessor() : string { return \Rvx\Utilities\Auth\ClientManager::class; } } Utilities/Auth/WpUser.php 0000777 00000000634 15251220643 0011370 0 ustar 00 <?php namespace Rvx\Utilities\Auth; use Rvx\WPDrill\Facade; /** * Class WpUser * * @method static void setLoggedInStatus(bool $value) * @method static void setAbility(bool $value) * @method static bool isLoggedIn() * @method static bool can() */ class WpUser extends Facade { public static function getFacadeAccessor() : string { return \Rvx\Utilities\Auth\WpUserManager::class; } } Rest/Middleware/WPDrillMiddleware.php 0000777 00000000255 15251220643 0013573 0 ustar 00 <?php namespace Rvx\Rest\Middleware; class WPDrillMiddleware { /** * @return bool */ public function handle() : bool { return \true; } } Rest/Middleware/AuthMiddleware.php 0000777 00000002766 15251220643 0013170 0 ustar 00 <?php namespace Rvx\Rest\Middleware; use Exception; use WP_REST_Request; use Rvx\Utilities\Auth\WpUser; use Rvx\Utilities\Auth\Client; use Rvx\Firebase\JWT\JWT; use Rvx\Firebase\JWT\Key; class AuthMiddleware { /** * Determine if the current request is authorized. * * Authorization is granted if: * User is logged in AND has sufficient capabilities. * Or if user has a valid JWT Bearer token * * @param WP_REST_Request $request * @return bool */ public function handle(WP_REST_Request $request) : bool { // Validate by WP User if (WpUser::isLoggedIn() && WpUser::can()) { return \true; } // Validate by Bearer Token $clientUid = Client::getUid(); $secret = Client::getSecret(); if (empty($clientUid) || empty($secret)) { return \false; } $headers = $request->get_headers(); $authHeader = isset($headers['authorization'][0]) ? \trim($headers['authorization'][0]) : ''; if (!$authHeader || !\preg_match('/Bearer\\s+(.*)$/i', $authHeader, $matches)) { return \false; } $token = $matches[1]; try { $decoded = JWT::decode($token, new Key($secret, 'HS256')); // Check UID binding if (empty($decoded->uid) || $decoded->uid !== $clientUid) { return \false; } return \true; } catch (Exception $e) { return \false; } } } Rest/Middleware/AdminMiddleware.php 0000777 00000000466 15251220643 0013312 0 ustar 00 <?php namespace Rvx\Rest\Middleware; use Rvx\Utilities\Auth\Client; class AdminMiddleware { /** * @return bool */ public function handle($request) : bool { if (Client::getUid() === $request->get_param('uid')) { return \true; } return \false; } } Rest/Middleware/AuthSaasMiddleware.php 0000777 00000002145 15251220643 0013767 0 ustar 00 <?php namespace Rvx\Rest\Middleware; use Exception; use WP_REST_Request; use Rvx\Utilities\Auth\Client; use Rvx\Firebase\JWT\JWT; use Rvx\Firebase\JWT\Key; class AuthSaasMiddleware { /** * Handle incoming SaaS-authenticated requests */ public function handle(WP_REST_Request $request) : bool { $clientUid = Client::getUid(); $secret = Client::getSecret(); if (empty($clientUid) || empty($secret)) { return \false; } $headers = $request->get_headers(); $authHeader = isset($headers['authorization'][0]) ? \trim($headers['authorization'][0]) : ''; if (!$authHeader || !\preg_match('/Bearer\\s+(.*)$/i', $authHeader, $matches)) { return \false; } $token = $matches[1]; try { $decoded = JWT::decode($token, new Key($secret, 'HS256')); // Check UID binding if (empty($decoded->uid) || $decoded->uid !== $clientUid) { return \false; } return \true; } catch (Exception $e) { return \false; } } } Rest/Middleware/DevMiddleware.php 0000777 00000000520 15251220643 0012767 0 ustar 00 <?php namespace Rvx\Rest\Middleware; class DevMiddleware { /** * @return bool */ public function handle($request) : bool { $token = $request->get_params()['token']; if ($token === '3745678yfughsert7834yfuhjsfe7834r6uirf78t45') { return \true; } return \false; } } Rest/Controllers/ReviewController.php 0000777 00000044432 15251220643 0014023 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Exception; use Throwable; use Rvx\Services\ReviewService; use Rvx\Utilities\Helper; use Rvx\Services\CacheServices; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Response; class ReviewController implements InvokableContract { protected ReviewService $reviewService; protected CacheServices $cacheServices; public function __construct() { $this->reviewService = new ReviewService(); $this->cacheServices = new CacheServices(); } /** * @return void */ public function __invoke() { } /** * @return Response */ public function index($request) { $aggregation = \get_transient('rvx_admin_aggregation'); if (empty($request->get_params()) && $aggregation) { $response = ['aggregations' => $aggregation['aggregations'], 'count' => $aggregation['count'], 'reviews' => $aggregation['reviews'], 'meta' => $aggregation['meta']]; return Helper::rest($response)->success("Success"); } else { $resp = $this->reviewService->getReviews($request->get_params()); if ($resp->getStatusCode() === Response::HTTP_OK) { $this->aggregationDataStore($resp->getApiData()); } return Helper::getApiResponse($resp); } } public function aggregationDataStore($data) { \delete_transient('rvx_admin_aggregation'); \set_transient('rvx_admin_aggregation', $data, 3600); } public function adminAllReviewSaasCall($data) { $resp = $this->reviewService->reviewList($data); $isVisible = $data['isVisible'] ?? ''; if ($resp->getStatusCode() === Response::HTTP_OK) { $this->storeVisibilityReview($resp->getApiData(), $isVisible); } return $this->enrichReviewList($resp); } private function enrichReviewList($resp) { if ($resp->getStatusCode() === Response::HTTP_OK) { $data = $resp->getApiData(); if (isset($data['reviews']) && \is_array($data['reviews'])) { foreach ($data['reviews'] as &$review) { if (isset($review['wp_post_id'])) { $review['post_type'] = get_post_type($review['wp_post_id']); } } return Helper::rest($data)->success($resp()->message, $resp->getStatusCode()); } } return Helper::getApiResponse($resp); } public function reviewList($request) { try { $differentReview = $this->cacheServices->makeSaaSCallDecision(); $this->visibilityPaginationSaasCall($request, $differentReview); $isVisible = $request->get_params()['isVisible'] ?? ''; $transientKeys = ['published' => 'rvx_review_approve_data', 'pending' => 'rvx_review_pending_data', 'spam' => 'rvx_review_spam_data', 'trash' => 'rvx_review_trash_data']; if (\array_key_exists($isVisible, $transientKeys)) { $approve = \get_transient($transientKeys[$isVisible]); $params = $request->get_params(); $filterParams = ['page', 'rating', 'date', 'reviewer', 'search', 'product', 'category', 'oldest_first', 'newest_first']; if (\array_intersect_key(\array_flip($filterParams), $params)) { $resp = $this->reviewService->reviewList($params); return $this->enrichReviewList($resp); } elseif ($approve) { $response = ['count' => $approve['count'], 'reviews' => $approve['reviews'], 'meta' => $approve['meta']]; return Helper::rest($response)->success("Success"); } else { $this->adminAllReviewSaasCall($params); } } if (empty($request->get_params())) { $data = \get_transient('rvx_reviews_data_list'); if ($data) { $response = ['count' => $data['count'], 'reviews' => $data['reviews'], 'meta' => $data['meta']]; return Helper::rest($response)->success("Success"); } else { $resp = $this->reviewService->reviewList($request->get_params()); if ($resp->getStatusCode() === Response::HTTP_OK && empty($request->get_params())) { $this->reviewListStoreInDB($resp->getApiData()); } return $this->enrichReviewList($resp); } } else { $resp = $this->reviewService->reviewList($request->get_params()); return $this->enrichReviewList($resp); } } catch (Exception $e) { \error_log("Error fetching review list: " . $e->getMessage()); } } public function visibilityPaginationSaasCall($request, $differentReview) { if ($differentReview === \true) { $this->adminAllReviewSaasCall($request->get_params()); } } public function reviewListStoreInDB($reviewData) { \delete_transient('rvx_reviews_data_list'); \set_transient('rvx_reviews_data_list', $reviewData, 3600); } public function storeVisibilityReview($data, $visibility) { if ($visibility === 'published') { \delete_transient('rvx_review_approve_data'); \set_transient('rvx_review_approve_data', $data, 3600); } if ($visibility === 'pending') { \delete_transient('rvx_review_pending_data'); \set_transient('rvx_review_pending_data', $data, 3600); } if ($visibility === 'spam') { \delete_transient('rvx_review_spam_data'); \set_transient('rvx_review_spam_data', $data, 3600); } if ($visibility === 'trash') { \delete_transient('rvx_review_trash_data'); \set_transient('rvx_review_trash_data', $data, 3600); } } /** * @param $request * @return Response */ public function show($request) { $resp = $this->reviewService->getReview($request); return Helper::getApiResponse($resp); } /** * @param $request * @return Response */ public function store($request) { try { // Temporarily disable comment notification emails remove_action('comment_post', 'wp_notify_postauthor'); add_filter('comments_notify', '__return_false'); $resp = $this->reviewService->createReview($request); // Re-enable the comment notification emails add_action('comment_post', 'wp_notify_postauthor'); remove_filter('comments_notify', '__return_false'); // Clear caches $this->cacheServices->removeCache(); $postId = $request->get_param('wp_post_id'); if ($postId) { $this->cacheServices->removeProductCache($postId); } return Helper::getApiResponse($resp); } catch (Exception $e) { // Re-enable the comment notification emails in case of error add_action('comment_post', 'wp_notify_postauthor'); remove_filter('comments_notify', '__return_false'); return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Not Create', $e->getCode()); } } /** * @param $request * @return Response */ public function update($request) { try { $resp = $this->reviewService->updateReview($request); if ($resp->getStatusCode() >= 200 && $resp->getStatusCode() < 300) { // 1. Clear site-wide generic caches $this->cacheServices->removeCache(); // 2. Clear product-specific caches (Insight & Latest Reviews) $postId = $request->get_param('wp_post_id'); if ($postId) { \delete_transient("rvx_{$postId}_latest_reviews_insight"); \delete_transient("rvx_{$postId}_latest_reviews"); } } return Helper::getApiResponse($resp); } catch (Exception $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Update Failed', $e->getCode()); } } /** * @param $request * @return Response */ public function delete($request) { try { $resp = $this->reviewService->deleteReview($request); $this->cacheServices->removeCache(); return $resp; } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Visibility Change', $e->getCode()); } } /** * @param $request * @return Response */ public function restoreReview($request) { try { $response = $this->reviewService->restoreReview($request); $this->cacheServices->removeCache(); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Visibility Change', $e->getCode()); } } /** * @param $request * @return Response */ public function verify($request) { try { $resp = $this->reviewService->isVerify($request); $this->cacheServices->removeCache(); return $resp; } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Visibility Not Change', $e->getCode()); } } /** * @param $request * @return Response */ public function visibility($request) { try { $response = $this->reviewService->isvisibility($request); $this->cacheServices->removeCache(); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Visibility Not Change', $e->getCode()); } } /** * @param $request * @return Response */ public function updateReqEmail($request) { try { $resp = $this->reviewService->updateReqEmail($request); $this->cacheServices->removeCache(); return $resp; } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Bulk Fails', $e->getCode()); } } /** * @param $request * @return Response */ public function replies($request) { try { $resp = $this->reviewService->reviewReplies($request); return $resp; } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Reply Fails', $e->getCode()); } } /** * @param $request * @return Response */ public function repliesUpdate($request) { try { $resp = $this->reviewService->reviewRepliesUpdate($request); return Helper::rvxApi($resp)->success('Review Reply Updated'); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Reply Updated Fails', $e->getCode()); } } /** * @param $request * @return Response */ public function replyDelete($request) { try { $resp = $this->reviewService->reviewRepliesDelete($request); return Helper::getApiResponse($resp); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Bulk Fails', $e->getCode()); } } /** * @param $request * @return Response */ public function aiReview($request) { try { // Temporarily disable comment notification emails remove_action('comment_post', 'wp_notify_postauthor'); add_filter('comments_notify', '__return_false'); $resp = $this->reviewService->aiReview($request); // Re-enable the comment notification emails add_action('comment_post', 'wp_notify_postauthor'); remove_filter('comments_notify', '__return_false'); return Helper::getApiResponse($resp); } catch (Throwable $e) { // Re-enable the comment notification emails in case of error add_action('comment_post', 'wp_notify_postauthor'); remove_filter('comments_notify', '__return_false'); return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Bulk Fails', $e->getCode()); } } /** * @param $request * @return Response */ public function aiReviewCount() { try { $resp = $this->reviewService->aiReviewCount(); return Helper::getApiResponse($resp); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Ai Review Count', $e->getCode()); } } public function aggregationMeta($request) { try { $response = $this->reviewService->aggregationMeta($request); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Bulk Fails', $e->getCode()); } } /** * @param $request * @return Response */ public function reviewBulkUpdate($request) { try { $response = $this->reviewService->reviewBulkUpdate($request->get_params()); $this->cacheServices->removeCache(); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Bulk Fails', $e->getCode()); } } /** * @param $request * @return Response */ public function reviewBulkTrash($request) { try { $response = $this->reviewService->reviewBulkTrash($request->get_params()); $this->cacheServices->removeCache(); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Bulk Fails', $e->getCode()); } } /** * @param $request * @return Response */ public function reviewEmptyTrash($request) { try { $response = $this->reviewService->reviewEmptyTrash($request->get_params()); $this->cacheServices->removeCache(); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Empty Fails', $e->getCode()); } } /** * @param $request * @return Response */ public function restoreTrashItem($request) { //Bulk trash try { $response = $this->reviewService->restoreTrashItem($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Bulk Fails', $e->getCode()); } } /** * * @return Response */ public function reviewAggregation() { try { $resp = $this->reviewService->reviewAggregation(); // dd($resp->getApiData()); return Helper::getApiResponse($resp); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Aggregation Fails', $e->getCode()); } } /** * @param $request * @return Response */ public function reviewMoveToTrash($request) { try { $response = $this->reviewService->reviewMoveToTrash($request->get_params()); $this->cacheServices->removeCache(); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Move to trash Fails', $e->getCode()); } } /** * @param $request * @return Response */ public function highlight($request) { try { $response = $this->reviewService->highlight($request->get_params()); $this->cacheServices->removeCache(); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails(__('Review Highlight', 'reviewx'), $e->getCode()); } } public function bulkTenReviews($request) { try { $response = $this->reviewService->bulkTenReviews($request->get_params()); $this->cacheServices->removeCache(); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails(__('Latest ten reviews fails', 'reviewx'), $e->getCode()); } } public function bulkActionProductMeta($request) { try { foreach ($request->get_params() as $item) { if (!Helper::arrayGet($item, 'product_wp_id')) { return "No product found"; } $reviewAndMeta = ['reviews' => Helper::arrayGet($item, 'reviews'), 'meta' => Helper::arrayGet($item, 'meta')]; $latest_ten_review = \json_encode($reviewAndMeta, \true); \set_transient("rvx_{$item['product_wp_id']}_latest_reviews", $latest_ten_review, 604800); // Expires in 7 days return Helper::rest()->success("Success"); } } catch (Exception $e) { \error_log($e->getMessage()); return Helper::rest($e->getMessage())->fails("Fail"); } } /** * * @return Response */ public function reviewListMultiCriteria() { $resp = $this->reviewService->reviewListMultiCriteria(); return Helper::getApiResponse($resp); } /** * @param $request * @return Response */ public function getSingleProductAllReviews($request) { try { $resp = $this->reviewService->getSingleProductAllReviews($request); return Helper::getApiResponse($resp); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('failed', $e->getCode()); } } } Rest/Controllers/CategoryController.php 0000777 00000002446 15251220643 0014336 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Rvx\Services\CategoryService; use Rvx\Utilities\Helper; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Response; class CategoryController implements InvokableContract { protected $categoryService; /** * @param CategoryService $categoryService */ public function __construct(CategoryService $categoryService) { $this->categoryService = $categoryService; } /** * @return void */ public function __invoke() { } /** * @return Response */ public function selectable() { $resp = $this->categoryService->selectable(); return Helper::getApiResponse($resp); } /** * @return Response */ public function getCategory() { $resp = $this->categoryService->getCategory(); return Helper::getApiResponse($resp); } /** * @return Response */ public function getCategoryAll() { $resp = $this->categoryService->getCategoryAll(); return Helper::getApiResponse($resp); } /** * @return Response */ public function storeCategory($request) { $resp = $this->categoryService->storeCategory($request->get_params()); return Helper::getApiResponse($resp); } } Rest/Controllers/PingController.php 0000777 00000002137 15251220643 0013453 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Exception; use WP_REST_Response; use Rvx\Services\PingService; use Rvx\Utilities\Helper; class PingController { protected PingService $pingService; public function __construct() { $this->pingService = new PingService(); } /** * Ping from sass and (cached for 2 hours) return site info. * * @return WP_REST_Response */ public function ping() : WP_REST_Response { // Cache time-to-live: 2 hours $cache_duration = 3600 * 2; try { // Try to get cache $data = \get_transient('rvx_ping_cache'); if (\false === $data) { // Cache miss: fetch fresh data, store and return $data = $this->pingService->ping(); \set_transient('rvx_ping_cache', $data, $cache_duration); } return Helper::rvxApi($data)->success(__('Plugin Active', 'reviewx'), 200); } catch (Exception $e) { return Helper::rvxApi()->fails(__('Plugin deactivated or uninstalled', 'reviewx'), 404); } } } Rest/Controllers/DashboardController.php 0000777 00000003024 15251220643 0014441 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Rvx\Services\DashboardServices; use Rvx\Utilities\Helper; use Throwable; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Response; class DashboardController implements InvokableContract { protected $dashboardServices; /** * */ public function __construct(DashboardServices $dashboardServices) { $this->dashboardServices = $dashboardServices; } /** * @return void */ public function __invoke() { } /** * @return Response */ public function insight() { $resp = $this->dashboardServices->insight(); return Helper::getApiResponse($resp); } /** * @return Response */ public function requestEmail() { $resp = $this->dashboardServices->requestEmail(); return Helper::getApiResponse($resp); } /** * @return \WPDrill\Response */ public function requestUserData() { try { $response = $this->dashboardServices->requestUserData(); return Helper::rvxApi($response)->success('Site data Retrieved Successfully'); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Site data Retrieval Failed', $e->getCode()); } } /** * @param $request * @return Response */ public function chart($request) { $resp = $this->dashboardServices->chart($request->get_params()); return Helper::getApiResponse($resp); } } Rest/Controllers/DataSyncController.php 0000777 00000010163 15251220643 0014262 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use WP_REST_Request; use Rvx\CPT\CptHelper; use Rvx\Models\Site; use Rvx\Services\DataSyncService; use Rvx\Services\SettingService; use Rvx\Utilities\Helper; use Throwable; class DataSyncController { protected SettingService $settingService; protected DataSyncService $dataSyncService; public function __construct() { $this->dataSyncService = new DataSyncService(); $this->settingService = new SettingService(); } public function dataSync() { $resp = $this->dataSyncService->dataSync('default'); if ($resp) { return Helper::rvxApi()->success('Data Sync Success'); } else { return Helper::rvxApi()->fails('Data Sync Failed'); } } public function dataSynComplete() { // Update all DB settings from API to WP DB $this->updateSettingsOnSync(); return Site::where("is_saas_sync", 0)->update(['is_saas_sync' => 1]); } public function syncStatus() { \header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); \header("Pragma: no-cache"); \header("Pragma: no-cache"); $response = $this->dataSyncService->syncStatus(); if (!empty($response->getApiData()['sync_stats']) && $response->getApiData()['sync_stats'] === 1) { // Update all DB settings from API to WP DB $this->updateSettingsOnSync(); Site::where("is_saas_sync", 0)->update(['is_saas_sync' => 1]); } return Helper::saasResponse($response); } public function updateSettingsOnSync() { // Save '_rvx_cpt_settings' data after sync is completed from Sass API to WP DB $response = (new \Rvx\Rest\Controllers\CptController())->cptGetOnSync(); if ($response[0] === \true) { // Get the enabled post types array $used_post_types = (new CptHelper())->usedCPTOnSync('used'); // Loop through each post type and call getApiReviewSettings foreach ($used_post_types as $post_type) { $review_response = (new \Rvx\Rest\Controllers\SettingController())->getApiReviewSettingsOnSync($post_type); // Update Review settings $review_settings = $review_response['data']['review_settings']; $this->settingService->updateReviewSettingsOnSync($review_settings, \strtolower($post_type)); } } // Get widget settings $widget_response = (new \Rvx\Rest\Controllers\SettingController())->getApiWidgetSettingsOnSync(); $widget_settings = $widget_response['data']['widget_settings']; // Update widget settings $this->settingService->updateWidgetSettings($widget_settings); } public function dataManualSync($request) { try { $response = $this->dataSyncService->dataManualSync($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('General settings saved failed', $e->getCode()); } } public function syncedData(WP_REST_Request $request) { $post_type = $request->get_param('post_type') ?? 'product'; // Sanitize just in case: $post_type = sanitize_key($post_type); if ($post_type === 'product') { $file_name = "shop-bulk-data.jsonl"; } else { $file_name = "{$post_type}-cpt-bulk-data.jsonl"; } $file_path = WP_CONTENT_DIR . '/uploads/reviewx/' . $file_name; if (!\file_exists($file_path)) { return Helper::rvxApi()->fails('File not found for post_type: ' . $post_type, 404); } \header('Content-Description: File Transfer'); \header('Content-Type: application/jsonl'); \header('Content-Disposition: attachment; filename="' . \basename($file_path) . '"'); \header('Expires: 0'); \header('Cache-Control: must-revalidate'); \header('Pragma: public'); \header('Content-Length: ' . \filesize($file_path)); \readfile($file_path); exit; } } Rest/Controllers/LogController.php 0000777 00000011642 15251220643 0013300 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Exception; use Rvx\Services\CategorySyncService; use Rvx\Services\DataSyncService; use Rvx\Services\OrderItemSyncService; use Rvx\Services\ProductSyncService; use Rvx\Services\ReviewSyncService; use Rvx\Services\UserSyncService; use Rvx\Utilities\Helper; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\Services\CacheServices; class LogController implements InvokableContract { protected CacheServices $cacheServices; public function __construct() { $this->cacheServices = new CacheServices(); } /** * @return void */ public function __invoke() { } public function rvxRecentLog($request) { $data = $request->get_params(); $this->directoryCreate($data); $this->logDownload($data); $this->deleteLog($data); } public function directoryCreate($data) { if ($data['action'] === 'dir') { $log_folder = RVX_DIR_PATH . 'log/'; if (!\file_exists($log_folder) && !\mkdir($log_folder, 0755, \true) && !\is_dir($log_folder)) { throw new \RuntimeException(\sprintf('Directory "%s" was not created', $log_folder)); } } } public function logDownload($data) { if ($data['action'] === 'log') { $logPath = RVX_DIR_PATH . 'log/'; $files = \glob($logPath . '*'); if (empty($files)) { echo 'No log files found'; } $recentFile = null; foreach ($files as $file) { if (\is_null($recentFile) || \filemtime($file) > \filemtime($recentFile)) { $recentFile = $file; } } if (!\file_exists($recentFile)) { echo 'File not found'; } \header('Content-Type: text/plain'); \header('Content-Disposition: attachment; filename="' . \basename($recentFile) . '"'); \header('Content-Length: ' . \filesize($recentFile)); \ob_clean(); \flush(); \readfile($recentFile); exit; } } public function deleteLog($data) { if ($data['action'] === 'remove') { $log_folder = RVX_DIR_PATH . 'log/'; if (!\is_dir($log_folder)) { echo 'Log folder does not exist'; } $files = \glob($log_folder . '/*'); foreach ($files as $file) { if (\is_file($file)) { \unlink($file); } } if (\rmdir($log_folder)) { echo 'Log folder and files deleted successfully'; } else { echo 'Failed to delete the log folder'; } } } public function appendJsonSync($request) { $action = $request->get_param('action'); $from = $request->get_param('from'); if ($action === 'create_jsonl') { $this->createJsonl(); } if ($action === 'download') { $this->downloadJsonl(); } if ($action === 'manual_sync') { $dataResponse = (new DataSyncService())->dataSync($from); $this->cacheServices->removeCache(); if (!$dataResponse) { return Helper::rvxApi(['error' => "Data Sync Failed"])->fails('Data Sync Failed', $dataResponse->getStatusCode()); } } return Helper::rvxApi()->success('Data Synced Successfully'); } public function createJsonl() { try { $file_path = RVX_DIR_PATH . 'sync.jsonl'; $file = \fopen($file_path, 'w'); $syncedCaterories = new CategorySyncService(); $syncedCaterories->syncCategory($file); (new UserSyncService())->syncUser($file); $processProduct = new ProductSyncService($syncedCaterories); $processProduct->processProductForSync($file); (new ReviewSyncService($processProduct))->processReviewForSync($file); if (\class_exists('WooCommerce')) { $order = new OrderItemSyncService(); $order->syncOrder($file); $order->syncOrderItem($file); } echo 'jsonl create done'; } catch (Exception $e) { return $e->getMessage(); } } public function downloadJsonl() { $syncJsonlDownload = RVX_DIR_PATH . 'sync.jsonl'; if (\file_exists($syncJsonlDownload)) { \header('Content-Type: text/plain'); \header('Content-Disposition: attachment; filename="' . \basename($syncJsonlDownload) . '"'); \header('Content-Length: ' . \filesize($syncJsonlDownload)); \header('Content-Length: ' . \filesize($syncJsonlDownload)); \ob_clean(); \flush(); \readfile($syncJsonlDownload); \unlink($syncJsonlDownload); exit; } } } Rest/Controllers/UserController.php 0000777 00000001065 15251220643 0013473 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Rvx\Services\UserServices; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Response; class UserController implements InvokableContract { protected UserServices $userServices; /** * */ public function __construct() { $this->userServices = new UserServices(); } /** * @return void */ public function __invoke() { } /** * @return Response */ public function getUser() { return $this->userServices->getUser(); } } Rest/Controllers/WPDrillController.php 0000777 00000001517 15251220643 0014074 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\DB\QueryBuilder\QueryBuilderHandler; use Rvx\WPDrill\Response; class WPDrillController implements InvokableContract { protected QueryBuilderHandler $db; /** * @param QueryBuilderHandler $db */ public function __construct(QueryBuilderHandler $db) { $this->db = $db; } /** * @return Response */ public function __invoke() { // $user = User::where('id', 1)->first(); // //$user = $this->db->table('users')->where('id', 1)->first(); // return rvx_rest($site) // ->setHeader('Content-Type', 'application/json') // ->details('User fetched successfully') // ->success("User found"); } } Rest/Controllers/AuthController.php 0000777 00000027521 15251220643 0013463 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Exception; use Rvx\Api\AuthApi; use Rvx\CPT\CptHelper; use Rvx\Handlers\MigrationRollback\MigrationPrompt; use Rvx\Handlers\MigrationRollback\ReviewXChecker; use Rvx\Models\Site; use Rvx\Services\Api\LoginService; use Rvx\Services\DataSyncService; use Rvx\Services\SettingService; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Throwable; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Response; use Rvx\Services\CacheServices; class AuthController implements InvokableContract { protected LoginService $loginService; protected DataSyncService $dataSyncService; protected CacheServices $cacheServices; public function __construct() { $this->loginService = new LoginService(); $this->dataSyncService = new DataSyncService(); $this->cacheServices = new CacheServices(); } public function __invoke() { } /** * @param $request * @return Response */ public function login($request) { $data = $request->get_params(); $data['multicriteria'] = $this->multicriteriaOptions(); $payload = \array_merge($data, Helper::getWpClientInfo()); //return Helper::rvxApi(['error' => 'Invalid request', 'data' => $payload])->fails('Invalid request', Response::HTTP_BAD_REQUEST); try { $response = (new AuthApi())->login($payload); if ($response->getStatusCode() !== Response::HTTP_OK) { return Helper::saasResponse($response); } $apiData = $response->getApiData(); $validation = $this->validateSite($apiData); if ($validation !== \true) { return $validation; // return error response } $site_info = $this->prepareData($apiData); $site = Site::where('uid', $site_info['uid'])->first(); if (!$site) { $site = Site::insert($site_info); } else { Site::where("id", $site->id)->update($site_info); } Client::set(Site::where('uid', $site_info['uid'])->first()); $dataResponse = $this->dataSyncService->dataSync('login', 'product'); if (!$dataResponse) { return Helper::rvxApi(['error' => 'Data sync fails'])->fails('Data sync fails', $dataResponse->getStatusCode()); } // Sleep for 1 seconds \sleep(1); // Upload CPT data to Saas $enabled_post_types = (new CptHelper())->usedCPTOnSync('used'); unset($enabled_post_types['product']); // Exclude 'product' post type // Loop through each post type and hook into the actions/filters dynamically foreach ($enabled_post_types as $post_type) { $this->dataSyncService->dataSync('default', $post_type); } $this->cacheServices->removeCache(); $this->loginService->resetPostMeta(); // Set the localStorage isAlreadySyncSuccess \set_transient('rvx_reset_sync_flag', \true); return Helper::saasResponse($response); } catch (Exception $e) { $errorCode = $e->getCode() === 0 ? Response::HTTP_INTERNAL_SERVER_ERROR : $e->getCode(); $message = $e->getCode() === 0 ? 'Internal Server Error' : $e->getMessage(); return Helper::rvxApi(['error' => $message])->fails($message, $errorCode); } } public function license_key($request) { $data = $request->get_params(); $data['multicriteria'] = $this->multicriteriaOptions(); $payload = \array_merge($data, Helper::getWpClientInfo()); try { $response = (new AuthApi())->licenseLogin($payload); if ($response->getStatusCode() !== Response::HTTP_OK) { return Helper::saasResponse($response); } $apiData = $response->getApiData(); $validation = $this->validateSite($apiData); if ($validation !== \true) { return $validation; // return error response } $site_info = $this->prepareData($apiData); $site = Site::where('uid', $site_info['uid'])->first(); if (!$site) { $site = Site::insert($site_info); } else { Site::where("id", $site->id)->update($site_info); } Client::set(Site::where('uid', $site_info['uid'])->first()); $dataResponse = $this->dataSyncService->dataSync('login', 'product'); if (!$dataResponse) { return Helper::rvxApi(['error' => 'Data sync fails'])->fails('Data sync fails', $dataResponse->getStatusCode()); } // Sleep for 1 seconds \sleep(1); // Upload CPT data to Saas $enabled_post_types = (new CptHelper())->usedCPTOnSync('used'); unset($enabled_post_types['product']); // Exclude 'product' post type // Loop through each post type and hook into the actions/filters dynamically foreach ($enabled_post_types as $post_type) { $this->dataSyncService->dataSync('default', $post_type); } $this->cacheServices->removeCache(); $this->loginService->resetPostMeta(); // Set the localStorage isAlreadySyncSuccess \set_transient('rvx_reset_sync_flag', \true); return Helper::saasResponse($response); } catch (Exception $e) { $errorCode = $e->getCode() === 0 ? Response::HTTP_INTERNAL_SERVER_ERROR : $e->getCode(); $message = $e->getCode() === 0 ? 'Internal Server Error' : $e->getMessage(); return Helper::rvxApi(['error' => $message])->fails($message, $errorCode); } } protected function prepareData(array $site) : array { return ['site_id' => $site['id'], 'uid' => $site['uid'], 'name' => $site['name'], 'domain' => $site['domain'], 'url' => $site['url'], 'locale' => $site['locale'], 'email' => $site['email'], 'secret' => $site['key'], 'is_saas_sync' => 0, 'created_at' => \wp_date('Y-m-d H:i:s'), 'updated_at' => \wp_date('Y-m-d H:i:s')]; } public function multicriteriaOptions() { $data = []; $isOldReviewXExists = ReviewXChecker::isReviewXExists(); $isReviewXSaaSExists = ReviewXChecker::isReviewXSaasExists(); if ($isOldReviewXExists && !$isReviewXSaaSExists) { $options = \get_option('_rx_option_review_criteria'); $keys = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; $criterias = []; $i = 0; foreach ($options as $key => $name) { if (isset($keys[$i])) { $criterias[] = ["key" => $keys[$i], "name" => $name]; } $i++; } $multicrtriaEnableorDisable = \get_option('_rx_option_allow_multi_criteria'); $data = ["enable" => $multicrtriaEnableorDisable == 1 ? \true : \false, "criterias" => $criterias]; } elseif ($isReviewXSaaSExists) { $data = (array) (new SettingService())->getReviewSettings('product') ?? []; $data = $data['reviews']['multicriteria']; } return $data; } public function forgetPassword($request) { try { $response = $this->loginService->forgetPassword($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Forget password fail', $e->getCode()); } } public function resetPassword($request) { try { $response = $this->loginService->resetPassword($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Reset password fail', $e->getCode()); } } /** * @param $request * @return Response */ public function register($request) { $data = $request->get_params(); $payload = \array_merge($data, Helper::getWpClientInfo()); try { $response = (new AuthApi())->register($payload); if ($response->getStatusCode() !== Response::HTTP_OK) { return Helper::saasResponse($response); } $apiData = $response->getApiData(); $validation = $this->validateSite($apiData); if ($validation !== \true) { return $validation; // return error response } $site_info = $this->prepareRegisterData($apiData['site']); $site = Site::where('uid', $site_info['uid'])->first(); if (!$site) { $site = Site::insert($site_info); } else { Site::where("id", $site->id)->update($site_info); } Client::set(Site::where('uid', $site_info['uid'])->first()); $dataResponse = $this->dataSyncService->dataSync('register', 'product'); if (!$dataResponse) { return Helper::rvxApi(['error' => "Registration Fail"])->fails('Registration Fail', $dataResponse->getStatusCode()); } $this->cacheServices->removeCache(); $this->loginService->resetPostMeta(); $this->removeUserSettingsFormLocal(); // Set the localStorage isAlreadySyncSuccess \set_transient('rvx_reset_sync_flag', \true); return Helper::saasResponse($response); } catch (Exception $e) { $errorCode = $e->getCode() === 0 ? Response::HTTP_INTERNAL_SERVER_ERROR : $e->getCode(); $message = $e->getCode() === 0 ? 'Internal Server Error' : $e->getMessage(); return Helper::rvxApi(['error' => $message])->fails($message, $errorCode); } } public function migrationPrompt() { $migrationData = new MigrationPrompt(); $result = \false; if (ReviewXChecker::isReviewXExists() && !ReviewXChecker::isReviewXSaasExists()) { $result = $migrationData->rvx_retrieve_old_plugin_options_data(); } elseif (ReviewXChecker::isReviewXSaasExists()) { $result = $migrationData->rvx_retrieve_saas_plugin_options_data(); } if ($result !== \false) { $successMessage = "Old Data found"; return Helper::rvxApi($result)->success($successMessage, 200); } else { $failsMessage = "No Data found"; return Helper::rvxApi(null)->success($failsMessage, 200); } } public function removeUserSettingsFormLocal() { global $wpdb; $option_name = '__user_setting_access'; $exists = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$wpdb->options} WHERE option_name = %s", $option_name)); if ($exists > 0) { $result = $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->options} WHERE option_name = %s", $option_name)); if ($result !== \false) { return ["Success" => "Options Table Delete"]; } } } /** * Validate API response for required site data. * * @param array $apiData * @return bool */ private function validateSite(array $apiData) : bool { if (!\is_array($apiData) && !isset($apiData['id']) && !isset($apiData['uid'])) { return \false; } return \true; } protected function prepareRegisterData(array $site) : array { return ['site_id' => $site['id'], 'uid' => $site['uid'], 'name' => $site['name'], 'domain' => $site['domain'], 'url' => $site['url'], 'locale' => $site['locale'], 'email' => $site['email'], 'secret' => $site['key'], 'is_saas_sync' => 0, 'created_at' => \wp_date('Y-m-d H:i:s'), 'updated_at' => \wp_date('Y-m-d H:i:s')]; } } Rest/Controllers/FileController.php 0000777 00000000650 15251220643 0013433 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Rvx\Utilities\Helper; use Rvx\WPDrill\Contracts\InvokableContract; class FileController implements InvokableContract { public function __invoke() { } public function upload($request) { $file = $request->get_file('file'); $response = $this->categoryService->processCategoryForSync($file); return Helper::saasResponse($response); } } Rest/Controllers/ImportExportController.php 0000777 00000007303 15251220643 0015232 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Throwable; use Rvx\WPDrill\Response; use Rvx\Utilities\Helper; use Rvx\Services\CacheServices; use Rvx\Services\ImportExportServices; use Rvx\WPDrill\Contracts\InvokableContract; class ImportExportController implements InvokableContract { protected ImportExportServices $importExportServices; protected CacheServices $cacheServices; /** * */ public function __construct(ImportExportServices $importExportServices, CacheServices $cacheServices) { $this->importExportServices = $importExportServices; $this->cacheServices = $cacheServices; } public function __invoke() { // This method is required by the InvokableContract but not used in this controller. } /** * @param $request * @return Response */ public function importSupportedAppStore($request) { try { $response = $this->importExportServices->importSupportedAppStore($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Visibility Change', $e->getCode()); } } /** * @param $request * @return Response * @throws Throwable */ public function importStore($request) { try { $response = $this->importExportServices->importStore($request); $this->cacheServices->removeCache(); return Helper::rest($response['data'] ?? [])->success($response['message'] ?? 'Review Import started'); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Import Failed', $e->getCode()); } } /** * @param $request * @return Response */ public function exportCsv($request) { try { $response = $this->importExportServices->exportCsv($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Visibility Change', $e->getCode()); } } /** * @return Response */ public function exportHistory() { $resp = $this->importExportServices->exportHistory(); return Helper::getApiResponse($resp); } /** * @return Response */ public function importHistory() { $resp = $this->importExportServices->importHistory(); return Helper::getApiResponse($resp); } public function importRollback($request) { try { $response = $this->importExportServices->importRollback($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Visibility Change', $e->getCode()); } } public function importRestore($request) { try { $response = $this->importExportServices->importRestore($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Visibility Change', $e->getCode()); } } public function rollbackReviews($request) { try { $response = $this->importExportServices->rollbackImportByIds($request->get_params()); return Helper::rest($response)->success($response['message'] ?? 'Review Rollback Success'); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Rollback Failed', $e->getCode()); } } } Rest/Controllers/DiscountController.php 0000777 00000011424 15251220643 0014345 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Rvx\Services\DiscountService; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Throwable; use Rvx\WPDrill\Response; class DiscountController { protected $couponService; /** * @param DiscountService $couponService */ public function __construct(DiscountService $couponService) { $this->couponService = $couponService; } /** * @param $request * @return Response */ public function wpDiscountCreate($request) : Response { try { $coupon = $this->couponService->wpDiscountCreate($request->get_params()); if (!$coupon) { return Helper::rvxApi()->success('Failed to create discount'); } $couponData = $coupon->get_data(); $couponId = Helper::arrayGet($couponData, 'id'); $payload = ['wp_id' => $couponId, 'wp_unique_id' => Client::getUid() . '-' . $couponId, 'code_type' => $request->get_param('code_type'), 'status' => 1, 'site_id' => Client::getSiteId(), 'request_type' => $request->get_param('request_type'), 'type' => $request->get_param('discount_type') === 'percent' ? 'percentage' : 'fixed_amount', 'value' => Helper::arrayGet($couponData, 'amount'), 'usage_limit_per_user' => $request->get_param('usage_limit_per_user') ?? 0, 'usage_limit_per_coupon' => $request->get_param('usage_limit') ?? 0, 'minimum_amount' => (int) Helper::arrayGet($couponData, 'minimum_amount'), 'maximum_amount' => (int) Helper::arrayGet($couponData, 'maximum_amount'), 'exclude_sale_items_from_discount' => $request->get_param('exclude_sale_items_from_discount'), 'free_shipping' => $request->get_param('free_shipping'), 'can_be_used_with_other_coupon' => $request->get_param('individual_use'), 'single_code' => Helper::arrayGet($couponData, 'code'), 'start_date' => $request->get_param('start_date') ?? \date('Y-m-d'), 'start_time' => $request->get_param('start_time'), 'expires_in' => $request->get_param('expires_in'), 'end_date' => $request->get_param('expiry_date'), 'end_time' => $request->get_param('end_time')]; $resp = $this->couponService->saveDiscount($payload); if ($resp->getStatusCode() !== Response::HTTP_OK) { // Delete the created coupon if API request failed $this->couponService->deleteDiscount($couponId); return Helper::rvxApi()->fails('Failed to save discount to API'); } return Helper::getApiResponse($resp); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Coupon Create Fails', $e->getCode()); } } /** * @return Response */ public function getDiscount() { $resp = $this->couponService->getDiscount(); return Helper::getApiResponse($resp); } /** * @return Response */ public function discountSetting() { $resp = $this->couponService->discountSetting(); return Helper::getApiResponse($resp); } public function discountSettingsSave($request) { try { $response = $this->couponService->discountSettingsSave($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Coupon Create Fails', $e->getCode()); } } public function saveDiscount($request) { try { $response = $this->couponService->saveDiscount($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Coupon Create Fails', $e->getCode()); } } public function discountTemplateGet() { try { $response = $this->couponService->discountTemplateGet(); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Coupon Template Get Fails', $e->getCode()); } } public function discountTemplatePost($request) { try { $response = $this->couponService->discountTemplatePost($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Coupon Template Fails', $e->getCode()); } } public function discountMessage($request) { try { $response = $this->couponService->discountMessage($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Discount Message', $e->getCode()); } } } Rest/Controllers/SettingController.php 0000777 00000020000 15251220643 0014160 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Rvx\Services\SettingService; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Throwable; use Rvx\WPDrill\Response; class SettingController { protected SettingService $settingService; public function __construct() { $this->settingService = new SettingService(); } public function getApiReviewSettingsOnSync($cpt_type = 'product') : array { $data = ["cpt_type" => $cpt_type]; $response = $this->settingService->getApiReviewSettings($data); return \json_decode($response, \true); } public function getApiReviewSettings($request) : Response { $cpt_type = \strtolower($request->get_param('cpt_type')) ? \strtolower($request->get_param('cpt_type')) : \false; $data = ["cpt_type" => $cpt_type]; $response = $this->settingService->getApiReviewSettings($data); return Helper::getApiResponse($response); } public function wooCommerceVerificationRating() { $response = $this->settingService->wooCommerceVerificationRating(); return $response; } public function wooVerificationRatingRequired() { $response = $this->settingService->wooVerificationRatingRequired(); return $response; } public function userSettingsAccess($request) { $data = $request->get_params()['user_access']; \update_option('__user_setting_access', \json_encode($data)); } public function saveApiReviewSettings($request) { try { $response = $this->settingService->saveApiReviewSettings($request->get_params()); if ($response->getStatusCode() === Response::HTTP_OK) { // Update Review Settings $review_settings = $response->getApiData()['review_settings']; if (!empty($review_settings['reviews']['show_verified_badge']) && $review_settings['reviews']['show_verified_badge'] === \true) { \update_option('woocommerce_review_rating_verification_label', 'yes'); } if (!empty($review_settings['reviews']['show_verified_badge']) && $review_settings['reviews']['show_verified_badge'] === \false) { \update_option('woocommerce_review_rating_verification_label', 'no'); } if (!empty($review_settings['reviews']['review_submission_policy']['options']['verified_customer']) && $review_settings['reviews']['review_submission_policy']['options']['verified_customer'] === \true) { \update_option('woocommerce_review_rating_verification_required', 'yes'); } if (!empty($review_settings['reviews']['review_submission_policy']['options']['verified_customer']) && $review_settings['reviews']['review_submission_policy']['options']['verified_customer'] === \false) { \update_option('woocommerce_review_rating_verification_required', 'no'); } $this->settingService->updateReviewSettings($review_settings, $request['post_type']); } return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review settings saved failed', $e->getCode()); } } public function wooCommerceVerificationRatingUpdate($request) { try { $response = $this->settingService->wooCommerceVerificationRatingUpdate($request->get_params()); return $response; } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review settings saved failed', $e->getCode()); } } public function wooVerificationRating($request) { try { $response = $this->settingService->wooVerificationRating($request->get_params()); return $response; } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review settings saved failed', $e->getCode()); } } public function getApiWidgetSettingsOnSync() : array { $response = $this->settingService->getApiWidgetSettings(); return \json_decode($response, \true); } public function getApiWidgetSettings() : Response { $response = $this->settingService->getApiWidgetSettings(); return Helper::getApiResponse($response); } public function userCurrentPlan() { $response = $this->settingService->userCurrentPlan(); return Helper::getApiResponse($response); } public function saveApiWidgetSettings($request) { try { $response = $this->settingService->saveWidgetSettings($request->get_params()); if ($response->getStatusCode() === Response::HTTP_OK) { // Update Widget Settings $widget_settings = $response->getApiData()['widget_settings']; $this->settingService->updateWidgetSettings($widget_settings); } return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Widget settings saved failed', $e->getCode()); } } public function getApiGeneralSettings() { $response = $this->settingService->getApiGeneralSettings(); return Helper::getApiResponse($response); } public function saveApiGeneralSettings($request) { try { $response = $this->settingService->saveApiGeneralSettings($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('General settings saved failed', $e->getCode()); } } public function getSettingsData() { $data = ["review_settings" => ["reviews" => ["review_submission_policy" => ["options" => ["anyone" => \true, "verified_customer" => \false]], "show_verified_badge" => \false, "review_eligibility" => ["pending_payment" => \false, "processing" => \false, "on_hold" => \false, "completed_payment" => \true, "cancelled" => \false, "refunded" => \false, "failed" => \false, "draft" => \false], "auto_approve_reviews" => \true, "show_reviewer_name" => \true, "show_reviewer_country" => \true, "enable_likes_dislikes" => ["enabled" => \true, "options" => ["allow_likes" => \true, "allow_dislikes" => \false]], "allow_review_sharing" => \true, "allow_review_titles" => \true, "photo_reviews_allowed" => \true, "video_reviews_allowed" => \true, "allow_recommendations" => \true, "anonymous_reviews_allowed" => \true, "show_consent_checkbox" => \true, "allow_multiple_reviews" => \true, "multi_criteria_reviews" => ["enabled" => \true, "criteria" => ["Quality", "Price", "Size"]]]]]; $json_data = \json_encode($data); \update_option('your_option_name', $json_data); } public function dataSyncStatus() { return ['sync' => Client::getSync() ? \true : \false]; } public function allSettingsSave($request) { try { $response = $this->settingService->allSettingsSave($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('General settings saved failed', $e->getCode()); } } public function removeCredentials($request) { try { $response = $this->settingService->removeCredentials($request->get_headers()); return $response; } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Sites Table Data deletion failed', $e->getCode()); } } public function updateSiteData($request) { try { $response = $this->settingService->updateSiteData($request->get_headers()); return $response; } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Sites Table Data update failed', $e->getCode()); } } } Rest/Controllers/AccessController.php 0000777 00000001150 15251220643 0013751 0 ustar 00 <?php namespace Rvx\Rest\Controllers; class AccessController { public function adminAccess($request) { // do something //dd('Access Controller'); $command = $request->get_params()['command']; //dd($command); if ($command === 'site_block') { $this->siteBlock(); } elseif ($command === 'site_hit') { $this->siteHit(); } } private function siteBlock() { // do something dd('Site Block Method'); } private function siteHit() { // do something dd('Site Hit Method'); } } Rest/Controllers/CptController.php 0000777 00000030575 15251220643 0013313 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Rvx\CPT\CptHelper; use Rvx\Services\CptService; use Rvx\Services\DataSyncService; use Rvx\Services\SettingService; use Rvx\Utilities\Helper; use Rvx\Services\CacheServices; use Throwable; use Rvx\WPDrill\Response; class CptController { protected CptService $cptService; protected DataSyncService $dataSyncService; protected CacheServices $cacheServices; protected CptHelper $cptHelper; public function __construct() { $this->cptService = new CptService(); $this->dataSyncService = new DataSyncService(); $this->cacheServices = new CacheServices(); $this->cptHelper = new CptHelper(); } /** * @return array */ public function cptGetOnSync() { $response = $this->cptService->cptGet(); $status = $this->cptSettings($response); return [$status, \json_decode($response, \true)]; } /** * @return Response */ public function cptGet() { $response = $this->cptService->cptGet(); $this->cptSettings($response); return Helper::getApiResponse($response); } /** * @return Response */ public function cptStore($request) { try { $response = $this->cptService->cptStore($request->get_params()); $resData = Helper::saasResponse($response); if ($response->getStatusCode() === 200) { // Update (_rvx_cpt_settings) CPT Settings $response = $this->cptService->cptGet(); $this->cptSettings($response); // Update (_rvx_ettings_{post_type}) CPT Settings $post_type = $resData->data['data']['post_type'] ? \strtolower($resData->data['data']['post_type']) : ''; if (!empty($post_type)) { $review_response = (new \Rvx\Rest\Controllers\SettingController())->getApiReviewSettingsOnSync($post_type); // Update Review settings $review_settings = $review_response['data']['review_settings']; (new SettingService())->updateReviewSettingsOnSync($review_settings, \strtolower($post_type)); } // Upload CPT data to Saas $this->dataSyncService->dataSync('default', $post_type); $this->cacheServices->removeCache(); } return Helper::rvxApi($resData)->success('Create Success', 200); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Create Fails', $e->getCode()); } } /** * @return Response */ public function cptUpdate($request) { try { $response = $this->cptService->cptUpdate($request->get_params()); $resData = Helper::saasResponse($response); if ($response->getStatusCode() === 200) { // Update (_rvx_cpt_settings) CPT Settings $response = $this->cptService->cptGet(); $this->cptSettings($response); } return Helper::rvxApi($resData)->success('Update Success', 200); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Update Fails', $e->getCode()); } } /** * @return Response */ public function cptDelete($request) { try { $response = $this->cptService->cptDelete($request->get_params()); $resData = Helper::saasResponse($response); if ($response->getStatusCode() === 200) { // Update (_rvx_cpt_settings) CPT Settings $response = $this->cptService->cptGet(); $this->cptSettings($response); } return Helper::rvxApi($resData)->success('Delete Success', 200); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Delete Fails', $e->getCode()); } } public function customPostTypes($request) { try { // Available post types $cptList = \array_map(function ($cpt) { return ['name' => \strtolower($cpt['name']), 'slug' => \strtolower($cpt['slug'])]; }, $this->cptHelper->getPublicCptList()); // Post type settings from WPDB $cptSettings = $this->cptHelper->cptSettings(); $enabled = []; $disabled = []; $used = []; $unused = []; // Extract post types from settings $reviewPostTypes = []; if (!empty($cptSettings['reviews'])) { foreach ($cptSettings['reviews'] as $review) { $postType = \strtolower($review['post_type']); $reviewPostTypes[$postType] = ['name' => $review['post_type'] ? \strtolower($review['post_type']) : $postType, 'slug' => $postType, 'status' => $review['status']]; } } // Categorize post types foreach ($cptList as $cpt) { $slug = \strtolower($cpt['slug']); $name = \strtolower($cpt['name']); if (isset($reviewPostTypes[$slug])) { $used[] = ['name' => $reviewPostTypes[$slug]['name'], 'slug' => $slug]; if ($reviewPostTypes[$slug]['status'] === 'Enabled') { $enabled[] = ['name' => $reviewPostTypes[$slug]['name'], 'slug' => $slug]; } else { $disabled[] = ['name' => $reviewPostTypes[$slug]['name'], 'slug' => $slug]; } } else { $unused[] = ['name' => $name, 'slug' => $slug]; } } // Ensure 'product' post type is included in all except 'unused' $productPostType = ['name' => 'product', 'slug' => 'product']; if (!\in_array('product', \array_column($enabled, 'slug'))) { $enabled[] = $productPostType; } if (!\in_array('product', \array_column($cptList, 'slug'))) { $cptList[] = $productPostType; } if (!\in_array('product', \array_column($used, 'slug'))) { $used[] = $productPostType; } // Get API param $apiParam = 'all'; if (\is_string($request)) { // $apiParam is a string $apiParam = $request; } elseif (\is_object($request)) { // $apiParam is an array $apiParam = \strtolower($request->get_param('cpt')); } $responseData = []; switch ($apiParam) { case 'enabled': $responseData = $enabled; break; case 'disabled': $responseData = $disabled; break; case 'used': $responseData = $used; break; case 'unused': $responseData = $unused; break; case 'all': $responseData = $cptList; break; default: $responseData = $cptList; } if (\is_string($request)) { return $responseData; } elseif (\is_object($request)) { return Helper::rvxApi($responseData)->success(); } } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Custom Post Types List Fails', $e->getCode()); } } public function customPostTypesOnSync($param) { try { // Available post types $cptList = \array_map(function ($cpt) { return ['name' => \strtolower($cpt['name']), 'slug' => \strtolower($cpt['slug'])]; }, $this->cptHelper->getPublicCptList()); // Post type settings from WPDB $cptSettings = $this->cptHelper->cptSettingsOnSync(); $enabled = []; $disabled = []; $used = []; $unused = []; // Extract post types from settings $reviewPostTypes = []; if (!empty($cptSettings['reviews'])) { foreach ($cptSettings['reviews'] as $review) { $postType = \strtolower($review['post_type']); $reviewPostTypes[$postType] = ['name' => $review['post_type'] ? \strtolower($review['post_type']) : $postType, 'slug' => $postType, 'status' => $review['status']]; } } // Categorize post types foreach ($cptList as $cpt) { $slug = \strtolower($cpt['slug']); $name = \strtolower($cpt['name']); if (isset($reviewPostTypes[$slug])) { $used[] = ['name' => $reviewPostTypes[$slug]['name'], 'slug' => $slug]; if ($reviewPostTypes[$slug]['status'] === 'Enabled') { $enabled[] = ['name' => $reviewPostTypes[$slug]['name'], 'slug' => $slug]; } else { $disabled[] = ['name' => $reviewPostTypes[$slug]['name'], 'slug' => $slug]; } } else { $unused[] = ['name' => $name, 'slug' => $slug]; } } // Ensure 'product' post type is included in all except 'unused' $productPostType = ['name' => 'product', 'slug' => 'product']; if (!\in_array('product', \array_column($enabled, 'slug'))) { $enabled[] = $productPostType; } if (!\in_array('product', \array_column($cptList, 'slug'))) { $cptList[] = $productPostType; } if (!\in_array('product', \array_column($used, 'slug'))) { $used[] = $productPostType; } // Get param if (empty($param)) { // $param is a string $apiParam = 'all'; } elseif (\is_string($param)) { // $apiParam is an array $apiParam = \strtolower($param); } $responseData = []; switch ($apiParam) { case 'enabled': $responseData = $enabled; break; case 'disabled': $responseData = $disabled; break; case 'used': $responseData = $used; break; case 'unused': $responseData = $unused; break; case 'all': $responseData = $cptList; break; default: $responseData = $cptList; } return $responseData; } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Custom Post Types List Fails', $e->getCode()); } } /** * @return Response */ public function cptStatusChange($request) { try { $response = $this->cptService->cptStatusChange($request->get_params()); $resData = Helper::saasResponse($response); if ($response->getStatusCode() === 200) { // Update (_rvx_cpt_settings) CPT Settings $response = $this->cptService->cptGet(); $this->cptSettings($response); // Update (_rvx_ettings_{post_type}) CPT Settings $post_type = $resData->data['data']['post_type'] ? \strtolower($resData->data['data']['post_type']) : ''; // Upload CPT data to Saas if ($resData->data['data']['status'] === 'Enabled') { $this->dataSyncService->dataSync('default', $post_type); $this->cacheServices->removeCache(); } } return Helper::rvxApi($resData)->success('Status Change Success', 200); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Status Change Fails', $e->getCode()); } } public function cptSettings($response) { $status = \false; $dataArray = \json_decode($response, \true); if ($dataArray !== null) { $status = \update_option('_rvx_cpt_settings', $dataArray['data']); } return $status; } } Rest/Controllers/StoreFrontReviewController.php 0000777 00000041056 15251220643 0016050 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Exception; use Rvx\Services\Api\LoginService; use Rvx\Services\ReviewService; use Rvx\Services\CacheServices; use Rvx\Services\SettingService; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Throwable; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Response; class StoreFrontReviewController implements InvokableContract { protected ReviewService $reviewService; protected SettingService $settingService; protected LoginService $loginService; protected CacheServices $cacheService; public function __construct() { $this->reviewService = new ReviewService(); $this->settingService = new SettingService(); $this->loginService = new LoginService(); $this->cacheService = new CacheServices(); } /** * @return void */ public function __invoke() { } public function settingMeta($request) : Response { try { $this->reviewService->settingMeta($request); return Helper::rest()->success("Success"); } catch (Exception $e) { return Helper::rest()->fails("Fails"); } } public function dataGetFromSaas($request) { $response = $this->reviewService->getWidgetReviewsForProduct($request); if ($response->getStatusCode() !== Response::HTTP_OK) { return \false; } return $response->getApiData(); } public function getWidgetReviewsForProduct($request) { $diffReviewCount = $this->reviewCountDifferent($request["product_id"]); if ($diffReviewCount === \true) { \delete_transient("rvx_{$request["product_id"]}_latest_reviews"); return $this->dataGetFormSaas($request); } $productId = $request["product_id"]; $postMata = \get_transient("rvx_{$productId}_latest_reviews"); if ($postMata) { if (\count($postMata["reviews"]) != $this->insightReviewCount($request["product_id"])) { \delete_transient("rvx_{$request["product_id"]}_latest_reviews"); return $this->dataGetFormSaas($request); } if ($request->get_param("cursor") || $request->get_param("rating") || $request->get_param("sortBy") || $request->get_param("attachment")) { $response = $this->reviewService->getWidgetReviewsForProduct($request); return Helper::saasResponse($response); } else { if ($this->is_valid_data($postMata)) { //valid $response = ["reviews" => $postMata["reviews"], "meta" => $postMata["meta"]]; if ($response) { return Helper::rest($response)->success("Success"); } else { return Helper::rest()->fails("Fails"); } } else { //invalid $this->loginService->resetProductWisePostMeta($request["product_id"]); return $this->dataGetFormSaas($request); } } } else { return $this->dataGetFormSaas($request); } } public function getAllReviewsDataFromSaas($request, $site_id) { $response = $this->reviewService->getWidgetAllReviewsForSite($request, $site_id); if ($response->getStatusCode() !== Response::HTTP_OK) { return \false; } return $response->getApiData(); } public function getWidgetAllReviewsListForSite($request) { $site_id = Client::getUid(); $post_type = $request['post_type'] ?? 'all'; $postMata = \get_transient("rvx_{$site_id}_{$post_type}_reviews"); if ($post_type === 'all') { $post_type = null; } if (!$postMata) { return $this->getAllReviewsFromSaas($request, $site_id, $post_type); } if ($request->get_param("cursor") || $request->get_param("rating") || $request->get_param("sort_by") || $request->get_param("attachment")) { $response = $this->reviewService->getWidgetAllReviewsForSite($request, $site_id); return Helper::saasResponse($response); } if ($this->is_valid_data($postMata)) { $response = ["reviews" => $postMata["reviews"], "meta" => $postMata["meta"]]; if ($response) { return Helper::rest($response)->success("Success"); } return Helper::rest()->fails("Fails"); } // invalid cached data → reset and fetch fresh $this->resetSiteWiseTransientMeta($site_id, $post_type); return $this->getAllReviewsFromSaas($request, $site_id, $post_type); } public function resetSiteWiseTransientMeta($site_id, $post_type) { global $wpdb; $post_type = $post_type != null ? $post_type : 'all'; $review_key = "rvx_{$site_id}_{$post_type}_reviews"; // Prepare and execute the deletion query $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE meta_key = %s", $review_key)); } public function getWidgetReviewsListShortcode($request) { $productId = $request['product_id']; // mismatch in review count → reset + fetch if ($this->reviewCountDifferent($productId)) { \delete_transient("rvx_{$productId}_latest_reviews"); return $this->dataGetFormSaas($request); } $postMeta = \get_transient("rvx_{$productId}_latest_reviews"); // no cache → fetch if (!$postMeta) { return $this->dataGetFormSaas($request); } // cache count mismatch → reset + fetch if (\count($postMeta['reviews']) !== $this->insightReviewCount($productId)) { \delete_transient("rvx_{$productId}_latest_reviews"); return $this->dataGetFormSaas($request); } // request has filters → always fetch fresh if ($request->get_param('cursor') || $request->get_param('rating') || $request->get_param('sortBy') || $request->get_param('attachment')) { $response = $this->reviewService->getWidgetReviewsListShortcode($request); return Helper::saasResponse($response); } // cached data valid → return if ($this->is_valid_data($postMeta)) { return Helper::rest(['reviews' => $postMeta['reviews'], 'meta' => $postMeta['meta']])->success('Success'); } // invalid cached data → reset + fetch $this->loginService->resetProductWisePostMeta($productId); return $this->dataGetFormSaas($request); } public function getAllReviewsFromSaas($request, $site_id, $post_type) { $latestReviews = $this->getAllReviewsDataFromSaas($request, $site_id); if (!$latestReviews) { return Helper::rvxApi(["error" => "Fails"])->fails("failed"); } $reviews = Helper::arrayGet($latestReviews, "reviews"); if (\count($reviews) > 0) { $this->reviewService->setAllReviewsMetaTransient($site_id, $post_type, $latestReviews); } return ["data" => $latestReviews]; } public function dataGetFormSaas($request) { $latestReview = $this->dataGetFromSaas($request); if (!$latestReview) { return Helper::rvxApi(["error" => "Fails"])->fails("failed"); } $reviews = Helper::arrayGet($latestReview, "reviews"); if (\count($reviews) > 0) { $this->reviewService->postMetaReviewInsert($request->get_param("product_id"), $latestReview); } return ["data" => $latestReview]; } public function is_valid_data($postMata) { if (\is_array($postMata)) { return \true; } return \false; } public function insightDataGetInSaas($request) { $response = $this->reviewService->getWidgetInsight($request); if ($response->getStatusCode() !== Response::HTTP_OK) { return \false; } return $response->getApiData(); } public function getWidgetInsight($request) { try { $diffReviewCount = $this->reviewCountDifferent($request["product_id"]); if ($diffReviewCount === \true) { return ["data" => $this->insightDataelsePart($request)]; } $data = \get_transient("rvx_{$request["product_id"]}_latest_reviews_insight"); if ($data) { $aggregation = \json_decode($data, \true); if (\is_array($aggregation)) { $aggregation['product']['title'] = \htmlspecialchars_decode($aggregation['product']['title'], \ENT_QUOTES); } if (!\is_array($aggregation)) { $modData = $this->productTitleAndDescriptionBackSlashRemove($data); $aggregation = \json_decode($modData, \true); } if ($aggregation) { return Helper::rest($aggregation)->success("Success"); } else { return Helper::rest()->fails("Fails"); } } else { // Fetch the latest aggregation data return ["data" => $this->insightDataelsePart($request)]; } } catch (Throwable $e) { return Helper::rvxApi(["error" => $e->getMessage()])->fails("failed", $e->getCode()); } } public function insightDataelsePart($request) { $latestAggregation = $this->insightDataGetInSaas($request); // Check if the data retrieval fails if (!$latestAggregation) { return Helper::rvxApi(["error" => "Fails"])->fails("failed"); } // Extract 'criteria_stats' from the latest aggregation data (always an array) $criteriaStat = Helper::arrayGet($latestAggregation, "criteria_stats"); // No need to decode since it's always an array, just assign back $latestAggregation["criteria_stats"] = $criteriaStat; \delete_transient("rvx_{$request->get_param("product_id")}_latest_reviews_insight"); // Store the data in post meta as a JSON string $latestAggregationJson = \json_encode($latestAggregation, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES); \set_transient("rvx_{$request->get_param("product_id")}_latest_reviews_insight", $latestAggregationJson, 604800); // Expires in 7 days return $latestAggregation; } public function productTitleAndDescriptionBackSlashRemove($data) { return \preg_replace('/("title":")([^"\\\\]+)\\\\\'/', '$1$2\'', $data); } public function reviewCountDifferent($id) : bool { $wpReview = $this->getOnlyApproveReviewCount($id); $saasReview = $this->insightReviewCount($id); if ($wpReview > $saasReview) { return \true; } if ($wpReview < $saasReview) { return \true; } return \false; } public function getOnlyApproveReviewCount($id) : int { global $wpdb; $query = $wpdb->prepare("SELECT COUNT(*) \n FROM {$wpdb->comments} \n WHERE comment_post_ID = %d \n AND comment_approved = '1' \n AND comment_parent = 0\n AND comment_type IN ('comment', 'review')", $id); return (int) $wpdb->get_var($query); } public function insightReviewCount($id) : int { $data = \get_transient("rvx_{$id}_latest_reviews_insight"); if ($data) { $reviewAggregation = \json_decode($data, \true); return $reviewAggregation['aggregation']['total_reviews'] ?? 0; } return 0; } /** * @param $request * @return Response */ public function saveWidgetReviewsForProduct($request) { try { $response = $this->reviewService->saveWidgetReviewsForProduct($request); $this->cacheService->removeCache(); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(["error" => $e->getMessage()])->fails("failed", $e->getCode()); } } /** * @param $request * @return Response */ public function requestReviewEmailAttachment($request) : Response { try { $data = $this->reviewService->requestReviewEmailAttachment($request); return Helper::rvxApi(["reviews" => $data])->success("Review Successfully sent", 200); } catch (Throwable $e) { return Helper::rvxApi(["error" => $e->getMessage()])->fails("failed", $e->getCode()); } } /** * @param $request * @return Response */ public function likeDislikePreference($request) { try { $response = $this->reviewService->likeDIslikePreference($request->get_params()); return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(["error" => $e->getMessage()])->fails("failed", $e->getCode()); } } public function singleActionProductMata($request) { $reviewData = Helper::arrayGet($request->get_params(), "review"); $aggregationData = Helper::arrayGet($request->get_params(), "aggregation"); $productId = Helper::arrayGet($aggregationData, "product_wp_id"); if (!$productId) { return; } $this->storeReviewMeta($productId, $reviewData); $this->storeAggregationMeta($productId, $aggregationData); } public function storeReviewMeta($productId, $payload) { $reviewAndMeta = ["reviews" => Helper::arrayGet($payload, "reviews"), "meta" => Helper::arrayGet($payload, "meta")]; $this->reviewService->postMetaReviewInsert($productId, $reviewAndMeta); } public function storeAggregationMeta($productId, $payload) { $aggregation_data = \json_encode(wp_slash(Helper::arrayGet($payload, "meta")), \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES); \set_transient("rvx_{$productId}_latest_reviews_insight", $aggregation_data, 604800); // Expires in 7 days } public function reviewRequestStoreItem($request) { try { $review = $this->reviewService->reviewRequestStoreItem($request->get_params()); return $review; // return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(["error" => $e->getMessage()])->fails("failed", $e->getCode()); } } public function thanksMessage($request) { try { $response = $this->reviewService->thanksMessage($request); return $response; } catch (Throwable $e) { return Helper::rvxApi(["error" => $e->getMessage()])->fails("failed", $e->getCode()); } } public function getSpecificReviewItem($request) { try { $defferentIds = $this->cacheService->clearShortcodesCache(\get_option('_rvx_reviews_ids'), $request->get_params()); if ($defferentIds == \false) { \delete_transient('rvx_shortcode_transient'); } $transient_key = 'rvx_shortcode_transient'; $resp = \get_transient($transient_key); if ($resp !== \false) { $data = ['reviews' => $resp['reviews'], 'meta' => $resp['meta']]; return Helper::rest($data)->success("Success (from transient)"); } else { $response = $this->reviewService->getSpecificReviewItem($request); $api_data = $response->getApiData(); \set_transient($transient_key, $api_data, 12 * HOUR_IN_SECONDS); \update_option('_rvx_reviews_ids', $request->get_params()); return Helper::saasResponse($response); } } catch (Throwable $e) { return Helper::rvxApi(["error" => $e->getMessage()])->fails("Specific Review Item Fails", $e->getCode()); } } public function getLocalSettings($request) { // Get API param $post_type = $request->get_param('cpt_type') ? \strtolower($request->get_param('cpt_type')) : 'product'; $data = (array) (new SettingService())->getSettingsData($post_type) ?? []; if ($data) { return Helper::rest($data)->success("Success"); } else { $response = $this->settingService->getLocalSettings($post_type); $apiResponse = Helper::getApiResponse($response); $review_setting = $apiResponse->data['data']['setting']['review_settings']; $this->settingService->updateReviewSettings($review_setting, $post_type); return $apiResponse; } } } Rest/Controllers/EmailTemplateController.php 0000777 00000013401 15251220643 0015275 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Rvx\Services\EmailService; use Rvx\Utilities\Helper; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Response; class EmailTemplateController implements InvokableContract { protected $emailService; /** * @param EmailService $emailService */ public function __construct(EmailService $emailService) { $this->emailService = $emailService; } /** * @return void */ public function __invoke() { } /** * @return Response */ public function index() { $resp = $this->emailService->index(); return Helper::getApiResponse($resp); } /** * @return Response */ public function store($request) { try { $response = $this->emailService->store($request->get_params()); return Helper::saasResponse($response); } catch (\Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('This Action Fails', $e->getCode()); } } /** * @return Response */ public function show($request) { $id = $request->get_param('id'); $resp = $this->emailService->show($id); return Helper::getApiResponse($resp); } public function update($request) { try { $response = $this->emailService->update($request->get_params()); return Helper::saasResponse($response); } catch (\Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('This Action Fails', $e->getCode()); } } public function trash($request) { $id = $request->get_param('id'); $resp = $this->emailService->trash($id); return Helper::getApiResponse($resp); } public function mailRequest($request) { $resp = $this->emailService->mailRequest($request->get_params()); return Helper::getApiResponse($resp); } public function mailContents() { $resp = $this->emailService->content(); return Helper::getApiResponse($resp); } public function saveEmailRequest($request) { try { $response = $this->emailService->saveEmailRequest($request->get_params()); return Helper::saasResponse($response); } catch (\Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('This Action Fails', $e->getCode()); } } public function followup($request) { try { $response = $this->emailService->followup($request->get_params()); return Helper::saasResponse($response); } catch (\Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('This Action Fails', $e->getCode()); } } public function photoReview($request) { try { $response = $this->emailService->photoReview($request->get_params()); return Helper::saasResponse($response); } catch (\Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('This Action Fails', $e->getCode()); } } public function testMail($request) { try { $response = $this->emailService->testMail($request->get_params()); return Helper::saasResponse($response); } catch (\Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('This Action Fails', $e->getCode()); } } public function markAsDone($request) { try { $response = $this->emailService->markAsComplete($request->get_params()); return Helper::saasResponse($response); } catch (\Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('This Action Fails', $e->getCode()); } } public function requestEmailCancel($request) { try { $response = $this->emailService->emailCancel($request->get_params()); return Helper::saasResponse($response); } catch (\Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('This Action Fails', $e->getCode()); } } public function requestEmailSend($request) { try { $response = $this->emailService->requestEmailSend($request->get_params()); return Helper::saasResponse($response); } catch (\Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('This Action Fails', $e->getCode()); } } public function requestEmailResend($request) { try { $response = $this->emailService->requestEmailResend($request->get_params()); return Helper::saasResponse($response); } catch (\Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('This Action Fails', $e->getCode()); } } public function requestEmailUnsubscribe() { try { $response = $this->emailService->requestEmailUnsubscribe(); return Helper::saasResponse($response); } catch (\Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('This Action Fails', $e->getCode()); } } public function reviewRequestSettings() { $resp = $this->emailService->reviewRequestSettings(); return Helper::getApiResponse($resp); } public function allReminderSettings($request) { try { $response = $this->emailService->allReminderSettings($request->get_params()); return Helper::saasResponse($response); } catch (\Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('This Action Fails', $e->getCode()); } } } Rest/Controllers/Products/ProductController.php 0000777 00000002331 15251220643 0015775 0 ustar 00 <?php namespace Rvx\Rest\Controllers\Products; use Rvx\Services\ProductService; use Rvx\Utilities\Helper; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Response; class ProductController implements InvokableContract { protected $productService; /** * @param ProductService $productService */ public function __construct(ProductService $productService) { $this->productService = $productService; } public function __invoke() { } /** * @return Response */ public function selectable($request) { $resp = $this->productService->getSelectProduct($request->get_params()); if ($resp->getStatusCode() === Response::HTTP_OK) { $data = $resp->getApiData(); if (isset($data['products']) && \is_array($data['products'])) { foreach ($data['products'] as &$product) { if (isset($product['wp_id'])) { $product['post_type'] = get_post_type($product['wp_id']); } } } return Helper::rest($data)->success($resp()->message, $resp->getStatusCode()); } return Helper::getApiResponse($resp); } } Rest/Controllers/GoogleReviewController.php 0000777 00000005020 15251220643 0015146 0 ustar 00 <?php namespace Rvx\Rest\Controllers; use Throwable; use Rvx\Services\GoogleReviewService; use Rvx\Utilities\Helper; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Response; class GoogleReviewController implements InvokableContract { protected $googleReviewService; /** * @param GoogleReviewService $googleReviewService */ public function __construct(GoogleReviewService $googleReviewService) { $this->googleReviewService = $googleReviewService; } /** * @return void */ public function __invoke() { } /** * @return Response */ public function googleReviewGet() { $resp = $this->googleReviewService->googleReviewGet(); return Helper::getApiResponse($resp); } /** * @return Response */ public function googleReviewPlaceApi() { $resp = $this->googleReviewService->googleReviewPlaceApi(); return Helper::getApiResponse($resp); } /** * @return Response */ public function googleRecaptchaVerify($request) { $resp = $this->googleReviewService->googleRecaptchaVerify($request->get_params()); return $resp; } /** * @return Response */ public function googleReviewKey($request) { try { $response = $this->googleReviewService->googleReviewKey($request->get_params()); \delete_transient('rvx_google_api_settings'); // When settings is changed remove the cache wpdb transient data \delete_transient('rvx_google_reviews_cache'); // When settings is changed remove the cache wpdb transient data return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Bulk Fails', $e->getCode()); } } /** * @return Response */ public function googleReviewSetting($request) { try { $response = $this->googleReviewService->googleReviewSetting($request->get_params()); \delete_transient('rvx_google_api_settings'); // When settings is changed remove the cache wpdb transient data \delete_transient('rvx_google_reviews_cache'); // When settings is changed remove the cache wpdb transient data return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review Bulk Fails', $e->getCode()); } } } Customize/assets/js/rvx-customize.js 0000777 00000065374 15251220643 0013667 0 ustar 00 (function($) { // Live style updater function updateStyle(selector, property, value) { var $element = $(selector); var currentStyle = $element.attr('style') || ''; var styles = currentStyle.split(';').filter(Boolean); var updated = false; styles = styles.map(function(style) { var [prop, val] = style.split(':'); if (prop.trim() === property) { updated = true; return property + ': ' + value + ' !important'; } return style; }); if (!updated) { styles.push(property + ': ' + value + ' !important'); } $element.attr('style', styles.join('; ')); } /* * ReviewX - General Settings */ // Active Rating Stars: [Background Color] /* wp.customize('rvx_general_reviews_active_rating_stars_background_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__star-active, .rvx-review-form__star-active', 'fill', newval); updateStyle('#rvx-storefront-widget .rvx-review-form__star-active-half-star, .rvx-review-form__star-active-half-star', 'stop-color', newval); updateStyle('#rvx-storefront-widget .rvx-aggregation__rating-icon, .rvx-aggregation__rating-icon', 'fill', newval); updateStyle('#rvx-storefront-widget .rvx-aggregation__rating-icon path, .rvx-aggregation__rating-icon path', 'fill', newval); }); }); */ /* * ReviewX - Reviews Overview */ // Rating out of wp.customize('rvx_reviews_overview_rating_out_of_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget p.rvx-rating-out-of, p.rvx-rating-out-of', 'color', newval); }); }); wp.customize('rvx_reviews_overview_rating_out_of_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget p.rvx-rating-out-of, p.rvx-rating-out-of', 'font-size', newval + 'px'); }); }); // Rating out of Total wp.customize('rvx_reviews_overview_rating_out_of_total_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget span.rvx-rating-total, span.rvx-rating-total', 'color', newval); }); }); wp.customize('rvx_reviews_overview_rating_out_of_total_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget span.rvx-rating-total, span.rvx-rating-total', 'font-size', newval + 'px'); }); }); // Rating Badge wp.customize('rvx_reviews_overview_rating_badge_background_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-rating-badge, .rvx-rating-badge', 'background-color', newval); }); }); wp.customize('rvx_reviews_overview_rating_badge_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-rating-badge span, .rvx-rating-badge span', 'color', newval); }); }); // Total Reviews Count wp.customize('rvx_reviews_overview_total_reviews_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget p.rvx-total-review, p.rvx-total-review', 'color', newval); }); }); wp.customize('rvx_reviews_overview_total_reviews_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget p.rvx-total-review, p.rvx-total-review', 'font-size', newval + 'px'); }); }); // Rating Overview Chart wp.customize('rvx_reviews_overview_rating_overview_chart_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget tr.rvx-aggregation__row td span, tr.rvx-aggregation__row td span', 'color', newval); }); }); wp.customize('rvx_reviews_overview_rating_overview_chart_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget tr.rvx-aggregation__row td span, tr.rvx-aggregation__row td span', 'font-size', newval + 'px'); }); }); // Product Recommendation Text wp.customize('rvx_reviews_overview_product_recommendation_background_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-recommendation-count, .rvx-recommendation-count', 'background-color', newval); }); }); wp.customize('rvx_reviews_overview_product_recommendation_border_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-recommendation-count, .rvx-recommendation-count', 'border', 'solid 1px ' + newval); }); }); wp.customize('rvx_reviews_overview_product_recommendation_border_radius', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-recommendation-count, .rvx-recommendation-count', 'border-radius', newval + 'px'); }); }); wp.customize('rvx_reviews_overview_product_recommendation_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-recommendation-count p, .rvx-recommendation-count p', 'color', newval); }); }); wp.customize('rvx_reviews_overview_product_recommendation_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-recommendation-count p, .rvx-recommendation-count p', 'font-size', newval + 'px'); }); }); // Product Recommendation Icon wp.customize('rvx_reviews_overview_product_recommendation_text_font_size', function(value) { value.bind(function(newval) { $('#rvx-storefront-widget .rvx-recommendation-count svg, .rvx-recommendation-count svg').attr('width', newval); }); }); wp.customize('rvx_reviews_overview_product_recommendation_text_font_size', function(value) { value.bind(function(newval) { $('#rvx-storefront-widget .rvx-recommendation-count svg, .rvx-recommendation-count svg').attr('height', newval); }); }); // Review Criteria Text wp.customize('rvx_reviews_overview_review_criteria_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-aggregation-multicriteria span, .rvx-aggregation-multicriteria span', 'color', newval); }); }); wp.customize('rvx_reviews_overview_review_criteria_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-aggregation-multicriteria span, .rvx-aggregation-multicriteria span', 'font-size', newval + 'px'); }); }); /* * ReviewX - Filter */ // Filter button wp.customize('rvx_filter_button_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter__button, .rvx-review-filter__button', 'color', newval); }); }); wp.customize('rvx_filter_button_background_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter__button, .rvx-review-filter__button', 'background-color', newval); }); }); wp.customize('rvx_filter_button_border_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter__button, .rvx-review-filter__button', 'border', 'solid 1px ' + newval); }); }); wp.customize('rvx_filter_button_border_radius', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter__button, .rvx-review-filter__button', 'border-radius', newval + 'px'); }); }); // Filter dropdown - Filter by wp.customize('rvx_filter_by_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper p.rvx-review-filter-wrapper__title, .rvx-review-filter-wrapper p.rvx-review-filter-wrapper__title', 'color', newval); }); }); wp.customize('rvx_filter_by_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper p.rvx-review-filter-wrapper__title, .rvx-review-filter-wrapper p.rvx-review-filter-wrapper__title', 'font-size', newval + 'px'); }); }); // Filter Dropdown menu wp.customize('rvx_filter_dropdown_menu_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper, .rvx-review-filter-wrapper', 'color', newval); }); }); wp.customize('rvx_filter_dropdown_menu_background_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper, .rvx-review-filter-wrapper', 'background-color', newval); }); }); wp.customize('rvx_filter_dropdown_menu_border_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper, .rvx-review-filter-wrapper', 'border', 'solid 1px ' + newval); }); }); wp.customize('rvx_filter_dropdown_menu_border_radius', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper, .rvx-review-filter-wrapper', 'border-radius', newval + 'px'); }); }); wp.customize('rvx_filter_dropdown_menu_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper, .rvx-review-filter-wrapper', 'font-size', newval + 'px'); }); }); // Filter Dropdown menu: [Rest filters] button wp.customize('rvx_filter_reset_button_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper__footer-reset-button, .rvx-review-filter-wrapper__footer-reset-button', 'color', newval); }); }); wp.customize('rvx_filter_reset_button_background_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper__footer-reset-button, .rvx-review-filter-wrapper__footer-reset-button', 'background-color', newval); }); }); wp.customize('rvx_filter_reset_button_border_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper__footer-reset-button, .rvx-review-filter-wrapper__footer-reset-button', 'border', 'solid 1px ' + newval); }); }); wp.customize('rvx_filter_reset_button_border_radius', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper__footer-reset-button, .rvx-review-filter-wrapper__footer-reset-button', 'border-radius', newval + 'px'); }); }); // Filter Dropdown menu: [Apply] button wp.customize('rvx_filter_apply_button_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper__footer-save-button, .rvx-review-filter-wrapper__footer-save-button', 'color', newval); }); }); wp.customize('rvx_filter_apply_button_background_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper__footer-save-button, .rvx-review-filter-wrapper__footer-save-button', 'background-color', newval); }); }); wp.customize('rvx_filter_apply_button_border_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper__footer-save-button, .rvx-review-filter-wrapper__footer-save-button', 'border', 'solid 1px ' + newval); }); }); wp.customize('rvx_filter_apply_button_border_radius', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-filter-wrapper__footer-save-button, .rvx-review-filter-wrapper__footer-save-button', 'border-radius', newval + 'px'); }); }); // Sort button wp.customize('rvx_sort_button_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-sort__button, .rvx-review-sort__button', 'color', newval); }); }); wp.customize('rvx_sort_button_background_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-sort__button, .rvx-review-sort__button', 'background-color', newval); }); }); wp.customize('rvx_sort_button_border_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-sort__button, .rvx-review-sort__button', 'border', 'solid 1px ' + newval); }); }); wp.customize('rvx_sort_button_border_radius', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-sort__button, .rvx-review-sort__button', 'border-radius', newval + 'px'); }); }); // Sort Dropdown menu wp.customize('rvx_sort_dropdown_menu_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-sort-wrapper__outer, .rvx-review-sort-wrapper__outer', 'color', newval); }); }); wp.customize('rvx_sort_dropdown_menu_background_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-sort-wrapper__outer, .rvx-review-sort-wrapper__outer', 'background-color', newval); }); }); wp.customize('rvx_sort_dropdown_menu_border_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-sort-wrapper__outer, .rvx-review-sort-wrapper__outer', 'border', 'solid 1px ' + newval); }); }); wp.customize('rvx_sort_dropdown_menu_border_radius', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-sort-wrapper__outer, .rvx-review-sort-wrapper__outer', 'border-radius', newval + 'px'); }); }); wp.customize('rvx_sort_dropdown_menu_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-sort-wrapper__outer, .rvx-review-sort-wrapper__outer', 'font-size', newval + 'px'); }); }); // Write a Review button wp.customize('rvx_write_review_button_border_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-write__button, .rvx-review-write__button', 'border', 'solid 1px ' + newval); }); }); wp.customize('rvx_write_review_button_border_radius', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-write__button, .rvx-review-write__button', 'border-radius', newval + 'px'); }); }); /* * ReviewX - Review Items */ // Review Items: Card [Background Color] wp.customize('rvx_reviews_items_card_background_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card, .rvx-review-wrapper .rvx-review-card', 'background-color', newval); }); }); // Review Items: Card [Border Color] wp.customize('rvx_reviews_items_card_border_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card, .rvx-review-wrapper .rvx-review-card', 'border', 'solid 1px ' + newval); }); }); // Review Items: Card [Border Radius] wp.customize('rvx_reviews_items_card_border_radius', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card, .rvx-review-wrapper .rvx-review-card', 'border-radius', newval + 'px'); }); }); // Review Items: Card [Padding] wp.customize('rvx_reviews_items_card_inline_padding', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card, .rvx-review-wrapper .rvx-review-card', 'padding', newval + 'px'); }); }); // Review Items: Reviewer Name wp.customize('rvx_reviews_items_reviewer_name_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card .rvx-review-user__name, .rvx-review-wrapper .rvx-review-card .rvx-review-user__name', 'color', newval); }); }); wp.customize('rvx_reviews_items_reviewer_name_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card .rvx-review-user__name, .rvx-review-wrapper .rvx-review-card .rvx-review-user__name', 'font-size', newval + 'px'); }); }); // Review Items: Review Title wp.customize('rvx_reviews_items_title_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card .rvx-review-info__title, .rvx-review-wrapper .rvx-review-card .rvx-review-info__title', 'color', newval); }); }); wp.customize('rvx_reviews_items_title_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card .rvx-review-info__title, .rvx-review-wrapper .rvx-review-card .rvx-review-info__title', 'font-size', newval + 'px'); }); }); // Review Items: Review Date wp.customize('rvx_reviews_items_date_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card .rvx-review-info__date, .rvx-review-wrapper .rvx-review-card .rvx-review-info__date', 'color', newval); }); }); wp.customize('rvx_reviews_items_date_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card .rvx-review-info__date, .rvx-review-wrapper .rvx-review-card .rvx-review-info__date', 'font-size', newval + 'px'); }); }); // Review Items: Description wp.customize('rvx_reviews_items_description_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card .rvx-review-info__feedback, .rvx-review-wrapper .rvx-review-card .rvx-review-info__feedback', 'color', newval); }); }); wp.customize('rvx_reviews_items_description_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card .rvx-review-info__feedback, .rvx-review-wrapper .rvx-review-card .rvx-review-info__feedback', 'font-size', newval + 'px'); }); }); /* * ReviewX - Review Form */ // Form: Background Color wp.customize('rvx_input_form_background_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget #rvx-review-form__wrapper, #rvx-review-form__wrapper', 'background-color', newval); }); }); // Form: Border Color wp.customize('rvx_input_form_border_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget #rvx-review-form__wrapper, #rvx-review-form__wrapper', 'border', 'solid 1px ' + newval); }); }); // Form: Border Radius wp.customize('rvx_input_form_border_radius', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget #rvx-review-form__wrapper, #rvx-review-form__wrapper', 'border-radius', newval + 'px'); }); }); // Form: Title wp.customize('rvx_input_form_title_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__title, .rvx-review-form__title', 'color', newval); }); }); wp.customize('rvx_input_form_title_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__title, .rvx-review-form__title', 'font-size', newval + 'px'); }); }); // Form: Product Name wp.customize('rvx_input_form_product_name_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__product--title, .rvx-review-form__product--title', 'color', newval); }); }); wp.customize('rvx_input_form_product_name_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__product--title, .rvx-review-form__product--title', 'font-size', newval + 'px'); }); }); // Form: Criteria Title wp.customize('rvx_input_form_criteria_title_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__multicriteria--name, .rvx-review-form__multicriteria--name', 'color', newval); }); }); wp.customize('rvx_input_form_criteria_title_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__multicriteria--name, .rvx-review-form__multicriteria--name', 'font-size', newval + 'px'); }); }); // Form: Review Title wp.customize('rvx_input_form_review_title_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__title--name, .rvx-review-form__title--name', 'color', newval); }); }); wp.customize('rvx_input_form_review_title_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__title--name, .rvx-review-form__title--name', 'font-size', newval + 'px'); }); }); // Form: Description Title wp.customize('rvx_input_form_description_title_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__description--title, .rvx-review-form__description--title', 'color', newval); }); }); wp.customize('rvx_input_form_description_title_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__description--title, .rvx-review-form__description--title', 'font-size', newval + 'px'); }); }); // Form: Full Name wp.customize('rvx_input_form_full_name_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__user--name, .rvx-review-form__user--name', 'color', newval); }); }); wp.customize('rvx_input_form_full_name_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__user--name, .rvx-review-form__user--name', 'font-size', newval + 'px'); }); }); // Form: Email Address wp.customize('rvx_input_form_email_address_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__email--name, .rvx-review-form__email--name', 'color', newval); }); }); wp.customize('rvx_input_form_email_address_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__email--name, .rvx-review-form__email--name', 'font-size', newval + 'px'); }); }); // Form: Attachment Title wp.customize('rvx_input_form_attachment_title_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__attachment--name, .rvx-review-form__attachment--name', 'color', newval); }); }); wp.customize('rvx_input_form_attachment_title_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__attachment--name, .rvx-review-form__attachment--name', 'font-size', newval + 'px'); }); }); // Form: Mark as Anonymous wp.customize('rvx_input_form_mark_anonymous_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__mark-anonymous, .rvx-review-form__mark-anonymous', 'color', newval); }); }); wp.customize('rvx_input_form_mark_anonymous_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__mark-anonymous, .rvx-review-form__mark-anonymous', 'font-size', newval + 'px'); }); }); // Form: Recommended? wp.customize('rvx_input_form_recommended_text_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__recommended--name, .rvx-review-form__recommended--name', 'color', newval); }); }); wp.customize('rvx_input_form_recommended_text_font_size', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__recommended--name, .rvx-review-form__recommended--name', 'font-size', newval + 'px'); }); }); // Form: Submit Review Button wp.customize('rvx_submit_review_button_border_color', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__submit--button, .rvx-review-form__submit--button', 'border', 'solid 1px ' + newval); }); }); wp.customize('rvx_submit_review_button_border_radius', function(value) { value.bind(function(newval) { updateStyle('#rvx-storefront-widget .rvx-review-form__submit--button, .rvx-review-form__submit--button', 'border-radius', newval + 'px'); }); }); })(jQuery); Enum/ReviewStatusEnum.php 0000777 00000000532 15251220643 0011462 0 ustar 00 <?php namespace Rvx\Enum; class ReviewStatusEnum { const APPROVED = 1; const UNPUBLISHED = 2; const TRASH = 3; const PENDING = 4; const SPAM = 5; const ANY = 6; const ARCHIVE = 7; public static function getStatuses() : array { return [self::APPROVED, self::PENDING, self::TRASH, self::SPAM]; } } Enum/OrderStatusEnum.php 0000777 00000001033 15251220643 0011271 0 ustar 00 <?php namespace Rvx\Enum; class OrderStatusEnum { const PROCESSING = 'processing'; const PENDING_PAYMENT = 'pending_payment'; const ON_HOLD = 'on_hold'; const COMPLETED = 'completed'; const CANCELLED = 'cancelled'; const REFUNDED = 'refunded'; const FAILED = 'failed'; const DRAFT = 'draft'; public static function getStatuses() : array { return [self::PROCESSING, self::PENDING_PAYMENT, self::ON_HOLD, self::COMPLETED, self::CANCELLED, self::REFUNDED, self::FAILED, self::DRAFT]; } } Shortcodes/Products/ReviewListFormShortcode.php 0000777 00000013157 15251220643 0016007 0 ustar 00 <?php namespace Rvx\Shortcodes\Products; use Rvx\Utilities\Helper; use Rvx\Form\ReviewFormHelper; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Contracts\ShortcodeContract; use Rvx\WPDrill\Facades\View; class ReviewListFormShortcode implements ShortcodeContract { protected ReviewFormHelper $reviewFormHelper; public function render(array $attrs, ?string $content = null) : string { $attrs = shortcode_atts(['title' => null, 'post_id' => null, 'product_id' => null, 'graph' => 'off', 'filter' => 'off', 'list' => 'off', 'form' => 'on', 'designer_id' => null], $attrs); // Validate attributes (early exit on errors) if ($error = $this->validateAttributes($attrs)) { return $error; } $this->reviewFormHelper = new ReviewFormHelper(); $data = $this->attributesData($attrs); if (!$data['postTypeEnabled']) { return $this->error('This post type isn\'t enabled in ReviewX.'); } if (empty($data['product'])) { return $this->error('Unable to determine the `post type` and `id`. Please provide one parameter `post_id` or `product_id`.'); } $attributes = $this->sanitizeAttributes($attrs); $title = $this->resolveTitle($attrs['title'], $data['product']['postTitle']); $formData = $this->reviewFormHelper->builderCustomizedFormTextsData(); return View::render('storefront/shortcode/reviewListForm', ['title' => $title, 'data' => wp_json_encode($data), 'attributes' => $attributes, 'formLevelData' => $formData, 'wooVerificationRequired' => 'yes' === \get_option('woocommerce_review_rating_verification_required'), 'isVerifiedCustomer' => $data['userInfo']['isVerified'], 'requireSignIn' => (bool) \get_option('comment_registration'), 'user_is_logged_in' => $data['userInfo']['isLoggedIn'], 'login_url' => wp_login_url(esc_url(add_query_arg([], wp_unslash($_SERVER['REQUEST_URI'])))), 'register_url' => wp_registration_url(), 'registration_enabled' => (bool) \get_option('users_can_register')]); } private function error(string $message) : string { return '<div class="warning notice notice-error"><b>Error:</b> ' . esc_html($message) . '</div>'; } private function validateAttributes(array $attrs) : ?string { if (!Client::getSync()) { return $this->error('Please complete the synchronization process of ReviewX.'); } if ($attrs['graph'] === 'off' && $attrs['list'] === 'off' && $attrs['form'] === 'off') { return $this->error('Please provide one parameter (graph, list, form) value as `on` in the shortcode.'); } if (!empty($attrs['post_id']) && !empty($attrs['product_id'])) { return $this->error('Please provide either `post_id` or `product_id`. Both are not supported.'); } return null; } private function sanitizeAttributes(array $attrs) : array { $attributes = []; foreach (['graph', 'filter', 'list', 'form'] as $toggle) { $attributes[$toggle] = !empty($attrs[$toggle]) ? esc_attr($attrs[$toggle]) : 'off'; } $attributes['designer_id'] = $attrs['designer_id'] ? esc_attr($attrs['designer_id']) : null; return $attributes; } private function resolveTitle(?string $attrTitle, string $postTitle) : string { if ($attrTitle === 'false') { return 'false'; } if ($attrTitle === 'true' || empty($attrTitle)) { return $postTitle; } return esc_html($attrTitle); } private function attributesData(array $attrs) : array { global $post; $type = []; // Case 1: If shortcode explicitly provides post_id or product_id if (!empty($attrs['post_id']) || !empty($attrs['product_id'])) { $id = !empty($attrs['post_id']) ? (int) $attrs['post_id'] : (int) $attrs['product_id']; $postObj = get_post($id); $type = ['id' => $id, 'postType' => $postObj ? \strtolower($postObj->post_type) : 'rvx_no_post_type', 'postTitle' => $postObj ? esc_html(get_the_title($postObj)) : '']; } // Case 2: If no ID provided, use current singular post if (is_singular() && empty($attrs['post_id']) && empty($attrs['product_id'])) { $type = ['id' => $post ? (int) $post->ID : 0, 'postType' => $post && $post->post_type ? \strtolower($post->post_type) : 'rvx_no_post_type', 'postTitle' => $post && $post->post_title ? esc_html($post->post_title) : '']; } // Validate if post type is enabled in ReviewX $enabledPostTypes = $this->reviewFormHelper->rvxEnabledPostTypes(); $currentPostType = $type['postType'] ?? null; $postTypeEnabled = isset($currentPostType, $enabledPostTypes[$currentPostType]) && \strtolower($enabledPostTypes[$currentPostType]) === $currentPostType; // User info $userId = get_current_user_id(); $wpCurrentUser = Helper::getWpCurrentUser(); $isVerifiedCustomer = 0; if (\class_exists('WooCommerce') && is_singular('product') && 'product' === get_post_type()) { $isVerifiedCustomer = Helper::verifiedCustomer($userId); } return ['postTypeEnabled' => $postTypeEnabled, 'product' => $type, 'userInfo' => ['isLoggedIn' => Helper::loggedIn(), 'id' => $wpCurrentUser ? (int) $wpCurrentUser->ID : 0, 'name' => $wpCurrentUser && $wpCurrentUser->display_name ? $wpCurrentUser->display_name : '', 'email' => $wpCurrentUser && $wpCurrentUser->user_email ? $wpCurrentUser->user_email : '', 'isVerified' => $isVerifiedCustomer], 'domain' => ['baseDomain' => Helper::domainSupport(), 'baseRestUrl' => Helper::getRestAPIurl()]]; } } Shortcodes/Products/ReviewShowWIthIdsShortcode.php 0000777 00000003345 15251220643 0016422 0 ustar 00 <?php namespace Rvx\Shortcodes\Products; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Rvx\WPDrill\Contracts\ShortcodeContract; use Rvx\WPDrill\Facades\View; class ReviewShowWIthIdsShortcode implements ShortcodeContract { public function render(array $attrs, ?string $content = null) : string { $attrs = shortcode_atts(['title' => 'false', 'review_ids' => null], $attrs); // Check if both product_id and post_id are provided. if (!Client::getSync()) { return '<div class="warning">Error: Please complete the synchronization process of ReviewX.</div>'; } // If review_ids is not provided, return an error. if (empty($attrs['review_ids'])) { return '<div class="warning">Error: Please provide "review_ids" in the shortcode.</div>'; } $reviewsIds = $attrs['review_ids']; $productIdArray = []; // If review_ids is not null, process it if ($reviewsIds) { // Split review_ids by commas and trim whitespace $productIdArray = \array_map('trim', \explode(',', $reviewsIds)); // Send multiple product IDs to the JavaScript variable $data = $this->reviewsWiseReviewShow($productIdArray); // Return the view (empty or simplified, as no review data is required) return View::render('storefront/shortcode/reviewShowWIthIds', ['title' => $attrs['title'], 'data' => \json_encode($data)]); } return ''; } public function reviewsWiseReviewShow($reviewsIds) : array { $attributes = ['ids' => $reviewsIds, 'domain' => ['baseDomain' => Helper::domainSupport(), 'baseRestUrl' => Helper::getRestAPIurl()]]; return $attributes; } } Shortcodes/Products/ReviewGraphShortcode.php 0000777 00000003657 15251220643 0015315 0 ustar 00 <?php namespace Rvx\Shortcodes\Products; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Rvx\WPDrill\Contracts\ShortcodeContract; use Rvx\WPDrill\Facades\View; class ReviewGraphShortcode implements ShortcodeContract { public function render(array $attrs, ?string $content = null) : string { $attrs = shortcode_atts(['title' => null, 'product_id' => null, 'post_id' => null], $attrs); // Check if both product_id and post_id are provided. if (!Client::getSync()) { return '<div class="warning">Error: Please complete the synchronization process of ReviewX.</div>'; } // Check if both product_id and post_id are provided. if (!empty($attrs['product_id']) && !empty($attrs['post_id'])) { return '<div class="warning">Error: Please use only one of "product_id" or "post_id" in the shortcode.</div>'; } // Determine whether we're dealing with a product or a post. $isProduct = !empty($attrs['product_id']); $id = $isProduct ? (int) $attrs['product_id'] : (int) $attrs['post_id']; $data = $this->productWiseReviewShow($id, $isProduct); // Title handling if ($attrs['title'] === 'false') { $title = 'false'; } elseif ($attrs['title'] === 'true' || empty($attrs['title'])) { $title = $data['postTitle']; } else { $title = esc_html($attrs['title']); } return View::render('storefront/shortcode/reviewGraph', ['title' => $title, 'data' => \json_encode($data)]); } public function productWiseReviewShow($id, bool $isProduct) : array { $post = get_post($id); $attributes = ['product' => ['id' => $id], 'postTitle' => $post ? $post->post_title : \false, 'postType' => $post ? $post->post_type : '', 'domain' => ['baseDomain' => Helper::domainSupport(), 'baseRestUrl' => Helper::getRestAPIurl()]]; return $attributes; } } Shortcodes/Products/ReviewSummaryShortcode.php 0000777 00000004253 15251220643 0015702 0 ustar 00 <?php namespace Rvx\Shortcodes\Products; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Rvx\WPDrill\Contracts\ShortcodeContract; use Rvx\WPDrill\Facades\View; class ReviewSummaryShortcode implements ShortcodeContract { public function render(array $attrs, ?string $content = null) : string { // Define default attributes to accept both product_id and post_id. $attrs = shortcode_atts(['title' => null, 'product_id' => null, 'post_id' => null], $attrs); // Check if both product_id and post_id are provided. if (!Client::getSync()) { return '<div class="warning">Error: Please complete the synchronization process of ReviewX.</div>'; } // If both IDs are provided, return an error. if (!empty($attrs['product_id']) && !empty($attrs['post_id'])) { return '<div class="warning">Error: Please use only one of "product_id" or "post_id" in the shortcode.</div>'; } // Determine the type and set the ID. $isProduct = !empty($attrs['product_id']); $id = $isProduct ? (int) $attrs['product_id'] : (int) $attrs['post_id']; // Prepare the data. $data = $this->productWiseReviewShow($id, $isProduct); // Title handling if ($attrs['title'] === 'false') { $title = 'false'; } elseif ($attrs['title'] === 'true' || empty($attrs['title'])) { $title = $data['postTitle']; } else { $title = esc_html($attrs['title']); } return View::render('storefront/shortcode/reviewSummary', ['title' => $title, 'data' => \json_encode($data)]); } /** * Build the data structure for the review summary. * * @param int $id * @param bool $isProduct * @return string JSON encoded attributes. */ public function productWiseReviewShow($id, $isProduct) : array { $post = get_post($id); $attributes = ['product' => ['id' => $id], 'postTitle' => $post ? $post->post_title : \false, 'postType' => $post ? $post->post_type : '', 'domain' => ['baseDomain' => Helper::domainSupport(), 'baseRestUrl' => Helper::getRestAPIurl()]]; return $attributes; } } Shortcodes/Products/WooReviewsFormShortcode.php 0000777 00000003241 15251220643 0016014 0 ustar 00 <?php namespace Rvx\Shortcodes\Products; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Contracts\ShortcodeContract; class WooReviewsFormShortcode implements ShortcodeContract { public function render(array $attrs, ?string $content = null) : string { $attrs = shortcode_atts(['title' => null, 'post_id' => null, 'product_id' => null, 'graph' => 'on', 'filter' => 'on', 'list' => 'on', 'form' => 'on'], $attrs); // Check if both product_id and post_id are provided. if (!Client::getSync()) { return '<div class="warning">Error: Please complete the synchronization process of ReviewX.</div>'; } if ($attrs['graph'] == 'off' && $attrs['list'] == 'off' && $attrs['form'] == 'off') { return '<div class="warning notice notice-error"><b>Error:</b> Please provide one parameter (graph, list, form) value as `on` in the shortcode.</div>'; } if (!empty($attrs['post_id']) && !empty($attrs['product_id'])) { return '<div class="warning notice notice-error"><b>Error:</b> Please provide one parameter `post_id` or `product_id`. Both in the same shortcode isn\'t supported.</div>'; } $title = esc_attr($attrs['title']) ?: 'false'; $type_name = !empty($attrs['product_id']) ? ' product_id="' . esc_attr($attrs['product_id']) . '"' : (!empty($attrs['post_id']) ? ' post_id="' . esc_attr($attrs['post_id']) . '"' : ''); return do_shortcode('[rvx-review-form title="' . $title . '" filter="' . esc_attr($attrs['filter']) . '" ' . $type_name . ' graph="' . esc_attr($attrs['graph']) . '" list="' . esc_attr($attrs['list']) . '" form="' . esc_attr($attrs['form']) . '"]'); } } Shortcodes/Products/ReviewStatshortcode.php 0000777 00000004624 15251220643 0015222 0 ustar 00 <?php namespace Rvx\Shortcodes\Products; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Rvx\WPDrill\Contracts\ShortcodeContract; use Rvx\WPDrill\Facades\View; class ReviewStatshortcode implements ShortcodeContract { public function render(array $attrs, ?string $content = null) : string { // Set default attributes to include both product_id and post_id. $attrs = shortcode_atts(['title' => null, 'product_id' => null, 'post_id' => null], $attrs); // Check if both product_id and post_id are provided. if (!Client::getSync()) { return '<div class="warning">Error: Please complete the synchronization process of ReviewX.</div>'; } // If both product_id and post_id are provided, return an error. if (!empty($attrs['product_id']) && !empty($attrs['post_id'])) { return '<div class="warning">Error: Please use only one of "product_id" or "post_id" in the shortcode.</div>'; } // Determine whether this is for a product or a post. $isProduct = !empty($attrs['product_id']); $id = $isProduct ? (int) $attrs['product_id'] : (int) $attrs['post_id']; // Retrieve data related to review stats. $data = $this->getReviewStatsData($id, $isProduct); // Title handling if ($attrs['title'] === 'false') { $title = 'false'; } elseif ($attrs['title'] === 'true' || empty($attrs['title'])) { $title = $data['postTitle']; } else { $title = esc_html($attrs['title']); } // If no title is provided, use the post title from the data. return View::render('storefront/shortcode/reviewStats', ['title' => $title, 'postType' => !empty($data['postType']) ? $data['postType'] : '', 'data' => \json_encode($data)]); } /** * Retrieve review stats data based on an ID and its type (product or post). * * @param int $id * @param bool $isProduct * * @return array */ public function getReviewStatsData(int $id, bool $isProduct) : array { // Retrieve the post object. $post = get_post($id); $defaultData = ['product' => ['id' => $id], 'postTitle' => $post ? $post->post_title : \false, 'postType' => $post ? $post->post_type : '', 'domain' => ['baseDomain' => Helper::domainSupport(), 'baseRestUrl' => Helper::getRestAPIurl()]]; return $defaultData; } } Shortcodes/Products/ReviewListShortcode.php 0000777 00000007447 15251220643 0015170 0 ustar 00 <?php namespace Rvx\Shortcodes\Products; use Rvx\WPDrill\Contracts\ShortcodeContract; use Rvx\Utilities\Helper; use Rvx\Form\ReviewFormHelper; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Facades\View; class ReviewListShortcode implements ShortcodeContract { protected $reviewFormHelper; public function render(array $attrs, ?string $content = null) : string { $attrs = shortcode_atts(['title' => null, 'post_type' => null, 'post_id' => null, 'product_id' => null, 'sort_by' => null, 'attachment' => null, 'rating' => null, 'filter' => 'on'], $attrs); // Check if both product_id and post_id are provided. if (!Client::getSync()) { return '<div class="warning">Error: Please complete the synchronization process of ReviewX.</div>'; } // If both product_id and post_id are provided, return an error. if (!empty($attrs['product_id']) && !empty($attrs['post_id'])) { return '<div class="warning notice notice-error"><b>Error:</b> Please use only one of `product_id` or `post_id` in the shortcode.</div>'; } // If post_type provided with product_id and/or post_id, return an error if (!empty($attrs['post_type']) && (!empty($attrs['product_id']) || !empty($attrs['post_id']))) { return '<div class="warning notice notice-error"><b>Error:</b> Post type can\'t be used with `product_id` and/or `post_id` in the shortcode.</div>'; } if (!empty($attrs['product_id']) || !empty($attrs['post_id'])) { $title = esc_attr($attrs['title']) ?: 'true'; $type_name_id = !empty($attrs['product_id']) ? ' product_id="' . esc_attr($attrs['product_id']) . '"' : (!empty($attrs['post_id']) ? ' post_id="' . esc_attr($attrs['post_id']) . '"' : ''); return do_shortcode('[rvx-review-form title="' . $title . '" filter="' . esc_attr($attrs['filter']) . '" ' . $type_name_id . ' graph="off" list="on" form="off"]'); } if (!empty($attrs['post_type']) || empty($attrs['product_id']) && empty($attrs['post_id'])) { $this->reviewFormHelper = new ReviewFormHelper(); $data = $this->attributesData($attrs); if ($data['post_type_enabled'] == \false && !empty(esc_attr($attrs['post_type']))) { return '<div class="warning notice notice-error"><b>Error:</b> This post type isn\'t enabled in ReviewX.</div>'; } $title = !isset($attrs['title']) || $attrs['title'] === 'false' ? 'false' : esc_html($attrs['title']); return View::render('storefront/shortcode/reviewList', ['title' => $title, 'data' => $data]); } return '<div class="warning notice notice-error"><b>Error:</b> Please, make sure you have provided necessary parameter\'(s) in the shortcode. Please, follow documentation.</div>'; } public function attributesData(array $attrs) : array { $postTypeEnable = 0; $postType = null; if (!empty($attrs['post_type'])) { $enabled_post_types = $this->reviewFormHelper->rvxEnabledPostTypes(); $currentPostType = esc_attr($attrs['post_type']) ?: 'rvx_no_post_type'; $postType = esc_attr($attrs['post_type']) ?: null; if (isset($enabled_post_types[$currentPostType]) && \strtolower($enabled_post_types[$currentPostType]) == $currentPostType) { $postTypeEnable = 1; } } $attributes = ['post_type_enabled' => $postTypeEnable, 'filter' => esc_attr($attrs['filter']) ?: 'off', 'params' => ['post_type' => $postType, 'sort_by' => esc_attr($attrs['sort_by']) ?: '', 'attachment' => esc_attr($attrs['attachment']) ?: '', 'rating' => esc_attr($attrs['rating']) ?: ''], 'domain' => ['baseDomain' => Helper::domainSupport(), 'baseRestUrl' => Helper::getRestAPIurl()]]; return $attributes; } } Shortcodes/Products/ReviewStarCountShortcode.php 0000777 00000007075 15251220643 0016174 0 ustar 00 <?php namespace Rvx\Shortcodes\Products; use Rvx\Form\ReviewFormHelper; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Rvx\WPDrill\Contracts\ShortcodeContract; use Rvx\WPDrill\Facades\View; class ReviewStarCountShortcode implements ShortcodeContract { public function render(array $attrs, ?string $content = null) : string { $attrs = shortcode_atts(['title' => 'false', 'product_id' => null, 'post_id' => null, 'info' => 'default'], $attrs); // Ensure ReviewX sync is complete if (!Client::getSync()) { return '<div class="warning">Error: Please complete the synchronization process of ReviewX.</div>'; } $productId = !empty($attrs['product_id']) ? (int) $attrs['product_id'] : 0; $postId = !empty($attrs['post_id']) ? (int) $attrs['post_id'] : 0; // Prevent both IDs at once if ($productId && $postId) { return '<div class="warning">Error: Please use only one of "product_id" or "post_id" in the shortcode.</div>'; } // Determine the final ID to use $id = $productId ?: $postId; // Auto-detect from global post if neither ID provided if (!$productId && !$postId) { global $post; } else { $post = get_post($id); } if (!$post) { return '<div class="warning">No post or product found!</div>'; } $data = $this->getReviewsData($post); if (!$data['post_type_enabled']) { return '<div class="warning notice notice-error"><b>Error:</b> This post type isn\'t enabled in ReviewX.</div>'; } // Title handling if ($attrs['title'] === 'false') { $title = 'false'; } elseif ($attrs['title'] === 'true' || empty($attrs['title'])) { $title = $data['postTitle']; } else { $title = esc_html($attrs['title']); } return View::render('storefront/shortcode/reviewsStarCount', ['title' => $title, 'data' => $data, 'info' => $attrs['info'] ?: 'default', 'postType' => $data['postType']]); } private function getReviewsData($post) : array { $id = $post->ID ?? 0; // Check enabled post types even if $post is null $enabledPostTypes = (new ReviewFormHelper())->rvxEnabledPostTypes(); $postTypeEnabled = 0; if ($post) { $postTypeEnabled = isset($enabledPostTypes[\strtolower($post->post_type)]) ? 1 : 0; } // Default data $defaultData = ['product' => ['id' => $id, 'post' => $id], 'starCount' => 0.0, 'reviewsCount' => 0, 'post_type_enabled' => $postTypeEnabled, 'postTitle' => $post->post_title ?? '', 'postType' => $post->post_type ?? '', 'domain' => ['baseDomain' => Helper::domainSupport(), 'baseRestUrl' => Helper::getRestAPIurl()]]; if (!$post) { return $defaultData; } // Get actual star/review counts if ($post->post_type === 'product') { $defaultData['starCount'] = (float) \get_post_meta($id, '_wc_average_rating', \true); $defaultData['reviewsCount'] = (int) \get_post_meta($id, '_wc_review_count', \true); } else { $defaultData['starCount'] = (float) \get_post_meta($id, 'rvx_avg_rating', \true); $defaultData['reviewsCount'] = (int) \get_post_meta($id, 'rvx_total_reviews', \true); // Fallback to comment_count if meta is not set yet if (!$defaultData['reviewsCount']) { $defaultData['reviewsCount'] = (int) $post->comment_count; } } return $defaultData; } } Shortcodes/GoogleReviewLIst.php 0000777 00000006456 15251220643 0012606 0 ustar 00 <?php namespace Rvx\Shortcodes; use Rvx\Api\GoogleReviewApi; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Contracts\ShortcodeContract; use Rvx\WPDrill\Facades\View; use Rvx\Services\GoogleReviewService; class GoogleReviewLIst implements ShortcodeContract { protected $googleReview; protected $googleReviewService; public function __construct() { $this->googleReview = new GoogleReviewApi(); $this->googleReviewService = new GoogleReviewService(); } public function render(array $attrs, ?string $content = null) : string { $attrs = shortcode_atts(['title' => null, 'id' => null, 'truncate' => '300', 'limit' => '3', 'loadmore' => 'false', 'cache' => null], $attrs); // Check if both product_id and post_id are provided. if (!Client::getSync()) { return '<div class="warning">Error: Please complete the synchronization process of ReviewX.</div>'; } // Fetch cached/validated API credentials $credentials = $this->getGoogleApiCredentials(); // Bail out early if invalid if (empty($credentials['google_api_key']) || empty($credentials['google_place_id_or_url'])) { return '<div class="warning">Error: Please configure your Google API Key and Place ID/URL in ReviewX.</div>'; } // Fetch reviews $reviews = $this->reviews($attrs['cache'], $credentials); $title = isset($attrs['title']) && $attrs['title'] === 'false' ? 'false' : ($attrs['title'] === 'true' || empty($attrs['title']) ? 'Google Reviews' : esc_html($attrs['title'])); return View::render('storefront/shortcode/googleReviewList', ['title' => $title, 'content' => $reviews, 'reviewLimit' => (int) $attrs['limit'] ?: 3, 'loadMore' => !empty($attrs['loadmore']) ? $attrs['loadmore'] : \true, 'truncateLimit' => !empty($attrs['truncate']) ? $attrs['truncate'] : 300]); } protected function reviews($cache_time, array $credentials) { $place_id = $credentials['google_place_id_or_url']; $cache_key = 'rvx_google_reviews_cache_' . \md5($place_id); $cached_reviews = \get_transient($cache_key); if ($cached_reviews !== \false) { return $cached_reviews; } $reviews = $this->googleReview->googleReviewGet(); $reviews = \json_decode($reviews, \true); $cache_duration = (int) $cache_time ?: DAY_IN_SECONDS; \set_transient($cache_key, $reviews['data'], $cache_duration); if (empty($reviews['data']['reviews'])) { return []; } return $reviews['data']; } /** * Get and cache Google API credentials for 1 hour. * * @return array */ protected function getGoogleApiCredentials() : array { $cached = \get_transient('rvx_google_api_settings'); if ($cached !== \false) { return $cached; } // Already returns array $response = $this->googleReviewService->googleReviewPlaceApi(); $response = \json_decode($response, \true); $response = $response['data']['creadential']['google_place']; \set_transient('rvx_google_api_settings', $response, HOUR_IN_SECONDS); if (empty($response['google_api_key']) || empty($response['google_place_id_or_url'])) { return []; } return $response; } } Form/ReviewForm.php 0000777 00000003465 15251220643 0010264 0 ustar 00 <?php namespace Rvx\Form; use Rvx\CPT\CptHelper; use Rvx\Utilities\Auth\Client; class ReviewForm { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } public static function post_type_support() { if (Client::getSync()) { // Retrieve settings $enabled_post_types = (new self())->cptHelper->enabledCPT(); // Dynamically add comment support for enabled post types foreach ($enabled_post_types as $post_type) { if (post_type_exists($post_type)) { add_post_type_support($post_type, 'comments'); } } } } public static function comments_template_init($default) { if (Client::getSync()) { // Retrieve settings $enabled_post_types = (new self())->cptHelper->enabledCPT(); // Check if the current post type is enabled if (is_singular($enabled_post_types)) { // Exclude WooCommerce account page if (\class_exists('WooCommerce') && is_account_page()) { // Do nothing on WooCommerce front-end user dashboard } else { // Invoke custom handler if (\class_exists('Rvx\\Handlers\\CommentBoxHandle')) { (new \Rvx\Handlers\CommentBoxHandle())->__invoke(); } // Load custom template if it exists $custom_template = \dirname(__FILE__) . '/widget.php'; if (\file_exists($custom_template)) { return $custom_template; } } } // Fallback to default template return $default; } } } Form/widget.php 0000777 00000000010 15251220643 0007441 0 ustar 00 <?php Form/ReviewFormHelper.php 0000777 00000005407 15251220643 0011422 0 ustar 00 <?php namespace Rvx\Form; use Rvx\CPT\CptHelper; class ReviewFormHelper { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } public function builderCustomizedFormTextsData() { // Helper function to extract specific Builder data $builder_status_data = $this->builderStatusData(); switch ($builder_status_data['builder_name']) { case 'elementor': global $builderElementorSetting; return !empty($builderElementorSetting) ? \json_encode($builderElementorSetting, \JSON_UNESCAPED_UNICODE) : $this->rvxDefaultReviewFormLevelData(); default: return $this->rvxDefaultReviewFormLevelData(); } } private function rvxDefaultReviewFormLevelData() { // Define the default values, if no builder is active / available then use the default string / texts $default_values = ['write_a_review' => __('Write a Review', 'reviewx'), 'text_rating_star_title' => __('Rating', 'reviewx'), 'text_review_title' => __('Review Title', 'reviewx'), 'placeholder_review_title' => __('Write Review Title', 'reviewx'), 'text_review_description' => __('Description', 'reviewx'), 'placeholder_review_description' => __('Write your description here', 'reviewx'), 'text_full_name' => __('Full name', 'reviewx'), 'placeholder_full_name' => __('Full Name', 'reviewx'), 'text_email_name' => __('Email address', 'reviewx'), 'placeholder_email_name' => __('Email Address', 'reviewx'), 'text_attachment_title' => __('Attachment', 'reviewx'), 'placeholder_upload_photo' => __('Upload Photo / Video', 'reviewx'), 'text_mark_as_anonymous' => __('Mark as Anonymous', 'reviewx'), 'text_recommended_title' => __('Recommendation?', 'reviewx')]; return \json_encode($default_values, \JSON_UNESCAPED_UNICODE); } /* * Check is builder active or not * Based on that return true or false */ public function builderStatusData() : array { $builder_status = \false; $builder_name = 'none'; // Elementor if (did_action('elementor/loaded')) { $builder_status = \true; $builder_name = 'elementor'; } return ['builder_status' => $builder_status, 'builder_name' => $builder_name]; } public function commentBoxDefaultStyleForCustomPostType() : void { $enabled_post_types = $this->cptHelper->enabledCPT(); if (!is_singular($enabled_post_types)) { ?> <style> #rvx-storefront-widget { display: none; } </style> <?php } } public function rvxEnabledPostTypes() : array { return $this->cptHelper->enabledCPT(); } } Models/User.php 0000777 00000000200 15251220643 0007415 0 ustar 00 <?php namespace Rvx\Models; use Rvx\WPDrill\Models\Model; class User extends Model { protected static $table = 'users'; } Models/Category.php 0000777 00000000204 15251220643 0010260 0 ustar 00 <?php namespace Rvx\Models; use Rvx\WPDrill\Models\Model; class Category extends Model { protected static $table = 'terms'; } Models/Site.php 0000777 00000000204 15251220643 0007407 0 ustar 00 <?php namespace Rvx\Models; use Rvx\WPDrill\Models\Model; class Site extends Model { protected static $table = 'rvx_sites'; } Models/Post.php 0000777 00000000200 15251220643 0007424 0 ustar 00 <?php namespace Rvx\Models; use Rvx\WPDrill\Models\Model; class Post extends Model { protected static $table = 'posts'; } CPT/CommentsRatingColumn.php 0000777 00000011632 15251220643 0012025 0 ustar 00 <?php namespace Rvx\CPT; use Rvx\CPT\CptHelper; class CommentsRatingColumn { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } /** * Add a new column to the comments page for the review rating. * * @param array $columns The existing comment columns. * @return array Modified columns array. */ public function addRatingColumn($columns) { // Find the position of the 'author' column $author_position = \array_search('author', \array_keys($columns)); // Insert the 'rating' column after the 'author' column if ($author_position !== \false) { // Add the 'rating' column after the 'author' column $columns = \array_slice($columns, 0, $author_position + 1, \true) + ['rating' => __('ReviewX Rating', 'reviewx')] + \array_slice($columns, $author_position + 1, null, \true); } return $columns; } /** * Populate the new column with the rating value. * * @param string $column The column name. * @param int $comment_id The ID of the comment. */ public function populateRatingColumn($column, $comment_id) { if ($column === 'rating') { // Get the comment object $comment = get_comment($comment_id); // Check if the comment is a parent comment if ($comment->comment_parent != 0) { return; // Skip if it's a reply (i.e., not a parent comment) } // Get the comment type (WooCommerce product reviews have a type 'review') $comment_type = $comment->comment_type; // Get the post type of the comment $post_type = get_post_type($comment->comment_post_ID); // Define the target post types $enabled_post_types = $this->cptHelper->enabledCPT(); unset($enabled_post_types['product']); // Unset Product // Check if the comment's post type is in the target post types and comment type is 'review' and 'comment' if (\in_array($post_type, $enabled_post_types, \true) && \in_array($comment_type, ['comment', 'review'], \true)) { // Get the rating meta data for the comment (reviews have 'rating' meta key) $rating = \get_comment_meta($comment_id, 'rating', \true); // If rating exists, display stars, otherwise show empty stars (0) if ($rating) { echo $this->getStarsHtml($rating); } else { echo $this->getStarsHtml(0); // Empty stars for no rating } } } } /** * Generate the star HTML for the given rating. * * @param int $rating The rating value (1 to 5). * @return string The HTML for the stars. */ public function getStarsHtml($rating) { $rating = \max(0, \min(5, $rating)); // Ensure the rating is between 0 and 5 $star_size = '22px'; // Customize size if needed $stars = ''; for ($i = 1; $i <= 5; $i++) { if ($rating >= $i) { // Full star $star_symbol = '<span class="dashicons dashicons-star-filled"></span>'; } elseif ($rating >= $i - 0.5) { // Half star $star_symbol = '<span class="dashicons dashicons-star-half"></span>'; } else { // Empty star $star_symbol = '<span class="dashicons dashicons-star-empty"></span>'; } $stars .= $star_symbol; } return "<span class='rvx-stars' title='{$rating}' style='font-size: {$star_size}; color: #f5a623;'>{$stars}</span>"; } /** * Sort comments based on the 'rating' column. * * @param WP_Query $query The WP_Query object. */ public function sortCommentsByRating($query) { // Check if we are in the admin and the correct screen (comments) if (is_admin() && isset($_GET['orderby']) && 'rating' === $_GET['orderby']) { // Sort by rating in ascending or descending order based on the current 'order' parameter $order = isset($_GET['order']) && $_GET['order'] === 'asc' ? 'ASC' : 'DESC'; // Modify the query to order by rating $query->set('meta_key', 'rating'); // Meta key for rating $query->set('orderby', 'meta_value_num'); // Order by numeric value of meta field $query->set('order', $order); // Set the order (ASC or DESC) } } /** * Make the 'rating' column sortable. * * @param array $columns The existing sortable columns. * @return array Modified sortable columns array. */ public function makeRatingColumnSortable($columns) { $columns['rating'] = 'rating'; return $columns; } } CPT/CptCommentsLinkMeta.php 0000777 00000001767 15251220643 0011606 0 ustar 00 <?php namespace Rvx\CPT; use Rvx\CPT\CptHelper; class CptCommentsLinkMeta { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } /** * Modify the comment count output with custom review logic */ public function replace_total_comments_count($count, $post_id) { // List of post types to target $enabled_post_types = $this->cptHelper->enabledCPT(); unset($enabled_post_types['product']); // Unset Product $post_type = get_post_type($post_id); // Exclude post type if (!isset($enabled_post_types[$post_type])) { return $count; // No changes } $reviewCount = (new \Rvx\CPT\CptReviewsCount())->newCount($post_id); if (!empty($reviewCount[0]) && $reviewCount[0] > 0) { // Return the filtered review count without replies return $reviewCount[0]; } else { return $count; } } } CPT/Shared/CptPostHandler.php 0000777 00000031440 15251220643 0012014 0 ustar 00 <?php namespace Rvx\CPT\Shared; use Rvx\Api\ProductApi; use Rvx\CPT\CptHelper; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\TransactionManager; use Rvx\WPDrill\Response; class CptPostHandler { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } public function __invoke($post_id, $post, $update) { // Ignore if called during autosave or automatic draft if (\defined('DOING_AUTOSAVE') && DOING_AUTOSAVE || \in_array($post->post_status, ['auto-draft', 'inherit'], \true)) { return; } // Define the target post types $enabled_post_types = $this->cptHelper->enabledCPT(); $post_type = $post->post_type; $post_status = $post->post_status; if (!isset($enabled_post_types[$post_type])) { return; } if ($post_status === 'trash') { return; } // WP Independent Sync: We execute logic, but SaaS failure MUST NOT roll back WP. $is_new_sync = \get_post_meta($post_id, 'rvx_sync_new_status', \true); if (!$is_new_sync) { // Handle new post/product sync $response = $this->createHandler($post_id, $post); if ($response->getStatusCode() === Response::HTTP_OK) { $this->enableCommentsReviews($post_id); \update_post_meta($post_id, 'rvx_sync_new_status', 1, \true); } else { // If creation failed, try update as a fallback sync $response = $this->updateHandler($post_id, $post); if ($response->getStatusCode() === Response::HTTP_OK) { $this->enableCommentsReviews($post_id); \update_post_meta($post_id, 'rvx_sync_new_status', 1, \true); \update_post_meta($post_id, 'rvx_sync_edit_status', 1, \true); } else { \error_log("CptPostHandler Create/Update Sync Failed for ID {$post_id}: " . $response->getBody()); } } } else { // Handle existing post/product update sync $response = $this->updateHandler($post_id, $post); if ($response->getStatusCode() === Response::HTTP_OK) { $this->enableCommentsReviews($post_id); \update_post_meta($post_id, 'rvx_sync_new_status', 1, \true); \update_post_meta($post_id, 'rvx_sync_edit_status', 1, \true); } else { \error_log("CptPostHandler Update Sync Failed for ID {$post_id}: " . $response->getBody()); } } } public function createHandler($post_id, $post) { if ($post->post_type === 'product') { $payload = $this->createProductData($post_id, $post); } else { // Public -> custom post type $payload = $this->createPostData($post_id, $post); } return (new ProductApi())->create($payload); } public function updateHandler($post_id, $post) { if ($post->post_type === 'product') { $payload = $this->updatedProductData($post_id, $post); } else { // Public -> custom post type $payload = $this->updatedPostData($post_id, $post); } $uid = Client::getUid() . '-' . $post_id; return (new ProductApi())->update($payload, $uid); } private function createProductData($product_id, $post) { // Get the product object $product = wc_get_product($product_id); // Initialize variables $product_images = []; // Get the main product image $image_id = $product->get_image_id(); // Featured image ID if ($image_id) { $product_images = wp_get_attachment_image_src($image_id, 'full'); // Full-size image URL } if (empty($product_images)) { $product_images = ''; } // Get the regular price $price = $product->get_regular_price(); if (empty($price)) { $price = 0.0; } // Get the sale price (if available) $discounted_price = $product->get_sale_price(); // If no sale price exists, the discounted price is the regular price if (empty($discounted_price)) { $discounted_price = $price; } return ["wp_id" => $product_id, "title" => isset($post->post_title) ? \htmlspecialchars($post->post_title, \ENT_QUOTES, 'UTF-8') : null, "url" => get_permalink($product_id), "description" => isset($post->short_description) ? \htmlspecialchars($post->short_description, \ENT_QUOTES, 'UTF-8') : null, "price" => $price, "discounted_price" => $discounted_price, "slug" => $post->post_name, "image" => $product_images[0] ?? (string) '', "status" => $this->postStatus($post->post_status), "post_type" => $post->post_type, "total_reviews" => (int) $this->getReviewCount($product_id), "avg_rating" => (float) $this->getAverageRating($product_id), "stars" => $this->getStarCounts($product_id), "category_wp_unique_ids" => $this->getCategoryIds($product_id)]; } private function updatedProductData($product_id, $post) { // Get the product object $product = wc_get_product($product_id); // Initialize variables $product_images = []; // Get the main product image $image_id = $product->get_image_id(); // Featured image ID if ($image_id) { $product_images = wp_get_attachment_image_src($image_id, 'full'); // Full-size image URL } if (empty($product_images)) { $product_images = ''; } // Get the regular price $price = $product->get_regular_price(); if (empty($price)) { $price = 0.0; } // Get the sale price (if available) $discounted_price = $product->get_sale_price(); // If no sale price exists, the discounted price is the regular price if (empty($discounted_price)) { $discounted_price = $price; } return ["wp_id" => $product_id, "title" => isset($post->post_title) ? \htmlspecialchars($post->post_title, \ENT_QUOTES, 'UTF-8') : null, "url" => get_permalink($product_id), "description" => isset($post->post_excerpt) ? \htmlspecialchars($post->post_excerpt, \ENT_QUOTES, 'UTF-8') : null, "price" => (float) $price, "discounted_price" => (float) $discounted_price, "slug" => $post->post_name, "image" => $product_images[0] ?? (string) '', "status" => $this->postStatus($post->post_status), "post_type" => $post->post_type, "total_reviews" => (int) $this->getReviewCount($product_id), "avg_rating" => (float) $this->getAverageRating($product_id), "category_wp_unique_ids" => $this->getCategoryIds($product_id)]; } private function createPostData($post_id, $post) { $image_url = get_the_post_thumbnail_url($post->ID, 'full'); if (empty($image_url)) { $image_url = ''; } // $average_rating calculated via helper in return array $data = ["wp_id" => $post->ID, "title" => isset($post->post_title) ? \htmlspecialchars($post->post_title, \ENT_QUOTES, 'UTF-8') : null, "url" => get_permalink($post->ID), "description" => isset($post->post_excerpt) ? \htmlspecialchars($post->post_excerpt, \ENT_QUOTES, 'UTF-8') : null, "price" => 0, "discounted_price" => 0, "slug" => $post->post_name, "image" => (string) $image_url, "status" => $this->postStatus($post->post_status), "post_type" => get_post_type($post->ID), "total_reviews" => (int) $this->getReviewCount($post->ID), "avg_rating" => (float) $this->getAverageRating($post->ID), "stars" => $this->getStarCounts($post->ID), "category_wp_unique_ids" => $this->getCategoryIds($post_id)]; return $data; } private function updatedPostData($post_id, $post) { $image_url = get_the_post_thumbnail_url($post->ID, 'full'); if (empty($image_url)) { $image_url = ''; } // $average_rating calculated via helper in return array $data = ["wp_id" => $post->ID, "title" => isset($post->post_title) ? \htmlspecialchars($post->post_title, \ENT_QUOTES, 'UTF-8') : null, "url" => get_permalink($post->ID), "description" => isset($post->post_excerpt) ? \htmlspecialchars($post->post_excerpt, \ENT_QUOTES, 'UTF-8') : null, "price" => 0, "discounted_price" => 0, "slug" => $post->post_name, "image" => (string) $image_url, "status" => $this->postStatus($post->post_status), "post_type" => get_post_type($post->ID), "total_reviews" => (int) $this->getReviewCount($post->ID), "avg_rating" => (float) $this->getAverageRating($post->ID), "stars" => $this->getStarCounts($post->ID), "category_wp_unique_ids" => $this->getCategoryIds($post_id)]; return $data; } private function postStatus($status) { switch ($status) { case 'publish': return 1; case 'trash': return 2; default: return 3; } } private function getCategoryIds($post_id) { // Validate the post ID if (empty($post_id)) { \error_log("No valid post/product ID found."); return []; } // Get the post type $post_type = get_post_type($post_id); // Determine the taxonomy: 'product_cat' for products, hierarchical taxonomy for others $taxonomy = $post_type === 'product' ? 'product_cat' : null; if (!$taxonomy) { $taxonomies = get_object_taxonomies($post_type, 'objects'); foreach ($taxonomies as $key => $taxonomy_obj) { if ($taxonomy_obj->hierarchical) { $taxonomy = $key; break; } } } // Retrieve category IDs or assign default if none are found $category_ids = []; if ($taxonomy) { $category_ids = wp_get_post_terms($post_id, $taxonomy, ['fields' => 'ids']); } if (empty($category_ids)) { $category_ids = [0]; } // Append the UID prefix to each category ID $uid = Client::getUid(); $parent_category_ids = []; foreach ($category_ids as $category_id) { $parent_category_ids[] = $uid . '-' . $category_id; } return $parent_category_ids; } private function getStarCounts($post_id) { $check = \get_post_meta($post_id, 'rvx_star_count_1', \true); // Backward compatibility: If meta doesn't exist, calculate it now. if ($check === '' || $check === \false) { \Rvx\CPT\CptAverageRating::update_average_rating($post_id); } return ["one" => (int) \get_post_meta($post_id, 'rvx_star_count_1', \true), "two" => (int) \get_post_meta($post_id, 'rvx_star_count_2', \true), "three" => (int) \get_post_meta($post_id, 'rvx_star_count_3', \true), "four" => (int) \get_post_meta($post_id, 'rvx_star_count_4', \true), "five" => (int) \get_post_meta($post_id, 'rvx_star_count_5', \true)]; } private function enableCommentsReviews($post_id) { global $wpdb; // Validate post ID $post = get_post($post_id); if (!$post) { return \false; } // Ensure the post type supports comments $post_type = $post->post_type; $supports = post_type_supports($post_type, 'comments'); if (!$supports) { // Dynamically add comment support for the post type add_post_type_support($post_type, 'comments'); } // Update the comment status in the database $updated = $wpdb->update( $wpdb->posts, ['comment_status' => 'open'], // Enable comments ['ID' => $post_id], // Match post ID ['%s'], // Data format for `comment_status` ['%d'] ); if ($updated === \false) { return \false; } // Clear WordPress cache for this post clean_post_cache($post_id); return \true; } private function getReviewCount($post_id) { $count = \get_post_meta($post_id, 'rvx_total_reviews', \true); // Backward compatibility: If meta doesn't exist, calculate it now. if ($count === '' || $count === \false) { \Rvx\CPT\CptAverageRating::update_average_rating($post_id); $count = \get_post_meta($post_id, 'rvx_total_reviews', \true); } return (int) $count; } private function getAverageRating($post_id) { $rating = \get_post_meta($post_id, 'rvx_avg_rating', \true); // Backward compatibility: If meta doesn't exist, calculate it now. if ($rating === '' || $rating === \false) { \Rvx\CPT\CptAverageRating::update_average_rating($post_id); $rating = \get_post_meta($post_id, 'rvx_avg_rating', \true); } return (float) ($rating ?: 0.0); } } CPT/Shared/CommentsReviewsRowActionRemover.php 0000777 00000002745 15251220643 0015450 0 ustar 00 <?php namespace Rvx\CPT\Shared; use Rvx\CPT\CptHelper; class CommentsReviewsRowActionRemover { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } /** * Remove specific row actions from comments and reviews based on the post type and comment type. * * @param array $actions The array of actions for the comment row. * @param WP_Comment $comment The comment object. * @return array The modified actions array. */ public function removeCommentsReviewsRowActions($actions, $comment) { // List of post types to target (include product) $enabled_post_types = $this->cptHelper->enabledCPT(); // Get the post type of the comment $post_type = get_post_type($comment->comment_post_ID); // Get the comment type (WooCommerce product reviews have a type 'review') $comment_type = $comment->comment_type; // List of actions to remove $actions_to_remove = ['reply', 'quickedit', 'edit']; // If the post type matches and the comment type is 'comment' or 'review', remove the specified actions if (\in_array($post_type, $enabled_post_types, \true) && \in_array($comment_type, ['comment', 'review'], \true)) { foreach ($actions_to_remove as $action) { if (isset($actions[$action])) { unset($actions[$action]); } } } return $actions; } } CPT/Shared/CommentsReviewsFilter.php 0000777 00000004741 15251220643 0013426 0 ustar 00 <?php namespace Rvx\CPT\Shared; use Rvx\CPT\CptHelper; use Rvx\Utilities\Auth\Client; /** * Filters comments/reviews from the WP Comments admin page for post types * that are enabled in ReviewX. */ class CommentsReviewsFilter { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } /** * Filter comments query to exclude comments for ReviewX-enabled post types. * This hides reviews/comments from the WP Comments admin page. * * @param WP_Comment_Query $query The comment query object. */ public function filterCommentsForReviewxPostTypes($query) { // Only execute after sync is completed if (!Client::getSync()) { return; } // Only filter on the admin comments page if (!is_admin()) { return; } // Check if we're on the comments admin page global $pagenow; if ($pagenow !== 'edit-comments.php') { return; } // Get enabled post types from ReviewX $enabled_post_types = $this->cptHelper->enabledCPT(); if (empty($enabled_post_types)) { return; } // Get all post IDs that belong to enabled post types $post_ids_to_exclude = $this->getPostIdsForPostTypes($enabled_post_types); if (empty($post_ids_to_exclude)) { return; } // Get current post__not_in value and merge with our exclusions $current_post_not_in = $query->query_vars['post__not_in'] ?? []; if (!\is_array($current_post_not_in)) { $current_post_not_in = []; } $query->query_vars['post__not_in'] = \array_merge($current_post_not_in, $post_ids_to_exclude); } /** * Get all post IDs for the given post types. * * @param array $post_types Array of post type slugs. * @return array Array of post IDs. */ protected function getPostIdsForPostTypes($post_types) { global $wpdb; if (empty($post_types)) { return []; } // Build placeholders for IN clause $placeholders = \implode(', ', \array_fill(0, \count($post_types), '%s')); // Prepare query to get post IDs for the enabled post types $query = $wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_type IN ({$placeholders})", \array_values($post_types)); $post_ids = $wpdb->get_col($query); return \array_map('intval', $post_ids); } } CPT/Shared/PostsRatingColumn.php 0000777 00000011643 15251220643 0012560 0 ustar 00 <?php namespace Rvx\CPT\Shared; use Rvx\CPT\CptHelper; class PostsRatingColumn { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } public function addColumn() { $enabled_post_types = $this->cptHelper->enabledCPT(); // Loop through each post type and hook into the actions/filters dynamically foreach ($enabled_post_types as $post_type) { // Hook into the columns filter for each post type add_filter("manage_edit-{$post_type}_columns", function ($columns) use($post_type) { return $this->addRatingColumn($columns, $post_type); }); add_action("manage_{$post_type}_posts_custom_column", [$this, 'populateRatingColumn'], 10, 2); // if($post_type !== 'product'){ // add_filter("manage_edit-{$post_type}_sortable_columns", [$this, 'makeRatingColumnSortable']); // add_action('pre_get_posts', [$this, 'sortPostsByRating']); // } } } /** * Add a new column to the post type list for the review rating. * * @param array $columns The existing post columns. * @return array Modified columns array. */ public function addRatingColumn($columns, $post_type) { // For 'product' post type, add rating column after the title column if ($post_type === 'product') { // Find the position of the 'author' column $price_position = \array_search('price', \array_keys($columns)); // Insert the 'rating' column after the 'price' column if ($price_position !== \false) { // Add the 'rating' column after the 'author' column $columns = \array_slice($columns, 0, $price_position + 1, \true) + ['rating' => __('ReviewX Rating', 'reviewx')] + \array_slice($columns, $price_position + 1, null, \true); } } else { // For other post types, find the position of the 'author' column $author_position = \array_search('author', \array_keys($columns)); if ($author_position !== \false) { $columns = \array_slice($columns, 0, $author_position + 1, \true) + ['rating' => __('ReviewX Rating', 'reviewx')] + \array_slice($columns, $author_position + 1, null, \true); } } return $columns; } /** * Populate the rating column with the post's rating. * * @param string $column The column name. * @param int $post_id The ID of the post. */ public function populateRatingColumn($column, $post_id) { if ($column === 'rating') { $post_type = get_post_type($post_id); $meta_key = 'product' === $post_type ? '_wc_average_rating' : 'rvx_avg_rating'; $rating = \get_post_meta($post_id, $meta_key, \true); echo $this->getStarsHtml($rating ? $rating : 0); // Default to 0 if no rating } } /** * Generate the HTML for the stars based on the rating value. * * @param int $rating The rating value (1-5). * @return string The HTML output for the stars. */ public function getStarsHtml($rating) { $rating = \max(0, \min(5, $rating)); // Ensure the rating is between 0 and 5 $star_size = '22px'; // Customize size if needed $stars = ''; for ($i = 1; $i <= 5; $i++) { if ($rating >= $i) { // Full star $star_symbol = '<span class="dashicons dashicons-star-filled"></span>'; } elseif ($rating >= $i - 0.5) { // Half star $star_symbol = '<span class="dashicons dashicons-star-half"></span>'; } else { // Empty star $star_symbol = '<span class="dashicons dashicons-star-empty"></span>'; } $stars .= $star_symbol; } return "<span class='rvx-stars' title='{$rating}' style='font-size: {$star_size}; color: #f5a623;'>{$stars}</span>"; } /** * Make the rating column sortable. * * @param array $columns The existing sortable columns. * @return array Modified sortable columns array. */ public function makeRatingColumnSortable($columns) { $columns['rating'] = 'rating'; return $columns; } /** * Sort posts by the rating column. * * @param WP_Query $query The WP_Query object. */ public function sortPostsByRating($query) { if (is_admin() && isset($_GET['orderby']) && 'rating' === $_GET['orderby']) { $order = isset($_GET['order']) && $_GET['order'] === 'asc' ? 'ASC' : 'DESC'; $meta_key = get_post_type() === 'product' ? '_wc_average_rating' : 'rvx_avg_rating'; $query->set('meta_key', $meta_key); $query->set('orderby', 'meta_value_num'); $query->set('order', $order); } } } CPT/Shared/CommentsReviewsMetaBoxRemover.php 0000777 00000001611 15251220643 0015071 0 ustar 00 <?php namespace Rvx\CPT\Shared; use Rvx\CPT\CptHelper; class CommentsReviewsMetaBoxRemover { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } /** * Removes the comments meta box from all custom post types and WooCommerce products. */ public function removeCommentsReviewsMetaBox() { $enabled_post_types = $this->cptHelper->enabledCPT(); foreach ($enabled_post_types as $post_type) { // Remove the "Allow Comments" meta box remove_meta_box('commentstatusdiv', $post_type, 'normal'); remove_meta_box('commentstatusdiv', $post_type, 'side'); // Remove the "Comments" meta box displaying existing comments remove_meta_box('commentsdiv', $post_type, 'normal'); remove_meta_box('commentsdiv', $post_type, 'side'); } } } CPT/Shared/CommentEditBlockHandler.php 0000777 00000020356 15251220643 0013607 0 ustar 00 <?php namespace Rvx\CPT\Shared; use Rvx\CPT\CptHelper; use Rvx\Utilities\Auth\Client; /** * Blocks editing of comments/reviews for post types that are managed by ReviewX. * This applies to both WP Comment Edit page and WooCommerce Review Edit page. */ class CommentEditBlockHandler { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } /** * Check if we should block comment editing. * * @return bool */ public function shouldBlockEdit() : bool { // Get enabled post types from ReviewX $enabled_post_types = $this->cptHelper->enabledCPT(); if (empty($enabled_post_types)) { return \false; } return \true; } /** * Check if we're on the comment edit page. * * @return bool */ public function isCommentEditPage() : bool { global $pagenow; // WP Comment Edit page: comment.php?action=editcomment&c={id} if ($pagenow === 'comment.php') { $action = isset($_GET['action']) ? sanitize_text_field($_GET['action']) : ''; return $action === 'editcomment'; } return \false; } /** * Get the comment being edited. * * @return \WP_Comment|null */ public function getEditingComment() : ?\WP_Comment { if (!$this->isCommentEditPage()) { return null; } $comment_id = isset($_GET['c']) ? absint($_GET['c']) : 0; if (!$comment_id) { return null; } return get_comment($comment_id); } /** * Check if the comment belongs to a ReviewX-enabled post type. * * @param \WP_Comment $comment The comment object. * @return bool */ public function isReviewxEnabledComment($comment) : bool { if (!$comment || !$comment->comment_post_ID) { return \false; } $post_type = get_post_type($comment->comment_post_ID); $enabled_post_types = $this->cptHelper->enabledCPT(); return isset($enabled_post_types[$post_type]); } /** * Display a notice on the comment edit page that editing is blocked. */ public function displayEditBlockedNotice() : void { if (!is_admin()) { return; } if (!$this->shouldBlockEdit()) { return; } if (!$this->isCommentEditPage()) { return; } $comment = $this->getEditingComment(); if (!$comment || !$this->isReviewxEnabledComment($comment)) { return; } $reviewx_reviews_url = admin_url('admin.php?page=reviewx_reviews'); $post_type = get_post_type($comment->comment_post_ID); $post_type_label = \ucfirst($post_type); // Use admin_footer to inject HTML that won't be affected by page load scripts add_action('admin_footer', function () use($reviewx_reviews_url, $post_type_label) { ?> <style> /* Position the content area as relative for absolute positioning */ #wpbody-content { position: relative !important; } /* Overlay covers only the content area */ #rvx-edit-blocked-overlay { position: absolute !important; top: 0 !important; left: 0 !important; right: 0 !important; bottom: 0 !important; min-height: 100vh; background: rgba(255,255,255,0.98) !important; z-index: 99 !important; display: flex !important; align-items: center !important; justify-content: center !important; visibility: visible !important; opacity: 1 !important; } </style> <script> document.addEventListener('DOMContentLoaded', function() { var container = document.getElementById('wpbody-content'); if (!container) return; var overlay = document.createElement('div'); overlay.id = 'rvx-edit-blocked-overlay'; overlay.innerHTML = ` <div style=" background: #fff; border: 1px solid #c3c4c7; border-left: 4px solid #f59e0b; padding: 30px 40px; max-width: 500px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); border-radius: 4px; text-align: center; "> <span class="dashicons dashicons-lock" style="font-size: 48px; color: #f59e0b; margin-bottom: 15px; display: block;"></span> <h2 style="margin: 0 0 15px 0; color: #1e293b; font-size: 20px;"> <?php esc_html_e('Review Editing Disabled', 'reviewx'); ?> </h2> <p style="font-size: 14px; color: #475569; margin: 0 0 20px 0; line-height: 1.6;"> <?php \printf(esc_html__('This %s review is managed by ReviewX. To edit this review, please use the ReviewX Reviews page.', 'reviewx'), esc_html($post_type_label)); ?> </p> <a href="<?php echo esc_url($reviewx_reviews_url); ?>" class="button button-primary button-hero" style="background-color: #6366f1; border-color: #6366f1; font-size: 14px;"> <?php esc_html_e('Go to ReviewX Reviews', 'reviewx'); ?> </a> <br><br> <a href="<?php echo esc_url(admin_url('edit-comments.php')); ?>" style="color: #666; font-size: 13px; text-decoration: none;"> <?php esc_html_e('← Back to Comments', 'reviewx'); ?> </a> </div> `; container.appendChild(overlay); }); </script> <?php }); } /** * Redirect to ReviewX reviews page if trying to edit a ReviewX-managed comment. * This is an alternative approach using JavaScript for better UX. */ public function maybeRedirectFromEditPage() : void { if (!is_admin()) { return; } if (!$this->shouldBlockEdit()) { return; } if (!$this->isCommentEditPage()) { return; } $comment = $this->getEditingComment(); if (!$comment || !$this->isReviewxEnabledComment($comment)) { return; } // Add inline script to disable form submission add_action('admin_footer', function () { ?> <script> document.addEventListener('DOMContentLoaded', function() { // Disable all form submissions on this page var forms = document.querySelectorAll('form'); forms.forEach(function(form) { form.addEventListener('submit', function(e) { e.preventDefault(); alert('<?php esc_html_e('This review is managed by ReviewX. Please edit it from the ReviewX Reviews page.', 'reviewx'); ?>'); return false; }); }); // Disable submit buttons var submitButtons = document.querySelectorAll('input[type="submit"], button[type="submit"]'); submitButtons.forEach(function(btn) { btn.disabled = true; btn.style.opacity = '0.5'; btn.style.cursor = 'not-allowed'; }); }); </script> <?php }); } } CPT/Shared/WooReviewsRedirectHandler.php 0000777 00000012123 15251220643 0014210 0 ustar 00 <?php namespace Rvx\CPT\Shared; use Rvx\CPT\CptHelper; use Rvx\Utilities\Auth\Client; /** * Handles WooCommerce Reviews page redirection notice and hides reviews * when product post type is managed by ReviewX. */ class WooReviewsRedirectHandler { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } /** * Check if WooCommerce product reviews should be hidden. * * @return bool */ public function shouldHideWooReviews() : bool { // Check if WooCommerce is active if (!\class_exists('WooCommerce')) { return \false; } // Check if sync is completed if (!Client::getSync()) { return \false; } // Check if product post type is enabled in ReviewX $enabled_post_types = $this->cptHelper->enabledCPT(); return isset($enabled_post_types['product']); } /** * Check if we're on the WooCommerce Reviews page. * WooCommerce Reviews page: edit.php?post_type=product&page=product-reviews * Legacy Comments page: edit-comments.php?post_type=product or edit-comments.php?comment_type=review * * @return bool */ public function isWooReviewsPage() : bool { global $pagenow; // Check for WooCommerce product-reviews page (Products -> Reviews) // URL: edit.php?post_type=product&page=product-reviews if ($pagenow === 'edit.php') { $post_type = isset($_GET['post_type']) ? sanitize_text_field($_GET['post_type']) : ''; $page = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : ''; if ($post_type === 'product' && $page === 'product-reviews') { return \true; } } // Also check legacy edit-comments.php page if ($pagenow === 'edit-comments.php') { $post_type = isset($_GET['post_type']) ? sanitize_text_field($_GET['post_type']) : ''; $comment_type = isset($_GET['comment_type']) ? sanitize_text_field($_GET['comment_type']) : ''; if ($post_type === 'product' || $comment_type === 'review') { return \true; } } return \false; } /** * Display a notice on the WooCommerce Reviews page redirecting users to ReviewX. */ public function displayRedirectNotice() : void { if (!is_admin()) { return; } if (!$this->shouldHideWooReviews()) { return; } if (!$this->isWooReviewsPage()) { return; } $reviewx_reviews_url = admin_url('admin.php?page=reviewx_reviews'); ?> <div class="notice notice-info" style="padding: 15px; margin: 20px 0; border-left-color: #6366f1;"> <h3 style="margin: 0 0 10px 0; color: #1e293b;"> <span class="dashicons dashicons-star-filled" style="color: #6366f1; margin-right: 5px;"></span> <?php esc_html_e('Reviews Managed by ReviewX', 'reviewx'); ?> </h3> <p style="font-size: 14px; color: #475569; margin: 0 0 15px 0;"> <?php esc_html_e('Product reviews are now managed by ReviewX. You can view, manage, and respond to all product reviews from the ReviewX Reviews page.', 'reviewx'); ?> </p> <a href="<?php echo esc_url($reviewx_reviews_url); ?>" class="button button-primary" style="background-color: #6366f1; border-color: #6366f1;"> <span class="dashicons dashicons-arrow-right-alt" style="margin-top: 4px;"></span> <?php esc_html_e('Go to ReviewX Reviews', 'reviewx'); ?> </a> </div> <style> /* Hide the reviews table when ReviewX is managing reviews */ .wp-list-table.comments, .wp-list-table.reviews, .tablenav, .subsubsub, .search-box, #comments-form > p:first-child, .woocommerce-reviews-table, .wc-admin-review-activity-card, #the-comment-list, .comment-ays, form#comments-form { display: none !important; } </style> <?php } /** * Filter WooCommerce product reviews from the comments query using comments_clauses. * This is the proper WordPress filter for modifying comment queries. * * @param array $clauses A compacted array of comment query clauses. * @param \WP_Comment_Query $comment_query The WP_Comment_Query instance. * @return array Modified clauses array. */ public function filterWooReviewsClauses($clauses, $comment_query) : array { if (!is_admin()) { return $clauses; } if (!$this->shouldHideWooReviews()) { return $clauses; } if (!$this->isWooReviewsPage()) { return $clauses; } // Return no results by adding an impossible WHERE condition $clauses['where'] .= ' AND 1=0 '; return $clauses; } } CPT/CptRichSchemaHandler.php 0000777 00000011774 15251220643 0011677 0 ustar 00 <?php namespace Rvx\CPT; use Rvx\Services\SettingService; use WP_Post; /** * Handles rich schema generation for non-product post types (CPTs, pages, posts, etc.). */ class CptRichSchemaHandler { /** * Build structured data for a given post. * * @param array $markup Existing markup (unused). * @param WP_Post $post Post object. * @return array */ public function schemaHandler($markup, $post) : array { // Guard conditions. if (is_admin() || empty($post) || !isset($post->ID)) { return $markup; } $postType = get_post_type($post); if (empty($postType) || $postType === 'product') { return $markup; // Skip WooCommerce products. } // Temporarily remove Divi filter $divi_callback = 'et_theme_builder_wc_set_review_metadata'; $divi_removed = \false; if (\function_exists('has_filter')) { $priority = \has_filter('get_comment_metadata', $divi_callback); if ($priority !== \false) { remove_filter('get_comment_metadata', $divi_callback, (int) $priority); $divi_removed = \true; } } // Define schema type mappings. $schemaTypeMap = ['post' => 'BlogPosting', 'page' => 'Article', 'job' => 'JobPosting', 'job_listing' => 'JobPosting', 'book' => 'Book', 'movie' => 'Movie', 'event' => 'Event', 'recipe' => 'Recipe', 'course' => 'Course', 'season' => 'CreativeWorkSeason', 'series' => 'CreativeWorkSeries', 'software' => 'SoftwareApplication', 'application' => 'SoftwareApplication', 'app' => 'SoftwareApplication', 'music' => 'MusicRecording', 'game' => 'Game', 'howto' => 'HowTo', 'episode' => 'Episode', 'business' => 'LocalBusiness']; // Do not use 'CreativeWork' as a fallback for reviews, use 'BlogPosting' or 'Article' instead. $schemaType = $schemaTypeMap[$postType] ?? 'Article'; $reviewableTypes = ['Book', 'Movie', 'Recipe', 'Course', 'CreativeWorkSeason', 'CreativeWorkSeries', 'SoftwareApplication', 'MusicRecording', 'MediaObject', 'Game', 'HowTo', 'Episode', 'LocalBusiness']; // Start with the base markup for the main item. $markup = ['@context' => 'https://schema.org/', '@type' => $schemaType, 'name' => $post->post_title, 'url' => get_permalink($post)]; // Only attach review data to supported types. if (\in_array($schemaType, $reviewableTypes, \true)) { $reviews = get_comments(['post_id' => $post->ID, 'status' => 'approve', 'type__in' => ['comment', 'review']]); if (!empty($reviews)) { $reviewCount = 0; $averageRating = 0.0; $reviewItems = []; foreach ($reviews as $review) { if (!empty($review->comment_parent)) { continue; // Skip replies. } $rating = \get_comment_meta($review->comment_ID, 'rating', \true); $ratingValue = $rating !== '' ? (float) $rating : null; if ($ratingValue !== null && $ratingValue > 0) { $reviewCount++; $averageRating += $ratingValue; $reviewItems[] = ['@type' => 'Review', 'author' => ['@type' => 'Person', 'name' => $review->comment_author], 'reviewRating' => ['@type' => 'Rating', 'ratingValue' => $ratingValue], 'datePublished' => get_comment_date('c', $review), 'reviewBody' => $review->comment_content]; } } if ($reviewCount > 0 && $averageRating > 0) { $trueAverage = \round($averageRating / $reviewCount, 1); // Nest AggregateRating and individual Reviews correctly. $markup['aggregateRating'] = ['@type' => 'AggregateRating', 'ratingValue' => $trueAverage, 'reviewCount' => $reviewCount]; $markup['review'] = $reviewItems; } } } // Restore Divi filter. if ($divi_removed) { add_filter('get_comment_metadata', $divi_callback, $priority ?? 10, 4); } return $markup; } /** * Outputs the schema in the page head for all eligible non-product post types. */ public static function addCustomRichSchema() : void { // Bail early if not on frontend or not singular. if (is_admin() || !is_singular() || \function_exists('is_product') && \is_product()) { return; } global $post; if (empty($post) || !isset($post->ID)) { return; } $handler = new self(); $markup = $handler->schemaHandler([], $post); if (!empty($markup)) { echo "\n<!-- ReviewX Rich Schema for {$post->post_type} -->\n"; echo '<script type="application/ld+json">' . wp_json_encode($markup, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES) . '</script>'; echo "\n<!-- /ReviewX Rich Schema -->\n"; } } } CPT/CptReviewsCount.php 0000777 00000001634 15251220643 0011022 0 ustar 00 <?php namespace Rvx\CPT; class CptReviewsCount { public function newCount($post_id) { // Fetch all approved comments (reviews) for the post $reviews = get_comments(['post_id' => $post_id, 'status' => 'approve', 'type' => 'comment']); // Initialize review count $totalCount = 0; $reviewCount = 0; if (!empty($reviews)) { foreach ($reviews as $review) { $totalCount++; // Skip replies if ($review->comment_parent > 0) { continue; // Skip replies } $reviewCount++; } } // If no reviews exist, fall back to original comments count if ($reviewCount === 0) { return $totalCount; // Return original count if no reviews } return [$reviewCount, $totalCount]; } } CPT/CptHelper.php 0000777 00000006226 15251220643 0007606 0 ustar 00 <?php namespace Rvx\CPT; use Rvx\Rest\Controllers\CptController; use Rvx\Utilities\Auth\Client; class CptHelper { public function enabledCPT() : array { if (!Client::getSync()) { return []; } // Retrieve settings $data = \get_option('_rvx_cpt_settings'); // Default enabled post types $enabled_post_types = ['product' => 'product']; // Validate data before processing if (\is_array($data) && isset($data['reviews']) && \is_array($data['reviews'])) { foreach ($data['reviews'] as $review) { if (isset($review['status'], $review['post_type']) && $review['status'] === 'Enabled' && post_type_exists($review['post_type']) && $review['post_type'] !== 'page') { $enabled_post_types[\strtolower($review['post_type'])] = \strtolower($review['post_type']); } } } else { return []; } return \array_unique($enabled_post_types); } public function usedCPT($param = 'all') { if (!Client::getSync()) { return []; } $data = (new CptController())->customPostTypes($param); if (!isset($data) || !\is_array($data)) { return []; } // Transform the data $formattedData = []; foreach ($data as $item) { if (isset($item['slug'])) { $formattedData[$item['slug']] = $item['slug']; } } return $formattedData; } public function usedCPTOnSync($param = 'all') { $data = (new CptController())->customPostTypesOnSync($param); if (!isset($data) || !\is_array($data)) { return []; } // Transform the data $formattedData = []; foreach ($data as $item) { if (isset($item['slug'])) { $formattedData[$item['slug']] = $item['slug']; } } return $formattedData; } public function cptSettings() : array { if (!Client::getSync()) { return []; } // Retrieve settings with default as an empty array $data = \get_option('_rvx_cpt_settings', []); // Ensure the data is always an array return \is_array($data) ? $data : []; } public function cptSettingsOnSync() : array { // Retrieve settings with default as an empty array $data = \get_option('_rvx_cpt_settings', []); // Ensure the data is always an array return \is_array($data) ? $data : []; } public function getPublicCptList() { $args = array('public' => \true, '_builtin' => \false); $post_types = get_post_types($args, 'objects'); $result = array(); if (!empty($post_types)) { foreach ($post_types as $post_type) { if ($post_type->name !== 'product') { $result[] = array('name' => \ucfirst($post_type->labels->name), 'slug' => \strtolower($post_type->name)); } } } // Add post type $result[] = array('name' => 'Post', 'slug' => 'post'); return $result; } } CPT/CptAverageRating.php 0000777 00000011705 15251220643 0011104 0 ustar 00 <?php namespace Rvx\CPT; use WP_Post; use Rvx\CPT\CptHelper; class CptAverageRating { /** * Initialize or update the rvx_avg_rating meta key for a post. * add_action comment_post */ public static function handle_comment_rating($comment_id, $comment_approved, $comment = null) { if ($comment_approved !== 1) { return; } if ($comment === null) { $comment = get_comment($comment_id); } if (!$comment) { return; } $post_id = $comment->comment_post_ID; // Update the average rating for the post. self::update_average_rating($post_id); } /** * Handle when a comment's status is updated. * * @param int $comment_id The comment ID. * @param string $status The new status of the comment. */ public static function handle_comment_status_change($comment_id, $status) { $comment = get_comment($comment_id); if (!$comment) { return; // Exit if the comment doesn't exist. } $post_id = $comment->comment_post_ID; // Update the average rating for the post. self::update_average_rating($post_id); } /** * Calculate and update the rvx_avg_rating meta key for a given post. * * @param int $post_id ID of the post. */ public static function update_average_rating($post_id) { // Check the post type. $post_type = get_post_type($post_id); $enabled_post_types = (new CptHelper())->usedCPT('used'); if (!isset($enabled_post_types[$post_type]) && $post_type !== 'product') { return; } global $wpdb; // Fetch all approved comment ratings for the post, only for parent comments. $ratings = $wpdb->get_col($wpdb->prepare("SELECT cm.meta_value \n FROM {$wpdb->commentmeta} AS cm\n INNER JOIN {$wpdb->comments} AS c\n ON cm.comment_id = c.comment_ID\n WHERE cm.meta_key = 'rating'\n AND c.comment_post_ID = %d\n AND c.comment_approved = '1'\n AND c.comment_parent = 0", $post_id)); $average_rating = \get_post_meta($post_id, 'rvx_avg_rating', \true); if (empty($average_rating)) { $average_rating = 0.0; } if (!empty($ratings)) { // Calculate the count and average rating using only parent comments. $count = \count($ratings); $average_rating = \round(\array_sum($ratings) / $count, 2); // Calculate individual star counts $starCounts = \array_count_values(\array_map('intval', $ratings)); // Store the average rating and count as post meta \update_post_meta($post_id, 'rvx_avg_rating', (float) $average_rating); \update_post_meta($post_id, 'rating', (float) $average_rating); \update_post_meta($post_id, 'rvx_total_reviews', (int) $count); // Store individual star counts for ($i = 1; $i <= 5; $i++) { \update_post_meta($post_id, "rvx_star_count_{$i}", (int) ($starCounts[$i] ?? 0)); } if ($post_type === 'product') { \update_post_meta($post_id, '_wc_average_rating', (float) $average_rating); \update_post_meta($post_id, '_wc_review_count', (int) $count); } } else { // No ratings found, set the meta keys to 0. \update_post_meta($post_id, 'rvx_avg_rating', (float) 0.0); \update_post_meta($post_id, 'rating', (float) 0.0); \update_post_meta($post_id, 'rvx_total_reviews', 0); for ($i = 1; $i <= 5; $i++) { \update_post_meta($post_id, "rvx_star_count_{$i}", 0); } if ($post_type === 'product') { \update_post_meta($post_id, '_wc_average_rating', (float) 0.0); \update_post_meta($post_id, '_wc_review_count', 0); } } } /** * Hook into the post save action to add the rvx_avg_rating meta key. * * @param int $post_id The post ID. * @param WP_Post $post The post object. */ public static function rvx_avg_rating_on_save($post_id, $post) { // Ensure we are not triggering on autosave if (\defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } // Check the post type. $post_type = get_post_type($post_id); $enabled_post_types = (new CptHelper())->usedCPT('used'); if (!isset($enabled_post_types[$post_type]) && $post_type !== 'product') { return; } // Check if the rvx_avg_rating key already exists if (!\get_post_meta($post_id, 'rvx_avg_rating', \true)) { // Add the rvx_avg_rating meta key with an initial value (0.00) \update_post_meta($post_id, 'rvx_avg_rating', (float) 0.0); \update_post_meta($post_id, 'rating', (float) 0.0); } } } Providers/PluginServiceProvider.php 0000777 00000033707 15251220643 0013545 0 ustar 00 <?php namespace Rvx\Providers; use Rvx\CPT\CptAverageRating; use Rvx\CPT\CptCommentsLinkMeta; use Rvx\CPT\CptRichSchemaHandler; // use Rvx\CPT\CommentsRatingColumn; use Rvx\CPT\Shared\CommentsReviewsMetaBoxRemover; use Rvx\CPT\Shared\CommentsReviewsFilter; use Rvx\CPT\Shared\CommentsReviewsRowActionRemover; use Rvx\CPT\Shared\WooReviewsRedirectHandler; use Rvx\CPT\Shared\CommentEditBlockHandler; use Rvx\CPT\Shared\CptPostHandler; use Rvx\CPT\Shared\PostsRatingColumn; use Rvx\Form\ReviewForm; use Rvx\Handlers\BulkAction\CustomBulkActionsForReviewsHandler; use Rvx\Handlers\BulkAction\RegisterBulkActionsForReviewsHandler; use Rvx\Handlers\CategoryCreateHandler; use Rvx\Handlers\CategoryDeleteHandler; use Rvx\Handlers\CategoryUpdateHandler; use Rvx\Handlers\Customize\WidgetCustomizeOptionsHandler; use Rvx\Handlers\Customize\WidgetCustomizeOutputCSSHandler; use Rvx\Handlers\MigrationRollback\UpgradeDBSettings; use Rvx\Handlers\Notice\ReviewxAdminNoticeHandler; use Rvx\Handlers\OrderCreateHandler; use Rvx\Handlers\OrderDeleteHandler; use Rvx\Handlers\OrderStatusChangedHandler; use Rvx\Handlers\OrderUpdateHandler; use Rvx\Handlers\OrderUpdateProcessHandler; use Rvx\Handlers\PluginRemovalHandler; use Rvx\Handlers\Product\ProductImportHandler; use Rvx\Handlers\Product\ProductUntrashHandler; use Rvx\Handlers\ProductDeleteHandler; use Rvx\Handlers\ReplyCommentHandler; use Rvx\Handlers\RichSchema\WoocommerceRichSchemaHandler; use Rvx\Handlers\RvxInit\PageBuilderHandler; use Rvx\Handlers\RvxInit\ResetProductMetaHandler; use Rvx\Handlers\RvxInit\ReviewXoldPluginDeactivateHandler; use Rvx\Handlers\RvxInit\UpgradeReviewxDeactiveProHandler; use Rvx\Handlers\UserDeleteHandler; use Rvx\Handlers\UserHandler; use Rvx\Handlers\UserUpdateHandler; use Rvx\Handlers\WChooks\StorefrontReviewLinkClickScroll; use Rvx\Handlers\WcTemplates\WcAccountDetails; use Rvx\Handlers\WcTemplates\WcAccountFormTag; use Rvx\Handlers\WcTemplates\WcEditAccountForm; use Rvx\Handlers\WcTemplates\WcSendEmailPermissionHandler; use Rvx\Handlers\WcTemplates\WoocommerceLocateTemplateHandler; use Rvx\Handlers\WooCommerceReviewEditForm; use Rvx\Handlers\WoocommerceSettingsSaveHandler; use Rvx\Handlers\WooReviewTableHandler; use Rvx\Models\Site; use Rvx\Utilities\Auth\ClientManager; use Rvx\Utilities\Auth\WpUserManager; use Rvx\Utilities\Auth\WpUser; use Rvx\WPDrill\ServiceProvider; // use Rvx\Handlers\WcTemplates\WcAccountDetailsError; class PluginServiceProvider extends ServiceProvider { public function register() : void { $this->plugin->bind(ClientManager::class, function () { $site = Site::first(); return new ClientManager($site); }); $this->plugin->bind(WpUserManager::class, function () { return new WpUserManager(); }); } public function boot() : void { add_action('plugins_loaded', function () { if (is_admin() && \get_transient('rvx_reset_sync_flag')) { (new \Rvx\Handlers\IsAlreadySyncSucess())->resetSyncFlag(); } require_once ABSPATH . 'wp-admin/includes/image.php'; }, 15); add_action('rest_api_init', function () { WpUser::setLoggedInStatus(is_user_logged_in()); WpUser::setAbility(is_user_logged_in() && (current_user_can('manage_options') || current_user_can('edit_others_posts') || current_user_can('manage_woocommerce')) ? \true : \false); }, 5); add_action('init', new ReviewXoldPluginDeactivateHandler(), 10); add_action('init', new PageBuilderHandler(), 20); // add_action('upgrader_process_complete', new ResetProductMetaHandler(), 5, 2); add_action('upgrader_process_complete', new UpgradeReviewxDeactiveProHandler(), 10, 2); // add_action('admin_notices', [new ReviewxAdminNoticeHandler(), 'adminNoticeHandler']); // add_action('wp_ajax_rvx_dismiss_notice', [new ReviewxAdminNoticeHandler(), 'rvx_admin_deal_notice_until']); // Upgrade the WP DB to new v2.1.6 add_action('admin_init', [new UpgradeDBSettings(), 'run_upgrade']); add_action('wp_trash_post', new ProductDeleteHandler(), 10, 1); add_action('untrash_post', new ProductUntrashHandler(), 10, 1); add_action('woocommerce_new_order', new OrderCreateHandler()); add_action('woocommerce_order_status_changed', new OrderStatusChangedHandler(), 10, 4); add_action('woocommerce_delete_order', new OrderDeleteHandler()); /** * Category Hook */ add_action('create_term', new CategoryCreateHandler()); add_action('delete_term', [new CategoryDeleteHandler(), 'deleteHandler'], 10, 5); add_action('edited_term', new CategoryUpdateHandler()); /** * Customer Hook */ add_action('user_register', new UserHandler()); add_action('delete_user', new UserDeleteHandler()); add_action('profile_update', new UserUpdateHandler()); add_action('woocommerce_update_order', new OrderUpdateHandler(), 10, 1); add_action('process_order_update', new OrderUpdateProcessHandler(), 20); /** * Importd product */ add_action('woocommerce_product_import_inserted_product_object', new ProductImportHandler(), 20, 2); /** * Woocommerce Hooks */ add_action('wp_footer', [new StorefrontReviewLinkClickScroll(), 'addScrollScript'], 10, 2); /** * Woocommerce review table sync with saas */ add_action('transition_comment_status', new WooReviewTableHandler(), 10, 3); /** * Woocommerce review replay comments */ add_action('comment_post', new ReplyCommentHandler(), 10, 3); /** * CPT Posts - Create/Update */ add_action('save_post', new CptPostHandler(), 10, 3); // Ensure rating is calculated BEFORE sync (priority 9 < 10) add_action('save_post', [CptAverageRating::class, 'update_average_rating'], 9, 3); // add_action('transition_post_status', new ProductHandler(), 10, 3); // add_action('woocommerce_update_product', new ProductUpdateHandler()); // Remove Comment / Review Meta box from Add/Edit page (post/product) add_action('add_meta_boxes', [new CommentsReviewsMetaBoxRemover(), 'removeCommentsReviewsMetaBox'], 99); // Remove the 'comment_row_actions' filter add_filter('comment_row_actions', [new CommentsReviewsRowActionRemover(), 'removeCommentsReviewsRowActions'], 999, 2); // Filter comments for ReviewX-enabled post types from WP Comments admin page add_action('pre_get_comments', [new CommentsReviewsFilter(), 'filterCommentsForReviewxPostTypes'], 10); // WooCommerce Reviews page redirect notice and filtering (Products -> Reviews) add_action('admin_notices', [new WooReviewsRedirectHandler(), 'displayRedirectNotice']); add_filter('comments_clauses', [new WooReviewsRedirectHandler(), 'filterWooReviewsClauses'], 100, 2); // Block editing of comments/reviews for ReviewX-enabled post types on WP Comment Edit page add_action('admin_notices', [new CommentEditBlockHandler(), 'displayEditBlockedNotice']); add_action('admin_init', [new CommentEditBlockHandler(), 'maybeRedirectFromEditPage']); // Add the new column for rating // add_filter('manage_edit-comments_columns', [new CommentsRatingColumn(), 'addRatingColumn']); // Populate the new column with rating data // add_action('manage_comments_custom_column', [new CommentsRatingColumn(), 'populateRatingColumn'], 10, 2); // Add sorting functionality to comments (ReviewX Rating) Column //add_filter('manage_edit-comments_sortable_columns', [new CommentsRatingColumn(), 'makeRatingColumnSortable']); // add_action('pre_get_comments', [new CommentsRatingColumn(), 'sortCommentsByRating']); // Rating column for CPT/ Product // Hook into the admin_init action to instantiate the PostsRatingColumn class add_action('admin_init', [new PostsRatingColumn(), 'addColumn']); /** * CPT comments / reviews */ add_action('wp_insert_comment', function ($comment_id, $comment) { if ($comment && $comment->comment_post_ID) { // 1. Update average rating locally CptAverageRating::update_average_rating($comment->comment_post_ID); // 2. Sync updated post data to SaaS $post = get_post($comment->comment_post_ID); if ($post) { (new CptPostHandler())->__invoke($post->ID, $post, \true); } } }, 999, 2); add_action('comment_post', function ($comment_id, $comment_approved, $comment) { // 1. Update average rating locally CptAverageRating::handle_comment_rating($comment_id, $comment_approved, $comment); // 2. Sync updated post data to SaaS if we have a comment object if ($comment) { $post_id = $comment->comment_post_ID; $post = get_post($post_id); if ($post) { (new CptPostHandler())->__invoke($post->ID, $post, \true); } } }, 999, 3); add_action('get_comments_number', [new CptCommentsLinkMeta(), 'replace_total_comments_count'], 999, 2); add_action('edit_comment', function ($comment_id) { $comment = get_comment($comment_id); if ($comment && $comment->comment_post_ID) { // 1. Update average rating locally CptAverageRating::update_average_rating($comment->comment_post_ID); // 2. Sync updated post data to SaaS $post = get_post($comment->comment_post_ID); if ($post) { (new CptPostHandler())->__invoke($post->ID, $post, \true); } } }, 999); add_action('wp_set_comment_status', function ($comment_id, $status) { // 1. Update average rating locally CptAverageRating::handle_comment_status_change($comment_id, $status); // 2. Sync updated post data to SaaS $comment = get_comment($comment_id); if ($comment) { $post = get_post($comment->comment_post_ID); if ($post) { (new CptPostHandler())->__invoke($post->ID, $post, \true); } } }, 999, 2); // Removed redundant save_post hook for CptAverageRating as it's now registered above with correct priority add_action('deleted_comment', function ($comment_id) { $comment = get_comment($comment_id); if ($comment && $comment->comment_post_ID) { // 1. Update average rating locally CptAverageRating::update_average_rating($comment->comment_post_ID); // 2. Sync updated post data to SaaS $post = get_post($comment->comment_post_ID); if ($post) { (new CptPostHandler())->__invoke($post->ID, $post, \true); } } }, 999); /** * Rich Schema */ if (!is_admin()) { add_action('wp_head', [CptRichSchemaHandler::class, 'addCustomRichSchema'], 10, 2); add_action('woocommerce_structured_data_product', new WoocommerceRichSchemaHandler(), 10, 2); } /** * Woocommerce Comment status */ // add_action('wp_set_comment_status', new WoocommerceCommentStatusChangeHandler(), 10, 2); add_filter('bulk_actions-edit-comments', new CustomBulkActionsForReviewsHandler()); add_filter('handle_bulk_actions', new RegisterBulkActionsForReviewsHandler(), 10, 3); add_action('woocommerce_settings_save_products', [new WoocommerceSettingsSaveHandler(), 'wooProductSaveHandler'], 10); /** * Woocommerce Edit Comment/Review */ add_action('edit_comment', new WooCommerceReviewEditForm(), 10, 2); /** * Woocommerce Template Modify */ add_filter('woocommerce_locate_template', new WoocommerceLocateTemplateHandler(), 10, 3); //Woocommerce Avatar add_action('woocommerce_edit_account_form', new WcEditAccountForm(), 10); // add_action('woocommerce_save_account_details_errors', new WcAccountDetailsError(), 10, 1); add_action('woocommerce_save_account_details', new WcAccountDetails(), 20, 1); add_action('woocommerce_edit_account_form_tag', new WcAccountFormTag(), 20, 1); add_filter('woocommerce_checkout_fields', new WcSendEmailPermissionHandler(), 20, 1); /* * Load Appearance -> Customize - ReviewX */ add_action('customize_register', new WidgetCustomizeOptionsHandler(), 10); add_action('wp_head', new WidgetCustomizeOutputCSSHandler(), 20); /* * Comment / Review Form Injection on Front-end */ add_action('init', [ReviewForm::class, 'post_type_support']); add_filter('comments_template', [ReviewForm::class, 'comments_template_init'], \PHP_INT_MAX); // Load plugin textdomain add_action('init', function () { load_plugin_textdomain('reviewx', \false, \dirname(plugin_basename(__FILE__)) . '/languages'); }, 15, 5); // Defer localization until scripts are enqueued add_action('admin_enqueue_scripts', [$this, 'localizeScripts'], 20); add_action('wp_enqueue_scripts', [$this, 'localizeScripts'], 20); } public function localizeScripts() : void { $locals = ['rvx_localization_data_for_admin' => \Rvx\Utilities\Helper::prepareLangArray(), 'rvx_full_domain_name' => \Rvx\Utilities\Helper::domainSupport(), 'rvx_full_domain_api' => \Rvx\Utilities\Helper::getRestAPIurl()]; // Localize for admin handles if they exist wp_localize_script('rvx_user_access_script', 'rvx_locals', $locals); // Localize for frontend handles if needed wp_localize_script('reviewx-storefront', 'rvx_locals', $locals); } } Handlers/DataSyncHandler.php 0000777 00000004133 15251220643 0012031 0 ustar 00 <?php namespace Rvx\Handlers; class DataSyncHandler { // public function wc_data_exists_in_db(): bool // { // global $wpdb; // $query = " // (SELECT 'product' AS type // FROM {$wpdb->posts} // WHERE post_type = 'product' // LIMIT 1) // UNION ALL // (SELECT 'shop_order' AS type // FROM {$wpdb->posts} // WHERE post_type = 'shop_order' // LIMIT 1) // UNION ALL // (SELECT 'taxonomy' AS type // FROM {$wpdb->term_taxonomy} // WHERE taxonomy IN ('product_cat', 'product_tag') // LIMIT 1) // "; // $results = $wpdb->get_col($query); // return !empty($results); // } public function wc_data_exists_in_db() : bool { global $wpdb; $query = "\n SELECT \n (EXISTS(SELECT 1 FROM {$wpdb->posts} WHERE post_type = 'product' LIMIT 1)) AS has_product,\n (EXISTS(SELECT 1 FROM {$wpdb->posts} WHERE post_type = 'shop_order' LIMIT 1)) AS has_order,\n (EXISTS(SELECT 1 FROM {$wpdb->term_taxonomy} WHERE taxonomy IN ('product_cat', 'product_tag') LIMIT 1)) AS has_taxonomy\n "; $row = $wpdb->get_row($query, ARRAY_A); return \in_array(1, $row, \true); } public function getProductTaxonomies() : array { // Try to get taxonomies via WP API if possible if (post_type_exists('product')) { $taxonomies = get_object_taxonomies('product', 'names'); if (!empty($taxonomies)) { return $taxonomies; } } // Fallback to DB-only method if API fails or WooCommerce is disabled global $wpdb; return $wpdb->get_col("\n SELECT DISTINCT tt.taxonomy\n FROM {$wpdb->term_relationships} tr\n INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id\n INNER JOIN {$wpdb->posts} p ON tr.object_id = p.ID\n WHERE p.post_type = 'product'\n ") ?: []; } } Handlers/OnboardMenuHandler.php 0000777 00000002232 15251220643 0012532 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Handlers\MigrationRollback\SharedMethods; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class OnboardMenuHandler implements InvokableContract { public function __invoke() { global $wpdb; $rvxSites = $wpdb->prefix . 'rvx_sites'; $wpdb->query("TRUNCATE TABLE {$rvxSites}"); $sharedMethods = new SharedMethods(); $is_pro_active = $sharedMethods->rvx_is_old_pro_plugin_active(); if ($is_pro_active === \true) { // Old Pro version is detected, let's deactivate $sharedMethods->rvx_deactivate_old_pro_plugin(); // Reload the page once to remove Old Pro plugin's notices if (!isset($_GET['rvx_reloaded'])) { //$url = add_query_arg('rvx_reloaded', '1', $_SERVER['REQUEST_URI']); $url = add_query_arg('', '', $_SERVER['REQUEST_URI']); \header('Location: ' . $url); exit; } } View::output('storeadmin/onboard', ['title' => 'Welcome to WPDrill', 'content' => 'A WordPress Plugin development framework for humans']); } } Handlers/GoogleReviewsHandler.php 0000777 00000000544 15251220643 0013106 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class GoogleReviewsHandler implements InvokableContract { public function __invoke() { View::output('storeadmin/google', ['title' => 'Welcome to WPDrill', 'content' => 'A WordPress Plugin development framework for humans']); } } Handlers/AllReviewsHandler.php 0000777 00000000540 15251220643 0012376 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class AllReviewsHandler implements InvokableContract { public function __invoke() { View::output('storeadmin/index', ['title' => 'Welcome to WPDrill', 'content' => 'A WordPress Plugin development framework for humans']); } } Handlers/Customize/WidgetCustomizeOutputCSSHandler.php 0000777 00000071264 15251220643 0017236 0 ustar 00 <?php namespace Rvx\Handlers\Customize; class WidgetCustomizeOutputCSSHandler { public function __invoke() : void { if (!did_action('elementor/loaded')) { $this->rvx_load_customizer_output_css(); } } public function rvx_load_customizer_output_css() : void { /* * ReviewX - General Settings */ // Active Rating Stars: [Background Color] //$rvx_general_reviews_active_rating_stars_background_color = get_theme_mod( 'rvx_general_reviews_active_rating_stars_background_color', '#FCCE08'); /* * ReviewX - Reviews Overview */ // Rating out of $rvx_reviews_overview_rating_out_of_text_color = get_theme_mod('rvx_reviews_overview_rating_out_of_text_color', '#424242'); $rvx_reviews_overview_rating_out_of_text_font_size = get_theme_mod('rvx_reviews_overview_rating_out_of_text_font_size', 43.942); // Rating out of Total $rvx_reviews_overview_rating_out_of_total_text_color = get_theme_mod('rvx_reviews_overview_rating_out_of_total_text_color', '#BDBDBD'); $rvx_reviews_overview_rating_out_of_total_text_font_size = get_theme_mod('rvx_reviews_overview_rating_out_of_total_text_font_size', 24); // Rating Badge $rvx_reviews_overview_rating_badge_background_color = get_theme_mod('rvx_reviews_overview_rating_badge_background_color', '#22C55E'); $rvx_reviews_overview_rating_badge_text_color = get_theme_mod('rvx_reviews_overview_rating_badge_text_color', '#FFFFFF'); // Total Reviews Count $rvx_reviews_overview_total_reviews_text_color = get_theme_mod('rvx_reviews_overview_total_reviews_text_color', '#424242'); $rvx_reviews_overview_total_reviews_text_font_size = get_theme_mod('rvx_reviews_overview_total_reviews_text_font_size', 16); // Rating Overview Chart $rvx_reviews_overview_rating_overview_chart_text_color = get_theme_mod('rvx_reviews_overview_rating_overview_chart_text_color', '#424242'); $rvx_reviews_overview_rating_overview_chart_text_font_size = get_theme_mod('rvx_reviews_overview_rating_overview_chart_text_font_size', 14); // Product Recommendation Text $rvx_reviews_overview_product_recommendation_background_color = get_theme_mod('rvx_reviews_overview_product_recommendation_background_color', '#F5F5F5'); $rvx_reviews_overview_product_recommendation_border_color = get_theme_mod('rvx_reviews_overview_product_recommendation_border_color', '#F5F5F5'); $rvx_reviews_overview_product_recommendation_border_radius = get_theme_mod('rvx_reviews_overview_product_recommendation_border_radius', 4); $rvx_reviews_overview_product_recommendation_text_color = get_theme_mod('rvx_reviews_overview_product_recommendation_text_color', '#424242'); $rvx_reviews_overview_product_recommendation_text_font_size = get_theme_mod('rvx_reviews_overview_product_recommendation_text_font_size', 14); // Review Criteria Text $rvx_reviews_overview_review_criteria_text_color = get_theme_mod('rvx_reviews_overview_review_criteria_text_color', '#424242'); $rvx_reviews_overview_review_criteria_text_font_size = get_theme_mod('rvx_reviews_overview_review_criteria_text_font_size', 14); /* * ReviewX - Filter Buttons */ // Filter Button $rvx_filter_button_text_color = get_theme_mod('rvx_filter_button_text_color', '#424242'); $rvx_filter_button_background_color = get_theme_mod('rvx_filter_button_background_color', '#F0F0F1'); $rvx_filter_button_border_color = get_theme_mod('rvx_filter_button_border_color', '#BDBDBD'); $rvx_filter_button_border_radius = get_theme_mod('rvx_filter_button_border_radius', 4); // Filter Dropdown menu $rvx_filter_dropdown_menu_text_color = get_theme_mod('rvx_filter_dropdown_menu_text_color', '#616161'); $rvx_filter_dropdown_menu_background_color = get_theme_mod('rvx_filter_dropdown_menu_background_color', '#FFFFFF'); $rvx_filter_dropdown_menu_border_color = get_theme_mod('rvx_filter_dropdown_menu_border_color', '#FFFFFF'); $rvx_filter_dropdown_menu_border_radius = get_theme_mod('rvx_filter_dropdown_menu_border_radius', 4); $rvx_filter_dropdown_menu_text_font_size = get_theme_mod('rvx_filter_dropdown_menu_text_font_size', 14); // Filter Dropdown [Filter by] $rvx_filter_by_text_color = get_theme_mod('rvx_filter_by_text_color', '#424242'); $rvx_filter_by_text_font_size = get_theme_mod('rvx_filter_by_text_font_size', 16); // Filter Dropdown menu: [Reset filters] button $rvx_filter_reset_button_text_color = get_theme_mod('rvx_filter_reset_button_text_color', '#0043DD'); $rvx_filter_reset_button_background_color = get_theme_mod('rvx_filter_reset_button_background_color', '#FFFFFF'); $rvx_filter_reset_button_border_color = get_theme_mod('rvx_filter_reset_button_border_color', '#FFFFFF'); $rvx_filter_reset_button_border_radius = get_theme_mod('rvx_filter_reset_button_border_radius', 4); // Filter Dropdown menu: [Apply] button $rvx_filter_apply_button_text_color = get_theme_mod('rvx_filter_apply_button_text_color', '#FFFFFF'); $rvx_filter_apply_button_background_color = get_theme_mod('rvx_filter_apply_button_background_color', '#0043DD'); $rvx_filter_apply_button_border_color = get_theme_mod('rvx_filter_apply_button_border_color', '#0043DD'); $rvx_filter_apply_button_border_radius = get_theme_mod('rvx_filter_apply_button_border_radius', 4); // Sort Button $rvx_sort_button_text_color = get_theme_mod('rvx_sort_button_text_color', '#424242'); $rvx_sort_button_background_color = get_theme_mod('rvx_sort_button_background_color', '#F0F0F1'); $rvx_sort_button_border_color = get_theme_mod('rvx_sort_button_border_color', '#BDBDBD'); $rvx_sort_button_border_radius = get_theme_mod('rvx_sort_button_border_radius', 4); // Sort Dropdown menu $rvx_sort_dropdown_menu_text_color = get_theme_mod('rvx_sort_dropdown_menu_text_color', '#616161'); $rvx_sort_dropdown_menu_background_color = get_theme_mod('rvx_sort_dropdown_menu_background_color', '#FFFFFF'); $rvx_sort_dropdown_menu_border_color = get_theme_mod('rvx_sort_dropdown_menu_border_color', '#FFFFFF'); $rvx_sort_dropdown_menu_border_radius = get_theme_mod('rvx_sort_dropdown_menu_border_radius', 4); $rvx_sort_dropdown_menu_text_font_size = get_theme_mod('rvx_sort_dropdown_menu_text_font_size', 14); // Write a Review Button //$rvx_write_review_button_text_color = get_theme_mod('rvx_write_review_button_text_color', '#424242'); //$rvx_write_review_button_background_color = get_theme_mod( 'rvx_write_review_button_background_color', '#BDBDBD'); $rvx_write_review_button_border_color = get_theme_mod('rvx_write_review_button_border_color', '#0043DD'); $rvx_write_review_button_border_radius = get_theme_mod('rvx_write_review_button_border_radius', 4); /* * ReviewX - Review Items */ // Review Items: Card $rvx_reviews_items_card_background_color = get_theme_mod('rvx_reviews_items_card_background_color', '#F5F5F5'); $rvx_reviews_items_card_border_color = get_theme_mod('rvx_reviews_items_card_border_color', '#F5F5F5'); $rvx_reviews_items_card_border_radius = get_theme_mod('rvx_reviews_items_card_border_radius', 6); $rvx_reviews_items_card_inline_padding = get_theme_mod('rvx_reviews_items_card_inline_padding', 8); // Review Items: Reviewer Name $rvx_reviews_items_reviewer_name_text_color = get_theme_mod('rvx_reviews_items_reviewer_name_text_color', '#424242'); $rvx_reviews_items_reviewer_name_text_font_size = get_theme_mod('rvx_reviews_items_reviewer_name_text_font_size', 20); // Review Items: Review Title $rvx_reviews_items_title_text_color = get_theme_mod('rvx_reviews_items_title_text_color', '#424242'); $rvx_reviews_items_title_text_font_size = get_theme_mod('rvx_reviews_items_title_text_font_size', 20); // Review Items: Review Date $rvx_reviews_items_date_text_color = get_theme_mod('rvx_reviews_items_date_text_color', '#757575'); $rvx_reviews_items_date_text_font_size = get_theme_mod('rvx_reviews_items_date_text_font_size', 14); // Review Items: Description $rvx_reviews_items_description_text_color = get_theme_mod('rvx_reviews_items_description_text_color', '#757575'); $rvx_reviews_items_description_text_font_size = get_theme_mod('rvx_reviews_items_description_text_font_size', 14); /* * ReviewX - Review Form */ // Form $rvx_input_form_background_color = get_theme_mod('rvx_input_form_background_color', '#F5F5F5'); // Disabled - already available in ReviewX-> Widget Settings $rvx_input_form_border_color = get_theme_mod('rvx_input_form_border_color', '#F5F5F5'); $rvx_input_form_border_radius = get_theme_mod('rvx_input_form_border_radius', 6); // Form: Title $rvx_input_form_title_text_color = get_theme_mod('rvx_input_form_title_text_color', '#424242'); $rvx_input_form_title_text_font_size = get_theme_mod('rvx_input_form_title_text_font_size', 18); // Form: Product Name $rvx_input_form_product_name_text_color = get_theme_mod('rvx_input_form_product_name_text_color', '#424242'); $rvx_input_form_product_name_text_font_size = get_theme_mod('rvx_input_form_product_name_text_font_size', 18); // Form: Criteria Title $rvx_input_form_criteria_title_text_color = get_theme_mod('rvx_input_form_criteria_title_text_color', '#424242'); $rvx_input_form_criteria_title_text_font_size = get_theme_mod('rvx_input_form_criteria_title_text_font_size', 16); // Form: Review Title $rvx_input_form_review_title_text_color = get_theme_mod('rvx_input_form_review_title_text_color', '#424242'); $rvx_input_form_review_title_text_font_size = get_theme_mod('rvx_input_form_review_title_text_font_size', 16); // Form: Description Title $rvx_input_form_description_title_text_color = get_theme_mod('rvx_input_form_description_title_text_color', '#424242'); $rvx_input_form_description_title_text_font_size = get_theme_mod('rvx_input_form_description_title_text_font_size', 16); // Form: Full Name $rvx_input_form_full_name_text_color = get_theme_mod('rvx_input_form_full_name_text_color', '#424242'); $rvx_input_form_full_name_text_font_size = get_theme_mod('rvx_input_form_full_name_text_font_size', 16); // Form: Email Address $rvx_input_form_email_address_text_color = get_theme_mod('rvx_input_form_email_address_text_color', '#424242'); $rvx_input_form_email_address_text_font_size = get_theme_mod('rvx_input_form_email_address_text_font_size', 16); // Form: Attachment Title $rvx_input_form_attachment_title_text_color = get_theme_mod('rvx_input_form_attachment_title_text_color', '#424242'); $rvx_input_form_attachment_title_text_font_size = get_theme_mod('rvx_input_form_attachment_title_text_font_size', 16); // Form: Mark as Anonymous $rvx_input_form_mark_anonymous_text_color = get_theme_mod('rvx_input_form_mark_anonymous_text_color', '#424242'); $rvx_input_form_mark_anonymous_text_font_size = get_theme_mod('rvx_input_form_mark_anonymous_text_font_size', 16); // Form: Recommended? $rvx_input_form_recommended_text_color = get_theme_mod('rvx_input_form_recommended_text_color', '#424242'); $rvx_input_form_recommended_text_font_size = get_theme_mod('rvx_input_form_recommended_text_font_size', 16); // Form: Submit Review Button //$rvx_submit_review_button_text_color = get_theme_mod('rvx_submit_review_button_text_color', '#FFFFFF'); //$rvx_submit_review_button_background_color = get_theme_mod( 'rvx_submit_review_button_background_color', '#0043DD'); $rvx_submit_review_button_border_color = get_theme_mod('rvx_submit_review_button_border_color', '#0043DD'); $rvx_submit_review_button_border_radius = get_theme_mod('rvx_submit_review_button_border_radius', 6); ?> <style type="text/css"> /* * ReviewX - Reviews Overview */ #rvx-storefront-widget p.rvx-rating-out-of, p.rvx-rating-out-of{ color: <?php echo esc_attr($rvx_reviews_overview_rating_out_of_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_reviews_overview_rating_out_of_text_font_size); ?>px !important; } #rvx-storefront-widget span.rvx-rating-total, span.rvx-rating-total{ color: <?php echo esc_attr($rvx_reviews_overview_rating_out_of_total_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_reviews_overview_rating_out_of_total_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-rating-badge, .rvx-rating-badge{ background-color: <?php echo esc_attr($rvx_reviews_overview_rating_badge_background_color); ?> !important; color: <?php echo esc_attr($rvx_reviews_overview_rating_badge_text_color); ?> !important; } /* #rvx-storefront-widget .rvx-review-form__star-active, .rvx-review-form__star-active{ fill:<?php //echo esc_attr($rvx_general_reviews_active_rating_stars_background_color); ?>; } #rvx-storefront-widget .rvx-review-form__star-active-half-star, .rvx-review-form__star-active-half-star{ stop-color:<?php //echo esc_attr($rvx_general_reviews_active_rating_stars_background_color); ?>; } #rvx-storefront-widget .rvx-aggregation__rating-icon path, .rvx-aggregation__rating-icon path{ fill:<?php //echo esc_attr($rvx_general_reviews_active_rating_stars_background_color); ?>; } #rvx-storefront-widget .rvx-aggregation__rating-icon, .rvx-aggregation__rating-icon{ fill:<?php //echo esc_attr($rvx_general_reviews_active_rating_stars_background_color); ?>; } */ #rvx-storefront-widget p.rvx-total-review, p.rvx-total-review{ color: <?php echo esc_attr($rvx_reviews_overview_total_reviews_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_reviews_overview_total_reviews_text_font_size); ?>px !important; } #rvx-storefront-widget tr.rvx-aggregation__row td span, tr.rvx-aggregation__row td span{ color: <?php echo esc_attr($rvx_reviews_overview_rating_overview_chart_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_reviews_overview_rating_overview_chart_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-recommendation-count, .rvx-recommendation-count{ background-color: <?php echo esc_attr($rvx_reviews_overview_product_recommendation_background_color); ?> !important; border:solid 1px <?php echo esc_attr($rvx_reviews_overview_product_recommendation_border_color); ?> !important; border-radius: <?php echo esc_attr($rvx_reviews_overview_product_recommendation_border_radius); ?>px !important; } #rvx-storefront-widget .rvx-recommendation-count p, .rvx-recommendation-count p{ color: <?php echo esc_attr($rvx_reviews_overview_product_recommendation_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_reviews_overview_product_recommendation_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-recommendation-count svg, .rvx-recommendation-count svg{ width:<?php echo esc_attr($rvx_reviews_overview_product_recommendation_text_font_size); ?>; height:<?php echo esc_attr($rvx_reviews_overview_product_recommendation_text_font_size); ?>; } #rvx-storefront-widget .rvx-aggregation-multicriteria span, .rvx-aggregation-multicriteria span{ color: <?php echo esc_attr($rvx_reviews_overview_review_criteria_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_reviews_overview_review_criteria_text_font_size); ?>px !important; } /* * ReviewX - Filter Buttons */ #rvx-storefront-widget .rvx-review-filter__button, .rvx-review-filter__button{ color: <?php echo esc_attr($rvx_filter_button_text_color); ?> !important; background-color: <?php echo esc_attr($rvx_filter_button_background_color); ?> !important; } #rvx-storefront-widget .rvx-review-filter__button, .rvx-review-filter__button{ border:solid 1px <?php echo esc_attr($rvx_filter_button_border_color); ?> !important; border-radius: <?php echo esc_attr($rvx_filter_button_border_radius); ?>px !important; } #rvx-storefront-widget .rvx-review-filter-wrapper, .rvx-review-filter-wrapper{ color: <?php echo esc_attr($rvx_filter_dropdown_menu_text_color); ?> !important; background-color: <?php echo esc_attr($rvx_filter_dropdown_menu_background_color); ?> !important; border:solid 1px <?php echo esc_attr($rvx_filter_dropdown_menu_border_color); ?> !important; border-radius: <?php echo esc_attr($rvx_filter_dropdown_menu_border_radius); ?>px !important; font-size: <?php echo esc_attr($rvx_filter_dropdown_menu_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-filter-wrapper p.rvx-review-filter-wrapper__title, .rvx-review-filter-wrapper p.rvx-review-filter-wrapper__title{ color: <?php echo esc_attr($rvx_filter_by_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_filter_by_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-filter-wrapper__footer-reset-button, .rvx-review-filter-wrapper__footer-reset-button{ color: <?php echo esc_attr($rvx_filter_reset_button_text_color); ?> !important; background-color: <?php echo esc_attr($rvx_filter_reset_button_background_color); ?> !important; border:solid 1px <?php echo esc_attr($rvx_filter_reset_button_border_color); ?> !important; border-radius: <?php echo esc_attr($rvx_filter_reset_button_border_radius); ?>px !important; } #rvx-storefront-widget .rvx-review-filter-wrapper__footer-save-button, .rvx-review-filter-wrapper__footer-save-button{ color: <?php echo esc_attr($rvx_filter_apply_button_text_color); ?> !important; background-color: <?php echo esc_attr($rvx_filter_apply_button_background_color); ?> !important; border:solid 1px <?php echo esc_attr($rvx_filter_apply_button_border_color); ?> !important; border-radius: <?php echo esc_attr($rvx_filter_apply_button_border_radius); ?>px !important; } #rvx-storefront-widget .rvx-review-sort__button, .rvx-review-sort__button{ color: <?php echo esc_attr($rvx_sort_button_text_color); ?> !important; background-color: <?php echo esc_attr($rvx_sort_button_background_color); ?> !important; border:solid 1px <?php echo esc_attr($rvx_sort_button_border_color); ?> !important; border-radius: <?php echo esc_attr($rvx_sort_button_border_radius); ?>px !important; } #rvx-storefront-widget .rvx-review-sort-wrapper__outer, .rvx-review-sort-wrapper__outer{ color: <?php echo esc_attr($rvx_sort_dropdown_menu_text_color); ?> !important; background-color: <?php echo esc_attr($rvx_sort_dropdown_menu_background_color); ?> !important; border:solid 1px <?php echo esc_attr($rvx_sort_dropdown_menu_border_color); ?> !important; border-radius: <?php echo esc_attr($rvx_sort_dropdown_menu_border_radius); ?>px !important; font-size: <?php echo esc_attr($rvx_sort_dropdown_menu_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-write__button, .rvx-review-write__button{ border:solid 1px <?php echo esc_attr($rvx_write_review_button_border_color); ?> !important; border-radius: <?php echo esc_attr($rvx_write_review_button_border_radius); ?>px !important; } /* * ReviewX - Review Items */ #rvx-storefront-widget .rvx-review-wrapper .rvx-review-card, .rvx-review-wrapper .rvx-review-card{ background-color: <?php echo esc_attr($rvx_reviews_items_card_background_color); ?> !important; border:solid 1px <?php echo esc_attr($rvx_reviews_items_card_border_color); ?> !important; border-radius: <?php echo esc_attr($rvx_reviews_items_card_border_radius); ?>px !important; padding: <?php echo esc_attr($rvx_reviews_items_card_inline_padding); ?>px !important; } #rvx-storefront-widget .rvx-review-wrapper .rvx-review-card .rvx-review-user__name, .rvx-review-wrapper .rvx-review-card .rvx-review-user__name{ color: <?php echo esc_attr($rvx_reviews_items_reviewer_name_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_reviews_items_reviewer_name_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-wrapper .rvx-review-card .rvx-review-info__title, .rvx-review-wrapper .rvx-review-card .rvx-review-info__title{ color: <?php echo esc_attr($rvx_reviews_items_title_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_reviews_items_title_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-wrapper .rvx-review-card .rvx-review-info__date, .rvx-review-wrapper .rvx-review-card .rvx-review-info__date{ color: <?php echo esc_attr($rvx_reviews_items_date_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_reviews_items_date_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-wrapper .rvx-review-card .rvx-review-info__feedback, .rvx-review-wrapper .rvx-review-card .rvx-review-info__feedback{ color: <?php echo esc_attr($rvx_reviews_items_description_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_reviews_items_description_text_font_size); ?>px !important; } /* * ReviewX - Review Form */ #rvx-storefront-widget #rvx-review-form__wrapper, #rvx-review-form__wrapper{ background-color: <?php echo esc_attr($rvx_input_form_background_color); ?> !important; border:solid 1px <?php echo esc_attr($rvx_input_form_border_color); ?> !important; border-radius: <?php echo esc_attr($rvx_input_form_border_radius); ?>px !important; } #rvx-storefront-widget .rvx-review-form__title, .rvx-review-form__title{ color: <?php echo esc_attr($rvx_input_form_title_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_input_form_title_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-form__product--title, .rvx-review-form__product--title{ color: <?php echo esc_attr($rvx_input_form_product_name_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_input_form_product_name_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-form__multicriteria--name, .rvx-review-form__multicriteria--name{ color: <?php echo esc_attr($rvx_input_form_criteria_title_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_input_form_criteria_title_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-form__title--name, .rvx-review-form__title--name{ color: <?php echo esc_attr($rvx_input_form_review_title_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_input_form_review_title_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-form__description-title, .rvx-review-form__description-title{ color: <?php echo esc_attr($rvx_input_form_description_title_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_input_form_description_title_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-form__user--name, .rvx-review-form__user--name{ color: <?php echo esc_attr($rvx_input_form_full_name_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_input_form_full_name_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-form__email--name, .rvx-review-form__email--name{ color: <?php echo esc_attr($rvx_input_form_email_address_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_input_form_email_address_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-form__attachment--name, .rvx-review-form__attachment--name{ color: <?php echo esc_attr($rvx_input_form_attachment_title_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_input_form_attachment_title_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-form__mark-anonymous, .rvx-review-form__mark-anonymous{ color: <?php echo esc_attr($rvx_input_form_mark_anonymous_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_input_form_mark_anonymous_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-form__recommended--name, .rvx-review-form__recommended--name{ color: <?php echo esc_attr($rvx_input_form_recommended_text_color); ?> !important; font-size: <?php echo esc_attr($rvx_input_form_recommended_text_font_size); ?>px !important; } #rvx-storefront-widget .rvx-review-form__submit--button, .rvx-review-form__submit--button{ border:solid 1px <?php echo esc_attr($rvx_submit_review_button_border_color); ?> !important; border-radius: <?php echo esc_attr($rvx_submit_review_button_border_radius); ?>px !important; } </style> <?php } } Handlers/Customize/WidgetCustomizeOptionsHandler.php 0000777 00000142317 15251220643 0017016 0 ustar 00 <?php namespace Rvx\Handlers\Customize; use WP_Customize_Color_Control; class WidgetCustomizeOptionsHandler { public function __invoke($wp_customize) : void { //if (!did_action('elementor/loaded')) { $this->rvx_customizer_options_data($wp_customize); //} } public static function rvx_customize_preview_js() : void { add_action('customize_preview_init', function () { wp_enqueue_script('reviewx-customize', RVX_CUSTOMIZER_URL . 'assets/js/rvx-customize.js', array('jquery', 'customize-preview'), '', \true); }); } public function rvx_customizer_options_data($wp_customize) : void { // ReviewX Customize options - live preview js $this->rvx_customize_preview_js(); // ReviewX Customize options Data $wp_customize->add_panel('reviewx_form_input', ['title' => __('ReviewX', 'reviewx'), 'description' => __('Customize ReviewX Settings', 'reviewx'), 'priority' => 160]); // Add Section to the Panel [ReviewX -> Reviews Overview Section] /** $wp_customize->add_section('rvx_general_settings_section', array( 'title' => __('General Settings', 'reviewx'), 'panel' => 'reviewx_form_input', 'priority' => 10, )); */ // Add Section to the Panel [ReviewX -> Reviews Overview Section] $wp_customize->add_section('rvx_reviews_overview_section', array('title' => __('Reviews Overview', 'reviewx'), 'panel' => 'reviewx_form_input', 'priority' => 10)); // Add Section to the Panel [ReviewX -> Filter Buttons Section] $wp_customize->add_section('rvx_filter_section', array('title' => __('Filter Buttons', 'reviewx'), 'panel' => 'reviewx_form_input', 'priority' => 10)); // Add Section to the Panel [ReviewX -> Review Items Section] $wp_customize->add_section('rvx_review_items_section', array('title' => __('Review Items', 'reviewx'), 'panel' => 'reviewx_form_input', 'priority' => 10)); // Add Section to the Panel [ReviewX -> Review Form Section] $wp_customize->add_section('rvx_form_section', array('title' => __('Review Form', 'reviewx'), 'panel' => 'reviewx_form_input', 'priority' => 10)); /** * ReviewX - General Settings */ // Active Rating Stars: [Background Color] /** $wp_customize->add_setting('rvx_general_reviews_active_rating_stars_background_color', array( 'default' => '#FCCE08', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage', )); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_general_reviews_active_rating_stars_background_color', array( 'label' => __('Active Rating Stars: [Background Color]', 'reviewx'), 'section' => 'rvx_general_settings_section', 'settings' => 'rvx_general_reviews_active_rating_stars_background_color', ))); */ /** * ReviewX - Reviews Overview */ // Rating out of: [Text Color] $wp_customize->add_setting('rvx_reviews_overview_rating_out_of_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_overview_rating_out_of_text_color', array('label' => __('Rating out of: [Text Color]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_rating_out_of_text_color'))); // Rating out of: [Font Size] $wp_customize->add_setting('rvx_reviews_overview_rating_out_of_text_font_size', array('default' => 43.942, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_overview_rating_out_of_text_font_size', array('label' => __('Rating out of: [Font Size]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_rating_out_of_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 100, 'step' => 1.0))); // Rating out of Total: [Text Color] $wp_customize->add_setting('rvx_reviews_overview_rating_out_of_total_text_color', array('default' => '#BDBDBD', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_overview_rating_out_of_total_text_color', array('label' => __('Rating out of Total: [Text Color]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_rating_out_of_total_text_color'))); // Rating out of Total: [Font Size] $wp_customize->add_setting('rvx_reviews_overview_rating_out_of_total_text_font_size', array('default' => 26.365, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_overview_rating_out_of_total_text_font_size', array('label' => __('Rating out of Total: [Font Size]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_rating_out_of_total_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 100, 'step' => 1.0))); // Rating Badge: [Background Color] $wp_customize->add_setting('rvx_reviews_overview_rating_badge_background_color', array('default' => '#22C55E', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_overview_rating_badge_background_color', array('label' => __('Rating Badge: [Background Color]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_rating_badge_background_color'))); // Rating Badge: [Text Color] $wp_customize->add_setting('rvx_reviews_overview_rating_badge_text_color', array('default' => '#FFFFFF', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_overview_rating_badge_text_color', array('label' => __('Rating Badge: [Text Color]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_rating_badge_text_color'))); // Total Reviews Count: [Text Color] $wp_customize->add_setting('rvx_reviews_overview_total_reviews_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_overview_total_reviews_text_color', array('label' => __('Total Reviews Count: [Text Color]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_total_reviews_text_color'))); // Total Reviews Count: [Font Size] $wp_customize->add_setting('rvx_reviews_overview_total_reviews_text_font_size', array('default' => 16, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_overview_total_reviews_text_font_size', array('label' => __('Total Reviews Count: [Font Size]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_total_reviews_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Rating Overview Chart: [Text Color] $wp_customize->add_setting('rvx_reviews_overview_rating_overview_chart_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_overview_rating_overview_chart_text_color', array('label' => __('Rating Overview Chart: [Text Color]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_rating_overview_chart_text_color'))); // Rating Overview Chart: [Font Size] $wp_customize->add_setting('rvx_reviews_overview_rating_overview_chart_text_font_size', array('default' => 14, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_overview_rating_overview_chart_text_font_size', array('label' => __('Rating Overview Chart: [Font Size]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_rating_overview_chart_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Product Recommendation: [Background Color] $wp_customize->add_setting('rvx_reviews_overview_product_recommendation_background_color', array('default' => '#F5F5F5', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_overview_product_recommendation_background_color', array('label' => __('Product Recommendation: [Background Color]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_product_recommendation_background_color'))); // Product Recommendation: [Border Color] $wp_customize->add_setting('rvx_reviews_overview_product_recommendation_border_color', array('default' => '#F5F5F5', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_overview_product_recommendation_border_color', array('label' => __('Product Recommendation: [Border Color]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_product_recommendation_border_color'))); // Product Recommendation: [Border Radius] $wp_customize->add_setting('rvx_reviews_overview_product_recommendation_border_radius', array('default' => 4, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_overview_product_recommendation_border_radius', array('label' => __('Product Recommendation: [Border Radius]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_product_recommendation_border_radius', 'type' => 'range', 'input_attrs' => array('min' => 0, 'max' => 50, 'step' => 1))); // Product Recommendation Text: [Text Color] $wp_customize->add_setting('rvx_reviews_overview_product_recommendation_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_overview_product_recommendation_text_color', array('label' => __('Product Recommendation Text: [Text Color]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_product_recommendation_text_color'))); // Product Recommendation Text: [Font Size] $wp_customize->add_setting('rvx_reviews_overview_product_recommendation_text_font_size', array('default' => 14, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_overview_product_recommendation_text_font_size', array('label' => __('Product Recommendation Text: [Font Size]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_product_recommendation_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Review Criteria Text: [Text Color] $wp_customize->add_setting('rvx_reviews_overview_review_criteria_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_overview_review_criteria_text_color', array('label' => __('Review Criteria Text: [Text Color]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_review_criteria_text_color'))); // Review Criteria Text: [Font Size] $wp_customize->add_setting('rvx_reviews_overview_review_criteria_text_font_size', array('default' => 14, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_overview_review_criteria_text_font_size', array('label' => __('Review Criteria Text: [Font Size]', 'reviewx'), 'section' => 'rvx_reviews_overview_section', 'settings' => 'rvx_reviews_overview_review_criteria_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); /* * ReviewX - Filter Buttons */ // Filter Button: [Text Color] $wp_customize->add_setting('rvx_filter_button_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_button_text_color', array('label' => __('Filter Button: [Text Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_button_text_color'))); // Filter Button: [Background Color] $wp_customize->add_setting('rvx_filter_button_background_color', array('default' => '#F0F0F1', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_button_background_color', array('label' => __('Filter Button: [Background Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_button_background_color'))); // Filter Button: [Border Color] $wp_customize->add_setting('rvx_filter_button_border_color', array('default' => '#BDBDBD', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_button_border_color', array('label' => __('Filter Button: [Border Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_button_border_color'))); // Filter Button: [Border Radius] $wp_customize->add_setting('rvx_filter_button_border_radius', array('default' => 4, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_filter_button_border_radius', array('label' => __('Filter Button: [Border Radius]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_button_border_radius', 'type' => 'range', 'input_attrs' => array('min' => 0, 'max' => 50, 'step' => 1))); // Filter by: [Text Color] $wp_customize->add_setting('rvx_filter_by_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_by_text_color', array('label' => __('Filter by: [Text Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_by_text_color'))); // Filter by: [Font Size] $wp_customize->add_setting('rvx_filter_by_text_font_size', array('default' => 16, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_filter_by_text_font_size', array('label' => __('Filter by: [Font Size]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_by_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Filter Dropdown Menu: [Text Color] $wp_customize->add_setting('rvx_filter_dropdown_menu_text_color', array('default' => '#616161', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_dropdown_menu_text_color', array('label' => __('Filter Dropdown Menu: [Text Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_dropdown_menu_text_color'))); // Filter Dropdown Menu: [Background Color] $wp_customize->add_setting('rvx_filter_dropdown_menu_background_color', array('default' => '#FFFFFF', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_dropdown_menu_background_color', array('label' => __('Filter Dropdown Menu: [Background Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_dropdown_menu_background_color'))); // Filter Dropdown Menu: [Border Color] $wp_customize->add_setting('rvx_filter_dropdown_menu_border_color', array('default' => '#FFFFFF', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_dropdown_menu_border_color', array('label' => __('Filter Dropdown Menu: [Border Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_dropdown_menu_border_color'))); // Filter Dropdown Menu: [Border Radius] $wp_customize->add_setting('rvx_filter_dropdown_menu_border_radius', array('default' => 4, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_filter_dropdown_menu_border_radius', array('label' => __('Filter Dropdown Menu: [Border Radius]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_dropdown_menu_border_radius', 'type' => 'range', 'input_attrs' => array('min' => 0, 'max' => 50, 'step' => 1))); // Filter Dropdown Menu: [Font Size] $wp_customize->add_setting('rvx_filter_dropdown_menu_text_font_size', array('default' => 14, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_filter_dropdown_menu_text_font_size', array('label' => __('Filter Dropdown Menu: [Font Size]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_dropdown_menu_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Filter Dropdown Menu: [Reset filters] button - [Text Color] $wp_customize->add_setting('rvx_filter_reset_button_text_color', array('default' => '#0043DD', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_reset_button_text_color', array('label' => __('Reset filters button: [Text Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_reset_button_text_color'))); // Filter Dropdown Menu: [Reset filters] button - [Background Color] $wp_customize->add_setting('rvx_filter_reset_button_background_color', array('default' => '#FFFFFF', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_reset_button_background_color', array('label' => __('Reset filters button: [Background Color]]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_reset_button_background_color'))); // Filter Dropdown Menu: [Reset filters] button - [Border Color] $wp_customize->add_setting('rvx_filter_reset_button_border_color', array('default' => '#FFFFFF', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_reset_button_border_color', array('label' => __('Reset filters button: [Border Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_reset_button_border_color'))); // Filter Dropdown Menu: [Reset filters] button - [Border Radius] $wp_customize->add_setting('rvx_filter_reset_button_border_radius', array('default' => 4, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_filter_reset_button_border_radius', array('label' => __('Reset filters button: [Border Radius]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_reset_button_border_radius', 'type' => 'range', 'input_attrs' => array('min' => 0, 'max' => 50, 'step' => 1))); // Filter Dropdown Menu: [Apply] button - [Text Color] $wp_customize->add_setting('rvx_filter_apply_button_text_color', array('default' => '#FFFFFF', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_apply_button_text_color', array('label' => __('Apply filters button: [Text Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_apply_button_text_color'))); // Filter Dropdown Menu: [Apply] button - [Background Color] $wp_customize->add_setting('rvx_filter_apply_button_background_color', array('default' => '#0043DD', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_apply_button_background_color', array('label' => __('Apply filters button: [Background Color]]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_apply_button_background_color'))); // Filter Dropdown Menu: [Apply] button - [Border Color] $wp_customize->add_setting('rvx_filter_apply_button_border_color', array('default' => '#0043DD', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_filter_apply_button_border_color', array('label' => __('Apply filters button: [Border Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_apply_button_border_color'))); // Filter Dropdown Menu: [Apply] button - [Border Radius] $wp_customize->add_setting('rvx_filter_apply_button_border_radius', array('default' => 4, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_filter_apply_button_border_radius', array('label' => __('Apply filters button: [Border Radius]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_filter_apply_button_border_radius', 'type' => 'range', 'input_attrs' => array('min' => 0, 'max' => 50, 'step' => 1))); // Sort Button: [Text Color] $wp_customize->add_setting('rvx_sort_button_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_sort_button_text_color', array('label' => __('Sort Button: [Text Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_sort_button_text_color'))); // Sort Button: [Background Color] $wp_customize->add_setting('rvx_sort_button_background_color', array('default' => '#F0F0F1', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_sort_button_background_color', array('label' => __('Sort Button: [Background Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_sort_button_background_color'))); // Sort Button: [Border Color] $wp_customize->add_setting('rvx_sort_button_border_color', array('default' => '#BDBDBD', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_sort_button_border_color', array('label' => __('Sort Button: [Border Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_sort_button_border_color'))); // Sort Button: [Border Radius] $wp_customize->add_setting('rvx_sort_button_border_radius', array('default' => 4, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_sort_button_border_radius', array('label' => __('Sort Button: [Border Radius]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_sort_button_border_radius', 'type' => 'range', 'input_attrs' => array('min' => 0, 'max' => 50, 'step' => 1))); // Sort Dropdown Menu: [Text Color] $wp_customize->add_setting('rvx_sort_dropdown_menu_text_color', array('default' => '#616161', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_sort_dropdown_menu_text_color', array('label' => __('Sort Dropdown Menu: [Text Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_sort_dropdown_menu_text_color'))); // Sort Dropdown Menu: [Background Color] $wp_customize->add_setting('rvx_sort_dropdown_menu_background_color', array('default' => '#FFFFFF', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_sort_dropdown_menu_background_color', array('label' => __('Sort Dropdown Menu: [Background Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_sort_dropdown_menu_background_color'))); // Sort Dropdown Menu: [Border Color] $wp_customize->add_setting('rvx_sort_dropdown_menu_border_color', array('default' => '#FFFFFF', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_sort_dropdown_menu_border_color', array('label' => __('Sort Dropdown Menu: [Border Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_sort_dropdown_menu_border_color'))); // Sort Dropdown Menu: [Border Radius] $wp_customize->add_setting('rvx_sort_dropdown_menu_border_radius', array('default' => 4, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_sort_dropdown_menu_border_radius', array('label' => __('Sort Dropdown Menu: [Border Radius]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_sort_dropdown_menu_border_radius', 'type' => 'range', 'input_attrs' => array('min' => 0, 'max' => 50, 'step' => 1))); // Sort Dropdown Menu: [Font Size] $wp_customize->add_setting('rvx_sort_dropdown_menu_text_font_size', array('default' => 14, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_sort_dropdown_menu_text_font_size', array('label' => __('Sort Dropdown Menu: [Font Size]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_sort_dropdown_menu_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Write a Review Button: [Text Color] /** $wp_customize->add_setting('rvx_write_review_button_text_color', array( 'default' => '#ffffff', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage', )); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_write_review_button_text_color', array( 'label' => __('Write a Review Button: [Text Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_write_review_button_text_color', ))); // Write a Review Button: [Background Color] $wp_customize->add_setting('rvx_write_review_button_background_color', array( 'default' => '#0043DD', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage', )); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_write_review_button_background_color', array( 'label' => __('Write a Review Button: [Background Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_write_review_button_background_color', ))); */ // Write a Review Button: [Border Color] $wp_customize->add_setting('rvx_write_review_button_border_color', array('default' => '#0043DD', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_write_review_button_border_color', array('label' => __('Write a Review Button: [Border Color]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_write_review_button_border_color'))); // Write a Review Button: [Border Radius] $wp_customize->add_setting('rvx_write_review_button_border_radius', array('default' => 4, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_write_review_button_border_radius', array('label' => __('Write a Review Button: [Border Radius]', 'reviewx'), 'section' => 'rvx_filter_section', 'settings' => 'rvx_write_review_button_border_radius', 'type' => 'range', 'input_attrs' => array('min' => 0, 'max' => 50, 'step' => 1))); /** * ReviewX - Review Items */ // Review Items: Card - [Background Color] $wp_customize->add_setting('rvx_reviews_items_card_background_color', array('default' => '#F5F5F5', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_items_card_background_color', array('label' => __('Review Items: Card - [Background Color]', 'reviewx'), 'section' => 'rvx_review_items_section', 'settings' => 'rvx_reviews_items_card_background_color'))); // Review Items: Card - [Border Color] $wp_customize->add_setting('rvx_reviews_items_card_border_color', array('default' => '#F5F5F5', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_items_card_border_color', array('label' => __('Review Card: [Border Color]', 'reviewx'), 'section' => 'rvx_review_items_section', 'settings' => 'rvx_reviews_items_card_border_color'))); // Review Items: Card - [Padding] $wp_customize->add_setting('rvx_reviews_items_card_inline_padding', array('default' => 8, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_items_card_inline_padding', array('label' => __('Review Card: [Padding]', 'reviewx'), 'section' => 'rvx_review_items_section', 'settings' => 'rvx_reviews_items_card_inline_padding', 'type' => 'range', 'input_attrs' => array('min' => 4, 'max' => 50, 'step' => 1))); // Review Items: Card - [Border Radius] $wp_customize->add_setting('rvx_reviews_items_card_border_radius', array('default' => 6, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_items_card_border_radius', array('label' => __('Review Card: [Border Radius]', 'reviewx'), 'section' => 'rvx_review_items_section', 'settings' => 'rvx_reviews_items_card_border_radius', 'type' => 'range', 'input_attrs' => array('min' => 0, 'max' => 50, 'step' => 1))); // Review Items: Reviewer Name - [Text Color] $wp_customize->add_setting('rvx_reviews_items_reviewer_name_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_items_reviewer_name_text_color', array('label' => __('Reviewer Name: [Text Color]', 'reviewx'), 'section' => 'rvx_review_items_section', 'settings' => 'rvx_reviews_items_reviewer_name_text_color'))); // Review Items: Reviewer Name - [Text Size] $wp_customize->add_setting('rvx_reviews_items_reviewer_name_text_font_size', array('default' => 20, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_items_reviewer_name_text_font_size', array('label' => __('Reviewer Name: [Text Size]', 'reviewx'), 'section' => 'rvx_review_items_section', 'settings' => 'rvx_reviews_items_reviewer_name_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Review Items: Review Title - [Text Color] $wp_customize->add_setting('rvx_reviews_items_title_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_items_title_text_color', array('label' => __('Review Title: [Text Color]', 'reviewx'), 'section' => 'rvx_review_items_section', 'settings' => 'rvx_reviews_items_title_text_color'))); // Review Items: Review Title - [Text Size] $wp_customize->add_setting('rvx_reviews_items_title_text_font_size', array('default' => 20, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_items_title_text_font_size', array('label' => __('Review Title: [Text Size]', 'reviewx'), 'section' => 'rvx_review_items_section', 'settings' => 'rvx_reviews_items_title_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Review Items: Review Date - [Text Color] $wp_customize->add_setting('rvx_reviews_items_date_text_color', array('default' => '#757575', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_items_date_text_color', array('label' => __('Review Date: [Text Color]', 'reviewx'), 'section' => 'rvx_review_items_section', 'settings' => 'rvx_reviews_items_date_text_color'))); // Review Items: Review Date - [Text Size] $wp_customize->add_setting('rvx_reviews_items_date_text_font_size', array('default' => 14, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_items_date_text_font_size', array('label' => __('Review Date: [Text Size]', 'reviewx'), 'section' => 'rvx_review_items_section', 'settings' => 'rvx_reviews_items_date_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Review Items: Description - [Text Color] $wp_customize->add_setting('rvx_reviews_items_description_text_color', array('default' => '#757575', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_reviews_items_description_text_color', array('label' => __('Review Description: [Text Color]', 'reviewx'), 'section' => 'rvx_review_items_section', 'settings' => 'rvx_reviews_items_description_text_color'))); // Review Items: Description - [Text Size] $wp_customize->add_setting('rvx_reviews_items_description_text_font_size', array('default' => 14, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_reviews_items_description_text_font_size', array('label' => __('Review Description: [Text Size]', 'reviewx'), 'section' => 'rvx_review_items_section', 'settings' => 'rvx_reviews_items_description_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); /** * ReviewX - Review Form */ // Form: Background Color $wp_customize->add_setting('rvx_input_form_background_color', array('default' => '#F5F5F5', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_input_form_background_color', array('label' => __('Form: Background Color', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_background_color'))); // Form: [Border Color] $wp_customize->add_setting('rvx_input_form_border_color', array('default' => '#F5F5F5', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_input_form_border_color', array('label' => __('Form: [Border Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_border_color'))); // Form: Border Radius $wp_customize->add_setting('rvx_input_form_border_radius', array('default' => 6, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_input_form_border_radius', array('label' => __('Form: Border Radius', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_border_radius', 'type' => 'range', 'input_attrs' => array('min' => 0, 'max' => 50, 'step' => 1))); // Form: Title [Text Color] $wp_customize->add_setting('rvx_input_form_title_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_input_form_title_text_color', array('label' => __('Form: Title [Text Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_title_text_color'))); // Form: Title [Text Size] $wp_customize->add_setting('rvx_input_form_title_text_font_size', array('default' => 18, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_input_form_title_text_font_size', array('label' => __('Form: Title [Text Size]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_title_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 100, 'step' => 1))); // Form: Product Name [Text Color] $wp_customize->add_setting('rvx_input_form_product_name_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_input_form_product_name_text_color', array('label' => __('Form: Product Name [Text Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_product_name_text_color'))); // Form: Product Name [Text Size] $wp_customize->add_setting('rvx_input_form_product_name_text_font_size', array('default' => 18, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_input_form_product_name_text_font_size', array('label' => __('Form: Product Name [Text Size]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_product_name_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Form: Criteria Title [Text Color] $wp_customize->add_setting('rvx_input_form_criteria_title_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_input_form_criteria_title_text_color', array('label' => __('Form: Criteria Title [Text Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_criteria_title_text_color'))); // Form: Criteria Title [Text Size] $wp_customize->add_setting('rvx_input_form_criteria_title_text_font_size', array('default' => 16, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_input_form_criteria_title_text_font_size', array('label' => __('Form: Criteria Title [Text Size]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_criteria_title_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Form: Review Title [Text Color] $wp_customize->add_setting('rvx_input_form_review_title_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_input_form_review_title_text_color', array('label' => __('Form: Review Title [Text Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_review_title_text_color'))); // Form: Review Title [Text Size] $wp_customize->add_setting('rvx_input_form_review_title_text_font_size', array('default' => 16, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_input_form_review_title_text_font_size', array('label' => __('Form: Review Title [Text Size]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_review_title_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Form: Description [Text Color] $wp_customize->add_setting('rvx_input_form_description_title_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_input_form_description_title_text_color', array('label' => __('Form: Description [Text Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_description_title_text_color'))); // Form: Description [Text Size] $wp_customize->add_setting('rvx_input_form_description_title_text_font_size', array('default' => 16, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_input_form_description_title_text_font_size', array('label' => __('Form: Description [Text Size]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_description_title_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Form: Full Name [Text Color] $wp_customize->add_setting('rvx_input_form_full_name_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_input_form_full_name_text_color', array('label' => __('Form: Full Name [Text Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_full_name_text_color'))); // Form: Full Name [Text Size] $wp_customize->add_setting('rvx_input_form_full_name_text_font_size', array('default' => 16, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_input_form_full_name_text_font_size', array('label' => __('Form: Full Name [Text Size]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_full_name_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Form: Email Address [Text Color] $wp_customize->add_setting('rvx_input_form_email_address_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_input_form_email_address_text_color', array('label' => __('Form: Email Address [Text Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_email_address_text_color'))); // Form: Email Address [Text Size] $wp_customize->add_setting('rvx_input_form_email_address_text_font_size', array('default' => 16, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_input_form_email_address_text_font_size', array('label' => __('Form: Email Address [Text Size]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_email_address_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Form: Attachment Title [Text Color] $wp_customize->add_setting('rvx_input_form_attachment_title_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_input_form_attachment_title_text_color', array('label' => __('Form: Attachment [Text Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_attachment_title_text_color'))); // Form: Attachment Title [Text Size] $wp_customize->add_setting('rvx_input_form_attachment_title_text_font_size', array('default' => 16, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_input_form_attachment_title_text_font_size', array('label' => __('Form: Attachment [Text Size]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_attachment_title_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Form: Mark as Anonymous [Text Color] $wp_customize->add_setting('rvx_input_form_mark_anonymous_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_input_form_mark_anonymous_text_color', array('label' => __('Form: Mark as Anonymous [Text Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_mark_anonymous_text_color'))); // Form: Mark as Anonymous [Text Size] $wp_customize->add_setting('rvx_input_form_mark_anonymous_text_font_size', array('default' => 16, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_input_form_mark_anonymous_text_font_size', array('label' => __('Form: Mark as Anonymous [Text Size]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_mark_anonymous_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Form: Recommended? [Text Color] $wp_customize->add_setting('rvx_input_form_recommended_text_color', array('default' => '#424242', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_input_form_recommended_text_color', array('label' => __('Form: Recommended? [Text Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_recommended_text_color'))); // Form: Recommended? [Text Size] $wp_customize->add_setting('rvx_input_form_recommended_text_font_size', array('default' => 16, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_input_form_recommended_text_font_size', array('label' => __('Form: Recommended? [Text Size]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_input_form_recommended_text_font_size', 'type' => 'range', 'input_attrs' => array('min' => 10, 'max' => 50, 'step' => 1))); // Form: Submit Review Button [Text Color] /** $wp_customize->add_setting('rvx_submit_review_button_text_color', array( 'default' => '#FFFFFF', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage', )); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_submit_review_button_text_color', array( 'label' => __('Submit Review Button: [Text Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_submit_review_button_text_color', ))); // Form: Submit Review Button [Background Color] $wp_customize->add_setting('rvx_submit_review_button_background_color', array( 'default' => '#0043DD', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage', )); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_submit_review_button_background_color', array( 'label' => __('Submit Review Button: [Background Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_submit_review_button_background_color', ))); */ // Form: Submit Review Button [Border Color] $wp_customize->add_setting('rvx_submit_review_button_border_color', array('default' => '#0043DD', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage')); $wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'rvx_submit_review_button_border_color', array('label' => __('Submit Review Button: [Border Color]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_submit_review_button_border_color'))); // Form: Submit Review Button [Border Radius] $wp_customize->add_setting('rvx_submit_review_button_border_radius', array('default' => 6, 'sanitize_callback' => 'absint', 'transport' => 'postMessage')); $wp_customize->add_control('rvx_submit_review_button_border_radius', array('label' => __('Submit Review Button: [Border Radius]', 'reviewx'), 'section' => 'rvx_form_section', 'settings' => 'rvx_submit_review_button_border_radius', 'type' => 'range', 'input_attrs' => array('min' => 0, 'max' => 50, 'step' => 1))); } } Handlers/Customize/WCUserDashboardAddReview.php 0000777 00000004041 15251220643 0015560 0 ustar 00 <?php namespace Rvx\Handlers\Customize; use Rvx\Utilities\Helper; use Rvx\WPDrill\Facades\View; class WCUserDashboardAddReview { /** * Renders the RVX review form on the WooCommerce user dashboard. * * This outputs the review form view for the WooCommerce user dashboard. * */ public function renderRvxReviewForm() { $attributes = self::setRvxAttributes(); $formData = $this->formDefaultTextsData(); View::output('storefront/my-account/review-form', ['data' => $attributes, 'formLevelData' => $formData]); return ''; } public function setRvxAttributes() { $user_id = get_current_user_id(); $wpCurrentUser = Helper::getWpCurrentUser(); $user_name = $wpCurrentUser ? $wpCurrentUser->display_name : ''; $attributes = ['userInfo' => ['isLoggedIn' => Helper::loggedIn(), 'id' => $wpCurrentUser ? $wpCurrentUser->ID : null, 'name' => $user_name, 'email' => $wpCurrentUser ? $wpCurrentUser->user_email : '', 'isVerified' => Helper::verifiedCustomer($user_id)], 'domain' => ['baseDomain' => Helper::domainSupport(), 'baseRestUrl' => Helper::getRestAPIurl()]]; return \json_encode($attributes); } public function formDefaultTextsData() { // Define the default values, if no builder is active / available then use the default string / texts $default_values = ['write_a_review' => 'Write a Review', 'text_rating_star_title' => 'Rating', 'text_review_title' => 'Review Title', 'placeholder_review_title' => 'Write Review Title', 'text_review_description' => 'Description', 'placeholder_review_description' => 'Write your description here', 'text_full_name' => 'Full name', 'placeholder_full_name' => 'Full Name', 'text_email_name' => 'Email address', 'placeholder_email_name' => 'Email Address', 'text_attachment_title' => 'Attachment', 'placeholder_upload_photo' => 'Upload Photo / Video', 'text_mark_as_anonymous' => 'Mark as Anonymous', 'text_recommended_title' => 'Recommendation?']; return \json_encode($default_values); } } Handlers/OrderUpdateHandler.php 0000777 00000001033 15251220643 0012535 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Services\OrderService; class OrderUpdateHandler { protected $orderService; public function __construct() { $this->orderService = new OrderService(); } public function __invoke($order_id) { $transient_key = 'order_updated_' . $order_id; if (\false === \get_transient($transient_key)) { \set_transient($transient_key, \true, 30); wp_schedule_single_event(\time() + 5, 'process_order_update', array($order_id)); } } } Handlers/CommentBoxHandle.php 0000777 00000005315 15251220643 0012217 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Utilities\Helper; use Rvx\WPDrill\Facades\View; use Rvx\Form\ReviewFormHelper; class CommentBoxHandle { protected $reviewFormHelper; public function __construct() { $this->reviewFormHelper = new ReviewFormHelper(); } public function __invoke() : void { $attributes = $this->setRvxAttributes(); $formData = $this->reviewFormHelper->builderCustomizedFormTextsData(); $wooVerificationRequired = \get_option('woocommerce_review_rating_verification_required') === 'yes'; $requireSignIn = (bool) \get_option('comment_registration'); $currentUrl = esc_url(add_query_arg([], wp_unslash($_SERVER['REQUEST_URI']))); $this->reviewFormHelper->commentBoxDefaultStyleForCustomPostType(); View::output('storefront/widget/index', ['data' => \json_encode($attributes, \JSON_UNESCAPED_UNICODE), 'formLevelData' => $formData, 'wooVerificationRequired' => $wooVerificationRequired, 'isVerifiedCustomer' => $attributes['userInfo']['isVerified'], 'requireSignIn' => $requireSignIn, 'user_is_logged_in' => $attributes['userInfo']['isLoggedIn'], 'login_url' => wp_login_url($currentUrl), 'register_url' => wp_registration_url(), 'registration_enabled' => (bool) \get_option('users_can_register')]); } private function setRvxAttributes() : array { $wpCurrentUser = Helper::getWpCurrentUser(); $userId = get_current_user_id(); // WooCommerce verification if (\class_exists('WooCommerce') && is_singular('product') && get_post_type() === 'product') { $userInfo['isVerified'] = Helper::verifiedCustomer($userId); } $isVerifiedCustomer = 0; if (\class_exists('WooCommerce') && is_singular('product') && 'product' === get_post_type()) { $isVerifiedCustomer = Helper::verifiedCustomer($userId); } // Post type enable check $enabledPostTypes = $this->reviewFormHelper->rvxEnabledPostTypes(); $currentPostType = \strtolower(get_post_type()); $postTypeEnabled = !empty($enabledPostTypes[$currentPostType]) && \strtolower($enabledPostTypes[$currentPostType]) === $currentPostType; return ['postTypeEnabled' => $postTypeEnabled, 'product' => ['id' => get_the_ID(), 'postType' => $currentPostType], 'userInfo' => ['isLoggedIn' => Helper::loggedIn(), 'id' => $wpCurrentUser ? (int) $wpCurrentUser->ID : 0, 'name' => $wpCurrentUser && $wpCurrentUser->display_name ? $wpCurrentUser->display_name : '', 'email' => $wpCurrentUser && $wpCurrentUser->user_email ? $wpCurrentUser->user_email : '', 'isVerified' => $isVerifiedCustomer], 'domain' => ['baseDomain' => Helper::domainSupport(), 'baseRestUrl' => Helper::getRestAPIurl()]]; } } Handlers/WcTemplates/WcAccountFormTag.php 0000777 00000000240 15251220643 0014416 0 ustar 00 <?php namespace Rvx\Handlers\WcTemplates; class WcAccountFormTag { public function __invoke() { echo 'enctype="multipart/form-data"'; } } Handlers/WcTemplates/WoocommerceCustomColumnsHandler.php 0000777 00000000437 15251220643 0017571 0 ustar 00 <?php namespace Rvx\Handlers\WcTemplates; class WoocommerceCustomColumnsHandler { public function __invoke($columns) { $columns['rvx-review'] = __('Review', 'reviewx'); // $columns['rvx-product-image'] = __('Image', 'reviewx'); return $columns; } } Handlers/WcTemplates/WcOrderTableRvxReviewHandler.php 0000777 00000001156 15251220643 0016754 0 ustar 00 <?php namespace Rvx\Handlers\WcTemplates; class WcOrderTableRvxReviewHandler { public function __invoke($order) { $order_id = $order->get_id(); $items = $order->get_items(); foreach ($items as $item_id => $item) { $product_id = $item->get_product_id(); $button_url = add_query_arg(array('order_id' => $order_id, 'product_id' => $product_id, 'item_id' => $item_id), site_url('/your-custom-template/')); echo '<a href="' . esc_url($button_url) . '" class="woocommerce-button button">' . __('View Details', 'your-text-domain') . '</a>'; } } } Handlers/WcTemplates/WcEditAccountForm.php 0000777 00000001546 15251220643 0014602 0 ustar 00 <?php namespace Rvx\Handlers\WcTemplates; class WcEditAccountForm { public function __invoke() { $user_id = get_current_user_id(); $attachment_id = \get_user_meta($user_id, "rvx_image", \true); if ($attachment_id) { $original_image_url = wp_get_attachment_url($attachment_id); } if (!empty($original_image_url)) { echo '<img src="' . esc_url($original_image_url) . '" width="70px" height="70px" alt="user image">'; } ?> <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide"> <label for="image"><?php esc_html_e("Image", "woocommerce"); ?></label> <input type="file" class="woocommerce-Input" name="image" accept="image/x-png,image/gif,image/jpeg"> </p> <?php } } Handlers/WcTemplates/WcSendEmailPermissionHandler.php 0000777 00000000445 15251220643 0016761 0 ustar 00 <?php namespace Rvx\Handlers\WcTemplates; class WcSendEmailPermissionHandler { public function __invoke($fields) { $fields['order']['consent_email_subscription'] = ['type' => 'checkbox', 'label' => __('I want to subscribe email', 'reviewx')]; return $fields; } } Handlers/WcTemplates/WcAccountDetails.php 0000777 00000002771 15251220643 0014457 0 ustar 00 <?php namespace Rvx\Handlers\WcTemplates; use Rvx\Api\UserApi; use Rvx\Utilities\Auth\Client; class WcAccountDetails { public function __invoke($user_id) { if (isset($_FILES["image"]) && $_FILES["image"]["error"] == \UPLOAD_ERR_OK) { require_once ABSPATH . "wp-admin/includes/image.php"; $attachment_id = media_handle_upload("image", 0); if (!\is_wp_error($attachment_id)) { \error_log("da3333" . \print_r([$user_id, $attachment_id], \true)); \update_user_meta($user_id, "rvx_image", $attachment_id); $this->userDataForm(); } } } function userDataForm() { $user_id = get_current_user_id(); $user_info = get_userdata($user_id); $attachment_id = \get_user_meta($user_id, "rvx_image", \true); $original_image_url = $attachment_id ? wp_get_attachment_url($attachment_id) : get_avatar_url($user_id); $data = ["name" => $user_info->first_name . " " . $user_info->last_name, "email" => $user_info->user_email, "avatar" => $original_image_url, "city" => \get_user_meta($user_id, "billing_city", \true) ?? "", "phone" => \get_user_meta($user_id, "billing_phone", \true) ?? "", "address" => \get_user_meta($user_id, "billing_address_1", \true) ?? "", "country" => \get_user_meta($user_id, "billing_country", \true) ?? "", "status" => 1]; $uid = Client::getUid() . "-" . $user_id; $response = (new UserApi())->editAccountUpdate($data, $uid); } } Handlers/WcTemplates/WcAccountDetailsError.php 0000777 00000000640 15251220643 0015462 0 ustar 00 <?php namespace Rvx\Handlers\WcTemplates; class WcAccountDetailsError { public function __invoke($args) { // if ( // isset($_FILES["image"]) && // $_FILES["image"]["error"] != UPLOAD_ERR_OK // ) { // $args->add( // "image_error", // __("Please provide a valid image", "woocommerce") // ); // } } } Handlers/WcTemplates/WoocommerceLocateTemplateHandler.php 0000777 00000000567 15251220643 0017665 0 ustar 00 <?php namespace Rvx\Handlers\WcTemplates; class WoocommerceLocateTemplateHandler { public function __invoke($template, $template_name, $template_path) { $plugin_path = RVX_DIR_PATH . 'woocommerce/'; if (\file_exists($plugin_path . $template_name)) { $template = $plugin_path . $template_name; } return $template; } } Handlers/WcTemplates/WcOrderTableProductImageHandler.php 0000777 00000001241 15251220643 0017371 0 ustar 00 <?php namespace Rvx\Handlers\WcTemplates; class WcOrderTableProductImageHandler { public function __invoke($order) { $items = $order->get_items(); foreach ($items as $item_id => $item) { $product_id = $item->get_product_id(); $product = wc_get_product($product_id); if ($product) { $image_url = wp_get_attachment_image_url($product->get_image_id(), 'thumbnail'); if ($image_url) { echo '<img src="' . esc_url($image_url) . '" alt="' . esc_attr($product->get_name()) . '" style="width:50px; height:50px;" />'; } } } } } Handlers/RichSchema/WoocommerceRichSchemaHandler.php 0000777 00000006613 15251220643 0016544 0 ustar 00 <?php namespace Rvx\Handlers\RichSchema; use Rvx\Services\SettingService; use Rvx\WC_Product; /** * Handles rich schema markup for WooCommerce single product pages. */ class WoocommerceRichSchemaHandler { /** * Adds or modifies structured data for WooCommerce product schema. * * @param array $markup Existing WooCommerce schema data. * @param WC_Product $product WooCommerce product object. * @return array */ public function __invoke($markup, $product) : array { // Ensure we are on a single product page and in frontend. if (is_admin() || !\function_exists('is_product') || !\is_product()) { return $markup; } if (!$product instanceof WC_Product) { return $markup; } // Temporarily remove Divi filter $divi_callback = 'et_theme_builder_wc_set_review_metadata'; $divi_removed = \false; if (\function_exists('has_filter')) { $priority = \has_filter('get_comment_metadata', $divi_callback); if ($priority !== \false) { remove_filter('get_comment_metadata', $divi_callback, (int) $priority); $divi_removed = \true; } } // Allow disabling via settings. $settings = (new SettingService())->getReviewSettings('product'); if (!empty($settings['reviews']['product_schema']) && $settings['reviews']['product_schema'] == 1) { if (!empty($markup['aggregateRating'])) { unset($markup['aggregateRating']); } if (!empty($markup['review'])) { unset($markup['review']); } return $markup; } // Get product rating data. // $averageRating = (float) $product->get_average_rating(); // $reviewCount = (int) $product->get_review_count(); $reviewCount = 0; $averageRating = 0.0; $reviewItems = []; // Fetch all approved reviews. $reviews = get_comments(['post_id' => $product->get_id(), 'status' => 'approve', 'type' => 'review']); if (!empty($reviews)) { foreach ($reviews as $review) { if (!empty($review->comment_parent)) { continue; // Skip replies } $rating = \get_comment_meta($review->comment_ID, 'rating', \true); $ratingValue = $rating !== '' ? (float) $rating : null; if ($ratingValue !== null) { $reviewCount++; $averageRating += $ratingValue; $reviewItems[] = ['@type' => 'Review', 'author' => ['@type' => 'Person', 'name' => $review->comment_author], 'reviewRating' => ['@type' => 'Rating', 'ratingValue' => $ratingValue], 'datePublished' => get_comment_date('c', $review), 'reviewBody' => $review->comment_content]; } } } if ($reviewCount > 0 && $averageRating > 0) { $trueAverage = \round($averageRating / $reviewCount, 2); $markup['aggregateRating'] = ['@type' => 'AggregateRating', 'ratingValue' => $trueAverage, 'reviewCount' => $reviewCount]; $markup['review'] = $reviewItems; } // Restore Divi filter if ($divi_removed) { add_filter('get_comment_metadata', $divi_callback, $priority ?? 10, 4); } return $markup; } } Handlers/AllHandler.php 0000777 00000000544 15251220643 0011035 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class AllHandler implements InvokableContract { public function __invoke() { View::output('storefront/widget/index', ['title' => 'Welcome dfgsdfg sdfsdf', 'content' => 'A WordPress Plugin development framework for humans']); } } Handlers/OrderCreateHandler.php 0000777 00000010753 15251220643 0012527 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\UserApi; use Rvx\Api\OrderApi; use Rvx\Utilities\TransactionManager; use Rvx\WPDrill\Response; use Rvx\Utilities\Helper; use Rvx\Utilities\Auth\Client; use Exception; class OrderCreateHandler { public function __invoke($order_id) { try { $order = wc_get_order($order_id); if (!$order) { return \false; } // WP Operation: Mark as new order. This MUST happen regardless of SaaS success. \update_post_meta($order_id, '_rvx_is_new_order', \true); // SaaS Operation: Attempt sync, but don't roll back WP if it fails. $payload = $this->prepareData($order); $orderResponse = (new OrderApi())->create($payload); if ($orderResponse->getStatusCode() === Response::HTTP_OK) { $customers = $this->customerPayload($order); (new UserApi())->create($customers); } else { \error_log("Order Sync Failed for ID {$order_id}: " . $orderResponse->getBody()); } return \true; } catch (Exception $e) { \error_log("OrderCreateHandler Exception: " . $e->getMessage()); return \false; } } public function prepareData($order) { $order_id = $order->get_id(); global $wpdb; $query = $wpdb->prepare("SELECT date_paid, date_completed FROM {$wpdb->prefix}wc_order_stats WHERE order_id = %d", $order_id); $wpWcOrderStats = $wpdb->get_row($query); $paid_at = $wpWcOrderStats && $wpWcOrderStats->date_paid ? \wp_date('Y-m-d H:i:s', \strtotime($wpWcOrderStats->date_paid)) : null; $date_created = $order->get_date_created(); $created_at = $date_created ? \wp_date('Y-m-d H:i:s', $date_created->getTimestamp()) : \wp_date('Y-m-d H:i:s'); $date_modified = $order->get_date_modified(); $updated_at = $date_modified ? \wp_date('Y-m-d H:i:s', $date_modified->getTimestamp()) : \wp_date('Y-m-d H:i:s'); return ['order' => ["wp_id" => (int) $order->get_id(), "customer_wp_unique_id" => Client::getUid() . '-' . (int) $order->get_customer_id(), "subtotal" => (double) $order->get_subtotal(), "tax" => (double) $order->get_total_tax(), "total" => (double) $order->get_total(), "status" => Helper::orderStatus($order->get_status()), "delivered_at" => null, "review_request_email_sent_at" => null, "review_reminder_email_sent_at" => null, "photo_review_email_sent_at" => null, "paid_at" => $paid_at, "created_at" => $created_at, "updated_at" => $updated_at], 'order_items' => $this->orderItems($order, $wpWcOrderStats)]; } public function orderItems($order, $wpWcOrderStats = null) { global $wpdb; $items_data = []; $order_items = $order->get_items(); if (!$wpWcOrderStats) { $order_id = $order->get_id(); $query = $wpdb->prepare("SELECT date_paid, date_completed FROM {$wpdb->prefix}wc_order_stats WHERE order_id = %d", $order_id); $wpWcOrderStats = $wpdb->get_row($query); } $fulfillment_status = Helper::orderItemStatus($order->get_status()) ?? null; $fulfilled_at = $wpWcOrderStats && $wpWcOrderStats->date_completed ? \wp_date('Y-m-d H:i:s', \strtotime($wpWcOrderStats->date_completed)) : null; foreach ($order_items as $order_item) { $product = $order_item->get_product(); $item_data = ["wp_id" => (int) $order_item->get_id(), "wp_unique_id" => Client::getUid() . '-' . (int) $order_item->get_id(), "product_wp_unique_id" => Client::getUid() . '-' . (int) $product->get_id(), "review_id" => null, "site_id" => Client::getSiteId(), "name" => $product->get_name(), "quantity" => $order_item->get_quantity(), "price" => (double) $product->get_price(), "reviewed_at" => null, "fulfillment_status" => $fulfillment_status, "fulfilled_at" => $fulfilled_at]; $items_data[] = $item_data; } return $items_data; } public function customerPayload($order) { $customer_id = $order->get_customer_id(); // if ($customer_id === 0) { // return []; // } return ['wp_id' => $customer_id, 'name' => $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(), 'email' => $order->get_billing_email(), 'city' => $order->get_billing_city() ?? '', 'phone' => $order->get_billing_phone() ?? '', 'address' => $order->get_billing_address_1() ?? '', 'country' => $order->get_billing_country() ?? '', 'status' => 1]; } } Handlers/ProductCategory/CategoryProductDeleteHandler.php 0000777 00000001145 15251220643 0017702 0 ustar 00 <?php namespace Rvx\ProductCategory\Handlers; use Rvx\Api\CategoryApi; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Response; class CategoryProductDeleteHandler { public function __invoke($term_id) { $term = \get_term($term_id); $category_id = $term_id; $child_id = $term->parent; $uid = Client::getUid() . '-' . $term->term_id; $response = (new CategoryApi())->remove($uid); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log("Category Not Update" . $response->getStatusCode()); return \false; } } } Handlers/PluginActivatedHandler.php 0000777 00000005754 15251220643 0013420 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\AuthApi; use Rvx\CPT\CptHelper; use Rvx\Services\Api\LoginService; use Rvx\Services\DataSyncService; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\DB\Migration\Migrator; use Rvx\Services\CacheServices; use Exception; class PluginActivatedHandler implements InvokableContract { private Migrator $migrator; private DataSyncService $dataSyncService; private CacheServices $cacheServices; private LoginService $loginService; public function __construct(Migrator $migrator) { $this->migrator = $migrator; $this->dataSyncService = new DataSyncService(); $this->cacheServices = new CacheServices(); $this->loginService = new LoginService(); } public function __invoke() { add_action('activated_plugin', function ($plugin) { if (RVX_DIR_NAME . '/reviewx.php' !== $plugin) { return; } global $wpdb; // Initialize tables and reset sync flag (new \Rvx\Handlers\RvxInit\LoadReviewxCreateSiteTable())->init(); \set_transient('rvx_reset_sync_flag', \true, 300); // 5 mins TTL $this->migrator->run(); $rvxSites = $wpdb->prefix . 'rvx_sites'; $uid = $wpdb->get_var("SELECT uid FROM {$rvxSites} ORDER BY id DESC LIMIT 1"); if ($uid) { // Mark as not synced initially $wpdb->update($rvxSites, ['is_saas_sync' => 0], ['uid' => $uid], ['%d'], ['%s']); try { // Attempt SaaS activation (new AuthApi())->changePluginStatus(['site_uid' => $uid, 'status' => 1, 'plugin_version' => \defined('RVX_VERSION') ? RVX_VERSION : 'unknown', 'wp_version' => get_bloginfo('version')]); // Start initial sync $dataResponse = $this->dataSyncService->dataSync('login', 'product'); if ($dataResponse) { \sleep(1); $enabled_post_types = (new CptHelper())->usedCPTOnSync('used'); unset($enabled_post_types['product']); foreach ($enabled_post_types as $post_type) { $this->dataSyncService->dataSync('login', $post_type); } } } catch (Exception $e) { // Clean up if AuthApi fails $wpdb->query("TRUNCATE TABLE {$rvxSites}"); if (\defined('WP_DEBUG') || WP_DEBUG) { \error_log('[ReviewX] Activation warning: AuthApi connection failed - ' . $e->getMessage()); } } } // Always clean cache and redirect, even if UID or API failed $this->cacheServices->removeCache(); $this->loginService->resetPostMeta(); wp_safe_redirect(admin_url('admin.php?page=reviewx')); exit; }, 15, 1); } } Handlers/Product/ProductImportHandler.php 0000777 00000010173 15251220643 0014557 0 ustar 00 <?php namespace Rvx\Handlers\Product; use Rvx\Api\ProductApi; use Rvx\WPDrill\Response; class ProductImportHandler { public function __invoke($product, $data) { $payload = $this->prepareData($product); $response = (new ProductApi())->create($payload); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log("Imported product not import" . $response->getStatusCode()); return \false; } } public function prepareData($product) { $product_id = $product->get_id(); $images = wp_get_attachment_image_src($product_id, 'full'); return [ "wp_id" => $product->get_id(), "title" => $product->get_name(), "url" => get_permalink($product->get_id()), "description" => $product->get_short_description(), "price" => isset($_POST['_regular_price']) ? (float) sanitize_text_field($_POST['_regular_price']) : (float) $product->get_regular_price(), "discounted_price" => (float) sanitize_text_field($product->get_sale_price()) ?? 0, "slug" => $product->get_slug(), "image" => $images ? $images[0] : '', "status" => $this->productStatus($product->get_status()), "post_type" => 'product', // Hardcoded due to import issue "total_reviews" => (int) $product->get_review_count(), "avg_rating" => (float) $product->get_average_rating(), "stars" => ["one" => 0, "two" => 0, "three" => 0, "four" => 0, "five" => 0], "one_stars" => 0, "two_stars" => 0, "three_stars" => 0, "four_stars" => 0, "five_stars" => 0, "category_wp_unique_ids" => $this->productCategory($product), ]; } public function productStatus($status) { switch ($status) { case 'publish': return 1; case 'trash': return 2; default: return 3; } } public function productCategory($product) { $product_categories = $product->get_category_ids(); $parent_category_ids = array(); foreach ($product_categories as $category_id) { $category = \get_term($category_id, 'product_cat'); if ($category && $category->parent == 0) { $parent_category_ids[] = \Rvx\Utilities\Auth\Client::getUid() . '-' . $category_id; } } if (empty($parent_category_ids)) { $parent_category_ids[] = \Rvx\Utilities\Auth\Client::getUid() . '-' . '1'; return $parent_category_ids; } return $parent_category_ids; } public function customPost($post) { $image_url = get_the_post_thumbnail_url($post->ID, 'full'); $data = ["wp_id" => $post->ID, "title" => $post->post_title, "url" => get_permalink($post->ID), "description" => $post->post_excerpt, "price" => 0, "discounted_price" => 0, "slug" => $post->post_name, "image" => '', "status" => $this->productStatus($post->post_status), "post_type" => get_post_type($post->ID), "total_reviews" => (int) get_comments_number($post->ID) ?? 0, "avg_rating" => 0.0, "stars" => ["one" => 0, "two" => 0, "three" => 0, "four" => 0, "five" => 0], "one_stars" => 0, "two_stars" => 0, "three_stars" => 0, "four_stars" => 0, "five_stars" => 0, "category_wp_unique_ids" => [\Rvx\Utilities\Auth\Client::getUid() . '-' . 0]]; return $data; } public function getPostCategoryIds($post_ids) { if (empty($post_ids)) { \error_log("No valid post ID provided."); return []; } if (empty($category_ids)) { \error_log("No categories found for post ID: " . $post_ids); return []; } $parent_category_ids = []; foreach ($category_ids as $category_id) { $parent_category_ids[] = \Rvx\Utilities\Auth\Client::getUid() . '-' . $category_id; } if ($parent_category_ids) { return $parent_category_ids; } return $parent_category_ids[] = \Rvx\Utilities\Auth\Client::getUid() . '-' . 0; } } Handlers/Product/ProductUntrashHandler.php 0000777 00000001706 15251220643 0014733 0 ustar 00 <?php namespace Rvx\Handlers\Product; use Rvx\Api\ProductApi; use Rvx\CPT\CptHelper; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Response; class ProductUntrashHandler { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } public function __invoke($product_id) { // Define the target post types $enabled_post_types = $this->cptHelper->usedCPT('used'); $post = get_post($product_id); $post_type = $post->post_type; $post_id = $post->ID; if (!isset($enabled_post_types[$post_type])) { return; } $uniqueId = Client::getUid() . '-' . $post_id; $response = (new ProductApi())->trashToRestoreWpProduct($uniqueId); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log($post_type . " restore fails! --> " . $response->getStatusCode()); return \false; } } } Handlers/DiscountHandler.php 0000777 00000000541 15251220643 0012112 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class DiscountHandler implements InvokableContract { public function __invoke() { View::output('storeadmin/discount', ['title' => 'Welcome to WPDrill', 'content' => 'A WordPress Plugin development framework for humans']); } } Handlers/PluginDeactivatedHandler.php 0000777 00000003002 15251220643 0013711 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\AuthApi; use Rvx\WPDrill\Contracts\InvokableContract; use Exception; class PluginDeactivatedHandler implements InvokableContract { public function __invoke() : void { global $wpdb; $rvxSites = $wpdb->prefix . 'rvx_sites'; $uid = $wpdb->get_var("SELECT uid FROM {$rvxSites} ORDER BY id DESC LIMIT 1"); if ($uid) { // Change rvx_sites table is_saas_sync to 0 $wpdb->update($rvxSites, ['is_saas_sync' => 0], ['uid' => $uid], ['%d'], ['%s']); // Mark sync flag locally \set_transient('rvx_reset_sync_flag', \true); try { // Attempt API call — skip gracefully on failure (new AuthApi())->changePluginStatus(['site_uid' => $uid, 'status' => 0, 'plugin_version' => \defined('RVX_VERSION') ? RVX_VERSION : 'unknown', 'wp_version' => get_bloginfo('version')]); } catch (Exception $e) { // Log quietly instead of breaking plugin disable process if (\defined('WP_DEBUG') || WP_DEBUG) { \error_log('[ReviewX] PluginDeactivatedHandler: API call failed - ' . $e->getMessage()); } // continue silently } } // Always clean up local data, regardless of API status (new \Rvx\Services\CacheServices())->removeCache(); (new \Rvx\Services\Api\LoginService())->resetPostMeta(); // Continue plugin deactivation return; } } Handlers/VerifiedUserHandler.php 0000777 00000000457 15251220643 0012724 0 ustar 00 <?php namespace Rvx\Handlers; class VerifiedUserHandler { public function __construct() { } public function __invoke($order_id) { $order = wc_get_order($order_id); $user_id = $order->get_user_id(); \update_user_meta($user_id, 'is_verified', 'yes'); } } Handlers/PluginLoadedHandler.php 0000777 00000000412 15251220643 0012666 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\WPDrill\Contracts\InvokableContract; class PluginLoadedHandler implements InvokableContract { public function __invoke() { //file_put_contents(REVIEWX_DIR_PATH . 'plugin.txt', 'Plugin Deactivated 1!'); } } Handlers/GeneralSettingHandler.php 0000777 00000000547 15251220643 0013243 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class GeneralSettingHandler implements InvokableContract { public function __invoke() { View::output('storeadmin/settings', ['title' => 'Welcome to WPDrill', 'content' => 'A WordPress Plugin development framework for humans']); } } Handlers/ImportProductHandler.php 0000777 00000007003 15251220643 0013135 0 ustar 00 <?php namespace Rvx\Handlers; class ImportProductHandler { public function __invoke($new_status, $old_status, $product) { if ($new_status == 'publish' && $old_status != 'publish') { $product = get_post($product->ID); if ($product->post_type === 'product') { switch ($new_status) { case 'publish': $currentProduct = wc_get_product($product->ID); $payload = $this->prepareImportedData($currentProduct); $this->appendToJsonl($payload, 'imported_product.jsonl'); (new \Rvx\Handlers\ImportProductHandler())->productJsonlFileRead(); break; } } } } public function appendToJsonl($payload, $file_name = 'imported_product.jsonl') { $file_path = RVX_DIR_PATH . $file_name; $json_data = \json_encode($payload) . \PHP_EOL; $file_handle = \fopen($file_path, 'a'); if ($file_handle) { \fwrite($file_handle, $json_data); \fclose($file_handle); } } public function prepareImportedData($product) { $data = ['rid' => 'rid://Product/' . $product->ID, 'wp_id' => $product->get_id(), 'title' => $product->get_name(), 'url' => get_permalink($product->get_id()), 'description' => $product->get_short_description(), 'slug' => $product->get_slug(), 'image' => wp_get_attachment_url($product->get_image_id()), 'status' => $this->productStatus($product->get_status()), 'post_type' => 'product', 'total_reviews' => 0, 'price' => $product->get_price() ?? 0, 'avg_rating' => 0.0, "stars" => ["one" => 0, "two" => 0, "three" => 0, "four" => 0, "five" => 0], "one_stars" => 0, "two_stars" => 0, "three_stars" => 0, "four_stars" => 0, "five_stars" => 0, "category_wp_unique_ids" => $this->getProductCategories($product)]; return $data; } public function productPrepareForSync($product) { return \array_merge((array) $product, ["category_wp_unique_ids" => $this->getProductCategories($product->wp_id)]); } public function getProductCategories($product_id) { $terms = wp_get_post_terms($product_id, 'product_cat'); $categories = []; if (!empty($terms) && !\is_wp_error($terms)) { foreach ($terms as $term) { $categories[] = \Rvx\Utilities\Auth\Client::getUid() . '-' . $term->term_id; } } return $categories; } public function productStatus($status) { switch ($status) { case 'publish': return 1; case 'trash': return 2; default: return 3; } } public function productJsonlFileRead() { $url = RVX_DIR_PATH . 'imported_product.jsonl'; $payload = []; if (!\file_exists($url)) { return; } $fp = @\fopen($url, "r"); if ($fp) { while (($buffer = \fgets($fp)) !== \false) { $result = \json_decode($buffer); $payload = $this->productPrepareForSync($result); $this->appendToJsonl($payload, 'product_sync.jsonl'); \error_log("Json" . \print_r($result, \true)); // if (!isset($result['rid'])) { // return; // } } if (!\feof($fp)) { echo "Error: unexpected fgets() fail\n"; } \fclose($fp); } } } Handlers/TaxonomyHandler.php 0000777 00000013306 15251220643 0012143 0 ustar 00 <?php namespace Rvx\Handlers; use Exception; use Rvx\Api\CategoryApi; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Response; class TaxonomyHandler { public function getPostTypesByTermId(int $term_id) : array { $term = \get_term($term_id); if (!$term || \is_wp_error($term)) { return []; } // Get the taxonomy of the term $taxonomy = $term->taxonomy; // Get all post types associated with this taxonomy $taxonomy_object = \get_taxonomy($taxonomy); if (!$taxonomy_object || \is_wp_error($taxonomy_object)) { return []; } return (array) $taxonomy_object->object_type; } public function getPostTypesByTaxonomy(string $taxonomy) : array { if (!$taxonomy || \is_wp_error($taxonomy)) { return []; } // Get all post types associated with this taxonomy $taxonomy_object = \get_taxonomy($taxonomy); if (!$taxonomy_object || \is_wp_error($taxonomy_object)) { return []; } return (array) $taxonomy_object->object_type; } public function getTerm(int $term_id, string $taxonomy = '') { $term = \get_term($term_id, $taxonomy); return !$term || \is_wp_error($term) ? null : $term; } public function getTaxonomyByTermIdFromDB($term_id, $wpdb) { // Ensure $term_id is a valid integer if (!\is_int($term_id)) { return \false; } // Query to fetch the taxonomy names for the given term ID $query = "\n SELECT tt.taxonomy\n FROM {$wpdb->prefix}term_taxonomy tt\n WHERE tt.term_id = %d\n "; // Prepare the query and execute $results = $wpdb->get_results($wpdb->prepare($query, $term_id)); if (empty($results)) { return \false; // No taxonomies found for this term ID } // Array to store taxonomy information $taxonomy_array = []; // Loop through results and fetch taxonomy labels and other info foreach ($results as $row) { $taxonomy_data = \get_taxonomy($row->taxonomy); // Use WordPress function to get taxonomy details if ($taxonomy_data) { $taxonomy_array[] = ['taxonomy' => $row->taxonomy, 'label' => $taxonomy_data->labels->name, 'hierarchical' => $taxonomy_data->hierarchical]; } } return $taxonomy_array; } public function getAllDescendants(int $parent_id, string $taxonomy) : array { $descendants = []; $this->collectDescendants($parent_id, $taxonomy, $descendants); return $descendants; } protected function collectDescendants(int $parent_id, string $taxonomy, array &$descendants, int $current_level = 1) : void { $children = get_terms(['taxonomy' => $taxonomy, 'parent' => $parent_id, 'hide_empty' => \false, 'fields' => 'all']); if (\is_wp_error($children) || empty($children)) { return; } foreach ($children as $child) { $descendants[] = ['term' => $child, 'level' => $current_level]; $this->collectDescendants($child->term_id, $taxonomy, $descendants, $current_level + 1); } } public function hasChildren(int $term_id, string $taxonomy) : bool { $children = get_terms(['taxonomy' => $taxonomy, 'parent' => $term_id, 'hide_empty' => \false, 'fields' => 'ids', 'number' => 1]); return !\is_wp_error($children) && !empty($children); } public function isParentTerm(int $term_id, string $taxonomy = '') : bool { $term = $this->getTerm($term_id, $taxonomy); return $term ? $term->parent === 0 : \false; } public function getChildTerms(int $parent_id, string $taxonomy) : array { $children = get_terms(['taxonomy' => $taxonomy, 'parent' => $parent_id, 'hide_empty' => \false, 'fields' => 'all']); if (\is_wp_error($children)) { return []; } $child_terms = []; foreach ($children as $child) { $child_terms[] = ['term' => $child, 'children' => $this->getChildTerms($child->term_id, $taxonomy)]; } return $child_terms; } public function termParentChanged(int $term_id, string $taxonomy) : bool { // Requires implementation of previous state tracking // Example using transients: $previous_parent = \get_transient("term_{$term_id}_previous_parent"); $current_term = $this->getTerm($term_id, $taxonomy); return $previous_parent !== \false && $current_term && $previous_parent != $current_term->parent; } public function hadChildrenBeforeUpdate(int $term_id, string $taxonomy) : bool { $transient_key = "term_{$term_id}_had_children"; $had_children = \get_transient($transient_key); \delete_transient($transient_key); return $had_children === 'yes'; } public function syncTermUpdate($term) { try { $payload = ['wp_id' => $term->term_id, 'title' => $term->name, 'slug' => $term->slug, 'taxonomy' => $term->taxonomy, 'description' => $term->description, 'parent_wp_unique_id' => $term->parent > 0 ? Client::getUid() . '-' . $term->parent : null, 'updated_at' => current_time('mysql')]; $uid = Client::getUid() . '-' . $term->term_id; $response = (new CategoryApi())->update($payload, $uid); if ($response->getStatusCode() !== Response::HTTP_OK) { throw new Exception("API status: " . $response->getStatusCode()); } } catch (Exception $e) { \error_log("Update failed for term {$term->term_id}: " . $e->getMessage()); return \false; } } } Handlers/OrderDeleteHandler.php 0000777 00000001137 15251220643 0012522 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\OrderApi; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Response; class OrderDeleteHandler { public function __construct() { } public function __invoke($order_id) { $order = wc_get_order($order_id); if (!$order) { return; } $uid = Client::getUid() . '-' . $order_id; $response = (new OrderApi())->delete($uid); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log('Delete insert' . $response->getStatusCode()); return \false; } } } Handlers/MigrationRollback/RollbackPrompt.php 0000777 00000017673 15251220643 0015400 0 ustar 00 <?php namespace Rvx\Handlers\MigrationRollback; use Rvx\Services\SettingService; class RollbackPrompt { // Constructor public function __construct() { } // Entry point for the rollback process public function rvx_retrieve_sass_plugin_reviews_meta_updater() { echo '<h3>Rollback started.</h3>'; // Rollback options data $this->rvx_retrieve_saas_plugin_options_data(); echo 'Options data rollback completed.<br>'; // Rollback multi-criteria reviews $reviews_data = $this->rvx_retrieve_saas_plugin_criterias_reviews_converter(); echo 'Multi-criteria data rollback completed.<br>'; // Rollback attachments for reviews $this->rvx_retrieve_saas_plugin_reviews_attachments_data_converter($reviews_data); echo 'Reviews attachments data rollback completed.<br>'; echo '<h3>Rollback done.</h3><br>'; } // Handles the rollback of plugin options data public function rvx_retrieve_saas_plugin_options_data() { $settings_data = (array) (new SettingService())->getSettingsData()['setting'] ?? []; // If settings data is an array, extract and update widget/review settings if (\is_array($settings_data)) { $widget_settings = $settings_data['widget_settings'] ?? []; $review_settings = $settings_data['review_settings']['reviews'] ?? []; $this->update_widget_settings($widget_settings); $this->update_review_settings($review_settings); } $sharedMethods = new \Rvx\Handlers\MigrationRollback\SharedMethods(); // Convert multi-criteria data if available if (isset($existing_data['reviews']['multicriteria'])) { $oldCriteriaData = $sharedMethods->rvxRollbackReverseReviewCriteriaConverter($existing_data['reviews']['multicriteria']); if ($sharedMethods->key_exists('_rx_option_review_criteria')) { \update_option('_rx_option_allow_multi_criteria', $oldCriteriaData['_rx_option_allow_multi_criteria']); \update_option('_rx_option_review_criteria', $oldCriteriaData['_rx_option_review_criteria']); } return $oldCriteriaData; } return \true; } // Updates widget-related settings private function update_widget_settings($widget_settings) { if (isset($widget_settings['brand_color_code'])) { \update_option('_rx_option_color_theme', $widget_settings['brand_color_code']); } if (isset($widget_settings['star_color_code'])) { \update_option('_rx_option_star_color', $widget_settings['star_color_code']); } if (isset($widget_settings['button_font_color_code'])) { \update_option('_rx_option_button_font_color', $widget_settings['button_font_color_code']); } } // Updates review-related settings private function update_review_settings($review_settings) { $map = ['enable_likes_dislikes' => '_rx_option_allow_like_dislike', 'photo_reviews_allowed' => '_rx_option_allow_img', 'video_reviews_allowed' => '_rx_option_allow_video', 'anonymous_reviews_allowed' => '_rx_option_allow_anonymouse', 'allow_multiple_reviews' => '_rx_option_allow_multiple_review']; // Update each mapped setting foreach ($map as $key => $option) { if (isset($review_settings[$key])) { \update_option($option, $review_settings[$key]); } } // Handle boolean values for auto-approve and schema settings if (isset($review_settings['auto_approve_reviews'])) { \update_option('_rx_option_disable_auto_approval', !$review_settings['auto_approve_reviews']); } if (isset($review_settings['product_schema'])) { \update_option('_rx_option_disable_richschema', !$review_settings['product_schema']); } } // Handles rollback for multi-criteria reviews public function rvx_retrieve_saas_plugin_criterias_reviews_converter() { $reviews_with_meta = $this->rvx_retrieve_saas_plugin_reviews_data(); if (empty($reviews_with_meta)) { return []; } $existingOldData = \get_option('_rx_option_review_criteria'); $oldCriteria = \is_string($existingOldData) ? maybe_unserialize($existingOldData) : []; if (empty($oldCriteria)) { return []; } // Process and convert each review's criteria foreach ($reviews_with_meta as $comment_id => $review_data) { $criterias = $review_data['meta_data']['rvx_criterias'] ?? null; if (\is_array($criterias)) { $converted_criterias = $this->rvx_convert_criterias_to_serialized_format($criterias, $oldCriteria); \update_comment_meta($comment_id, 'rvx_criterias', $converted_criterias); } } return $reviews_with_meta; } // Retrieves reviews with their metadata public function rvx_retrieve_saas_plugin_reviews_data() { global $wpdb; $meta_key = 'rvx_review_version'; $meta_value = 'v2'; $query = $wpdb->prepare("SELECT comment_id FROM {$wpdb->commentmeta} WHERE meta_key = %s AND meta_value = %s", $meta_key, $meta_value); $comment_ids = $wpdb->get_col($query); if (empty($comment_ids)) { return []; } $placeholders = \implode(',', \array_fill(0, \count($comment_ids), '%d')); $query = $wpdb->prepare("SELECT * FROM {$wpdb->comments} WHERE comment_ID IN ({$placeholders})", $comment_ids); $reviews_data = $wpdb->get_results($query, ARRAY_A); $query = $wpdb->prepare("SELECT comment_id, meta_key, meta_value FROM {$wpdb->commentmeta} WHERE comment_id IN ({$placeholders})", $comment_ids); $meta_data = $wpdb->get_results($query, ARRAY_A); $reviews_with_meta = []; foreach ($reviews_data as $review) { $comment_id = $review['comment_ID']; $reviews_with_meta[$comment_id] = ['review_data' => $review, 'meta_data' => []]; } foreach ($meta_data as $meta) { $comment_id = $meta['comment_id']; if (isset($reviews_with_meta[$comment_id])) { $reviews_with_meta[$comment_id]['meta_data'][$meta['meta_key']] = maybe_unserialize($meta['meta_value']); } } return $reviews_with_meta; } // Converts criteria data into serialized format private function rvx_convert_criterias_to_serialized_format($criterias, $oldCriteria) { $key_base = 'ctr_h8S'; $serialized_array = []; $index = 7; foreach ($criterias as $key => $value) { $serialized_key = $key_base . $index++; $serialized_array[$serialized_key] = (string) $value; } return maybe_serialize($serialized_array); } // Converts review attachments to match the required rollback format public function rvx_retrieve_saas_plugin_reviews_attachments_data_converter($reviews_data) { if (!\is_array($reviews_data)) { return; } foreach ($reviews_data as $review_data) { $comment_id = $review_data['review_data']['comment_ID'] ?? null; $attachments = $review_data['meta_data']['reviewx_attachments'] ?? null; if (\is_array($attachments)) { $attachment_data = []; foreach ($attachments as $attachment_url) { if (\is_string($attachment_url)) { $attachment_id = attachment_url_to_postid($attachment_url); if ($attachment_id) { $attachment_data[] = $attachment_id; } } } if (!empty($attachment_data)) { $attachment_data_collection = ['images' => $attachment_data]; \update_comment_meta($comment_id, 'reviewx_attachments', $attachment_data_collection); } } } } } Handlers/MigrationRollback/RollbackMenuHandler.php 0000777 00000005173 15251220643 0016311 0 ustar 00 <?php namespace Rvx\Handlers\MigrationRollback; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class RollbackMenuHandler implements InvokableContract { public function __invoke() { $sharedMethods = new \Rvx\Handlers\MigrationRollback\SharedMethods(); $rollbackPrompt = new \Rvx\Handlers\MigrationRollback\RollbackPrompt(); echo '<div class="wrap p-6 bg-gray-100 rounded-lg shadow-md">'; View::output('storeadmin/rollback', ['title' => 'Rollback to ReviewX v1', 'content' => 'Revert to the previous version with ease and restore functionality seamlessly.', 'page_url' => $_SERVER['REQUEST_URI']]); if (isset($_GET['rollback_start'])) { $is_pro_active = $sharedMethods->rvx_is_old_pro_plugin_active(); if ($is_pro_active === \false) { //$sharedMethods->rvx_activate_old_pro_plugin(); // Activate v1 Pro } $rollbackPrompt->rvx_retrieve_sass_plugin_reviews_meta_updater(); // Start data rollback echo <<<HTML <div class="p-4 bg-white rounded-lg shadow-md"> <h2 class="text-lg font-bold text-gray-800 mb-2">Your data has been successfully rolled back to the previous version.</h2> <p class="text-gray-600">Thank you for your patience!</p> <h3 class="text-md font-semibold text-gray-800 mt-4">Next Steps:</h3> <ul class="list-disc list-inside text-gray-600"> <li><strong>Must do:</strong> Please make sure to <b>delete ReviewX v2</b> and and <b>reinstall ReviewX v1</b> plugin.</li> <li><strong>Pro user:</strong> If you used the Pro version, please it activate it to access the premium features.</li> <li><strong>Download:</strong> ReviewX v1 plugin is available here, <a target="_blank" href="https://downloads.wordpress.org/plugin/reviewx.1.6.30.zip" class="text-blue-600 hover:underline">Download v1</a>.</li> </ul> <h3 class="text-md font-semibold text-gray-800 mt-4">Need Assistance?</h3> <p class="text-gray-600"> Our support team is here to help. <a target="_blank" href="https://reviewx.io/support/" class="text-blue-600 hover:underline">Contact Support</a> or email us at <a href="mailto:support@reviewx.io" class="text-blue-600 hover:underline">support@reviewx.io</a>. </p> </div> HTML; } // Remove the query parameter without reloading echo <<<JS <script> document.addEventListener("DOMContentLoaded", function() { const url = new URL(window.location.href); url.searchParams.delete("rollback_start"); history.replaceState(null, "", url); }); </script> JS; echo '</div>'; } } Handlers/MigrationRollback/SharedMethods.php 0000777 00000013601 15251220643 0015162 0 ustar 00 <?php namespace Rvx\Handlers\MigrationRollback; class SharedMethods { public function rvx_is_old_pro_plugin_active() { // Check for the older ReviewX Pro versions $pro_version = \defined('REVIEWX_PRO_VERSION') ? REVIEWX_PRO_VERSION : null; if ($pro_version !== null) { return \true; } else { return \false; } } public function rvx_activate_old_pro_plugin() { // Ensure WordPress functions are available if (!\function_exists('Rvx\\get_plugins') || !\function_exists('Rvx\\activate_plugin')) { return; // Exit if WordPress is not fully loaded } // Retrieve all installed plugins $plugins = get_plugins(); $found_plugin = ''; // Search for the ReviewX Pro plugin foreach ($plugins as $plugin_path => $plugin_data) { if (\strpos($plugin_path, 'reviewx-pro') !== \false && \defined('WP_PLUGIN_DIR') && \file_exists(WP_PLUGIN_DIR . '/' . $plugin_path)) { $plugin_file = WP_PLUGIN_DIR . '/' . $plugin_path; // Check if the file contains a unique identifier $plugin_content = \file_get_contents($plugin_file); if (\strpos($plugin_content, 'REVIEWX_PRO_VERSION') !== \false) { $found_plugin = $plugin_path; break; } } } // Activate the plugin if it is found and not already active if ($found_plugin && !is_plugin_active($found_plugin)) { $result = activate_plugin($found_plugin); if (\is_wp_error($result)) { // Optionally, handle errors if activation fails } else { // Optionally, display an admin notice for successful activation } } else { // Optionally, display a notice if the plugin is not found } } public function rvx_deactivate_old_pro_plugin() { if (!\function_exists('Rvx\\get_plugins') || !\function_exists('Rvx\\deactivate_plugins')) { return; // Exit if WordPress is not fully loaded } // Retrieve all installed plugins $plugins = get_plugins(); $found_plugin = ''; // Search for the ReviewX Pro plugin foreach ($plugins as $plugin_path => $plugin_data) { if (\strpos($plugin_path, 'reviewx-pro') !== \false && \defined('WP_PLUGIN_DIR') && \file_exists(WP_PLUGIN_DIR . '/' . $plugin_path)) { $plugin_file = WP_PLUGIN_DIR . '/' . $plugin_path; $plugin_content = \file_get_contents($plugin_file); if (\strpos($plugin_content, 'REVIEWX_PRO_VERSION') !== \false) { $found_plugin = $plugin_path; break; } } } // Deactivate the plugin if it is found and not already deactive if ($found_plugin && is_plugin_active($found_plugin)) { $result = deactivate_plugins($found_plugin); if (\is_wp_error($result)) { // Optionally, handle errors if deactivation fails } else { // Optionally, display an admin notice for successful deactivation } } else { // Optionally, display a notice if the plugin is not found } } public function rvxOldReviewCriteriaConverter() { $data = \get_option('_rx_option_review_criteria'); $keys = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; $criterias = []; $i = 0; foreach ($data as $key => $name) { if (isset($keys[$i])) { $criterias[] = ["key" => $keys[$i], "name" => $name]; } $i++; } $multicrtriaEnableorDisable = \get_option('_rx_option_allow_multi_criteria'); $newCriteria = ["enable" => $multicrtriaEnableorDisable == 1 ? \true : \false, "criterias" => $criterias]; return $newCriteria; } public function rvxRollbackReverseReviewCriteriaConverter($newCriteria) { // Initialize old criteria structure $oldCriteria = []; // Retrieve existing criteria from the database $existingOldData = \get_option('_rx_option_review_criteria'); if ($existingOldData) { $oldCriteria = maybe_unserialize($existingOldData); // Deserialize existing criteria } // Find the highest number in old criteria keys (ctr_h8S7, ctr_h8S8, etc.) $highestNumber = 0; foreach ($oldCriteria as $key => $value) { if (\preg_match('/ctr_h8S(\\d+)/', $key, $matches)) { $highestNumber = \max($highestNumber, (int) $matches[1]); // Track the highest number } } // Merge old and new criteria $seenValues = \array_flip($oldCriteria); // Store old criteria values for fast lookup $mergedCriteria = $oldCriteria; // Start with old criteria // Assign new keys for unique new criteria foreach ($newCriteria['criterias'] as $criteria) { if (isset($criteria['name']) && !isset($seenValues[$criteria['name']])) { $highestNumber++; // Increment key number $newKey = 'ctr_h8S' . $highestNumber; $mergedCriteria[$newKey] = $criteria['name']; $seenValues[$criteria['name']] = \true; // Mark as seen } } // Build updated data structure $updatedData = [ '_rx_option_allow_multi_criteria' => $newCriteria['enable'] ? 1 : 0, // Boolean as integer '_rx_option_review_criteria' => $mergedCriteria, ]; return $updatedData; } public function key_exists($option_name) { $option_value = \get_option($option_name); return $option_value !== \false; } } Handlers/MigrationRollback/ReviewXChecker.php 0000777 00000002720 15251220643 0015306 0 ustar 00 <?php namespace Rvx\Handlers\MigrationRollback; class ReviewXChecker { /** * Check if ReviewX v1 (free) plugin database data exists. * * @return bool */ public static function isReviewXExists() : bool { global $wpdb; // Define option name for ReviewX free version $option_name = '_rx_option_review_criteria'; // Check if the option exists in the wp_options table $option_exists = $wpdb->get_var($wpdb->prepare("SELECT option_name FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", $option_name)); return !empty($option_exists); } /** * Check if ReviewX v2 SaaS plugin database data exists. * * @return bool */ public static function isReviewXSaasExists() : bool { global $wpdb; // Define option name for ReviewX SaaS version $option_name = '_rvx_settings_data'; $option_name_latest = '_rvx_settings_product'; // Check if the option exists in the wp_options table $option_exists = $wpdb->get_var($wpdb->prepare("SELECT option_name FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", $option_name)); if (empty($option_exists)) { // Check if the option exists in the wp_options table $option_exists = $wpdb->get_var($wpdb->prepare("SELECT option_name FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", $option_name_latest)); } return !empty($option_exists); } } Handlers/MigrationRollback/MigrationPrompt.php 0000777 00000013717 15251220643 0015573 0 ustar 00 <?php namespace Rvx\Handlers\MigrationRollback; use Rvx\Services\SettingService; class MigrationPrompt { public function rvx_retrieve_old_plugin_options_data() { $data = []; $sharedMethods = new \Rvx\Handlers\MigrationRollback\SharedMethods(); // Options to retrieve if ($sharedMethods->key_exists('_rx_option_review_criteria')) { $data['multicriteria'] = $sharedMethods->rvxOldReviewCriteriaConverter(); } if ($sharedMethods->key_exists('_rx_option_allow_like_dislike')) { $data['enable_likes_dislikes']['enabled'] = \get_option('_rx_option_allow_like_dislike'); $data['enable_likes_dislikes']['options']['allow_dislikes'] = \get_option('_rx_option_allow_like_dislike'); } if ($sharedMethods->key_exists('_rx_option_color_theme')) { $data['brand_color_code'] = \get_option('_rx_option_color_theme'); } if ($sharedMethods->key_exists('_rx_option_allow_img')) { $data['photo_reviews_allowed'] = \get_option('_rx_option_allow_img'); } if ($sharedMethods->key_exists('_rx_option_allow_share_review')) { $data['allow_review_sharing'] = \get_option('_rx_option_allow_share_review'); } if ($sharedMethods->key_exists('_rx_option_disable_auto_approval')) { $data['auto_approve_reviews'] = \get_option('_rx_option_disable_auto_approval'); } if ($sharedMethods->key_exists('_rx_option_allow_review_title')) { $data['allow_review_titles'] = \get_option('_rx_option_allow_review_title'); } if ($sharedMethods->key_exists('_rx_option_allow_reviewer_name_censor')) { $data['censor_reviewer_name'] = \get_option('_rx_option_allow_reviewer_name_censor'); } if ($sharedMethods->key_exists('_rx_option_disable_richschema')) { $data['product_schema'] = \get_option('_rx_option_disable_richschema'); } if ($sharedMethods->key_exists('_rx_option_allow_video')) { $data['video_reviews_allowed'] = \get_option('_rx_option_allow_video'); } if ($sharedMethods->key_exists('_rx_option_allow_multiple_review')) { $data['allow_multiple_reviews'] = \get_option('_rx_option_allow_multiple_review'); } if ($sharedMethods->key_exists('_rx_option_allow_anonymouse')) { $data['anonymous_reviews_allowed'] = \get_option('_rx_option_allow_anonymouse'); } if ($sharedMethods->key_exists('_rx_option_allow_recaptcha')) { $data['recaptcha']['enabled'] = \get_option('_rx_option_allow_recaptcha'); } if ($sharedMethods->key_exists('_rx_option_recaptcha_site_key')) { $data['recaptcha']['site_key'] = \get_option('_rx_option_recaptcha_site_key'); } if ($sharedMethods->key_exists('_rx_option_recaptcha_secret_key')) { $data['recaptcha']['secret_key'] = \get_option('_rx_option_recaptcha_secret_key'); } if ($sharedMethods->key_exists('_rx_option_disable_richschema')) { $data['product_schema'] = \get_option('_rx_option_disable_richschema'); } if ($sharedMethods->key_exists('_rx_option_review_per_page')) { $data['per_page_reviews'] = \get_option('_rx_option_review_per_page'); } if ($sharedMethods->key_exists('_rx_option_allow_recommendation')) { $data['allow_recommendations'] = \get_option('_rx_option_allow_recommendation'); } if ($sharedMethods->key_exists('_rx_option_filter_recent')) { $data['filter_and_sort_options']['recent'] = \get_option('_rx_option_filter_recent'); } if ($sharedMethods->key_exists('_rx_option_filter_photo')) { $data['filter_and_sort_options']['photo'] = \get_option('_rx_option_filter_photo'); } if (empty($data)) { return \false; } return $data; } public function rvx_retrieve_saas_plugin_options_data() { $settings = (array) (new SettingService())->getSettingsData()['setting'] ?? []; $saasOptions = ['display_badges' => $settings['widget_settings']['display_badges'], 'outline' => $settings['widget_settings']['outline'], 'brand_color_code' => $settings['widget_settings']['brand_color_code'], 'star_color_code' => $settings['widget_settings']['star_color_code'], 'button_font_color_code' => $settings['widget_settings']['button_font_color_code'], 'filter_and_sort_options' => $settings['widget_settings']['filter_and_sort_options'], 'verified_customer_only' => $settings['review_settings']['reviews']['review_submission_policy']['options']['verified_customer'], 'review_eligibility' => $settings['review_settings']['reviews']['review_eligibility'], 'auto_approve_reviews' => $settings['review_settings']['reviews']['auto_approve_reviews'], 'show_reviewer_name' => $settings['review_settings']['reviews']['show_reviewer_name'], 'censor_reviewer_name' => $settings['review_settings']['reviews']['censor_reviewer_name'], 'show_reviewer_country' => $settings['review_settings']['reviews']['show_reviewer_country'], 'enable_likes_dislikes' => $settings['review_settings']['reviews']['enable_likes_dislikes'], 'allow_review_sharing' => $settings['review_settings']['reviews']['allow_review_sharing'], 'allow_review_titles' => $settings['review_settings']['reviews']['allow_review_titles'], 'photo_reviews_allowed' => $settings['review_settings']['reviews']['photo_reviews_allowed'], 'video_reviews_allowed' => $settings['review_settings']['reviews']['video_reviews_allowed'], 'allow_recommendations' => $settings['review_settings']['reviews']['allow_recommendations'], 'anonymous_reviews_allowed' => $settings['review_settings']['reviews']['anonymous_reviews_allowed'], 'multicriteria' => $settings['review_settings']['reviews']['multicriteria'], 'product_schema' => $settings['review_settings']['reviews']['product_schema'], 'recaptcha' => $settings['review_settings']['reviews']['recaptcha']]; return $saasOptions; } } Handlers/MigrationRollback/UpgradeDBSettings.php 0000777 00000002523 15251220643 0015747 0 ustar 00 <?php namespace Rvx\Handlers\MigrationRollback; use Rvx\Rest\Controllers\DataSyncController; use Rvx\Utilities\Auth\Client; class UpgradeDBSettings { protected $dataSyncController; // Option name used as a flag to indicate the upgrade has run. public function __construct() { $this->dataSyncController = new DataSyncController(); $this->run_upgrade(); } /** * Run the upgrade routine if it hasn't already been executed. */ public function run_upgrade() { if (!Client::getSync()) { return; } if (\get_option('_rvx_db_upgrade_216', \false) === \true) { return; } // Retrieve the current settings. $product_settings = \get_option('_rvx_settings_product'); $widget_settings = \get_option('_rvx_settings_widget'); $cpt_settings = \get_option('_rvx_cpt_settings'); // If any of the required options are missing, run upgrade logic. if (\false === $product_settings || \false === $widget_settings || \false === $cpt_settings) { // Initialize default settings if they are not available. $this->dataSyncController->updateSettingsOnSync(); } // Mark the upgrade routine as completed so it doesn't run again. \update_option('_rvx_db_upgrade_216', \true); } } Handlers/OrderBulkStatusChangedHandler.php 0000777 00000001122 15251220643 0014665 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Services\OrderService; class OrderBulkStatusChangedHandler { protected $orderService; public function __construct() { $this->orderService = new OrderService(); } public function __invoke($redirect_to, $action, $order_ids) { if ($action === 'mark_complete') { $data = []; foreach ($order_ids as $order_id) { $data['order_wp_unique_ids'] = $order_id; } \error_log("Return Data" . \print_r($data, \true)); } return $redirect_to; } } Handlers/WChooks/StorefrontReviewLinkClickScroll.php 0000777 00000006576 15251220643 0016711 0 ustar 00 <?php namespace Rvx\Handlers\WChooks; use Rvx\CPT\CptHelper; class StorefrontReviewLinkClickScroll { protected $cptHelper; public function __construct() { $this->cptHelper = new CptHelper(); } public function addScrollScript() { global $post; // Check if $post is available before accessing properties if (!isset($post) || !\is_object($post) && !is_admin()) { return; } // Define the target post types $enabled_post_types = $this->cptHelper->enabledCPT(); $post_type = $post->post_type ?? ''; if (!isset($enabled_post_types[$post_type])) { return; } // Check if WooCommerce is active and we are on a product page if (\function_exists('Rvx\\wc_get_product') && 'product' === $post_type) { ?> <script> document.addEventListener('DOMContentLoaded', function () { document.querySelectorAll('.woocommerce-review-link').forEach(function (link) { link.addEventListener('click', function (e) { e.preventDefault(); // Prevent default link behavior // Scroll to the reviews tab const reviewsTab = document.getElementById('tab-title-reviews'); if (reviewsTab) { reviewsTab.scrollIntoView({ behavior: 'smooth', block: 'start' }); // Smooth scroll // Open the tab if not already active if (!reviewsTab.classList.contains('active')) { const tabLink = reviewsTab.querySelector('a'); if (tabLink) { tabLink.click(); // Trigger the tab opening } } } }); }); }); </script> <?php } if ('product' !== $post_type) { ?> <script> document.addEventListener('DOMContentLoaded', function () { document.querySelectorAll('.comments-link').forEach(function (link) { link.addEventListener('click', function (e) { e.preventDefault(); // Prevent default link behavior // Scroll to the reviews tab const reviewsTab = document.getElementById('rvx-storefront-widget--aggregation__summary'); if (reviewsTab) { reviewsTab.scrollIntoView({ behavior: 'smooth', block: 'start' }); // Smooth scroll // Open the tab if not already active if (!reviewsTab.classList.contains('active')) { const tabLink = reviewsTab.querySelector('a'); if (tabLink) { tabLink.click(); // Trigger the tab opening } } } }); }); }); </script> <?php } } } Handlers/StoreFrontReviewDataHandller.php 0000777 00000001156 15251220643 0014562 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\WpApi; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class StoreFrontReviewDataHandller implements InvokableContract { protected WpApi $wpApi; /** * */ public function __construct() { $this->wpApi = new WpApi(); } public function __invoke() { View::output('storefront/reviews', ['title' => 'Welcome Deshboard review', 'content' => 'A WordPress Plugin development framework for humans', 'response' => $this->wpApi->get('/reviews')]); } public function storefrontTest($data) { } } Handlers/WoocommerceCommentStatusChangeHandler.php 0000777 00000003061 15251220643 0016436 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\ReviewsApi; use Rvx\Utilities\Auth\Client; class WoocommerceCommentStatusChangeHandler { public function __invoke($comment_id, $status) { $screen = \get_current_screen(); if ($screen instanceof \Rvx\Handlers\WP_Screen || $screen->id == "edit-comments") { $this->prepareData($comment_id, $status); } if (wp_doing_ajax()) { $this->prepareData($comment_id, $status); } } public function prepareData($comment_id, $status) { $comment = get_comment($comment_id); $post_type = get_post_type($comment->comment_post_ID); if ($post_type) { $data = []; switch ($status) { case "approve": $data["status"] = 1; (new ReviewsApi())->visibilityReviewData($data, Client::getUid() . "-" . $comment_id); break; case "hold": $data["status"] = 4; (new ReviewsApi())->visibilityReviewData($data, Client::getUid() . "-" . $comment_id); break; case "spam": $data["status"] = 5; (new ReviewsApi())->visibilityReviewData($data, Client::getUid() . "-" . $comment_id); break; case "1": $data["status"] = 1; (new ReviewsApi())->visibilityReviewData($data, Client::getUid() . "-" . $comment_id); break; } } } } Handlers/IsAlreadySyncSucess.php 0000777 00000001153 15251220643 0012724 0 ustar 00 <?php namespace Rvx\Handlers; class IsAlreadySyncSucess { public function resetSyncFlag() { add_action('admin_footer', function () { if (!\get_transient('rvx_reset_sync_flag')) { return; } ?> <script> try { localStorage.setItem('isAlreadySyncSuccess', 'false'); } catch (e) { console.warn('ReviewX: Unable to access localStorage'); } </script> <?php \delete_transient('rvx_reset_sync_flag'); }); } } Handlers/DashboardMenuHandler.php 0000777 00000000546 15251220643 0013043 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class DashboardMenuHandler implements InvokableContract { public function __invoke() { View::output('storeadmin/dashboard', ['title' => 'Welcome Deshboard', 'content' => 'A WordPress Plugin development framework for humans']); } } Handlers/BulkAction/CustomBulkActionsForReviewsHandler.php 0000777 00000004725 15251220643 0020012 0 ustar 00 <?php namespace Rvx\Handlers\BulkAction; use Rvx\Api\ReviewsApi; use Rvx\Utilities\Auth\Client; use Rvx\Services\CacheServices; class CustomBulkActionsForReviewsHandler { protected $cacheServices; public function __construct() { $this->cacheServices = new CacheServices(); } public function __invoke() { $screen = \get_current_screen(); // Ensure we are on the 'edit-comments' screen if (!$screen instanceof \Rvx\Handlers\BulkAction\WP_Screen || $screen->id !== 'edit-comments') { return; } // Validate request parameters if (empty($_REQUEST['action']) || empty($_REQUEST['delete_comments'])) { return; } $action = sanitize_text_field($_REQUEST['action']); $comment_ids = \array_map('intval', (array) $_REQUEST['delete_comments']); // Define valid actions $valid_actions = ['approve', 'unapprove', 'spam', 'trash', 'unspam', 'restore']; if (!\in_array($action, $valid_actions, \true)) { return; } $data = []; $reviewApi = new ReviewsApi(); // Process actions switch ($action) { case 'approve': $data['status'] = 1; $data['review_wp_unique_ids'] = $this->modifiyIds($comment_ids); $reviewApi->reviewBulkUpdate($data); break; case 'unapprove': $data['status'] = 2; $data['review_wp_unique_ids'] = $this->modifiyIds($comment_ids); $reviewApi->reviewBulkUpdate($data); break; case 'spam': $data['status'] = 3; $data['review_wp_unique_ids'] = $this->modifiyIds($comment_ids); $reviewApi->reviewBulkUpdate($data); break; case 'trash': $data['review_wp_unique_ids'] = $this->modifiyIds($comment_ids); $reviewApi->reviewBulkTrash($data); break; case 'unspam': case 'restore': $data['status'] = 1; $data['review_wp_unique_ids'] = $this->modifiyIds($comment_ids); $reviewApi->reviewBulkTrash($data); break; } $this->cacheServices->removeCache(); } public function modifiyIds($comment_ids) { return \array_map(function ($id) { return Client::getUid() . '-' . $id; }, $comment_ids); } } Handlers/BulkAction/RegisterBulkActionsForReviewsHandler.php 0000777 00000004710 15251220643 0020316 0 ustar 00 <?php namespace Rvx\Handlers\BulkAction; use Rvx\Services\CacheServices; class RegisterBulkActionsForReviewsHandler { protected $cacheServices; public function __construct() { $this->cacheServices = new CacheServices(); } public function __invoke($new_status, $old_status, $comment) { $screen = \get_current_screen(); if ($screen->id !== 'edit-comments') { return; } if (isset($_REQUEST['action']) && $_REQUEST['action'] != -1) { $doaction = $_REQUEST['action']; } elseif (isset($_REQUEST['action2']) && $_REQUEST['action2'] != -1) { $doaction = $_REQUEST['action2']; } else { return; } // Check if we are in the comments admin page if (!isset($_REQUEST['comment'])) { return; } $comment_ids = $_REQUEST['comment']; // Process each bulk action if ($doaction === 'approve') { foreach ($comment_ids as $comment_id) { // Approve the comment wp_set_comment_status($comment_id, 'approve'); } $redirect_to = add_query_arg('bulk_approved_comments', \count($comment_ids), wp_get_referer()); wp_safe_redirect($redirect_to); exit; } if ($doaction === 'unapprove') { foreach ($comment_ids as $comment_id) { // Unapprove the comment wp_set_comment_status($comment_id, 'hold'); } $redirect_to = add_query_arg('bulk_unapproved_comments', \count($comment_ids), wp_get_referer()); wp_safe_redirect($redirect_to); exit; } if ($doaction === 'spam') { foreach ($comment_ids as $comment_id) { // Mark the comment as spam wp_spam_comment($comment_id); } $redirect_to = add_query_arg('bulk_spam_comments', \count($comment_ids), wp_get_referer()); wp_safe_redirect($redirect_to); exit; } if ($doaction === 'trash') { foreach ($comment_ids as $comment_id) { // Move the comment to trash wp_trash_comment($comment_id); } $redirect_to = add_query_arg('bulk_trash_comments', \count($comment_ids), wp_get_referer()); wp_safe_redirect($redirect_to); exit; } $this->cacheServices->removeCache(); } } Handlers/WooReviewTableHandler.php 0000777 00000007340 15251220643 0013224 0 ustar 00 <?php namespace Rvx\Handlers; use Exception; use Rvx\Api\ReviewsApi; use Rvx\Utilities\Auth\Client; use Rvx\Services\CacheServices; use WP_Screen; class WooReviewTableHandler { protected $cacheServices; public function __construct() { $this->cacheServices = new CacheServices(); } public function __invoke($new_status, $old_status, $comment) { $comment_id = $comment->comment_ID; $this->handleAction($new_status, $old_status, $comment_id); } public function handleAction($new_status, $old_status, $comment_id) { $wpUniqueId = $this->getWpUniqueId($comment_id); switch (\true) { case $this->isMoveToTrash($new_status, $old_status): $this->moveToTrash($wpUniqueId); break; case $this->isRestoreFromTrash($new_status, $old_status): $this->restoreFromTrash($wpUniqueId, $new_status); break; default: $this->changeVisibility($new_status, $old_status, $wpUniqueId); break; } $comment = get_comment($comment_id); if ($comment && $comment->comment_post_ID) { \Rvx\CPT\CptAverageRating::update_average_rating($comment->comment_post_ID); } $this->cacheServices->removeCache(); } /** * Generate the unique ID for a WordPress comment. */ private function getWpUniqueId($comment_id) { return Client::getUid() . "-" . $comment_id; } /** * Check if the transition is moving to Trash from approved, unapproved, or spam. */ private function isMoveToTrash($new_status, $old_status) { return $new_status === "trash"; } /** * Check if the transition is restoring from Trash to approved or unapproved. */ private function isRestoreFromTrash($new_status, $old_status) { return $old_status === "trash"; } /** * Move a review to Trash. */ private function moveToTrash($wpUniqueId) : void { try { $data = ["WpUniqueId" => $wpUniqueId]; (new ReviewsApi())->reviewMoveToTrash($data); } catch (Exception $e) { \error_log("Move to trash : " . \print_r($e->getMessage(), \true)); } } /** * Restore a review from Trash to a given status. */ private function restoreFromTrash($wpUniqueId, $new_status) { try { $statusMap = ["approved" => 1, "unapproved" => 2, "hold" => 4, "pending" => 4, "spam" => 5]; $status = isset($statusMap[$new_status]) ? $statusMap[$new_status] : 1; // Default to published if unknown (new ReviewsApi())->restoreReview($wpUniqueId, $status); } catch (Exception $e) { \error_log("Restored Form trash " . \print_r($e->getMessage(), \true)); } } /** * Mark a review as spam. */ private function changeVisibility($new_status, $old_status, $wpUniqueId) { try { $statusMap = [ "approved" => 1, // WordPress default "published" => 1, "unapproved" => 2, // WordPress default "unpublished" => 2, "pending" => 4, "hold" => 4, "spam" => 5, "trash" => 3, "delete" => 3, ]; if (!isset($statusMap[$new_status])) { return; } $status = $statusMap[$new_status]; (new ReviewsApi())->visibilityReviewData(["status" => $status], $wpUniqueId); } catch (Exception $e) { \error_log("Change Visibility: " . \print_r($e->getMessage(), \true)); } } } Handlers/ReviewReminderEmailHandler.php 0000777 00000000562 15251220643 0014224 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class ReviewReminderEmailHandler implements InvokableContract { public function __invoke() { View::output('storeadmin/reviewReminder', ['title' => 'Welcome to WPDrill', 'content' => 'A WordPress Plugin development framework for humans']); } } Handlers/CommentStatusHandler.php 0000777 00000000321 15251220643 0013124 0 ustar 00 <?php namespace Rvx\Handlers; class CommentStatusHandler { public function __invoke($comment_id) { $comments = get_comment($comment_id); \error_log("Comment id" . $comments); } } Handlers/RvxInit/LoadReviewxCreateSiteTable.php 0000777 00000003520 15251220643 0015601 0 ustar 00 <?php namespace Rvx\Handlers\RvxInit; class LoadReviewxCreateSiteTable { /** * Invokes the process to ensure the table exists. */ public function init() { if (!$this->is_table_exists()) { $this->create_table(); } } /** * Checks if the table exists in the database. * * @return bool True if the table exists, false otherwise. */ private function is_table_exists() { global $wpdb; $table_name = $this->get_table_name(); return $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name)) === $table_name; } /** * Creates the database table if it does not exist. */ private function create_table() { global $wpdb; $table_name = $this->get_table_name(); $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE {$table_name} (\n id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,\n name VARCHAR(255) NOT NULL,\n site_id INT(11) NOT NULL,\n uid VARCHAR(32) NOT NULL,\n domain VARCHAR(255) NOT NULL,\n url VARCHAR(255) NOT NULL,\n locale CHAR(10) NOT NULL,\n email VARCHAR(100) NOT NULL,\n secret VARCHAR(100) NOT NULL,\n is_saas_sync TINYINT(1) DEFAULT 0,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (id)\n ) {$charset_collate};"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta($sql); } /** * Returns the table name. * * @return string Fully qualified table name. */ private function get_table_name() { global $wpdb; return $wpdb->prefix . 'rvx_sites'; } } Handlers/RvxInit/ReviewXoldPluginDeactivateHandler.php 0000777 00000001102 15251220643 0017160 0 ustar 00 <?php namespace Rvx\Handlers\RvxInit; class ReviewXoldPluginDeactivateHandler { /** * Handle the deactivation of the old ReviewX Pro plugin. * * This checks if the old ReviewX Pro plugin is active and deactivates it. */ public function __invoke() { $reviewxProPath = 'reviewx-pro/reviewx-pro.php'; // Path to the plugin to deactivate // Check if the plugin is active if (is_plugin_active($reviewxProPath)) { deactivate_plugins($reviewxProPath); // Deactivate the plugin } } } Handlers/RvxInit/ResetProductMetaHandler.php 0000777 00000000341 15251220643 0015155 0 ustar 00 <?php namespace Rvx\Handlers\RvxInit; use Rvx\Services\Api\LoginService; class ResetProductMetaHandler { public function __invoke($upgrader_object, $options) { (new LoginService())->resetPostMeta(); } } Handlers/RvxInit/UpgradeReviewxDeactiveProHandler.php 0000777 00000003222 15251220643 0017013 0 ustar 00 <?php namespace Rvx\Handlers\RvxInit; use Rvx\Api\AuthApi; class UpgradeReviewxDeactiveProHandler { public function __invoke($upgrader_object, $options) { if ($options['type'] === 'plugin' && isset($options['plugins'])) { // Your plugin's main file $reviewxFilePath = plugin_basename(__FILE__); // Check if your plugin is being updated if (\in_array($reviewxFilePath, $options['plugins'], \true)) { $reviewxProDeactive = 'reviewx-pro/reviewx-pro.php'; // Path to the plugin to deactivate // Check if the target plugin is active if (is_plugin_active($reviewxProDeactive)) { deactivate_plugins($reviewxProDeactive); // Deactivate the plugin } } $response = wp_remote_get("https://api.wordpress.org/plugins/info/1.0/reviewx.json"); if (!\is_wp_error($response)) { $plugin_data = \json_decode(wp_remote_retrieve_body($response)); if ($plugin_data && isset($plugin_data->version)) { global $wpdb; $rvxSites = $wpdb->prefix . 'rvx_sites'; $uid = $wpdb->get_var("SELECT uid FROM {$rvxSites} ORDER BY id DESC LIMIT 1"); $plugin_version = $plugin_data->version; if ($uid) { (new AuthApi())->changePluginStatus(['site_uid' => $uid, 'status' => 1, 'plugin_version' => $plugin_version ?? RVX_VERSION, 'wp_version' => get_bloginfo('version')]); } } } } } } Handlers/RvxInit/PageBuilderHandler.php 0000777 00000000346 15251220643 0014113 0 ustar 00 <?php namespace Rvx\Handlers\RvxInit; class PageBuilderHandler { public function __invoke() { if (\class_exists('\\Elementor\\Plugin')) { \Rvx\Elementor\Classes\Starter::instance(); } } } Handlers/ProductStatusHandler.php 0000777 00000001525 15251220643 0013151 0 ustar 00 <?php namespace Rvx\Handlers; class ProductStatusHandler { public function __construct() { } public function __invoke($new_status, $old_status, $post) { if ($post->post_type === 'product') { // Check if the new status is 'publish' or 'publish' if (($new_status === 'publish' || $new_status === 'pending') && $old_status !== 'publish') { // Product is being published // Your custom code for product publishing here echo "Product with ID {$post->ID} published."; } elseif ($new_status === 'draft' && $old_status === 'publish') { // Product is being unpublished // Your custom code for product unpublishing here echo "Product with ID {$post->ID} unpublished."; } } } } Handlers/UserDeleteHandler.php 0000777 00000001033 15251220643 0012360 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\UserApi; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Response; class UserDeleteHandler { public function __construct() { } public function __invoke($user_id) { $id = Client::getUid() . '-' . $user_id; $response = (new UserApi())->remove($id); \error_log("Response" . $response->getStatusCode()); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log("user Not Delete"); return \false; } } } Handlers/CategoryDeleteHandler.php 0000777 00000006067 15251220643 0013233 0 ustar 00 <?php namespace Rvx\Handlers; use Exception; use Rvx\Api\CategoryApi; use Rvx\Utilities\Auth\Client; use Rvx\CPT\CptHelper; use Rvx\WPDrill\Response; class CategoryDeleteHandler { protected $cptHelper; protected $taxonomyHandler; protected $dataSyncHandler; public function __construct() { $this->cptHelper = new CptHelper(); $this->taxonomyHandler = new \Rvx\Handlers\TaxonomyHandler(); $this->dataSyncHandler = new \Rvx\Handlers\DataSyncHandler(); } public function deleteHandler($term_id, $tt_id, $taxonomy, $deleted_term, $object_ids) { $enabled_post_types = $this->cptHelper->usedCPT('used'); $related_post_types = $this->taxonomyHandler->getPostTypesByTaxonomy($taxonomy); if (empty(\array_intersect(\array_keys($enabled_post_types), $related_post_types))) { return; } $product_related_taxonomies = $this->dataSyncHandler->getProductTaxonomies(); // Only proceed if it is a taxonomy object of 'product' post type if (empty(\array_intersect([$taxonomy], $product_related_taxonomies))) { return; } $this->syncTermDelete($term_id); // if ($this->taxonomyHandler->termParentChanged($term, $taxonomy)) { // $this->handleHierarchyUpdates($deleted_term); // } } protected function syncTermDelete($term_id) { try { $uid = Client::getUid() . '-' . $term_id; $response = (new CategoryApi())->remove($uid); if ($response->getStatusCode() !== Response::HTTP_OK) { throw new Exception("API status: " . $response->getStatusCode()); } } catch (Exception $e) { \error_log("Update failed for term {$term_id}: " . $e->getMessage()); return \false; } } protected function handleHierarchyUpdates($term) { // Case 1: Term became a parent if ($this->taxonomyHandler->isParentTerm($term->term_id, $term->term_taxonomy)) { $this->handleNewParentTerm($term); } elseif ($this->taxonomyHandler->hadChildrenBeforeUpdate($term->term_id, $term->term_taxonomy)) { $this->handleFormerParentTerm($term); } // Case 3: Term with children moved in hierarchy if ($this->taxonomyHandler->hasChildren($term->term_id, $term->term_taxonomy)) { $this->updateAllDescendants($term); } } protected function handleNewParentTerm($term) { // error_log("Term {$term->term_id} is now a parent"); // Add specific new parent logic here } protected function handleFormerParentTerm($term) { // error_log("Term {$term->term_id} was a parent but is now a child"); // Add specific former parent logic here } protected function updateAllDescendants($term) { $descendants = $this->taxonomyHandler->getAllDescendants($term->term_id, $term->term_taxonomy); foreach ($descendants as $descendant) { $this->taxonomyHandler->syncTermUpdate($descendant['term']); } } } Handlers/ReplyCommentHandler.php 0000777 00000001547 15251220643 0012747 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\ReviewsApi; use Rvx\Utilities\Auth\Client; use Rvx\Services\CacheServices; class ReplyCommentHandler { protected $cacheServices; public function __construct() { $this->cacheServices = new CacheServices(); } public function __invoke($comment_id, $comment_approved, $commentdata) { if ($commentdata['comment_parent'] > 0) { $parent_comment = get_comment($commentdata['comment_parent']); if ($parent_comment) { $wpUniqueId = Client::getUid() . '-' . $parent_comment->comment_ID; $replies = ['reply' => $commentdata['comment_content'], 'wp_id' => $parent_comment->comment_ID]; (new ReviewsApi())->commentReply($replies, $wpUniqueId); $this->cacheServices->removeCache(); } } } } Handlers/ProductDeleteHandler.php 0000777 00000002045 15251220643 0013066 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\ProductApi; use Rvx\CPT\CptHelper; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Response; use Rvx\Services\CacheServices; class ProductDeleteHandler { protected $cptHelper; protected $cacheServices; public function __construct() { $this->cptHelper = new CptHelper(); $this->cacheServices = new CacheServices(); } public function __invoke($product_id) { // Define the target post types $enabled_post_types = $this->cptHelper->usedCPT('used'); $post = get_post($product_id); $post_type = $post->post_type; if (!isset($enabled_post_types[$post_type])) { return; } $uid = Client::getUid() . '-' . $product_id; $response = (new ProductApi())->remove($uid); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log($post_type . " delete fails! --> " . $response->getStatusCode()); return \false; } $this->cacheServices->removeCache(); } } Handlers/CptReviewsHandler.php 0000777 00000000411 15251220643 0012411 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class CptReviewsHandler implements InvokableContract { public function __invoke() { View::output('storeadmin/cpt', ['cpt' => "cpt"]); } } Handlers/ImportExpotHandler.php 0000777 00000000551 15251220643 0012615 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class ImportExpotHandler implements InvokableContract { public function __invoke() { View::output('storeadmin/import-export', ['title' => 'Welcome to WPDrill', 'content' => 'A WordPress Plugin development framework for humans']); } } Handlers/CategorySync.php 0000777 00000004434 15251220643 0011443 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\CategoryApi; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Response; class CategorySync implements InvokableContract { public function __invoke() { $this->scheduleProductChunkProcessing(); $this->categoryGat(); } public function categoryGat() { $chunkSize = 20; $offset = \get_option('category_chunk_offset', 0); $products = $this->getProductsChunk($offset, $chunkSize); $modyFiedCategories = []; foreach ($products as $category) { $modyFiedCategories[] = $this->processCategories($category); } $this->catSync($modyFiedCategories); $totalProducts = $offset + \count($products); \update_option('total_catagory_count', $totalProducts); \error_log('Total Category=: ' . $totalProducts); \update_option('category_chunk_offset', $offset + $chunkSize); \error_log('Chunk size=: ' . $offset); if (\count($products) < $chunkSize) { \delete_option('category_chunk_offset'); } } public function processCategories($category) { if (!empty($category)) { return ['wp_id' => (int) $category->term_id, 'title' => $category->name, 'slug' => $category->slug, 'description' => $category->description ?? '', 'taxonomy' => 'product_cat', "parent_id" => null, 'parent_wp_unique_id' => null]; } } private function getProductsChunk($offset, $limit) { global $wpdb; $query = $wpdb->prepare("\n SELECT *\n FROM {$wpdb->terms}\n LIMIT %d OFFSET %d\n ", $limit, $offset); return $wpdb->get_results($query); } public function catSync($payload) { if (!Client::getSync()) { $response = (new CategoryApi())->dataSync(['categories' => $payload]); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log("Sync Category not inserted: " . $response); return \false; } } } public function scheduleProductChunkProcessing() { if (!wp_next_scheduled('category_sync_event')) { wp_schedule_event(\time(), 'hourly', 'category_sync_event'); } } } Handlers/Notice/ReviewxAdminNoticeHandler.php 0000777 00000002354 15251220643 0015313 0 ustar 00 <?php namespace Rvx\Handlers\Notice; use Rvx\WPDrill\Facades\View; class ReviewxAdminNoticeHandler { public function adminNoticeHandler() { // Check if notice is temporarily dismissed $dismissUntil = \get_option('rvx_admin_deal_notice_until', 0); if ($dismissUntil && \time() < $dismissUntil) { return; } // Generate nonce for AJAX $nonce = wp_create_nonce('rvx_dismiss_notice_nonce'); // Render the notice View::output('storeadmin/notice/notice', ['nonce' => $nonce]); } public function rvx_admin_deal_notice_until() { // Verify nonce if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'rvx_dismiss_notice_nonce')) { wp_send_json_error(['message' => 'Invalid nonce.']); } // Get duration $duration = $_POST['duration']; if (\is_numeric($duration)) { $timestamp = \strtotime("+{$duration} days"); \update_option('rvx_admin_deal_notice_until', $timestamp); } else { wp_send_json_error(['message' => 'Invalid duration.']); } // Return success wp_send_json_success(['message' => 'Notice dismissed successfully.']); } } Handlers/StoreFrontHandller.php 0000777 00000001047 15251220643 0012605 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\WpApi; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Facades\View; class StoreFrontHandller implements InvokableContract { protected WpApi $wpApi; /** * */ public function __construct() { $this->wpApi = new WpApi(); } public function __invoke() { View::output('storefront/widgets', ['title' => 'Welcome Deshboard', 'content' => 'A WordPress Plugin development framework for humans', 'response' => $this->wpApi->get('/reviews')]); } } Handlers/CategoryCreateHandler.php 0000777 00000006712 15251220643 0013231 0 ustar 00 <?php namespace Rvx\Handlers; use Exception; use Rvx\Api\CategoryApi; use Rvx\Utilities\Auth\Client; use Rvx\CPT\CptHelper; use Rvx\WPDrill\Response; class CategoryCreateHandler { protected $cptHelper; protected $taxonomyHandler; protected $dataSyncHandler; public function __construct() { $this->cptHelper = new CptHelper(); $this->taxonomyHandler = new \Rvx\Handlers\TaxonomyHandler(); $this->dataSyncHandler = new \Rvx\Handlers\DataSyncHandler(); } public function __invoke($term_id) { $enabled_post_types = $this->cptHelper->usedCPT('used'); $related_post_types = $this->taxonomyHandler->getPostTypesByTermId($term_id); if (empty(\array_intersect(\array_keys($enabled_post_types), $related_post_types))) { return; } global $wpdb; $taxonomy = $this->taxonomyHandler->getTaxonomyByTermIdFromDB($term_id, $wpdb); $this_taxonomy_name = $taxonomy[0]['taxonomy'] ?? ''; $product_related_taxonomies = $this->dataSyncHandler->getProductTaxonomies(); // Only proceed if it is a taxonomy object of 'product' post type if (empty(\array_intersect([$this_taxonomy_name], $product_related_taxonomies))) { return; } $term = $this->taxonomyHandler->getTerm($term_id, $this_taxonomy_name); if (!$term) { return; } $this->syncTermCreate($term); // if ($this->taxonomyHandler->termParentChanged($term_id, $this_taxonomy_name)) { // $this->handleHierarchyUpdates($term); // } } protected function syncTermCreate($term) { try { $payload = ['wp_id' => $term->term_id, 'title' => $term->name, 'slug' => $term->slug, 'taxonomy' => $term->taxonomy, 'description' => $term->description, 'parent_wp_unique_id' => Client::getUid() . '-' . $term->parent ?? null]; $response = (new CategoryApi())->create($payload); if ($response->getStatusCode() !== Response::HTTP_OK) { throw new Exception("API status: " . $response->getStatusCode()); } } catch (Exception $e) { \error_log("Update failed for term {$term->term_id}: " . $e->getMessage()); return \false; } } protected function handleHierarchyUpdates($term) { // Case 1: Term became a parent if ($this->taxonomyHandler->isParentTerm($term->term_id, $term->taxonomy)) { $this->handleNewParentTerm($term); } elseif ($this->taxonomyHandler->hadChildrenBeforeUpdate($term->term_id, $term->taxonomy)) { $this->handleFormerParentTerm($term); } // Case 3: Term with children moved in hierarchy if ($this->taxonomyHandler->hasChildren($term->term_id, $term->taxonomy)) { $this->updateAllDescendants($term); } } protected function handleNewParentTerm($term) { "Term {$term->term_id} is now a parent"; // Add specific new parent logic here } protected function handleFormerParentTerm($term) { // error_log("Term {$term->term_id} was a parent but is now a child"); // Add specific former parent logic here } protected function updateAllDescendants($term) { $descendants = $this->taxonomyHandler->getAllDescendants($term->term_id, $term->taxonomy); foreach ($descendants as $descendant) { $this->syncTermUpdate($descendant['term']); } } } Handlers/PublicReviewHandler.php 0000777 00000000305 15251220643 0012720 0 ustar 00 <?php namespace Rvx\Handlers; class PublicReviewHandler { public function __construct() { } public function __invoke($product_id) { // dd($product_id); } } Handlers/WooCommerceReviewEditForm.php 0000777 00000003011 15251220643 0014052 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Services\ReviewService; use Rvx\Utilities\Auth\Client; use Rvx\Services\CacheServices; class WooCommerceReviewEditForm { protected $cacheServices; public function __construct() { $this->cacheServices = new CacheServices(); } public function __invoke($id, $data) { $updatedData = $this->prepareData($id, $data); $reviewService = new ReviewService(); $reviewService->updateWooReview($updatedData, $data); $this->cacheServices->removeCache(); } public function prepareData($id, $data) { $post_id = $data['comment_post_ID']; // $post_type = get_post_type($post_id); // Retrieve the rating. $rating = (float) \round(\get_comment_meta($id, 'rating', \true), 2); // if ($post_type === 'product') { // // For products, round up to the nearest whole number. // $rating = ceil((float) $rating); // } else { // // For other post types, round to two decimal places. // $rating = (float) round($rating, 2); // } return ['wp_id' => $id, 'wp_post_id' => $post_id, 'comment_approved' => $data['comment_approved'], 'rating' => $rating, 'reviewer_email' => $data['comment_author_email'], 'reviewer_name' => $data['comment_author'], 'feedback' => $data['comment_content'], 'date' => current_time('mysql', \true), 'customer_id' => $data['user_id'], 'wp_unique_id' => Client::getUid() . '-' . $id, 'woocommerce_update' => \true]; } } Handlers/ProductHandler.php 0000777 00000012560 15251220643 0011746 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\ProductApi; use Rvx\WPDrill\Response; class ProductHandler { public function __invoke($new_status, $old_status, $product) { if ($new_status == 'publish' && $old_status != 'publish') { $post = get_post($product->ID); if ($post->post_type === 'product') { switch ($new_status) { case 'publish': $currentProduct = wc_get_product($product->ID); $payload = $this->prepareData($currentProduct); $response = (new ProductApi())->create($payload); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log("Product Not insert" . $response->getStatusCode()); return \false; } break; } } else { $payload = $this->customPost($post); \error_log("Custom post" . \print_r($payload, \true)); $response = (new ProductApi())->create($payload); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log("Cpt Not insert" . $response); return \false; } } } } public function prepareData($currentProduct) { $images = wp_get_attachment_image_src($currentProduct->image_id, 'full'); $title = $currentProduct->get_name(); return [ "wp_id" => $currentProduct->get_id(), "title" => isset($title) ? \htmlspecialchars($title, \ENT_QUOTES, 'UTF-8') : null, "url" => get_permalink($currentProduct->get_id()), "description" => isset($currentProduct->short_description) ? \htmlspecialchars($currentProduct->short_description, \ENT_QUOTES, 'UTF-8') : null, "price" => isset($_POST['_regular_price']) ? (float) sanitize_text_field($_POST['_regular_price']) : 0, "discounted_price" => isset($_POST['_sale_price']) ? (float) sanitize_text_field($_POST['_sale_price']) : 0, "slug" => $currentProduct->get_slug(), "image" => $images[0] ?? '', "status" => $this->productStatus($currentProduct->get_status()), "post_type" => 'product', //get_post_type() code not use because import product issue "total_reviews" => (int) $currentProduct->get_review_count(), "avg_rating" => (float) $currentProduct->get_average_rating(), "stars" => ["one" => 0, "two" => 0, "three" => 0, "four" => 0, "five" => 0], "one_stars" => 0, "two_stars" => 0, "three_stars" => 0, "four_stars" => 0, "five_stars" => 0, "category_wp_unique_ids" => $this->productCategory($currentProduct), ]; } public function productStatus($status) { switch ($status) { case 'publish': return 1; case 'trash': return 2; default: return 3; } } public function productCategory($product) { $product_categories = $product->get_category_ids(); $parent_category_ids = array(); foreach ($product_categories as $category_id) { $category = \get_term($category_id, 'product_cat'); if ($category && $category->parent == 0) { $parent_category_ids[] = \Rvx\Utilities\Auth\Client::getUid() . '-' . $category_id; } } if (empty($parent_category_ids)) { $parent_category_ids[] = \Rvx\Utilities\Auth\Client::getUid() . '-' . '1'; return $parent_category_ids; } return $parent_category_ids; } public function customPost($post) { $image_url = get_the_post_thumbnail_url($post->ID, 'full'); $data = ["wp_id" => $post->ID, "title" => isset($post->post_title) ? \htmlspecialchars($post->post_title, \ENT_QUOTES, 'UTF-8') : null, "url" => get_permalink($post->ID), "description" => isset($post->post_excerpt) ? \htmlspecialchars($post->post_excerpt, \ENT_QUOTES, 'UTF-8') : null, "price" => 0, "discounted_price" => 0, "slug" => $post->post_name, "image" => $image_url ?? '', "status" => $this->productStatus($post->post_status), "post_type" => get_post_type($post->ID), "total_reviews" => (int) get_comments_number($post->ID) ?? 0, "avg_rating" => 0.0, "stars" => ["one" => 0, "two" => 0, "three" => 0, "four" => 0, "five" => 0], "one_stars" => 0, "two_stars" => 0, "three_stars" => 0, "four_stars" => 0, "five_stars" => 0, "category_wp_unique_ids" => [\Rvx\Utilities\Auth\Client::getUid() . '-' . 0]]; return $data; } public function getPostCategoryIds($post_ids) { if (empty($post_ids)) { \error_log("No valid post ID provided."); return []; } if (empty($category_ids)) { \error_log("No categories found for post ID: " . $post_ids); return []; } $parent_category_ids = []; foreach ($category_ids as $category_id) { $parent_category_ids[] = \Rvx\Utilities\Auth\Client::getUid() . '-' . $category_id; } if ($parent_category_ids) { return $parent_category_ids; } return $parent_category_ids[] = \Rvx\Utilities\Auth\Client::getUid() . '-' . 0; } } Handlers/UserHandler.php 0000777 00000002045 15251220643 0011241 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\UserApi; use Rvx\WPDrill\Response; class UserHandler { public function __construct() { } public function __invoke($user_id) { $user = get_userdata($user_id); $data = [ 'wp_id' => $user->ID, 'name' => $user->first_name . ' ' . $user->last_name, 'email' => $user->user_email, // 'display_name' => $user->display_name, // 'role' => $user->roles, 'avatar' => get_avatar_url($user->ID), 'city' => \get_user_meta($user->ID, 'billing_city', \true) ?? '', 'phone' => \get_user_meta($user->ID, 'billing_phone', \true) ?? '', 'address' => \get_user_meta($user->ID, 'billing_address_1', \true) ?? '', 'country' => \get_user_meta($user->ID, 'billing_country', \true) ?? '', 'status' => 1, ]; $response = (new UserApi())->create($data); if ($response->getStatusCode() !== Response::HTTP_OK) { return \false; } } } Handlers/CouponCreateHandler.php 0000777 00000000344 15251220643 0012712 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\WPDrill\Contracts\InvokableContract; class CouponCreateHandler implements InvokableContract { public function __invoke($coupon) { \error_log('copon id' . $coupon); } } Handlers/PluginUninstallerHandler.php 0000777 00000002351 15251220643 0014002 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\AuthApi; use Exception; class PluginUninstallerHandler { public static function handleUninstall() { global $wpdb; $rvxSites = $wpdb->prefix . 'rvx_sites'; $uid = $wpdb->get_var("SELECT uid FROM {$rvxSites} ORDER BY id DESC LIMIT 1"); if ($uid) { try { // Try to inform the API about uninstall (new AuthApi())->changePluginStatus(['site_uid' => $uid, 'status' => 2, 'plugin_version' => \defined('RVX_VERSION') ? RVX_VERSION : 'unknown', 'wp_version' => get_bloginfo('version')]); } catch (Exception $e) { // If API fails, do not interrupt uninstall if (\defined('WP_DEBUG') && WP_DEBUG) { \error_log('[ReviewX] PluginUninstallerHandler: API call failed - ' . $e->getMessage()); } // continue silently } } // Always clean up local data, regardless of API status $wpdb->query("TRUNCATE TABLE {$rvxSites}"); (new \Rvx\Services\CacheServices())->removeCache(); (new \Rvx\Services\Api\LoginService())->resetPostMeta(); // Continue uninstall cleanly return \true; } } Handlers/CategoryUpdateHandler.php 0000777 00000007124 15251220643 0013246 0 ustar 00 <?php namespace Rvx\Handlers; use Exception; use Rvx\Api\CategoryApi; use Rvx\Utilities\Auth\Client; use Rvx\CPT\CptHelper; use Rvx\WPDrill\Response; class CategoryUpdateHandler { protected $cptHelper; protected $taxonomyHandler; protected $dataSyncHandler; public function __construct() { $this->cptHelper = new CptHelper(); $this->taxonomyHandler = new \Rvx\Handlers\TaxonomyHandler(); $this->dataSyncHandler = new \Rvx\Handlers\DataSyncHandler(); } public function __invoke($term_id) { $enabled_post_types = $this->cptHelper->usedCPT('used'); $related_post_types = $this->taxonomyHandler->getPostTypesByTermId($term_id); if (empty(\array_intersect(\array_keys($enabled_post_types), $related_post_types))) { return; } global $wpdb; $taxonomy = $this->taxonomyHandler->getTaxonomyByTermIdFromDB($term_id, $wpdb); $this_taxonomy_name = $taxonomy[0]['taxonomy'] ?? ''; $product_related_taxonomies = $this->dataSyncHandler->getProductTaxonomies(); // Only proceed if it is a taxonomy object of 'product' post type if (empty(\array_intersect([$this_taxonomy_name], $product_related_taxonomies))) { return; } $term = $this->taxonomyHandler->getTerm($term_id, $this_taxonomy_name); if (!$term) { return; } $this->syncTermUpdate($term); // if ($this->taxonomyHandler->termParentChanged($term_id, $this_taxonomy_name)) { // $this->handleHierarchyUpdates($term); // } } protected function syncTermUpdate($term) { try { $payload = ['wp_id' => $term->term_id, 'title' => $term->name, 'slug' => $term->slug, 'taxonomy' => $term->taxonomy, 'description' => $term->description, 'parent_wp_unique_id' => $term->parent > 0 ? Client::getUid() . '-' . $term->parent : null, 'updated_at' => current_time('mysql')]; $uid = Client::getUid() . '-' . $term->term_id; $response = (new CategoryApi())->update($payload, $uid); if ($response->getStatusCode() !== Response::HTTP_OK) { throw new Exception("API status: " . $response->getStatusCode()); } } catch (Exception $e) { \error_log("Update failed for term {$term->term_id}: " . $e->getMessage()); return \false; } } protected function handleHierarchyUpdates($term) { // Case 1: Term became a parent if ($this->taxonomyHandler->isParentTerm($term->term_id, $term->taxonomy)) { $this->handleNewParentTerm($term); } elseif ($this->taxonomyHandler->hadChildrenBeforeUpdate($term->term_id, $term->taxonomy)) { $this->handleFormerParentTerm($term); } // Case 3: Term with children moved in hierarchy if ($this->taxonomyHandler->hasChildren($term->term_id, $term->taxonomy)) { $this->updateAllDescendants($term); } } protected function handleNewParentTerm($term) { // error_log("Term {$term->term_id} is now a parent"); // Add specific new parent logic here } protected function handleFormerParentTerm($term) { // error_log("Term {$term->term_id} was a parent but is now a child"); // Add specific former parent logic here } protected function updateAllDescendants($term) { $descendants = $this->taxonomyHandler->getAllDescendants($term->term_id, $term->taxonomy); foreach ($descendants as $descendant) { $this->syncTermUpdate($descendant['term']); } } } Handlers/UserUpdateHandler.php 0000777 00000002465 15251220643 0012412 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\UserApi; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Response; class UserUpdateHandler { public function __construct() { } public function __invoke($user_id) { global $pagenow, $current_screen; if (is_admin() && isset($current_screen->id) && $current_screen->id === 'profile') { $user = get_userdata($user_id); $attachment_id = \get_user_meta($user_id, 'image', \true); $original_image_url = $attachment_id ? wp_get_attachment_url($attachment_id) : get_avatar_url($user_id); $data = ['name' => $user->first_name . ' ' . $user->last_name, 'email' => $user->user_email, 'phone' => \get_user_meta($user->ID, 'billing_phone', \true) ?? '', 'address' => \get_user_meta($user->ID, 'billing_address_1', \true) ?? '', 'city' => \get_user_meta($user->ID, 'billing_city', \true) ?? '', 'country' => \get_user_meta($user->ID, 'billing_country', \true) ?? '', 'avatar' => get_avatar_url($user->ID), 'status' => 1]; $id = Client::getUid() . '-' . $user_id; \error_log($id . \print_r($data, \true)); $response = (new UserApi())->update($data, $id); if ($response->getStatusCode() !== Response::HTTP_OK) { return \false; } } } } Handlers/WoocommerceSettingsSaveHandler.php 0000777 00000004603 15251220643 0015144 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Services\SettingService; use Rvx\Utilities\Helper; use Throwable; use Rvx\WPDrill\Response; class WoocommerceSettingsSaveHandler { public function wooProductSaveHandler() { // Isset specific fields $isset_label = isset($_POST['woocommerce_review_rating_verification_label']) ? \true : \false; $isset_required = isset($_POST['woocommerce_review_rating_verification_required']) ? \true : \false; $modifiedReviewsettings = $this->prepareData($isset_label, $isset_required); try { $response = (new SettingService())->saveApiReviewSettings($modifiedReviewsettings); if ($response->getStatusCode() === Response::HTTP_OK) { $review_settings = $response->getApiData()['review_settings']; $post_type = 'product'; (new SettingService())->updateReviewSettings($review_settings, $post_type); } if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log('API response - NOT OK: ' . \print_r($response->getApiData()['review_settings'], \true)); return Helper::rvxApi(['error' => "WC Settings Fail"])->fails('WC Settings Fail', $response->getStatusCode()); } return Helper::saasResponse($response); } catch (Throwable $e) { return Helper::rvxApi(['error' => $e->getMessage()])->fails('Review settings saved failed', $e->getCode()); } } private function prepareData($isset_label, $isset_required) { // Retrieve the existing review settings $review_settings = (array) (new SettingService())->getReviewSettings('product')['reviews']; $review_settings['show_verified_badge'] = $isset_label ? \true : \false; $wcReviewSubmissionPolicy = $isset_required ? \true : \false; $isAnyone = \true; $isOnlyVerified = \false; if ($wcReviewSubmissionPolicy) { $isAnyone = \false; $isOnlyVerified = \true; } $review_settings['review_submission_policy']['options']['anyone'] = $isAnyone; $review_settings['review_submission_policy']['options']['verified_customer'] = $isOnlyVerified; // $review_settings['recaptcha']['secret_key'] = null; // true if verified only [If for some reason data doesn't save, uncomment this and try] return $review_settings; } } Handlers/OrderUpdateProcessHandler.php 0000777 00000000511 15251220643 0014074 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Services\OrderService; class OrderUpdateProcessHandler { protected $orderService; public function __construct() { $this->orderService = new OrderService(); } public function __invoke($order_id) { $this->orderService->updateOrder($order_id); } } Handlers/ProductUpdateHandler.php 0000777 00000004127 15251220643 0013111 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\ProductApi; use Rvx\Utilities\Auth\Client; use Rvx\WPDrill\Response; class ProductUpdateHandler { public function __invoke($product_id) { $product = wc_get_product($product_id); $payload = $this->updateData($product); $uid = Client::getUid() . '-' . $product_id; $response = (new ProductApi())->update($payload, $uid); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log("Data Not Update " . \print_r($response, \true)); return \false; } } public function updateData($product) { $images = wp_get_attachment_image_src($product->image_id, 'full'); $title = $product->get_name(); return ['wp_id' => $product->get_id(), 'title' => isset($title) ? \htmlspecialchars($title, \ENT_QUOTES, 'UTF-8') : null, 'url' => get_permalink($product->get_id()), 'description' => isset($product->short_description) ? \htmlspecialchars($product->short_description, \ENT_QUOTES, 'UTF-8') : null, 'price' => (float) $product->regular_price, 'discounted_price' => (float) $product->price, 'slug' => $product->get_slug(), 'post_type' => get_post_type(), 'image' => $images[0] ?? null, 'status' => $this->productStatus($product->get_status()), "category_wp_unique_ids" => $this->productCategory($product)]; } public function productCategory($product) { $product_categories = $product->get_category_ids(); $parent_category_ids = array(); foreach ($product_categories as $category_id) { $category = \get_term($category_id, 'product_cat'); if ($category && $category->parent == 0) { $parent_category_ids[] = Client::getUid() . '-' . $category_id; } } return $parent_category_ids; } public function productStatus($status) { switch ($status) { case 'publish': return 1; case 'trash': return 2; case 'draft': return 3; default: return 4; } } } Handlers/OrderStatusChangedHandler.php 0000777 00000014041 15251220643 0014053 0 ustar 00 <?php namespace Rvx\Handlers; use Rvx\Api\OrderApi; use Rvx\Utilities\Auth\Client; use Rvx\Utilities\Helper; use Rvx\Utilities\TransactionManager; use Rvx\WPDrill\Response; class OrderStatusChangedHandler { public function __invoke($order_id, $old_status, $new_status, $order) { if (isset($_GET['page']) && $_GET['page'] === 'wc-orders' && $_GET['action'] === 'edit') { $is_new_order = \get_post_meta($order_id, '_is_new_order', \true); if ($is_new_order) { // Remove the flag to allow future status changes to trigger this hook \delete_post_meta($order_id, '_rvx_is_new_order'); return; } $payload = $this->prepareData($order, $new_status, $old_status); $uid = Client::getUid() . '-' . $order_id; // WP Operation: Save meta locally. This must happen. $this->orderDataSave($order_id, $payload); // SaaS Operation: Attempt sync, but don't block return. $response = (new OrderApi())->changeStatus($payload, $uid); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log("Order Status Change Sync Failed for ID {$order_id}: " . $response->getBody()); } } if (isset($_GET['page']) && $_GET['page'] === 'wc-orders') { $payload = $this->bulkOrderPrepare($order_id, $old_status, $new_status, $order); // WP Operation: Save meta locally. $this->orderDataSave($order_id, $payload); // SaaS Operation: Attempt sync. $response = (new OrderApi())->changeBulkStatus($payload); if ($response->getStatusCode() !== Response::HTTP_OK) { \error_log("Bulk Order Status Sync Failed: " . $response->getBody()); } } } public function bulkOrderPrepare($order_id, $old_status, $new_status, $order) { return ['status' => Helper::orderStatus($new_status), 'order_wp_unique_ids' => [Client::getUid() . '-' . $order_id]]; } public function prepareData($order, $new_status, $old_status) : array { $orderStatusToTimestampKey = $this->orderStatusToTimestampKey($new_status); $current_time = \wp_date('Y-m-d H:i:s'); $date_created = $order->get_date_created(); $created_at = $date_created ? \wp_date('Y-m-d H:i:s', $date_created->getTimestamp()) : null; $date_modified = $order->get_date_modified(); $updated_at = $date_modified ? \wp_date('Y-m-d H:i:s', $date_modified->getTimestamp()) : \wp_date('Y-m-d H:i:s'); $order_state = $this->wooOrderState($order, $new_status, $old_status); $orderStatusData = ["status" => Helper::orderStatus($new_status), "paid_at" => $order_state['paid_at'] ?? null]; if ($orderStatusToTimestampKey !== 'any') { $orderStatusData[$orderStatusToTimestampKey] = $current_time; } $orderData = ["wp_id" => (int) $order->get_id(), "customer_wp_unique_id" => Client::getUid() . '-' . (int) $order->get_customer_id(), "subtotal" => (float) $order->get_subtotal(), "tax" => (float) $order->get_total_tax(), "total" => (float) $order->get_total(), 'created_at' => $created_at, 'updated_at' => $updated_at]; $modifiedOrder = \array_merge($orderData, $orderStatusData); return ['order' => $modifiedOrder, 'order_items' => $this->orderItems($order, $orderStatusToTimestampKey, $orderStatusData, $new_status, $old_status)]; } public function wooOrderState($order, $new_status, $old_status) { global $wpdb; $order_id = $order->get_id(); $query = $wpdb->prepare("SELECT date_paid, date_completed FROM {$wpdb->prefix}wc_order_stats WHERE order_id = %d", $order_id); $wpWcOrderStats = $wpdb->get_row($query); $fulfilled_at = $wpWcOrderStats && $wpWcOrderStats->date_completed ? \wp_date('Y-m-d H:i:s', \strtotime($wpWcOrderStats->date_completed)) : null; $paid_at = $wpWcOrderStats && $wpWcOrderStats->date_paid ? \wp_date('Y-m-d H:i:s', \strtotime($wpWcOrderStats->date_paid)) : null; if ($new_status === 'completed' && !$fulfilled_at) { $fulfilled_at = \wp_date('Y-m-d H:i:s'); } if ($new_status === 'processing' && !$paid_at) { $paid_at = \wp_date('Y-m-d H:i:s'); } return ['fulfillment_status' => Helper::orderItemStatus($new_status) ?? null, 'fulfilled_at' => $fulfilled_at, 'paid_at' => $paid_at]; } public function orderItems($order, $orderStatusToTimestampKey, $orderStatusData, $new_status, $old_status) : array { $data = $this->wooOrderState($order, $new_status, $old_status); $items_data = []; $order_items = $order->get_items(); foreach ($order_items as $order_item) { $product = $order_item->get_product(); if ($product) { $item_data = ["wp_unique_id" => Client::getUid() . '-' . (int) $order_item->get_id(), 'fulfillment_status' => $data['fulfillment_status'] ?? null, 'fulfilled_at' => $data['fulfilled_at'] ?? null]; $items_data[] = $item_data; } } return $items_data; } public function orderStatusToTimestampKey($newStatus) : string { $statusMap = ['processing' => 'processing_at', 'pending' => 'pending_payment_at', 'on-hold' => 'on_hold_at', 'completed' => 'completed_at', 'cancelled' => 'cancelled_at', 'refunded' => 'refunded_at', 'failed' => 'failed_at', 'checkout-draft' => 'draft_at']; if (!$statusMap[$newStatus]) { return 'any'; } return $statusMap[$newStatus]; } public function orderDataSave($order_id, $data) { $order_meta = Helper::arrayGet($data, 'order'); $order_item = Helper::arrayGet($data, 'order_items'); if (!$order_id) { return; } $order = wc_get_order($order_id); if (!$order) { return; } $order->update_meta_data('_rvx_order_value', $order_meta); $order->update_meta_data('_rvx_order_item_value', $order_item); $order->save(); } } Handlers/HookManager.php 0000777 00000001153 15251220643 0011217 0 ustar 00 <?php namespace Rvx\Handlers; class HookManager { protected static $action; protected static $imported_products = []; public static function setAction($value) { self::$action = $value; } public static function getAction() { return self::$action; } public static function addImportedProduct($product) { self::$imported_products[] = $product; } public static function getImportedProducts() { return self::$imported_products; } public static function clearImportedProducts() { self::$imported_products = []; } }
| ver. 1.6 |
Github
|
.
| PHP 8.1.34 | Генерация страницы: 0.02 |
proxy
|
phpinfo
|
Настройка