From 55ff65a627ae3a6a8211c3bfed3fed750bb333fe Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Tue, 24 Oct 2023 23:01:07 +0200 Subject: [PATCH 01/45] init endpoints --- .../doofinder-for-woocommerce.php | 4 ++- .../includes/api/class-store-api.php | 30 +++---------------- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/doofinder-for-woocommerce/doofinder-for-woocommerce.php b/doofinder-for-woocommerce/doofinder-for-woocommerce.php index e4611e2d..037ee45d 100644 --- a/doofinder-for-woocommerce/doofinder-for-woocommerce.php +++ b/doofinder-for-woocommerce/doofinder-for-woocommerce.php @@ -97,6 +97,8 @@ public function __construct() // Load classes on demand self::autoload(self::plugin_path() . 'includes/'); + Endpoints::init(); + add_action('init', function () use ($class) { //Initialize update on save Update_On_Save::init(); @@ -335,7 +337,7 @@ public static function initialize_rest_endpoints() { add_action('rest_api_init', function () { Config::register(); - REST_API_Handler::initialize(); + //REST_API_Handler::initialize(); Index_Status_Handler::initialize(); }); } diff --git a/doofinder-for-woocommerce/includes/api/class-store-api.php b/doofinder-for-woocommerce/includes/api/class-store-api.php index d4ff4d36..24ed70f3 100644 --- a/doofinder-for-woocommerce/includes/api/class-store-api.php +++ b/doofinder-for-woocommerce/includes/api/class-store-api.php @@ -128,11 +128,11 @@ public function normalize_store_and_indices() } if (isset($api_keys[$lang])) { - $se_hashid = $api_keys[$lang]['hash']; + $se_hashid = $api_keys[$lang]['hash']; $payload['search_engines'][$se_hashid] = $search_engine['datatypes'][0]['datasources'][0]['options']; } else { $this->log->log("No search engine retrieved for the language - " . $lang); - } + } } $this->log->log("Sending request to normalize indices."); @@ -157,27 +157,6 @@ public static function has_application_credentials() return WP_Application_Passwords::application_name_exists_for_user(get_current_user_id(), 'doofinder'); } - public function update_custom_attributes($custom_attributes){ - $multilanguage = Multilanguage::instance(); - $search_engines_by_language = Setup_Wizard::are_api_keys_present(true, $multilanguage); - - if (!Multilanguage::$is_multilang) { - $search_engines_by_language = [ - '' => [ - 'hash' => Settings::get_search_engine_hash() - ] - ]; - } - foreach ($search_engines_by_language as $language => $search_engine) { - $se_hash = $search_engine["hash"]; - if(empty($se_hash)){ - continue; - } - $response = $this->sendRequest("plugins/wordpress/$se_hash/update-custom-attributes/", $custom_attributes); - } - - } - /** * Send a POST request with the given $body to the given $endpoint. * @@ -301,8 +280,7 @@ private function get_product_datatype($language) "type" => "wordpress", "options" => [ "feed_type" => "product", - "url" => $this->language->get_home_url($language), - "custom_attributes" => Settings::get_custom_attributes() + "lang" => $language ] ] ] @@ -324,7 +302,7 @@ private function get_post_datatype($language) "type" => "wordpress", "options" => [ "feed_type" => "posts", - "url" => $this->language->get_home_url($language) + "lang" => $language ] ] ] From 2e0637444a931c07661556e30cf21ab60c22ee2e Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Fri, 3 Nov 2023 17:44:09 +0100 Subject: [PATCH 02/45] new endpoints --- .../doofinder-for-woocommerce.php | 3 +- .../includes/class-settings.php | 32 ++++++------------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/doofinder-for-woocommerce/doofinder-for-woocommerce.php b/doofinder-for-woocommerce/doofinder-for-woocommerce.php index 508c4dbb..ba1da1c9 100644 --- a/doofinder-for-woocommerce/doofinder-for-woocommerce.php +++ b/doofinder-for-woocommerce/doofinder-for-woocommerce.php @@ -33,7 +33,7 @@ class Doofinder_For_WordPress * * @var string */ - public static $version = '2.0.31'; + public static $version = '2.1.0'; /** * The only instance of Doofinder_For_WordPress @@ -338,7 +338,6 @@ public static function initialize_rest_endpoints() { add_action('rest_api_init', function () { Config::register(); - //REST_API_Handler::initialize(); Index_Status_Handler::initialize(); }); } diff --git a/doofinder-for-woocommerce/includes/class-settings.php b/doofinder-for-woocommerce/includes/class-settings.php index 6365a93b..9e643604 100755 --- a/doofinder-for-woocommerce/includes/class-settings.php +++ b/doofinder-for-woocommerce/includes/class-settings.php @@ -64,7 +64,7 @@ class Settings "df_price", "df_regular_price", "df_sale_price", - + ]; /** @@ -143,26 +143,12 @@ public static function initialize() { $option = static::$custom_attributes_option; add_action("update_option_{$option}", function ($old_value, $value, $option) { - //Make an API call to update custom attributes in our admin - //do_action("doofinder_update_custom_attributes"); - try { - $store_api = new Store_Api(); - $store_api->update_custom_attributes($value); - - add_settings_error( - 'doofinder_for_wp_messages', - 'doofinder_for_wp_message', - __('Custom Attributes updated successfully.
Please, keep in mind that you need to reindex in order for the changes to be reflected in the search layer.', 'doofinder_for_wp'), - 'success' - ); - } catch (\Throwable $th) { - add_settings_error( - 'doofinder_for_wp_messages', - 'doofinder_for_wp_message', - __(sprintf('An error ocurred while sending the custom attributes to the Doofinder server.
If the problem persists, please contact our support team.
Error message: %s', $th->getMessage()), 'doofinder_for_wp'), - 'error' - ); - } + add_settings_error( + 'doofinder_for_wp_messages', + 'doofinder_for_wp_message', + __('Custom Attributes updated successfully.
Please, keep in mind that you need to reindex in order for the changes to be reflected in the search layer.', 'doofinder_for_wp'), + 'success' + ); }, 10, 3); add_filter('cron_schedules', [self::class, 'add_schedules'], 100, 1); @@ -202,7 +188,7 @@ public static function get_additional_attributes_options() } /** - * Make a request to the WooCommerce Products endpoint to get the available + * Make a request to the WooCommerce Products endpoint to get the available * field list. * * @return array List of Product base attributes @@ -285,6 +271,6 @@ public static function add_schedules($schedules) ] ]; - return array_merge($schedules, $df_schedules); + return array_merge($schedules, $df_schedules); } } From f399246e512c50cf0da603b3256ce2160099c8be Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Fri, 3 Nov 2023 17:47:19 +0100 Subject: [PATCH 03/45] new endpoints --- .../api/endpoints/class-endpoint-custom.php | 148 +++++ .../class-endpoint-post-category.php | 81 +++ .../class-endpoint-product-category.php | 120 ++++ .../api/endpoints/class-endpoint-product.php | 521 ++++++++++++++++++ 4 files changed, 870 insertions(+) create mode 100644 doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php create mode 100644 doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php create mode 100644 doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php create mode 100644 doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php new file mode 100644 index 00000000..133f1fbd --- /dev/null +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php @@ -0,0 +1,148 @@ + 'GET', + 'callback' => array(Endpoint_Custom::class, 'custom_endpoint') + )); + }); + } + + /** + * Custom item endpoint callback. + * + * @param WP_REST_Request $request The REST request object. + * @return WP_REST_Response Response containing modified data. + */ + public static function custom_endpoint($request) { + + Endpoints::CheckSecureToken(); + + // Get the 'fields' parameter from the request + $fields_param = $request->get_param('fields'); + $fields = !empty($fields_param) ? explode(',', $fields_param) : array(); + + $config_request["per_page"] = $request->get_param('per_page') ?? self::PER_PAGE; + $config_request["page"] = $request->get_param('page') ?? 1; + $config_request["lang"] = $request->get_param('lang') ?? ""; + $config_request["type"] = $request->get_param('type'); + + // Retrieve the original items data + $items = self::get_items($config_request); + $modified_items = array(); + + // Process and filter items data + if (!empty($items)) { + foreach ($items as $item_data) { + // Filter fields + $filtered_data = !empty($fields) ? array_intersect_key($item_data, array_flip($fields)) : $item_data; + + if(isset($filtered_data["title"]["rendered"]) && in_array('title', $fields)){ + $filtered_data["title"] = $filtered_data["title"]["rendered"]; + } + if(isset($filtered_data["content"]["rendered"]) && in_array('content', $fields)){ + $filtered_data["content"] = self::process_content($filtered_data["content"]["rendered"]); + } + if(isset($filtered_data["excerpt"]["rendered"]) && in_array('excerpt', $fields)){ + $filtered_data["description"] = self::process_content($filtered_data["excerpt"]["rendered"]); + unset($filtered_data["excerpt"]); + } + unset($filtered_data["author"]); + if(in_array('author', $fields) && $config_request["type"] != "posts"){ + $filtered_data["author"] = isset($filtered_data["_embedded"]["author"][0]["name"]) ? $filtered_data["_embedded"]["author"][0]["name"] : "Default"; + } + if(isset($filtered_data["_embedded"]["wp:featuredmedia"][0]["media_details"]["sizes"]["medium"]["source_url"]) && in_array('image_link', $fields)){ + $filtered_data["image_link"] = $filtered_data["_embedded"]["wp:featuredmedia"][0]["media_details"]["sizes"]["medium"]["source_url"]; + } + if(isset($filtered_data["_embedded"]["wp:term"][0]) && in_array('post_tags', $fields)){ + $filtered_data["post_tags"] = self::get_terms("post_tag", $filtered_data["_embedded"]["wp:term"]); + } + if(isset($filtered_data["_embedded"]["wp:term"][0]) && in_array('categories', $fields)){ + $filtered_data["categories"] = self::get_terms("category", $filtered_data["_embedded"]["wp:term"]); + } + unset($filtered_data["_embedded"]); + $modified_items[] = $filtered_data; + } + } + + // Return the modified items data as a response + return new WP_REST_Response($modified_items); + } + + /** + * Process content by decoding HTML entities, stripping HTML tags, and replacing sequences of whitespace characters. + * + * @param string $content The content to process, including HTML markup. + * + * @return string The processed content with HTML entities decoded, HTML tags removed, and whitespace sequences replaced with a single space. + */ + private static function process_content($content) { + $content = html_entity_decode(strip_tags($content)); + $content = preg_replace('/[ \t\r\n]+/', ' ', $content); + + return trim($content); + } + + /** + * Retrieves the names of taxonomies of a specific type within an array of items. + * + * @param string $type The taxonomy type to search for (e.g., "category" or "post_tag"). + * @param array $array_items The array of items containing taxonomy information. + * @return array An array of taxonomy names that match the specified type. + */ + private static function get_terms($type, $array_items){ + $names = array(); + foreach($array_items as $array_item){ + foreach($array_item as $item){ + if(isset($item["taxonomy"]) && $item["taxonomy"] == $type){ + $names[] = self::process_content($item["name"]); + } + } + } + return $names; + } + + /** + * Retrieve a list of items with pagination. + * + * @param array $config_request Config request params (page, per_page, type) + * @return array|null An array of items data or null on failure. + */ + private static function get_items($config_request){ + // Retrieve the original items data + $request = new WP_REST_Request('GET', "/wp/v2/".$config_request["type"]); + $request->set_query_params(array( + 'page' => $config_request["page"], + 'per_page' => $config_request["per_page"], + 'lang' => $config_request["lang"] + )); + $response = rest_do_request($request); + $data = rest_get_server()->response_to_data($response, true); + + if(!empty($data["data"]["status"]) && $data["data"]["status"] != 200){ + $data = []; + } + + return $data; + } +} +?> diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php new file mode 100644 index 00000000..cbddf4b4 --- /dev/null +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php @@ -0,0 +1,81 @@ + 'GET', + 'callback' => array(Endpoint_Post_Category::class, 'post_category_endpoint') + )); + }); + } + + /** + * Custom item endpoint callback. + * + * @param WP_REST_Request $request The REST request object. + * @return WP_REST_Response Response containing modified data. + */ + public static function post_category_endpoint($request) { + + Endpoints::CheckSecureToken(); + + $config_request["per_page"] = $request->get_param('per_page') ?? self::PER_PAGE; + $config_request["page"] = $request->get_param('page') ?? 1; + $config_request["lang"] = $request->get_param('lang') ?? ""; + $config_request["fields"] = $request->get_param('fields') ?? ""; + + // Get the 'fields' parameter from the request + $fields = !empty($config_request["fields"]) ? explode(',', $config_request["fields"]) : array(); + + // Retrieve the original items data + $items = self::get_items($config_request); + + // Return the modified items data as a response + return new WP_REST_Response($items); + } + + /** + * Retrieve a list of items with pagination. + * + * @param array $config_request Config request params (page, per_page, type) + * @return array|null An array of items data or null on failure. + */ + private static function get_items($config_request){ + // Retrieve the original items data + $request = new WP_REST_Request('GET', "/wp/v2/categories"); + $request->set_query_params(array( + 'page' => $config_request["page"], + 'per_page' => $config_request["per_page"], + 'lang' => $config_request["lang"], + '_fields' => $config_request["fields"] + )); + $response = rest_do_request($request); + $data = rest_get_server()->response_to_data($response, true); + + if(!empty($data["data"]["status"]) && $data["data"]["status"] != 200){ + $data = []; + } + + return $data; + } +} +?> diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php new file mode 100644 index 00000000..689a980a --- /dev/null +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php @@ -0,0 +1,120 @@ + 'GET', + 'callback' => array(Endpoint_Product_Category::class, 'product_category_endpoint') + )); + }); + } + + /** + * Custom item endpoint callback. + * + * @param WP_REST_Request $request The REST request object. + * @return WP_REST_Response Response containing modified data. + */ + public static function product_category_endpoint($request) { + + Endpoints::CheckSecureToken(); + + $config_request["per_page"] = $request->get_param('per_page') ?? self::PER_PAGE; + $config_request["page"] = $request->get_param('page') ?? 1; + $config_request["lang"] = $request->get_param('lang') ?? ""; + $config_request["fields"] = $request->get_param('fields') ?? ""; + + // Get the 'fields' parameter from the request + $fields = !empty($config_request["fields"]) ? explode(',', $config_request["fields"]) : array(); + + // Retrieve the original items data + $items = self::get_items($config_request); + + if (!empty($items)) { + foreach ($items as &$item_data) { + + if(in_array('image_link', $fields)){ + $item_data["image_link"] = self::get_product_cat_df_image_link($item_data); + } + } + } + + // Return the modified items data as a response + return new WP_REST_Response($items); + } + + /** + * Check that image link is absolute, if not, add the site url + * + * @param string $image_link + * @return string $image_link + */ + private static function add_base_url_if_needed($image_link) + { + if (0 === strpos($image_link, "/")) { + $image_link = get_site_url() . $image_link; + } + return $image_link; + } + + /** + * Returns the image link for a given term. + * + * @param array $product WooCommerce Product or Variable Product as array. + * @return string The image link + */ + public static function get_product_cat_df_image_link($term) + { + // get the thumbnail id using the queried category term_id + $thumbnail_id = get_term_meta($term['id'], 'thumbnail_id', true); + $image_link = empty($thumbnail_id) ? "" : wp_get_attachment_url($thumbnail_id); + $image_link = empty($image_link) ? wc_placeholder_img_src(Thumbnail::get_size()) : $image_link; + $image_link = self::add_base_url_if_needed($image_link); + return $image_link; + } + + /** + * Retrieve a list of items with pagination. + * + * @param array $config_request Config request params (page, per_page, type) + * @return array|null An array of items data or null on failure. + */ + private static function get_items($config_request){ + // Retrieve the original items data + $request = new WP_REST_Request('GET', "/wp/v2/product_cat"); + $request->set_query_params(array( + 'page' => $config_request["page"], + 'per_page' => $config_request["per_page"], + 'lang' => $config_request["lang"], + '_fields' => $config_request["fields"] + )); + $response = rest_do_request($request); + $data = rest_get_server()->response_to_data($response, true); + + if(!empty($data["data"]["status"]) && $data["data"]["status"] != 200){ + $data = []; + } + + return $data; + } +} +?> diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php new file mode 100644 index 00000000..f6312ad6 --- /dev/null +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -0,0 +1,521 @@ + 'GET', + 'callback' => array(Endpoint_Product::class, 'custom_product_endpoint'), + )); + }); + } + + /** + * Custom product endpoint callback. + * + * @param WP_REST_Request $request The REST request object. + * @return WP_REST_Response Response containing modified data. + */ + public static function custom_product_endpoint($request) { + + Endpoints::CheckSecureToken(); + + // Get the 'fields' parameter from the request + $fields_param = $request->get_param('fields'); + $fields = !empty($fields_param) ? explode(',', $fields_param) : array(); + $per_page = $request->get_param('per_page') ?? self::PER_PAGE; + $page = $request->get_param('page') ?? 1; + $lang = $request->get_param('lang') ?? ""; + + // Retrieve the original product data + $products = self::get_products($per_page, $page, $lang, $fields); + $custom_attr = Settings::get_custom_attributes(); + $modified_products = array(); + + // Process and filter product data + if (!empty($products)) { + + // Include variants if requested + $products = self::get_variations($products); + + foreach ($products as $product_data) { + // Filter fields + $filtered_product_data = !empty($fields) ? array_intersect_key($product_data, array_flip($fields)) : $product_data; + if (in_array('categories', $fields) && isset($product_data["categories"])) { + $filtered_product_data['categories'] = self::get_category_path($product_data["categories"]); + } + //If shop has custom attributes + if (count($custom_attr) > 0) { + $filtered_product_data = array_merge($filtered_product_data, self::get_custom_attributes($product_data["id"])); + //unset($filtered_product_data["attributes"]); + } + // Include images if requested + if (in_array('images', $fields)) { + $filtered_product_data = self::clear_images_fields($filtered_product_data); + } + $filtered_product_data = self::format_prices($filtered_product_data); + + if (in_array('stock_status', $fields)) { + $filtered_product_data = self::check_availability($filtered_product_data); + } + + if (in_array('description', $fields)) { + $filtered_product_data["description"] = self::process_content($filtered_product_data["description"]); + } + if (in_array('short_description', $fields)) { + $filtered_product_data["short_description"] = self::process_content($filtered_product_data["short_description"]); + } + if (in_array('tags', $fields)) { + $filtered_product_data["tags"] = self::get_tag_names($filtered_product_data["tags"]); + } + + $filtered_product_data = self::clean_fields($filtered_product_data); + $modified_products[] = $filtered_product_data; + } + // Cascade variants to their parent products + $modified_products = self::cascade_variants($modified_products); + } + // Return the modified product data as a response + return new WP_REST_Response($modified_products); + } + + /** + * Retrieves an array of names from a given array. + * + * @param array $array The input array containing the elements. + * + * @return array An array containing only the names of the elements. + */ + private static function get_tag_names($array) { + $names = array(); + foreach ($array as $element) { + $names[] = self::process_content($element['name']); + } + return $names; + } + + /** + * Process content by decoding HTML entities, stripping HTML tags, and replacing sequences of whitespace characters. + * + * @param string $content The content to process, including HTML markup. + * + * @return string The processed content with HTML entities decoded, HTML tags removed, and whitespace sequences replaced with a single space. + */ + private static function process_content($content) { + $content = html_entity_decode(strip_tags($content)); + $content = preg_replace('/[ \t\r\n]+/', ' ', $content); + + return trim($content); + } + + /** + * Retrieve a list of products with pagination. + * + * @param int $per_page The number of products per page. + * @param int $page The current page number. + * @param int $lang Language. + * @param int $fields Fields API we want to order + * @return array|null An array of product data or null on failure. + */ + private static function get_products($per_page, $page, $lang, $fields){ + // Retrieve the original product data + $request = new WP_REST_Request('GET', '/wc/v3/products'); + $request->set_query_params(array( + 'page' => $page, + 'per_page' => $per_page, + 'lang' => $lang, + '_fields' => $fields + )); + $original_response = rest_do_request($request); + return $original_response->data; + } + + /** + * Format prices of product + * + * @param array $product The product array to format prices. + * @return array $product with formatted prices + */ + private static function format_prices($product) + { + $product["price"] = self::get_price($product["id"]); + $product["regular_price"] = self::get_regular_price($product["id"]); + $product["sale_price"] = self::get_sale_price($product["id"]); + + return $product; + } + + /** + * Returns the raw price for the given product. + * + * @param array $product The product we want to add the field + * @param string $price_name The price name. By default 'price' + * @return void + */ + private static function get_raw_price($id, $price_name = 'price') + { + $wc_product = wc_get_product($id); + $fn_name = "get_$price_name"; + if (is_a($wc_product, 'WC_Product') && method_exists($wc_product, $fn_name)) { + $price = $wc_product->$fn_name(); + $raw_price = $price_name === "sale_price" && $price === "" ? "" : self::get_raw_real_price($price, $wc_product); + //If price is equal to 0, return an empty string + $raw_price = (0 == $raw_price) ? "" : $raw_price; + return $raw_price; + } + } + + /** + * Returns the raw price for the given product with taxes or witouht taxes depends the tax display. + * + * @param string $product Type of price we want + * @param array WooCommerce Product $product Select product + * @return void + */ + private static function get_raw_real_price($price, $product) + { + $woocommerce_tax_display_shop = get_option('woocommerce_tax_display_shop', 'incl'); + return 'incl' === $woocommerce_tax_display_shop ? + wc_get_price_including_tax( + $product, + array( + 'price' => $price, + ) + ) : + wc_get_price_excluding_tax( + $product, + array( + 'price' => $price, + ) + ); + } + + /** + * Get the raw price + * + * @param integer $id Product ID to get field. + * @return float The raw price including or excluding taxes (defined in WC settings). + */ + private static function get_price($id) + { + return self::get_raw_price($id); + } + + /** + * Get the raw sale price + * + * @param integer $id Product ID to get field. + * @return float The raw sale price including or excluding taxes (defined in WC settings). + */ + private static function get_sale_price($id) + { + return self::get_raw_price($id, 'sale_price'); + } + + /** + * Get the raw regular price + * + * @param integer $id Product ID to get field. + * @return float The raw regular price including or excluding taxes (defined in WC settings). + */ + private static function get_regular_price($id) + { + return self::get_raw_price($id, 'regular_price'); + } + + /** + * Returns the image link for a given product. + * If the product is a variation and doesn't have an image, return the parent image link + * + * @param array $id Product ID selected + * @return string The image link + */ + public static function get_image_link($id) + { + $post = get_post($id); + $thumbnail = new Thumbnail($post); + $image_link = $thumbnail->get(); + if (empty($image_link) && $post->post_type === 'product_variation') { + $thumbnail = new Thumbnail(get_post($post->post_parent)); + $image_link = $thumbnail->get(); + } + + //If neither the variant and the product have an image, return the woocommerce placeholder image + $image_link = empty($image_link) ? wc_placeholder_img_src(Thumbnail::get_size()) : $image_link; + $image_link = self::add_base_url_if_needed($image_link); + + return $image_link; + } + + /** + * Check that image link is absolute, if not, add the site url + * + * @param string $image_link + * @return string $image_link + */ + private static function add_base_url_if_needed($image_link) + { + if (0 === strpos($image_link, "/")) { + $image_link = get_site_url() . $image_link; + } + return $image_link; + } + + /** + * Field names to exchange + * + * @param array $product The product array to process. + * @return array $product without fields excluded + */ + private static function clean_fields($product){ + $product["title"] = $product["name"]; + $product["link"] = $product["permalink"]; + + unset($product["name"]); + unset($product["permalink"]); + + return $product; + } + + /** + * Check availability product + * + * @param array $product The product array to process. + * @return array $product with availability string type (in stock / out of stock) + */ + private static function check_availability($product){ + if($product["purchasable"] && ($product["stock_status"] == "instock" || $product["stock_status"] == "onbackorder")){ + $product["availability"] = "in stock"; + } + else{ + $product["availability"] = "out of stock"; + } + return $product; + } + + /** + * Clears image fields from a product array. + * + * @param array $product The product array to process. + * @return array The product array with empty image fields removed. + */ + private static function clear_images_fields($product){ + $product["image_link"] = self::get_image_link($product["id"]); + unset($product["images"]); + + return $product; + } + + /** + * Cascade variants to their parent products. + * + * @param array $products The array of product data. + * @return array The modified array of product data with variants cascaded. + */ + private static function cascade_variants($products) { + foreach ($products as $key => $product) { + if (!empty($product["parent_id"])) { + foreach ($products as $key2 => $product2) { + if ($product2["id"] == $product["parent_id"]) { + if (!isset($products[$key2]["variants"])) { + $products[$key2]["variants"] = array(); + } + $products[$key2]["variants"][] = $products[$key]; + unset($products[$key]); + } + } + } + } + return array_values($products); + } + + /** + * Get variations for variable products. + * + * @param array $products_data The array of product data. + * @return array The modified array of product data with variations. + */ + private static function get_variations($products_data){ + + $products = array(); + + foreach($products_data as $product){ + + if($product["type"] == "variable"){ + + $page = 1; + $variations_data = array(); + + //variations pagination + do{ + $request = new WP_REST_Request('GET', '/wc/v3/products/'.$product["id"].'/variations'); + $request->set_query_params(array( + 'page' => $page, + 'per_page' => self::PER_PAGE, + )); + $variants_response = rest_do_request($request); + $variations_data = array_merge($variations_data, $variants_response->data); + $page++; + } + while(count($variants_response->data) >= self::PER_PAGE); + + //Setting parent_id in variations + foreach ($variations_data as &$variation) { + foreach ($product as $field => $value) { + if (!isset($variation[$field])) { + $variation[$field] = $value; + $variation["parent_id"] = $product["id"]; + } + } + } + //Setting df_variants_information when variation attribute = true + if($product["parent_id"] == 0){ + $attr_variation_true = self::get_df_variants_information($product); + $product["df_variants_information"] = $attr_variation_true; + $products[] = $product; + } + $products = array_merge($products, $variations_data); + } + else{ + $products[] = $product; + } + } + return $products; + } + + + /** + * Generate df_variants_information node response + * + * @param array $product + * @return array df_variants_information + */ + private static function get_df_variants_information($product){ + + $product_attributes = array_keys(wc_get_product($product["id"])->get_attributes()); + + array_walk($product_attributes, function (&$element) { + $element = str_replace(['pa_', 'wc_'], '', $element); + }); + $attr_variation_true = []; + foreach($product["attributes"] as $p_attr){ + if($p_attr["variation"] && in_array(strtolower($p_attr["name"]), $product_attributes)){ + $attr_variation_true[] = strtolower($p_attr["name"]); + } + } + return $attr_variation_true; + } + + /** + * Get custom attributes for a product. + * + * @param int $product_id The ID of the product. + * @return array The custom attributes for the product. + */ + private static function get_custom_attributes($product_id){ + + $doofinder_attributes = Settings::get_custom_attributes(); + $product_attributes = wc_get_product($product_id)->get_attributes(); + $custom_attributes = array(); + + foreach ($product_attributes as $attribute_name => $attribute_data) { + $attribute_slug = str_replace("pa_", "", $attribute_name); + $matching_attribute = false; + + foreach ($doofinder_attributes as $doofinder_attribute) { + if ($doofinder_attribute['field'] === $attribute_slug) { + $matching_attribute = true; + break; + } + } + if($matching_attribute){ + + $attribute_options = $attribute_data['options'] ?? array($attribute_data); + + foreach ($attribute_options as $option) { + $term = get_term_by('name', $option, $attribute_name); + if(empty($term)){ + $term = get_term_by('id', $option, $attribute_name); + } + if(empty($term)){ + $custom_attributes[$attribute_slug][] = $option; + } + else if ($term && !is_wp_error($term)) { + $custom_attributes[$attribute_slug][] = $term->name; + } + } + } + } + + foreach($custom_attributes as $key=>$custom_attribute){ + if(is_array($custom_attribute) && count($custom_attribute) == 1){ + $custom_attributes[$key] = $custom_attribute[0]; + } + } + + return $custom_attributes; + } + + /** + * Get the category path for a product. + * + * @param array $category_ids The array of category IDs. + * @return array The array of category paths. + */ + private static function get_category_path($category_ids) { + + $category_paths = array(); + + foreach ($category_ids as $category_id) { + $category_path = self::get_category_hierarchy($category_id["id"]); + if (!empty($category_path)) { + $category_paths[] = self::process_content($category_path); + } + } + return $category_paths; + } + + /** + * Get the hierarchy of a category. + * + * @param int $category_id The ID of the category. + * @return string The category hierarchy. + */ + private static function get_category_hierarchy($category_id) { + $category = get_term($category_id, 'product_cat'); + if (is_wp_error($category)) { + return ''; + } + $category_path = $category->name; + $parent_id = $category->parent; + + while ($parent_id !== 0) { + $parent_category = get_term($parent_id, 'product_cat'); + if (!is_wp_error($parent_category)) { + $category_path = $parent_category->name . ' > ' . $category_path; + $parent_id = $parent_category->parent; + } + } + return $category_path; + } +} +?> From bcfc87ffa770c6cb58003177f5ba16166775de6d Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Fri, 3 Nov 2023 17:54:07 +0100 Subject: [PATCH 04/45] - New endpoints - Refactor custom attributes - Token auth --- .../includes/class-endpoints.php | 77 +++++++++++++++++++ .../includes/class-migration.php | 12 ++- .../class-reset-credentials-index.php | 12 +++ .../includes/class-update-manager.php | 12 ++- .../includes/helpers/class-store-helpers.php | 18 ++++- 5 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 doofinder-for-woocommerce/includes/class-endpoints.php diff --git a/doofinder-for-woocommerce/includes/class-endpoints.php b/doofinder-for-woocommerce/includes/class-endpoints.php new file mode 100644 index 00000000..be99c8d5 --- /dev/null +++ b/doofinder-for-woocommerce/includes/class-endpoints.php @@ -0,0 +1,77 @@ +reset_credentials(); + } + /** - * Converts the former product attribute name from pa_ + * Converts the former product attribute name from pa_ * format to wc_ format. * Example: * pa_color => wc_4 diff --git a/doofinder-for-woocommerce/includes/class-reset-credentials-index.php b/doofinder-for-woocommerce/includes/class-reset-credentials-index.php index 26182b7e..11ae8213 100755 --- a/doofinder-for-woocommerce/includes/class-reset-credentials-index.php +++ b/doofinder-for-woocommerce/includes/class-reset-credentials-index.php @@ -41,4 +41,16 @@ public function reset_credentials() $payload = Store_Helpers::get_store_options(); $this->api->resetCredentials($payload); } + + public function reset_token_auth() + { + $endpoints_token = Store_Helpers::create_endpoints_token(); + update_option('doofinder_for_wp_token', $endpoints_token); + + $payload = [ + 'df_token' => $endpoints_token + ]; + + $this->api->resetCredentials($payload); + } } diff --git a/doofinder-for-woocommerce/includes/class-update-manager.php b/doofinder-for-woocommerce/includes/class-update-manager.php index 59cedf0f..76e73ffe 100644 --- a/doofinder-for-woocommerce/includes/class-update-manager.php +++ b/doofinder-for-woocommerce/includes/class-update-manager.php @@ -63,7 +63,7 @@ public static function check_updates($plugin_version) } if ($result) { - //All updates executed successfully, update the plugin version to the latest one + //All updates executed successfully, update the plugin version to the latest one Settings::set_plugin_version($plugin_version); } @@ -185,4 +185,14 @@ public static function update_020013() Migration::migrate_custom_attributes(); return true; } + + /** + * Update: 2.0.32 + * Update the woocommerce product attributes + */ + public static function update_020100() + { + Migration::create_token_auth(); + return true; + } } diff --git a/doofinder-for-woocommerce/includes/helpers/class-store-helpers.php b/doofinder-for-woocommerce/includes/helpers/class-store-helpers.php index 6d27a897..6332b84d 100755 --- a/doofinder-for-woocommerce/includes/helpers/class-store-helpers.php +++ b/doofinder-for-woocommerce/includes/helpers/class-store-helpers.php @@ -16,11 +16,16 @@ class Store_Helpers public static function get_store_options() { $password_data = Store_Helpers::create_application_credentials(); + $endpoints_token = Store_Helpers::create_endpoints_token(); + + update_option('doofinder_for_wp_token', $endpoints_token); + if (!is_null($password_data)) { return [ "url" => get_bloginfo('url'), 'api_pass' => $password_data['api_pass'], - 'api_user' => $password_data['api_user'] + 'api_user' => $password_data['api_user'], + 'df_token' => $endpoints_token, ]; } else { throw new Exception("Error creating application credentials"); @@ -64,4 +69,15 @@ private static function create_application_credentials() } return $password_data; } + + /** + * To create a new token that will be used to authenticate new product endpoints via headers + * + * @return string New token to authenticate woocommerce endpoints created by doofinder + */ + public static function create_endpoints_token() + { + $randomString = uniqid(); + return md5($randomString); + } } From 861fa40ce52903c607851f3e03c03bdb00678b11 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Fri, 3 Nov 2023 17:58:40 +0100 Subject: [PATCH 05/45] Upgrade version 2.1.0 --- doofinder-for-woocommerce/doofinder-for-woocommerce.php | 2 +- .../includes/class-update-manager.php | 2 +- doofinder-for-woocommerce/readme.txt | 7 ++++++- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/doofinder-for-woocommerce/doofinder-for-woocommerce.php b/doofinder-for-woocommerce/doofinder-for-woocommerce.php index f77df600..6369f188 100644 --- a/doofinder-for-woocommerce/doofinder-for-woocommerce.php +++ b/doofinder-for-woocommerce/doofinder-for-woocommerce.php @@ -4,7 +4,7 @@ * Plugin Name: Doofinder WP & WooCommerce Search * License: GPLv2 or later * License URI: http://www.gnu.org/licenses/gpl-2.0.html - * Version: 2.0.32 + * Version: 2.1.0 * Requires at least: 5.6 * Requires PHP: 7.0 * Author: Doofinder diff --git a/doofinder-for-woocommerce/includes/class-update-manager.php b/doofinder-for-woocommerce/includes/class-update-manager.php index 76e73ffe..dbb15fe3 100644 --- a/doofinder-for-woocommerce/includes/class-update-manager.php +++ b/doofinder-for-woocommerce/includes/class-update-manager.php @@ -187,7 +187,7 @@ public static function update_020013() } /** - * Update: 2.0.32 + * Update: 2.1.0 * Update the woocommerce product attributes */ public static function update_020100() diff --git a/doofinder-for-woocommerce/readme.txt b/doofinder-for-woocommerce/readme.txt index c5cb5273..6a29871c 100644 --- a/doofinder-for-woocommerce/readme.txt +++ b/doofinder-for-woocommerce/readme.txt @@ -1,7 +1,7 @@ === Doofinder WP & WooCommerce Search === Contributors: Doofinder Tags: search, autocomplete -Version: 2.0.32 +Version: 2.1.0 Requires at least: 5.6 Tested up to: 6.3.1 Requires PHP: 7.0 @@ -82,6 +82,11 @@ Just send your questions to and we will try to an == Changelog == += 2.1.0 = +New internal endpoints to obtain products, posts, pages and custom items. +Refactor in custom attributes management. +Secure authentication via token in headers. + = 2.0.32 = Adjusted minimum requirements to install the plugin. diff --git a/package-lock.json b/package-lock.json index 8be31ea2..2103366a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doofinder-woocommerce", - "version": "2.0.32", + "version": "2.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "doofinder-woocommerce", - "version": "2.0.32", + "version": "2.1.0", "license": "MIT", "devDependencies": { "grunt": "^1.0.1", diff --git a/package.json b/package.json index 311be804..e597eb99 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doofinder-woocommerce", - "version": "2.0.32", + "version": "2.1.0", "description": "Integrate Doofinder in your WooCommerce site with (almost) no effort.", "main": "index.js", "scripts": { From 1802d64650496fe568ee96c3bab5568cb7592746 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 8 Nov 2023 10:52:40 +0100 Subject: [PATCH 06/45] image link field --- .../includes/api/endpoints/class-endpoint-product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index f6312ad6..d63e8ae0 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -69,7 +69,7 @@ public static function custom_product_endpoint($request) { //unset($filtered_product_data["attributes"]); } // Include images if requested - if (in_array('images', $fields)) { + if (in_array('image_link', $fields)) { $filtered_product_data = self::clear_images_fields($filtered_product_data); } $filtered_product_data = self::format_prices($filtered_product_data); From a8109851de692d51f700a627e1e12065415d666d Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 8 Nov 2023 11:30:37 +0100 Subject: [PATCH 07/45] one element in custom attributes --- .../api/endpoints/class-endpoint-product.php | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index d63e8ae0..25b6aadc 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -438,17 +438,10 @@ private static function get_custom_attributes($product_id){ $custom_attributes = array(); foreach ($product_attributes as $attribute_name => $attribute_data) { - $attribute_slug = str_replace("pa_", "", $attribute_name); - $matching_attribute = false; - - foreach ($doofinder_attributes as $doofinder_attribute) { - if ($doofinder_attribute['field'] === $attribute_slug) { - $matching_attribute = true; - break; - } - } - if($matching_attribute){ + $attribute_slug = str_replace("pa_", "", $attribute_name); + $found_key = array_search($attribute_slug, array_column($doofinder_attributes, 'field')); + if ($found_key){ $attribute_options = $attribute_data['options'] ?? array($attribute_data); foreach ($attribute_options as $option) { @@ -465,13 +458,6 @@ private static function get_custom_attributes($product_id){ } } } - - foreach($custom_attributes as $key=>$custom_attribute){ - if(is_array($custom_attribute) && count($custom_attribute) == 1){ - $custom_attributes[$key] = $custom_attribute[0]; - } - } - return $custom_attributes; } From de25c76c8ee16bf4e4c4a61bb75db2b9a07ede3e Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 8 Nov 2023 18:03:39 +0100 Subject: [PATCH 08/45] refactor get_custom_attributes --- .../api/endpoints/class-endpoint-product.php | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 25b6aadc..cfc252ca 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -389,7 +389,7 @@ private static function get_variations($products_data){ } //Setting df_variants_information when variation attribute = true if($product["parent_id"] == 0){ - $attr_variation_true = self::get_df_variants_information($product); + $attr_variation_true = self::get_df_variants_information($product); $product["df_variants_information"] = $attr_variation_true; $products[] = $product; } @@ -441,20 +441,11 @@ private static function get_custom_attributes($product_id){ $attribute_slug = str_replace("pa_", "", $attribute_name); $found_key = array_search($attribute_slug, array_column($doofinder_attributes, 'field')); - if ($found_key){ - $attribute_options = $attribute_data['options'] ?? array($attribute_data); - + if ($found_key) { + $attribute_options = (array) ($attribute_data['options'] ?? $attribute_data); foreach ($attribute_options as $option) { - $term = get_term_by('name', $option, $attribute_name); - if(empty($term)){ - $term = get_term_by('id', $option, $attribute_name); - } - if(empty($term)){ - $custom_attributes[$attribute_slug][] = $option; - } - else if ($term && !is_wp_error($term)) { - $custom_attributes[$attribute_slug][] = $term->name; - } + $term = get_term_by('name', $option, $attribute_name) ?? get_term_by('id', $option, $attribute_name); + $custom_attributes[$attribute_slug][] = empty($term) || is_wp_error($term) ? $option : $term->name; } } } From 1d4b6a1707b3c2a8bc6b53e94b77dcdf38b4261f Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 8 Nov 2023 18:04:11 +0100 Subject: [PATCH 09/45] reset_token_auth migration --- doofinder-for-woocommerce/includes/class-migration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doofinder-for-woocommerce/includes/class-migration.php b/doofinder-for-woocommerce/includes/class-migration.php index 91acb553..03283809 100755 --- a/doofinder-for-woocommerce/includes/class-migration.php +++ b/doofinder-for-woocommerce/includes/class-migration.php @@ -269,7 +269,7 @@ public static function transform_additional_attributes($additional_attributes) public static function create_token_auth() { $reset_credentials_context = new Reset_Credentials_Index(); - $reset_credentials_context->reset_credentials(); + $reset_credentials_context->reset_token_auth(); } /** From 49b164c4eba67dc9b1fb39b4b8054e371185d077 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Fri, 10 Nov 2023 12:13:53 +0100 Subject: [PATCH 10/45] Review code split functions --- .../api/endpoints/class-endpoint-custom.php | 188 ++++++++++++---- .../api/endpoints/class-endpoint-product.php | 212 +++++++++++++----- 2 files changed, 298 insertions(+), 102 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php index 133f1fbd..5ab25926 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php @@ -34,60 +34,164 @@ public static function initialize() { * @return WP_REST_Response Response containing modified data. */ public static function custom_endpoint($request) { - Endpoints::CheckSecureToken(); - // Get the 'fields' parameter from the request - $fields_param = $request->get_param('fields'); - $fields = !empty($fields_param) ? explode(',', $fields_param) : array(); + $fields = explode(',', $request->get_param('fields') ?? ''); - $config_request["per_page"] = $request->get_param('per_page') ?? self::PER_PAGE; - $config_request["page"] = $request->get_param('page') ?? 1; - $config_request["lang"] = $request->get_param('lang') ?? ""; - $config_request["type"] = $request->get_param('type'); + $config_request = [ + 'per_page' => $request->get_param('per_page') ?? self::PER_PAGE, + 'page' => $request->get_param('page') ?? 1, + 'lang' => $request->get_param('lang') ?? "", + 'type' => $request->get_param('type'), + ]; - // Retrieve the original items data - $items = self::get_items($config_request); - $modified_items = array(); + $items = self::get_items($config_request); + $modified_items = []; - // Process and filter items data - if (!empty($items)) { - foreach ($items as $item_data) { - // Filter fields - $filtered_data = !empty($fields) ? array_intersect_key($item_data, array_flip($fields)) : $item_data; + foreach ($items as $item_data) { + $filtered_data = array_intersect_key($item_data, array_flip($fields)); - if(isset($filtered_data["title"]["rendered"]) && in_array('title', $fields)){ - $filtered_data["title"] = $filtered_data["title"]["rendered"]; - } - if(isset($filtered_data["content"]["rendered"]) && in_array('content', $fields)){ - $filtered_data["content"] = self::process_content($filtered_data["content"]["rendered"]); - } - if(isset($filtered_data["excerpt"]["rendered"]) && in_array('excerpt', $fields)){ - $filtered_data["description"] = self::process_content($filtered_data["excerpt"]["rendered"]); - unset($filtered_data["excerpt"]); - } - unset($filtered_data["author"]); - if(in_array('author', $fields) && $config_request["type"] != "posts"){ - $filtered_data["author"] = isset($filtered_data["_embedded"]["author"][0]["name"]) ? $filtered_data["_embedded"]["author"][0]["name"] : "Default"; - } - if(isset($filtered_data["_embedded"]["wp:featuredmedia"][0]["media_details"]["sizes"]["medium"]["source_url"]) && in_array('image_link', $fields)){ - $filtered_data["image_link"] = $filtered_data["_embedded"]["wp:featuredmedia"][0]["media_details"]["sizes"]["medium"]["source_url"]; - } - if(isset($filtered_data["_embedded"]["wp:term"][0]) && in_array('post_tags', $fields)){ - $filtered_data["post_tags"] = self::get_terms("post_tag", $filtered_data["_embedded"]["wp:term"]); - } - if(isset($filtered_data["_embedded"]["wp:term"][0]) && in_array('categories', $fields)){ - $filtered_data["categories"] = self::get_terms("category", $filtered_data["_embedded"]["wp:term"]); - } - unset($filtered_data["_embedded"]); - $modified_items[] = $filtered_data; - } + $filtered_data = self::get_title($filtered_data, $fields); + $filtered_data = self::get_content($filtered_data, $fields); + $filtered_data = self::get_description($filtered_data, $fields); + $filtered_data = self::get_author($filtered_data, $fields, $config_request); + $filtered_data = self::get_image_link($filtered_data, $fields); + $filtered_data = self::get_post_tags($filtered_data, $fields); + $filtered_data = self::get_categories($filtered_data, $fields); + $filtered_data = self::clear_unused_fields($filtered_data); + + $modified_items[] = $filtered_data; } // Return the modified items data as a response return new WP_REST_Response($modified_items); } + /** + * Retrieves and processes the post tags information if requested by the fields. + * + * @param array $filtered_data The filtered data array. + * @param array $fields The requested fields. + * + * @return array The filtered data array with post tags information if requested. + */ + private static function get_post_tags($filtered_data, $fields) { + if (in_array('post_tags', $fields) && isset($filtered_data["_embedded"]["wp:term"][0])) { + $filtered_data["post_tags"] = self::get_terms("post_tag", $filtered_data["_embedded"]["wp:term"]); + } + + return $filtered_data; + } + + /** + * Retrieves and processes the categories information if requested by the fields. + * + * @param array $filtered_data The filtered data array. + * @param array $fields The requested fields. + * + * @return array The filtered data array with categories information if requested. + */ + private static function get_categories($filtered_data, $fields) { + if (in_array('categories', $fields) && isset($filtered_data["_embedded"]["wp:term"][0])) { + $filtered_data["categories"] = self::get_terms("category", $filtered_data["_embedded"]["wp:term"]); + } + + return $filtered_data; + } + + + /** + * Retrieves and processes the title information if requested by the fields. + * + * @param array $filtered_data The filtered data array. + * @param array $fields The requested fields. + * + * @return array The filtered data array with title information if requested. + */ + private static function get_title($filtered_data, $fields) { + $filtered_data["title"] = $filtered_data["title"]["rendered"] ?? null; + + return $filtered_data; + } + + /** + * Retrieves and processes the content information if requested by the fields. + * + * @param array $filtered_data The filtered data array. + * @param array $fields The requested fields. + * + * @return array The filtered data array with content information if requested. + */ + private static function get_content($filtered_data, $fields) { + $filtered_data["content"] = self::process_content($filtered_data["content"]["rendered"] ?? null); + + return $filtered_data; + } + + /** + * Retrieves and processes the description information if requested by the fields. + * + * @param array $filtered_data The filtered data array. + * @param array $fields The requested fields. + * + * @return array The filtered data array with description information if requested. + */ + private static function get_description($filtered_data, $fields) { + $filtered_data["description"] = self::process_content($filtered_data["excerpt"]["rendered"] ?? null); + + return $filtered_data; + } + + /** + * Retrieves and processes the author information if requested by the fields. + * + * @param array $filtered_data Product data array. + * @param array $fields The requested fields. + * @param array $config_request The configuration request array. + * + * @return array The filtered data array with author information if requested. + */ + private static function get_author($filtered_data, $fields, $config_request) { + if (in_array('author', $fields) && $config_request["type"] != "posts") { + $filtered_data["author"] = $filtered_data["_embedded"]["author"][0]["name"] ?? "Default"; + } + + return $filtered_data; + } + + /** + * Retrieves and processes the image link information if requested by the fields. + * + * @param array $filtered_data The filtered data array. + * @param array $fields The requested fields. + * + * @return array The filtered data array with image link information if requested. + */ + private static function get_image_link($filtered_data, $fields) { + $featured_media = $filtered_data["_embedded"]["wp:featuredmedia"][0]["media_details"]["sizes"]["medium"]["source_url"] ?? null; + $filtered_data["image_link"] = in_array('image_link', $fields) ? $featured_media : null; + + return $filtered_data; + } + + + /** + * Clears unused fields from the filtered data array. + * + * This function removes specific keys from the provided array, including "excerpt," "_embedded," and "author." + * + * @param array $filtered_data The data array to be processed. + * + * @return array The processed data array with unused fields removed. + */ + private static function clear_unused_fields($filtered_data){ + unset($filtered_data["excerpt"]); + unset($filtered_data["_embedded"]); + unset($filtered_data["author"]); + + return $filtered_data; + } + /** * Process content by decoding HTML entities, stripping HTML tags, and replacing sequences of whitespace characters. * diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index cfc252ca..31571199 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -42,12 +42,15 @@ public static function custom_product_endpoint($request) { // Get the 'fields' parameter from the request $fields_param = $request->get_param('fields'); $fields = !empty($fields_param) ? explode(',', $fields_param) : array(); - $per_page = $request->get_param('per_page') ?? self::PER_PAGE; - $page = $request->get_param('page') ?? 1; - $lang = $request->get_param('lang') ?? ""; + + $config_request = [ + 'per_page' => $request->get_param('per_page') ?? self::PER_PAGE, + 'page' => $request->get_param('page') ?? 1, + 'lang' => $request->get_param('lang') ?? "", + ]; // Retrieve the original product data - $products = self::get_products($per_page, $page, $lang, $fields); + $products = self::get_products($config_request); $custom_attr = Settings::get_custom_attributes(); $modified_products = array(); @@ -60,35 +63,17 @@ public static function custom_product_endpoint($request) { foreach ($products as $product_data) { // Filter fields $filtered_product_data = !empty($fields) ? array_intersect_key($product_data, array_flip($fields)) : $product_data; - if (in_array('categories', $fields) && isset($product_data["categories"])) { - $filtered_product_data['categories'] = self::get_category_path($product_data["categories"]); - } - //If shop has custom attributes - if (count($custom_attr) > 0) { - $filtered_product_data = array_merge($filtered_product_data, self::get_custom_attributes($product_data["id"])); - //unset($filtered_product_data["attributes"]); - } - // Include images if requested - if (in_array('image_link', $fields)) { - $filtered_product_data = self::clear_images_fields($filtered_product_data); - } - $filtered_product_data = self::format_prices($filtered_product_data); - - if (in_array('stock_status', $fields)) { - $filtered_product_data = self::check_availability($filtered_product_data); - } - - if (in_array('description', $fields)) { - $filtered_product_data["description"] = self::process_content($filtered_product_data["description"]); - } - if (in_array('short_description', $fields)) { - $filtered_product_data["short_description"] = self::process_content($filtered_product_data["short_description"]); - } - if (in_array('tags', $fields)) { - $filtered_product_data["tags"] = self::get_tag_names($filtered_product_data["tags"]); - } + $filtered_product_data = self::get_categories($filtered_product_data, $fields); + $filtered_product_data = self::merge_custom_attributes($filtered_product_data, $custom_attr, $product_data["id"]); + $filtered_product_data = self::get_image_field($filtered_product_data, $fields); + $filtered_product_data = self::format_prices($filtered_product_data); + $filtered_product_data = self::check_stock_status($filtered_product_data, $fields); + $filtered_product_data = self::get_description($filtered_product_data, $fields); + $filtered_product_data = self::get_short_description($filtered_product_data, $fields); + $filtered_product_data = self::get_tags($filtered_product_data, $fields); $filtered_product_data = self::clean_fields($filtered_product_data); + $modified_products[] = $filtered_product_data; } // Cascade variants to their parent products @@ -98,6 +83,105 @@ public static function custom_product_endpoint($request) { return new WP_REST_Response($modified_products); } + /** + * Get categories in the data. + * + * @param array $data The data to process. + * @param array $fields The list of fields being processed. + * @return array The processed data. + */ + private static function get_categories($data, $fields) { + if (in_array('categories', $fields) && isset($data["categories"])) { + $data['categories'] = self::get_category_path($data["categories"]); + } + return $data; + } + + /** + * Merge custom attributes into the data. + * + * @param array $data The data to merge into. + * @param array $custom_attr The custom attributes to merge. + * @param int $product_id The ID of the product. + * @return array The merged data. + */ + private static function merge_custom_attributes($data, $custom_attr, $product_id) { + if (count($custom_attr) > 0) { + return array_merge($data, self::get_custom_attributes($product_id)); + } + return $data; + } + + /** + * Get the image link in the data. + * + * @param array $data The data to process. + * @param array $fields The list of fields being processed. + * @return array The processed data. + */ + private static function get_image_field($data, $fields) { + if (in_array('image_link', $fields)) { + return self::clear_images_fields($data); + } + return $data; + } + + /** + * Check the stock status in the data. + * + * @param array $data The data to check. + * @param array $fields The list of fields being processed. + * @return array The processed data. + */ + private static function check_stock_status($data, $fields) { + if (in_array('stock_status', $fields)) { + return self::check_availability($data); + } + return $data; + } + + /** + * Process the description field in the data. + * + * @param array $data The data to process. + * @param array $fields The list of fields being processed. + * @return array The processed data. + */ + private static function get_description($data, $fields) { + if (in_array('description', $fields)) { + $data['description'] = self::process_content($data['description']); + } + return $data; + } + + /** + * Process the short description field in the data. + * + * @param array $data The data to process. + * @param array $fields The list of fields being processed. + * @return array The processed data. + */ + private static function get_short_description($data, $fields) { + if (in_array('short_description', $fields)) { + $data['short_description'] = self::process_content($data['short_description']); + } + return $data; + } + + /** + * Get tags in the data. + * + * @param array $data The data to process. + * @param array $fields The list of fields being processed. + * @return array The processed data. + */ + private static function get_tags($data, $fields) { + if (in_array('tags', $fields)) { + $data['tags'] = self::get_tag_names($data['tags']); + } + return $data; + } + /** * Retrieves an array of names from a given array. * @@ -130,20 +214,17 @@ private static function process_content($content) { /** * Retrieve a list of products with pagination. * - * @param int $per_page The number of products per page. - * @param int $page The current page number. - * @param int $lang Language. - * @param int $fields Fields API we want to order + * @param int $config Config request for get products * @return array|null An array of product data or null on failure. */ - private static function get_products($per_page, $page, $lang, $fields){ + private static function get_products($config){ // Retrieve the original product data $request = new WP_REST_Request('GET', '/wc/v3/products'); $request->set_query_params(array( - 'page' => $page, - 'per_page' => $per_page, - 'lang' => $lang, - '_fields' => $fields + 'page' => $config["page"], + 'per_page' => $config["per_page"], + 'lang' => $config["lang"], + '_fields' => $config["fields"] )); $original_response = rest_do_request($request); return $original_response->data; @@ -362,21 +443,7 @@ private static function get_variations($products_data){ if($product["type"] == "variable"){ - $page = 1; - $variations_data = array(); - - //variations pagination - do{ - $request = new WP_REST_Request('GET', '/wc/v3/products/'.$product["id"].'/variations'); - $request->set_query_params(array( - 'page' => $page, - 'per_page' => self::PER_PAGE, - )); - $variants_response = rest_do_request($request); - $variations_data = array_merge($variations_data, $variants_response->data); - $page++; - } - while(count($variants_response->data) >= self::PER_PAGE); + $variations_data = self::request_variations($product["id"]); //Setting parent_id in variations foreach ($variations_data as &$variation) { @@ -389,8 +456,7 @@ private static function get_variations($products_data){ } //Setting df_variants_information when variation attribute = true if($product["parent_id"] == 0){ - $attr_variation_true = self::get_df_variants_information($product); - $product["df_variants_information"] = $attr_variation_true; + $product["df_variants_information"] = self::get_df_variants_information($product); $products[] = $product; } $products = array_merge($products, $variations_data); @@ -402,6 +468,31 @@ private static function get_variations($products_data){ return $products; } + /** + * Request variations for a given product ID. + * + * @param int $product_id The ID of the product. + * @return array The variations data. + */ + private static function request_variations($product_id) { + + $page = 1; + $variations_data = array(); + + do { + $request = new WP_REST_Request('GET', '/wc/v3/products/' . $product_id . '/variations'); + $request->set_query_params(array( + 'page' => $page, + 'per_page' => self::PER_PAGE, + )); + $variants_response = rest_do_request($request); + $variations_data = array_merge($variations_data, $variants_response->data); + $page++; + + } while (count($variants_response->data) >= self::PER_PAGE); + + return $variations_data; + } /** * Generate df_variants_information node response @@ -416,13 +507,14 @@ private static function get_df_variants_information($product){ array_walk($product_attributes, function (&$element) { $element = str_replace(['pa_', 'wc_'], '', $element); }); - $attr_variation_true = []; + + $variation_attributes = []; foreach($product["attributes"] as $p_attr){ if($p_attr["variation"] && in_array(strtolower($p_attr["name"]), $product_attributes)){ - $attr_variation_true[] = strtolower($p_attr["name"]); + $variation_attributes[] = strtolower($p_attr["name"]); } } - return $attr_variation_true; + return $variation_attributes; } /** From 33a37e1ed327cf7f49d6c7318b9d69733b2fcc37 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Fri, 10 Nov 2023 12:57:43 +0100 Subject: [PATCH 11/45] TODO remove api credentials --- .../includes/helpers/class-store-helpers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doofinder-for-woocommerce/includes/helpers/class-store-helpers.php b/doofinder-for-woocommerce/includes/helpers/class-store-helpers.php index 6332b84d..5fd630ea 100755 --- a/doofinder-for-woocommerce/includes/helpers/class-store-helpers.php +++ b/doofinder-for-woocommerce/includes/helpers/class-store-helpers.php @@ -19,7 +19,7 @@ public static function get_store_options() $endpoints_token = Store_Helpers::create_endpoints_token(); update_option('doofinder_for_wp_token', $endpoints_token); - + //TODO api_pass and api_user can be remove since new refactor endpoints if (!is_null($password_data)) { return [ "url" => get_bloginfo('url'), From 0f62e08bff40185a1ec65962f741fae21d9e9657 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Fri, 10 Nov 2023 17:50:47 +0100 Subject: [PATCH 12/45] optimize get_variations --- .../doofinder-for-woocommerce.php | 3 +- .../api/endpoints/class-endpoint-product.php | 28 +++++++++---------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/doofinder-for-woocommerce/doofinder-for-woocommerce.php b/doofinder-for-woocommerce/doofinder-for-woocommerce.php index 439f2fd5..f4d577d2 100644 --- a/doofinder-for-woocommerce/doofinder-for-woocommerce.php +++ b/doofinder-for-woocommerce/doofinder-for-woocommerce.php @@ -106,8 +106,9 @@ public function __construct() Update_On_Save::init(); //Initialize reset credentials Reset_Credentials::init(); - + REST_API_Handler::initialize(); Landing::init(); + // Init admin functionalities if (is_admin()) { Post::add_additional_settings(); diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 31571199..63967c5d 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -47,6 +47,7 @@ public static function custom_product_endpoint($request) { 'per_page' => $request->get_param('per_page') ?? self::PER_PAGE, 'page' => $request->get_param('page') ?? 1, 'lang' => $request->get_param('lang') ?? "", + 'fields' => $fields ]; // Retrieve the original product data @@ -58,7 +59,7 @@ public static function custom_product_endpoint($request) { if (!empty($products)) { // Include variants if requested - $products = self::get_variations($products); + $products = self::get_variations($products, $fields); foreach ($products as $product_data) { // Filter fields @@ -135,6 +136,7 @@ private static function get_image_field($data, $fields) { */ private static function check_stock_status($data, $fields) { if (in_array('stock_status', $fields)) { + unset($data["stock_status"]); return self::check_availability($data); } return $data; @@ -440,25 +442,18 @@ private static function get_variations($products_data){ $products = array(); foreach($products_data as $product){ - if($product["type"] == "variable"){ $variations_data = self::request_variations($product["id"]); - //Setting parent_id in variations foreach ($variations_data as &$variation) { - foreach ($product as $field => $value) { - if (!isset($variation[$field])) { - $variation[$field] = $value; - $variation["parent_id"] = $product["id"]; - } - } + $variation = array_merge($product, $variation, ["parent_id" => $product["id"]]); } + //Setting df_variants_information when variation attribute = true - if($product["parent_id"] == 0){ - $product["df_variants_information"] = self::get_df_variants_information($product); - $products[] = $product; - } + $attr_variation_true = self::get_df_variants_information($product); + $product["df_variants_information"] = $attr_variation_true; + $products[] = $product; $products = array_merge($products, $variations_data); } else{ @@ -483,10 +478,11 @@ private static function request_variations($product_id) { $request = new WP_REST_Request('GET', '/wc/v3/products/' . $product_id . '/variations'); $request->set_query_params(array( 'page' => $page, - 'per_page' => self::PER_PAGE, + 'per_page' => self::PER_PAGE )); $variants_response = rest_do_request($request); $variations_data = array_merge($variations_data, $variants_response->data); + $page++; } while (count($variants_response->data) >= self::PER_PAGE); @@ -533,14 +529,16 @@ private static function get_custom_attributes($product_id){ $attribute_slug = str_replace("pa_", "", $attribute_name); $found_key = array_search($attribute_slug, array_column($doofinder_attributes, 'field')); - if ($found_key) { + if (is_integer($found_key)) { $attribute_options = (array) ($attribute_data['options'] ?? $attribute_data); + foreach ($attribute_options as $option) { $term = get_term_by('name', $option, $attribute_name) ?? get_term_by('id', $option, $attribute_name); $custom_attributes[$attribute_slug][] = empty($term) || is_wp_error($term) ? $option : $term->name; } } } + return $custom_attributes; } From d325b12c6eae714407280b2c0bed3721c2901c80 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Fri, 10 Nov 2023 18:08:37 +0100 Subject: [PATCH 13/45] refactor get_variants function --- .../api/endpoints/class-endpoint-product.php | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 63967c5d..d908aa06 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -444,11 +444,7 @@ private static function get_variations($products_data){ foreach($products_data as $product){ if($product["type"] == "variable"){ - $variations_data = self::request_variations($product["id"]); - - foreach ($variations_data as &$variation) { - $variation = array_merge($product, $variation, ["parent_id" => $product["id"]]); - } + $variations_data = self::processVariations($product); //Setting df_variants_information when variation attribute = true $attr_variation_true = self::get_df_variants_information($product); @@ -463,6 +459,24 @@ private static function get_variations($products_data){ return $products; } + /** + * Process variations for a variable product. + * + * This function retrieves variations for a variable product, merges them with the product data, + * and sets the "parent_id" field. + * + * @param array $product The product data for a variable product. + * @return array The processed array of variations for the variable product. + */ + private static function processVariations($product) { + $variations_data = self::request_variations($product["id"]); + + foreach ($variations_data as &$variation) { + $variation = array_merge($product, $variation, ["parent_id" => $product["id"]]); + } + return $variations_data; + } + /** * Request variations for a given product ID. * From 7106e9ea0163413673a50899842ae0073c2fd4f4 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Sat, 11 Nov 2023 12:31:55 +0100 Subject: [PATCH 14/45] change endpoints names --- .../includes/api/endpoints/class-endpoint-post-category.php | 2 +- .../includes/api/endpoints/class-endpoint-product-category.php | 2 +- .../includes/api/endpoints/class-endpoint-product.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php index cbddf4b4..d0b47c01 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php @@ -12,7 +12,7 @@ class Endpoint_Post_Category { const PER_PAGE = 100; const CONTEXT = "doofinder/v1"; - const ENDPOINT = "/post-cat"; + const ENDPOINT = "/post_category"; /** * Initialize the custom item endpoint. diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php index 689a980a..34f6c3ab 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php @@ -12,7 +12,7 @@ class Endpoint_Product_Category { const PER_PAGE = 100; const CONTEXT = "doofinder/v1"; - const ENDPOINT = "/product-cat"; + const ENDPOINT = "/product_category"; /** * Initialize the custom item endpoint. diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index d908aa06..26b7651e 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -13,7 +13,7 @@ class Endpoint_Product { const PER_PAGE = 100; const CONTEXT = "doofinder/v1"; - const ENDPOINT = "/products"; + const ENDPOINT = "/product"; /** * Initialize the custom product endpoint. From 9018ae962d00e0b58b189618dbf87f8449d46ca4 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Mon, 13 Nov 2023 11:58:07 +0100 Subject: [PATCH 15/45] clean unused fields --- .../doofinder-for-woocommerce.php | 3 ++- .../api/endpoints/class-endpoint-product.php | 15 +++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/doofinder-for-woocommerce/doofinder-for-woocommerce.php b/doofinder-for-woocommerce/doofinder-for-woocommerce.php index f4d577d2..e93cbb7d 100644 --- a/doofinder-for-woocommerce/doofinder-for-woocommerce.php +++ b/doofinder-for-woocommerce/doofinder-for-woocommerce.php @@ -106,7 +106,7 @@ public function __construct() Update_On_Save::init(); //Initialize reset credentials Reset_Credentials::init(); - REST_API_Handler::initialize(); + Landing::init(); // Init admin functionalities @@ -343,6 +343,7 @@ public static function initialize_rest_endpoints() { add_action('rest_api_init', function () { Config::register(); + REST_API_Handler::initialize(); Index_Status_Handler::initialize(); Landing_Cache::register_endpoint(); }); diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 26b7651e..9ef9f61f 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -392,6 +392,7 @@ private static function check_availability($product){ else{ $product["availability"] = "out of stock"; } + unset($product["purchasable"]); return $product; } @@ -442,12 +443,17 @@ private static function get_variations($products_data){ $products = array(); foreach($products_data as $product){ - if($product["type"] == "variable"){ + $type = $product["type"]; + $attributes = $product["attributes"]; + unset($product["type"]); + unset($product["attributes"]); + + if($type == "variable"){ $variations_data = self::processVariations($product); //Setting df_variants_information when variation attribute = true - $attr_variation_true = self::get_df_variants_information($product); + $attr_variation_true = self::get_df_variants_information($product, $attributes); $product["df_variants_information"] = $attr_variation_true; $products[] = $product; $products = array_merge($products, $variations_data); @@ -508,9 +514,10 @@ private static function request_variations($product_id) { * Generate df_variants_information node response * * @param array $product + * @param array $attributes * @return array df_variants_information */ - private static function get_df_variants_information($product){ + private static function get_df_variants_information($product, $attributes){ $product_attributes = array_keys(wc_get_product($product["id"])->get_attributes()); @@ -519,7 +526,7 @@ private static function get_df_variants_information($product){ }); $variation_attributes = []; - foreach($product["attributes"] as $p_attr){ + foreach($attributes as $p_attr){ if($p_attr["variation"] && in_array(strtolower($p_attr["name"]), $product_attributes)){ $variation_attributes[] = strtolower($p_attr["name"]); } From d1917021d4fb83401acb94ecb4feffc9aba60c1e Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Tue, 14 Nov 2023 15:37:22 +0100 Subject: [PATCH 16/45] clear stock status --- .../includes/api/endpoints/class-endpoint-product.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 9ef9f61f..f0d99f24 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -136,7 +136,6 @@ private static function get_image_field($data, $fields) { */ private static function check_stock_status($data, $fields) { if (in_array('stock_status', $fields)) { - unset($data["stock_status"]); return self::check_availability($data); } return $data; @@ -392,7 +391,7 @@ private static function check_availability($product){ else{ $product["availability"] = "out of stock"; } - unset($product["purchasable"]); + unset($product["stock_status"]); return $product; } From 0d6ecf21c09f71680aa2297de358fa96e76832ac Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Tue, 14 Nov 2023 17:28:54 +0100 Subject: [PATCH 17/45] clear attributes --- .../includes/api/endpoints/class-endpoint-product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index f0d99f24..4fc40518 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -372,6 +372,7 @@ private static function clean_fields($product){ $product["title"] = $product["name"]; $product["link"] = $product["permalink"]; + unset($product["attributes"]); unset($product["name"]); unset($product["permalink"]); @@ -446,7 +447,6 @@ private static function get_variations($products_data){ $attributes = $product["attributes"]; unset($product["type"]); - unset($product["attributes"]); if($type == "variable"){ $variations_data = self::processVariations($product); From e806a8aca9f4301ad68edb7bea5ff976adf834be Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 15 Nov 2023 09:36:18 +0100 Subject: [PATCH 18/45] ids parameter filter --- .../includes/api/endpoints/class-endpoint-custom.php | 4 +++- .../includes/api/endpoints/class-endpoint-product.php | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php index 5ab25926..c0c98dd6 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php @@ -43,6 +43,7 @@ public static function custom_endpoint($request) { 'page' => $request->get_param('page') ?? 1, 'lang' => $request->get_param('lang') ?? "", 'type' => $request->get_param('type'), + 'ids' => $request->get_param('ids') ?? "" ]; $items = self::get_items($config_request); @@ -237,7 +238,8 @@ private static function get_items($config_request){ $request->set_query_params(array( 'page' => $config_request["page"], 'per_page' => $config_request["per_page"], - 'lang' => $config_request["lang"] + 'lang' => $config_request["lang"], + 'include' => $config_request["ids"] )); $response = rest_do_request($request); $data = rest_get_server()->response_to_data($response, true); diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 4fc40518..b7a16b5d 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -47,6 +47,7 @@ public static function custom_product_endpoint($request) { 'per_page' => $request->get_param('per_page') ?? self::PER_PAGE, 'page' => $request->get_param('page') ?? 1, 'lang' => $request->get_param('lang') ?? "", + 'ids' => $request->get_param('ids') ?? "", 'fields' => $fields ]; @@ -225,7 +226,8 @@ private static function get_products($config){ 'page' => $config["page"], 'per_page' => $config["per_page"], 'lang' => $config["lang"], - '_fields' => $config["fields"] + '_fields' => $config["fields"], + 'include' => $config["ids"] )); $original_response = rest_do_request($request); return $original_response->data; From e99836164e8a9e5f03cac535f35ec42ce01548b8 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 15 Nov 2023 12:10:50 +0100 Subject: [PATCH 19/45] remove decimal precission --- .../includes/api/endpoints/class-endpoint-product.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index b7a16b5d..1db9cf91 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -1,5 +1,7 @@ Date: Wed, 15 Nov 2023 16:33:33 +0100 Subject: [PATCH 20/45] All fields request and clean empty fields --- .../api/endpoints/class-endpoint-product.php | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 1db9cf91..9d40ed82 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -95,7 +95,7 @@ public static function custom_product_endpoint($request) { * @return array The processed data. */ private static function get_categories($data, $fields) { - if (in_array('categories', $fields) && isset($data["categories"])) { + if (isset($data["categories"])) { $data['categories'] = self::get_category_path($data["categories"]); } return $data; @@ -124,10 +124,7 @@ private static function merge_custom_attributes($data, $custom_attr, $product_id * @return array The processed data. */ private static function get_image_field($data, $fields) { - if (in_array('image_link', $fields)) { - return self::clear_images_fields($data); - } - return $data; + return self::clear_images_fields($data); } /** @@ -138,10 +135,7 @@ private static function get_image_field($data, $fields) { * @return array The processed data. */ private static function check_stock_status($data, $fields) { - if (in_array('stock_status', $fields)) { - return self::check_availability($data); - } - return $data; + return self::check_availability($data); } /** @@ -152,9 +146,7 @@ private static function check_stock_status($data, $fields) { * @return array The processed data. */ private static function get_description($data, $fields) { - if (in_array('description', $fields)) { - $data['description'] = self::process_content($data['description']); - } + $data['description'] = self::process_content($data['description']); return $data; } @@ -166,9 +158,7 @@ private static function get_description($data, $fields) { * @return array The processed data. */ private static function get_short_description($data, $fields) { - if (in_array('short_description', $fields)) { - $data['short_description'] = self::process_content($data['short_description']); - } + $data['short_description'] = self::process_content($data['short_description']); return $data; } @@ -180,9 +170,7 @@ private static function get_short_description($data, $fields) { * @return array The processed data. */ private static function get_tags($data, $fields) { - if (in_array('tags', $fields)) { - $data['tags'] = self::get_tag_names($data['tags']); - } + $data['tags'] = self::get_tag_names($data['tags']); return $data; } @@ -367,7 +355,7 @@ private static function add_base_url_if_needed($image_link) } /** - * Field names to exchange + * Field names to exchange and clear unused or empty fields * * @param array $product The product array to process. * @return array $product without fields excluded @@ -380,6 +368,10 @@ private static function clean_fields($product){ unset($product["name"]); unset($product["permalink"]); + $product = array_filter($product, function ($value) { + return $value !== '' && $value !== null; + }); + return $product; } From 0f5275ea3d44701e2b10452586a07e9b47c9f388 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 15 Nov 2023 16:34:22 +0100 Subject: [PATCH 21/45] clean empty fields --- .../includes/api/endpoints/class-endpoint-product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 9d40ed82..be052660 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -355,7 +355,7 @@ private static function add_base_url_if_needed($image_link) } /** - * Field names to exchange and clear unused or empty fields + * Field names to exchange and clean unused or empty fields * * @param array $product The product array to process. * @return array $product without fields excluded From 28b01688df71a6a417f73c4f460027d9475bb9b0 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 15 Nov 2023 16:49:52 +0100 Subject: [PATCH 22/45] comment fix --- doofinder-for-woocommerce/includes/class-endpoints.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doofinder-for-woocommerce/includes/class-endpoints.php b/doofinder-for-woocommerce/includes/class-endpoints.php index be99c8d5..a137491e 100644 --- a/doofinder-for-woocommerce/includes/class-endpoints.php +++ b/doofinder-for-woocommerce/includes/class-endpoints.php @@ -59,9 +59,8 @@ public static function init() /** * Verify a security token in the HTTP header. * - * This function checks whether a security token in the HTTP header matches - * an md5 hash of the server's host name. If they do not match, it returns a - * 403 (Forbidden) error response and terminates execution. + * This function checks the authentication token received in the headers against + * the one randomly generated by the plugin on installation. */ public static function CheckSecureToken() { From a9e0c8b472efcb7206b7ab94b4f428d16ff4a4de Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 15 Nov 2023 17:56:12 +0100 Subject: [PATCH 23/45] refactor custom attributes var --- .../api/endpoints/class-endpoint-product.php | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index be052660..94645ab4 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -111,7 +111,7 @@ private static function get_categories($data, $fields) { */ private static function merge_custom_attributes($data, $custom_attr, $product_id) { if (count($custom_attr) > 0) { - return array_merge($data, self::get_custom_attributes($product_id)); + return array_merge($data, self::get_custom_attributes($product_id, $custom_attr)); } return $data; } @@ -231,9 +231,11 @@ private static function get_products($config){ */ private static function format_prices($product) { - $product["price"] = self::get_price($product["id"]); - $product["regular_price"] = self::get_regular_price($product["id"]); - $product["sale_price"] = self::get_sale_price($product["id"]); + $wc_product = wc_get_product($product["id"]); + + $product["price"] = self::get_price($product["id"], $wc_product); + $product["regular_price"] = self::get_regular_price($product["id"], $wc_product); + $product["sale_price"] = self::get_sale_price($product["id"], $wc_product); return $product; } @@ -241,13 +243,12 @@ private static function format_prices($product) /** * Returns the raw price for the given product. * - * @param array $product The product we want to add the field + * @param array WooCommerce Product * @param string $price_name The price name. By default 'price' * @return void */ - private static function get_raw_price($id, $price_name = 'price') + private static function get_raw_price($wc_product, $price_name = 'price') { - $wc_product = wc_get_product($id); $fn_name = "get_$price_name"; if (is_a($wc_product, 'WC_Product') && method_exists($wc_product, $fn_name)) { $price = $wc_product->$fn_name(); @@ -289,9 +290,9 @@ private static function get_raw_real_price($price, $product) * @param integer $id Product ID to get field. * @return float The raw price including or excluding taxes (defined in WC settings). */ - private static function get_price($id) + private static function get_price($id, $product) { - return self::get_raw_price($id); + return self::get_raw_price($product); } /** @@ -300,9 +301,9 @@ private static function get_price($id) * @param integer $id Product ID to get field. * @return float The raw sale price including or excluding taxes (defined in WC settings). */ - private static function get_sale_price($id) + private static function get_sale_price($id, $product) { - return self::get_raw_price($id, 'sale_price'); + return self::get_raw_price($product, 'sale_price'); } /** @@ -311,9 +312,9 @@ private static function get_sale_price($id) * @param integer $id Product ID to get field. * @return float The raw regular price including or excluding taxes (defined in WC settings). */ - private static function get_regular_price($id) + private static function get_regular_price($id, $product) { - return self::get_raw_price($id, 'regular_price'); + return self::get_raw_price($product, 'regular_price'); } /** @@ -533,17 +534,17 @@ private static function get_df_variants_information($product, $attributes){ * Get custom attributes for a product. * * @param int $product_id The ID of the product. + * @param array $custom_attr List of custom attributes. * @return array The custom attributes for the product. */ - private static function get_custom_attributes($product_id){ + private static function get_custom_attributes($product_id, $custom_attr){ - $doofinder_attributes = Settings::get_custom_attributes(); $product_attributes = wc_get_product($product_id)->get_attributes(); $custom_attributes = array(); foreach ($product_attributes as $attribute_name => $attribute_data) { $attribute_slug = str_replace("pa_", "", $attribute_name); - $found_key = array_search($attribute_slug, array_column($doofinder_attributes, 'field')); + $found_key = array_search($attribute_slug, array_column($custom_attr, 'field')); if (is_integer($found_key)) { $attribute_options = (array) ($attribute_data['options'] ?? $attribute_data); From 33f5241b7d6677f032d485712384172f0d1b8f99 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Thu, 16 Nov 2023 00:27:20 +0100 Subject: [PATCH 24/45] change to self class --- .../api/endpoints/class-endpoint-custom.php | 2 +- .../class-endpoint-post-category.php | 2 +- .../class-endpoint-product-category.php | 2 +- .../api/endpoints/class-endpoint-product.php | 39 ++++++++++--------- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php index c0c98dd6..01aea16e 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php @@ -22,7 +22,7 @@ public static function initialize() { add_action('rest_api_init', function () { register_rest_route(self::CONTEXT, self::ENDPOINT, array( 'methods' => 'GET', - 'callback' => array(Endpoint_Custom::class, 'custom_endpoint') + 'callback' => array(self::class, 'custom_endpoint') )); }); } diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php index d0b47c01..4245f314 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php @@ -23,7 +23,7 @@ public static function initialize() { add_action('rest_api_init', function () { register_rest_route(self::CONTEXT, self::ENDPOINT, array( 'methods' => 'GET', - 'callback' => array(Endpoint_Post_Category::class, 'post_category_endpoint') + 'callback' => array(self::class, 'post_category_endpoint') )); }); } diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php index 34f6c3ab..45e842ac 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php @@ -23,7 +23,7 @@ public static function initialize() { add_action('rest_api_init', function () { register_rest_route(self::CONTEXT, self::ENDPOINT, array( 'methods' => 'GET', - 'callback' => array(Endpoint_Product_Category::class, 'product_category_endpoint') + 'callback' => array(self::class, 'product_category_endpoint') )); }); } diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 94645ab4..03c31dc0 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -26,7 +26,7 @@ public static function initialize(){ add_action('rest_api_init', function () { register_rest_route(self::CONTEXT, self::ENDPOINT, array( 'methods' => 'GET', - 'callback' => array(Endpoint_Product::class, 'custom_product_endpoint'), + 'callback' => array(self::class, 'custom_product_endpoint'), )); }); } @@ -35,23 +35,26 @@ public static function initialize(){ * Custom product endpoint callback. * * @param WP_REST_Request $request The REST request object. + * @param array $config_request Array config for internal requests. * @return WP_REST_Response Response containing modified data. */ - public static function custom_product_endpoint($request) { - - Endpoints::CheckSecureToken(); - - // Get the 'fields' parameter from the request - $fields_param = $request->get_param('fields'); - $fields = !empty($fields_param) ? explode(',', $fields_param) : array(); - - $config_request = [ - 'per_page' => $request->get_param('per_page') ?? self::PER_PAGE, - 'page' => $request->get_param('page') ?? 1, - 'lang' => $request->get_param('lang') ?? "", - 'ids' => $request->get_param('ids') ?? "", - 'fields' => $fields - ]; + public static function custom_product_endpoint($request, $config_request = false) { + + if(!$config_request){ + Endpoints::CheckSecureToken(); + + // Get the 'fields' parameter from the request + $fields_param = $request->get_param('fields'); + $fields = !empty($fields_param) ? explode(',', $fields_param) : array(); + + $config_request = [ + 'per_page' => $request->get_param('per_page') ?? self::PER_PAGE, + 'page' => $request->get_param('page') ?? 1, + 'lang' => $request->get_param('lang') ?? "", + 'ids' => $request->get_param('ids') ?? "", + 'fields' => $fields + ]; + } // Retrieve the original product data $products = self::get_products($config_request); @@ -369,9 +372,9 @@ private static function clean_fields($product){ unset($product["name"]); unset($product["permalink"]); - $product = array_filter($product, function ($value) { + /*$product = array_filter($product, function ($value) { return $value !== '' && $value !== null; - }); + });*/ return $product; } From 88768f880fd9be35c3c140ca040155000c0b58df Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Thu, 16 Nov 2023 09:34:47 +0100 Subject: [PATCH 25/45] clean empty fields --- .../includes/api/endpoints/class-endpoint-product.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 03c31dc0..bd6614a7 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -372,9 +372,9 @@ private static function clean_fields($product){ unset($product["name"]); unset($product["permalink"]); - /*$product = array_filter($product, function ($value) { + $product = array_filter($product, function ($value) { return $value !== '' && $value !== null; - });*/ + }); return $product; } From 9a62f7da2351bb235520b0fb6b82c8793dd7b864 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Thu, 16 Nov 2023 16:24:14 +0100 Subject: [PATCH 26/45] - Handler only in old requests - Get custom attributes with get_slugs --- doofinder-for-woocommerce/doofinder-for-woocommerce.php | 6 +++++- .../includes/api/endpoints/class-endpoint-product.php | 5 ++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/doofinder-for-woocommerce/doofinder-for-woocommerce.php b/doofinder-for-woocommerce/doofinder-for-woocommerce.php index e93cbb7d..15299978 100644 --- a/doofinder-for-woocommerce/doofinder-for-woocommerce.php +++ b/doofinder-for-woocommerce/doofinder-for-woocommerce.php @@ -343,7 +343,11 @@ public static function initialize_rest_endpoints() { add_action('rest_api_init', function () { Config::register(); - REST_API_Handler::initialize(); + + if(empty($_SERVER["HTTP_DOOFINDER_TOKEN"])){ + REST_API_Handler::initialize(); + } + Index_Status_Handler::initialize(); Landing_Cache::register_endpoint(); }); diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index bd6614a7..8fbf067a 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -550,11 +550,10 @@ private static function get_custom_attributes($product_id, $custom_attr){ $found_key = array_search($attribute_slug, array_column($custom_attr, 'field')); if (is_integer($found_key)) { - $attribute_options = (array) ($attribute_data['options'] ?? $attribute_data); + $attribute_options = is_string($attribute_data) ? [$attribute_data] : $attribute_data->get_slugs(); foreach ($attribute_options as $option) { - $term = get_term_by('name', $option, $attribute_name) ?? get_term_by('id', $option, $attribute_name); - $custom_attributes[$attribute_slug][] = empty($term) || is_wp_error($term) ? $option : $term->name; + $custom_attributes[$attribute_slug][] = $option; } } } From 9f9b774c65eaa4be39a2ab66341b8d023e48e1b8 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Fri, 17 Nov 2023 15:31:18 +0100 Subject: [PATCH 27/45] add $config_request param --- .../api/endpoints/class-endpoint-custom.php | 36 ++++++++++++------- .../class-endpoint-post-category.php | 3 +- .../api/endpoints/class-endpoint-product.php | 9 +++-- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php index 01aea16e..ab9d4438 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php @@ -31,25 +31,37 @@ public static function initialize() { * Custom item endpoint callback. * * @param WP_REST_Request $request The REST request object. + * @param array $config_request Array config for internal requests. * @return WP_REST_Response Response containing modified data. */ - public static function custom_endpoint($request) { - Endpoints::CheckSecureToken(); - - $fields = explode(',', $request->get_param('fields') ?? ''); - - $config_request = [ - 'per_page' => $request->get_param('per_page') ?? self::PER_PAGE, - 'page' => $request->get_param('page') ?? 1, - 'lang' => $request->get_param('lang') ?? "", - 'type' => $request->get_param('type'), - 'ids' => $request->get_param('ids') ?? "" - ]; + public static function custom_endpoint($request, $config_request = false) { + + if(!$config_request){ + Endpoints::CheckSecureToken(); + + // Get the 'fields' parameter from the request + $fields_param = $request->get_param('fields') ?? ""; + $fields = !empty($fields_param) ? explode(',', $fields_param) : []; + + $config_request = [ + 'per_page' => $request->get_param('per_page') ?? self::PER_PAGE, + 'page' => $request->get_param('page') ?? 1, + 'lang' => $request->get_param('lang') ?? "", + 'ids' => $request->get_param('ids') ?? "", + 'type' => $request->get_param('type'), + 'fields' => $fields + ]; + } + else{ + $fields_param = $config_request['fields'] ?? ""; + $fields = !empty($fields_param) ? explode(',', $fields_param) : []; + } $items = self::get_items($config_request); $modified_items = []; foreach ($items as $item_data) { + $filtered_data = array_intersect_key($item_data, array_flip($fields)); $filtered_data = self::get_title($filtered_data, $fields); diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php index 4245f314..01c9ebbf 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php @@ -1,7 +1,6 @@ get_param('fields') ?? ""; // Get the 'fields' parameter from the request - $fields = !empty($config_request["fields"]) ? explode(',', $config_request["fields"]) : array(); + $fields = !empty($config_request["fields"]) ? explode(',', $config_request["fields"]) : []; // Retrieve the original items data $items = self::get_items($config_request); diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 8fbf067a..d538432a 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -45,7 +45,7 @@ public static function custom_product_endpoint($request, $config_request = false // Get the 'fields' parameter from the request $fields_param = $request->get_param('fields'); - $fields = !empty($fields_param) ? explode(',', $fields_param) : array(); + $fields = !empty($fields_param) ? explode(',', $fields_param) : []; $config_request = [ 'per_page' => $request->get_param('per_page') ?? self::PER_PAGE, @@ -55,6 +55,11 @@ public static function custom_product_endpoint($request, $config_request = false 'fields' => $fields ]; } + else{ + $fields_param = $config_request['fields'] ?? ""; + $fields = !empty($fields_param) ? explode(',', $fields_param) : []; + } + // Retrieve the original product data $products = self::get_products($config_request); @@ -216,7 +221,7 @@ private static function get_products($config){ // Retrieve the original product data $request = new WP_REST_Request('GET', '/wc/v3/products'); $request->set_query_params(array( - 'page' => $config["page"], + 'page' => $config["page"] ?? self::PER_PAGE, 'per_page' => $config["per_page"], 'lang' => $config["lang"], '_fields' => $config["fields"], From fbedb90c7308a1537be052d435731cae0935c009 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 22 Nov 2023 13:04:17 +0100 Subject: [PATCH 28/45] - Update on save with dooplugins - Fix thumbnails autogenerate - New param at instalation plugin --- .../doofinder-for-woocommerce.php | 5 +- .../includes/api/class-store-api.php | 21 ----- .../includes/api/class-update-on-save-api.php | 77 +++++++++++++-- .../api/endpoints/class-endpoint-custom.php | 59 ++++++++++-- .../class-endpoint-post-category.php | 26 ++++- .../class-endpoint-product-category.php | 27 +++++- .../api/endpoints/class-endpoint-product.php | 94 +++++++++++++++++-- .../includes/class-setup-wizard.php | 17 +++- .../includes/class-thumbnail.php | 39 ++++++++ .../includes/settings/class-accessors.php | 26 +++++ 10 files changed, 333 insertions(+), 58 deletions(-) diff --git a/doofinder-for-woocommerce/doofinder-for-woocommerce.php b/doofinder-for-woocommerce/doofinder-for-woocommerce.php index 15299978..de9d367c 100644 --- a/doofinder-for-woocommerce/doofinder-for-woocommerce.php +++ b/doofinder-for-woocommerce/doofinder-for-woocommerce.php @@ -99,13 +99,14 @@ public function __construct() // Load classes on demand self::autoload(self::plugin_path() . 'includes/'); - Endpoints::init(); - add_action('init', function () use ($class) { + //Initialize update on save Update_On_Save::init(); //Initialize reset credentials Reset_Credentials::init(); + //Initialize custom endpoints + Endpoints::init(); Landing::init(); diff --git a/doofinder-for-woocommerce/includes/api/class-store-api.php b/doofinder-for-woocommerce/includes/api/class-store-api.php index a4da72af..ee7e9ad2 100644 --- a/doofinder-for-woocommerce/includes/api/class-store-api.php +++ b/doofinder-for-woocommerce/includes/api/class-store-api.php @@ -159,27 +159,6 @@ public static function has_application_credentials() return WP_Application_Passwords::application_name_exists_for_user(get_current_user_id(), 'doofinder'); } - public function update_custom_attributes($custom_attributes) - { - $multilanguage = Multilanguage::instance(); - $search_engines_by_language = Setup_Wizard::are_api_keys_present(true, $multilanguage); - - if (!Multilanguage::$is_multilang) { - $search_engines_by_language = [ - '' => [ - 'hash' => Settings::get_search_engine_hash() - ] - ]; - } - foreach ($search_engines_by_language as $language => $search_engine) { - $se_hash = $search_engine["hash"]; - if (empty($se_hash)) { - continue; - } - $response = $this->sendRequest("plugins/wordpress/$se_hash/update-custom-attributes/", $custom_attributes); - } - } - /** * Send a POST request with the given $body to the given $endpoint. * diff --git a/doofinder-for-woocommerce/includes/api/class-update-on-save-api.php b/doofinder-for-woocommerce/includes/api/class-update-on-save-api.php index 498a371d..17325c5a 100644 --- a/doofinder-for-woocommerce/includes/api/class-update-on-save-api.php +++ b/doofinder-for-woocommerce/includes/api/class-update-on-save-api.php @@ -5,6 +5,9 @@ use Doofinder\WP\Settings; use Doofinder\WP\Log; +use Endpoint_Product; +use Endpoint_Custom; + /** * Handles requests to the Management API. */ @@ -31,6 +34,13 @@ class Update_On_Save_Api */ private $api_key; + /** + * Dooplugins Host + * + * @var string + */ + private $dp_host; + /** * Hash * The search engine's unique id @@ -51,6 +61,7 @@ public function __construct($language) $this->log = new Log('update-on-save-api.log'); $this->api_key = Settings::get_api_key(); $this->api_host = Settings::get_api_host(); + $this->dp_host = Settings::get_dooplugins_host(); $this->hash = Settings::get_search_engine_hash($language); $this->authorization_header = array( 'Authorization' => "Token $this->api_key", @@ -70,16 +81,17 @@ public function __construct($language) * @param $data * */ - private function sendRequest($url, $ids, $method = 'POST') + private function sendRequest($url, $data, $method = 'POST') { $this->log->log("Making a request to: $url"); $data = [ 'headers' => $this->authorization_header, 'method' => $method, - 'body' => json_encode($ids), + 'body' => json_encode($data), ]; $response = wp_remote_request($url, $data); +exit(); if (!is_wp_error($response) && $response['response']['code'] === 200) { $this->log->log("The update on save request has been processed correctly"); return TRUE; @@ -90,9 +102,9 @@ private function sendRequest($url, $ids, $method = 'POST') return false; } - public function buildURL($path) + public function buildURL($host, $path) { - return "{$this->api_host}/{$path}"; + return "{$host}/{$path}"; } /** @@ -109,10 +121,59 @@ public function buildURL($path) public function updateBulk($post_type, $ids) { $this->log->log('Update items'); + $uri = $this->buildURL($this->dp_host, "item/" . $this->hash . "/" . $post_type . "?action=update&platform=wordpress"); - $uri = $this->buildURL("plugins/wordpress/" . $this->hash . "/" . $post_type . "/product_update"); + $chunks = array_chunk($ids, 100); + $resp = true; - return $this->sendRequest($uri, $ids); + foreach ($chunks as $chunk) { + $items = $this->get_items($chunk, $post_type); + $resp = $resp && $this->sendRequest($uri, $items); + } + return $resp; + } + + /** + * Get items data from our endpoint products (depends with post_type) + * + * @param array $ids ID product we want to get data + * @param string $post_type Type of item to request + * @return array API response with items list + * @since 1.0.0 + */ + public function get_items($ids, $post_type){ + if($post_type == "product"){ + return $this->get_products_data($ids); + } + else{ + return $this->get_custom_data($ids, $post_type); + } + } + + /** + * Get products data from our endpoint products + * + * @param array $ids ID product we want to get data + * @param array $feedtype Feedtype Product + * @since 1.0.0 + */ + public function get_products_data($ids){ + + require_once ('endpoints/class-endpoint-product.php'); + return Endpoint_Product::get_data($ids); + } + + /** + * Get products data from our endpoint products + * + * @param array $ids ID product we want to get data + * @param array $feedtype Feedtype Product + * @since 1.0.0 + */ + public function get_custom_data($ids, $post_type){ + + require_once ('endpoints/class-endpoint-custom.php'); + return Endpoint_Custom::get_data($ids, $post_type); } /** @@ -130,8 +191,8 @@ public function deleteBulk($post_type, $ids) { $this->log->log('Delete items'); - $uri = $this->buildURL("plugins/wordpress/" . $this->hash . "/" . $post_type . "/product_delete"); + $uri = $this->buildURL($this->dp_host, "item/" . $this->hash . "/" . $post_type . "?action=delete&platform=wordpress"); - return $this->sendRequest($uri, $ids, "DELETE"); + return $this->sendRequest($uri, $ids); } } diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php index ab9d4438..b6196f87 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php @@ -12,6 +12,20 @@ class Endpoint_Custom const PER_PAGE = 100; const CONTEXT = "doofinder/v1"; const ENDPOINT = "/custom"; + const FIELDS = [ + "_embedded", + "author", + "categories", + "content", + "excerpt", + "id", + "image_link", + "link", + "post_tags", + "slug", + "title" + ]; + /** * Initialize the custom item endpoint. @@ -40,21 +54,19 @@ public static function custom_endpoint($request, $config_request = false) { Endpoints::CheckSecureToken(); // Get the 'fields' parameter from the request - $fields_param = $request->get_param('fields') ?? ""; - $fields = !empty($fields_param) ? explode(',', $fields_param) : []; + $fields = $request->get_param('fields') == "all" ? [] : self::get_fields(); $config_request = [ 'per_page' => $request->get_param('per_page') ?? self::PER_PAGE, 'page' => $request->get_param('page') ?? 1, 'lang' => $request->get_param('lang') ?? "", 'ids' => $request->get_param('ids') ?? "", - 'type' => $request->get_param('type'), + 'type' => $request->get_param('type') ?? "", 'fields' => $fields ]; } else{ - $fields_param = $config_request['fields'] ?? ""; - $fields = !empty($fields_param) ? explode(',', $fields_param) : []; + $fields = !empty($config_request['fields']) ? explode(",", $config_request['fields']) : []; } $items = self::get_items($config_request); @@ -62,7 +74,7 @@ public static function custom_endpoint($request, $config_request = false) { foreach ($items as $item_data) { - $filtered_data = array_intersect_key($item_data, array_flip($fields)); + $filtered_data = !empty($fields) ? array_intersect_key($item_data, array_flip($fields)) : $item_data; $filtered_data = self::get_title($filtered_data, $fields); $filtered_data = self::get_content($filtered_data, $fields); @@ -80,6 +92,39 @@ public static function custom_endpoint($request, $config_request = false) { return new WP_REST_Response($modified_items); } + /** + * Get the array of fields. + * + * @return array The array of fields. + */ + public static function get_fields() { + return self::FIELDS; + } + + /** + * Get custom data from our endpoint products + * + * @param array $ids ID product we want to get data + * @param string $type Type of custom data + * @return array Array of custom data + */ + public static function get_data($ids, $type){ + + $request_params = array( + "ids" => implode(",", $ids), + "fields" => implode(",", self::get_fields()), + "type" => $type + ); + + $items = self::custom_endpoint(false, $request_params)->data; + + array_walk($items, function (&$product) { + unset($product['_links']); + }); + + return $items; + } + /** * Retrieves and processes the post tags information if requested by the fields. * @@ -263,4 +308,4 @@ private static function get_items($config_request){ return $data; } } -?> +?> \ No newline at end of file diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php index 01c9ebbf..ce722869 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-post-category.php @@ -12,6 +12,16 @@ class Endpoint_Post_Category const PER_PAGE = 100; const CONTEXT = "doofinder/v1"; const ENDPOINT = "/post_category"; + const FIELDS = [ + "description", + "_embedded", + "id", + "image_link", + "link", + "name", + "parent", + "slug" + ]; /** * Initialize the custom item endpoint. @@ -40,10 +50,7 @@ public static function post_category_endpoint($request) { $config_request["per_page"] = $request->get_param('per_page') ?? self::PER_PAGE; $config_request["page"] = $request->get_param('page') ?? 1; $config_request["lang"] = $request->get_param('lang') ?? ""; - $config_request["fields"] = $request->get_param('fields') ?? ""; - - // Get the 'fields' parameter from the request - $fields = !empty($config_request["fields"]) ? explode(',', $config_request["fields"]) : []; + $config_request["fields"] = $request->get_param('fields') == "all" ? "" : implode(",", self::get_fields()); // Retrieve the original items data $items = self::get_items($config_request); @@ -76,5 +83,14 @@ private static function get_items($config_request){ return $data; } + + /** + * Get the array of fields. + * + * @return array The array of fields. + */ + public static function get_fields() { + return self::FIELDS; + } } -?> +?> \ No newline at end of file diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php index 45e842ac..d73fb268 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product-category.php @@ -13,6 +13,16 @@ class Endpoint_Product_Category const PER_PAGE = 100; const CONTEXT = "doofinder/v1"; const ENDPOINT = "/product_category"; + const FIELDS = [ + "description", + "_embedded", + "id", + "image_link", + "link", + "name", + "parent", + "slug" + ]; /** * Initialize the custom item endpoint. @@ -41,10 +51,10 @@ public static function product_category_endpoint($request) { $config_request["per_page"] = $request->get_param('per_page') ?? self::PER_PAGE; $config_request["page"] = $request->get_param('page') ?? 1; $config_request["lang"] = $request->get_param('lang') ?? ""; - $config_request["fields"] = $request->get_param('fields') ?? ""; + $config_request["fields"] = $request->get_param('fields') == "all" ? "" : implode(",", self::get_fields()); // Get the 'fields' parameter from the request - $fields = !empty($config_request["fields"]) ? explode(',', $config_request["fields"]) : array(); + $fields = !empty($config_request["fields"]) ? self::get_fields() : []; // Retrieve the original items data $items = self::get_items($config_request); @@ -52,7 +62,7 @@ public static function product_category_endpoint($request) { if (!empty($items)) { foreach ($items as &$item_data) { - if(in_array('image_link', $fields)){ + if(in_array('image_link', $fields) || empty($fields)){ $item_data["image_link"] = self::get_product_cat_df_image_link($item_data); } } @@ -62,6 +72,15 @@ public static function product_category_endpoint($request) { return new WP_REST_Response($items); } + /** + * Get the array of fields. + * + * @return array The array of fields. + */ + public static function get_fields() { + return self::FIELDS; + } + /** * Check that image link is absolute, if not, add the site url * @@ -117,4 +136,4 @@ private static function get_items($config_request){ return $data; } } -?> +?> \ No newline at end of file diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index d538432a..d77668bb 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -16,6 +16,34 @@ class Endpoint_Product const PER_PAGE = 100; const CONTEXT = "doofinder/v1"; const ENDPOINT = "/product"; + const FIELDS = [ + "attributes", + "average_rating", + "best_price", + "catalog_visibility", + "categories", + "description", + "df_group_leader", + "df_variants_information", + "group_id", + "id", + "image_link", + "link", + "meta_data", + "name", + "parent_id", + "permalink", + "price", + "purchasable", + "regular_price", + "sale_price", + "short_description", + "sku", + "slug", + "stock_status", + "tags", + "type" + ]; /** * Initialize the custom product endpoint. @@ -44,8 +72,7 @@ public static function custom_product_endpoint($request, $config_request = false Endpoints::CheckSecureToken(); // Get the 'fields' parameter from the request - $fields_param = $request->get_param('fields'); - $fields = !empty($fields_param) ? explode(',', $fields_param) : []; + $fields = $request->get_param('fields') == "all" ? [] : self::get_fields(); $config_request = [ 'per_page' => $request->get_param('per_page') ?? self::PER_PAGE, @@ -77,13 +104,14 @@ public static function custom_product_endpoint($request, $config_request = false $filtered_product_data = !empty($fields) ? array_intersect_key($product_data, array_flip($fields)) : $product_data; $filtered_product_data = self::get_categories($filtered_product_data, $fields); - $filtered_product_data = self::merge_custom_attributes($filtered_product_data, $custom_attr, $product_data["id"]); + $filtered_product_data = self::merge_custom_attributes($filtered_product_data, $custom_attr); $filtered_product_data = self::get_image_field($filtered_product_data, $fields); $filtered_product_data = self::format_prices($filtered_product_data); $filtered_product_data = self::check_stock_status($filtered_product_data, $fields); $filtered_product_data = self::get_description($filtered_product_data, $fields); $filtered_product_data = self::get_short_description($filtered_product_data, $fields); $filtered_product_data = self::get_tags($filtered_product_data, $fields); + $filtered_product_data = self::get_meta_attributes($filtered_product_data, $custom_attr); $filtered_product_data = self::clean_fields($filtered_product_data); $modified_products[] = $filtered_product_data; @@ -95,6 +123,37 @@ public static function custom_product_endpoint($request, $config_request = false return new WP_REST_Response($modified_products); } + /** + * Get the array of fields. + * + * @return array The array of fields. + */ + public static function get_fields() { + return self::FIELDS; + } + + /** + * Get products data from our endpoint products + * + * @param array $ids ID product we want to get data + * @return array Array Products + */ + public static function get_data($ids){ + + $request_params = array( + "ids" => implode(",", $ids), + "fields" => implode(",", self::get_fields()) + ); + + $items = self::custom_product_endpoint(false, $request_params)->data; + + array_walk($items, function (&$product) { + unset($product['_links']); + }); + + return $items; + } + /** * Get categories in the data. * @@ -114,13 +173,34 @@ private static function get_categories($data, $fields) { * * @param array $data The data to merge into. * @param array $custom_attr The custom attributes to merge. - * @param int $product_id The ID of the product. * @return array The merged data. */ - private static function merge_custom_attributes($data, $custom_attr, $product_id) { + private static function merge_custom_attributes($data, $custom_attr) { if (count($custom_attr) > 0) { - return array_merge($data, self::get_custom_attributes($product_id, $custom_attr)); + return array_merge($data, self::get_custom_attributes($data["id"], $custom_attr)); + } + return $data; + } + + /** + * Get custom meta field data from product + * + * @param array $data The data to merge into. + * @param array $custom_attr The custom attributes to merge. + * @return array The merged data. + */ + private static function get_meta_attributes($data, $custom_attr) { + foreach ($custom_attr as $attr) { + if ($attr["type"] == "metafield") { + foreach ($data["meta_data"] as $meta) { + $meta_data = $meta->get_data(); + if ($meta_data["key"] == $attr["field"]) { + $data[$attr["field"]] = $meta_data["value"] ?? ""; + } + } + } } + unset($data["meta_data"]); return $data; } @@ -609,4 +689,4 @@ private static function get_category_hierarchy($category_id) { return $category_path; } } -?> +?> \ No newline at end of file diff --git a/doofinder-for-woocommerce/includes/class-setup-wizard.php b/doofinder-for-woocommerce/includes/class-setup-wizard.php index be630579..050747f7 100644 --- a/doofinder-for-woocommerce/includes/class-setup-wizard.php +++ b/doofinder-for-woocommerce/includes/class-setup-wizard.php @@ -1078,8 +1078,9 @@ private function clear_all_settings() private function check_api_settings($step) { - $api_key = $_REQUEST['api_token'] ?? null; - $api_host = $_REQUEST['admin_endpoint'] ?? null; // i.e: https://eu1-admin.doofinder.com + $api_key = $_REQUEST['api_token'] ?? null; + $api_host = $_REQUEST['admin_endpoint'] ?? null; // i.e: https://eu1-admin.doofinder.com + $dooplugins_host = $_REQUEST['dooplugins_endpoint'] ?? null; // i.e: https://eu1-plugins.doofinder.com if (empty($api_key)) { $this->add_wizard_step_error($step, 'api-key', __('API key is missing.', 'wordpress-doofinder')); @@ -1093,6 +1094,12 @@ private function check_api_settings($step) $this->remove_wizard_step_error($step, 'api-host'); } + if (empty($dooplugins_host)) { + $this->add_wizard_step_error($step, 'dooplugins-host', __('API dooplugins is missing.', 'wordpress-doofinder')); + } else { + $this->remove_wizard_step_error($step, 'dooplugins-host'); + } + if (!empty($this->errors['wizard-step-' . $step])) { return FALSE; } @@ -1103,8 +1110,9 @@ private function check_api_settings($step) } return [ - 'api_key' => $api_key, - 'api_host' => $api_host, + 'api_key' => $api_key, + 'api_host' => $api_host, + 'dooplugins_host' => $dooplugins_host, ]; } @@ -1138,6 +1146,7 @@ private function save_api_settings($api_settings) Settings::set_api_key($api_key); Settings::set_api_host($api_host); + Settings::set_dooplugins_host($dooplugins_host); } diff --git a/doofinder-for-woocommerce/includes/class-thumbnail.php b/doofinder-for-woocommerce/includes/class-thumbnail.php index 29302eb2..c5c7c43b 100755 --- a/doofinder-for-woocommerce/includes/class-thumbnail.php +++ b/doofinder-for-woocommerce/includes/class-thumbnail.php @@ -49,11 +49,50 @@ public function get() return $intermediate['url']; } + $thumb_size = $this->get_thumbnail_size(self::$size); + + //Full img size + $img_ori = wp_get_attachment_image_src($thumbnail_id, "full"); + $img_original["w"] = $img_ori[1] ?? 0; + $img_original["h"] = $img_ori[2] ?? 0; + + //Check if is posible generate a thumb or not + if($thumb_size["w"] >= $img_original["w"] || $thumb_size["h"] >= $img_original["h"]){ + return $img_ori[0] ?? ""; + } + $this->regenerate_thumbnail($thumbnail_id); $thumbnail = wp_get_attachment_image_src($thumbnail_id, self::$size); + return $thumbnail[0]; } + /** + * Get size of Format thumbnail requested + * + * @param string $format Format image (large, medium, etc...) + * @return void + */ + private function get_thumbnail_size($format){ + + $size = array(); + + $w_thumb = get_option($format."_size_w"); + $h_thumb = get_option($format."_size_h"); + + if(empty($w_thumb)){ + $size = explode("x", self::$size); + $size["w"] = $size[0] ?? 0; + $size["h"] = $size[1] ?? 0; + } + else{ + $size["w"] = $w_thumb ?? 0; + $size["h"] = $h_thumb ?? 0; + } + + return $size; + } + /** * Regenerate thumbnails for the current post. */ diff --git a/doofinder-for-woocommerce/includes/settings/class-accessors.php b/doofinder-for-woocommerce/includes/settings/class-accessors.php index dedc9ee2..b4804a94 100644 --- a/doofinder-for-woocommerce/includes/settings/class-accessors.php +++ b/doofinder-for-woocommerce/includes/settings/class-accessors.php @@ -51,6 +51,19 @@ public static function set_api_key($api_key) update_option('doofinder_for_wp_api_key', $api_key); } + /** + * Retrieve the API Host. + * + * Just an alias for "get_option" to avoid repeating the string + * (option name) in multiple files. + * + * @return string + */ + public static function get_dooplugins_host() + { + return get_option('doofinder_for_wp_dooplugins_host', 'https://plugins.doofinder.com'); + } + /** * Retrieve the API Host. * @@ -81,6 +94,19 @@ public static function set_api_host($api_host) update_option('doofinder_for_wp_api_host', $api_host); } + /** + * Set the value of the Dooplugins Host. + * + * Just an alias for "update_option" to avoid repeating the string + * (option name) in multiple files. + * + * @param string $dp_host + */ + public static function set_dooplugins_host($dp_host) + { + update_option('doofinder_for_wp_dooplugins_host', $dp_host); + } + /** * Retrieve the hash of the chosen Search engine. * From effd61037a3a73b1c0b13842c3b9c28c0494d1b6 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 22 Nov 2023 13:09:21 +0100 Subject: [PATCH 29/45] doc param return --- doofinder-for-woocommerce/includes/class-thumbnail.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doofinder-for-woocommerce/includes/class-thumbnail.php b/doofinder-for-woocommerce/includes/class-thumbnail.php index c5c7c43b..c26a368f 100755 --- a/doofinder-for-woocommerce/includes/class-thumbnail.php +++ b/doofinder-for-woocommerce/includes/class-thumbnail.php @@ -71,7 +71,7 @@ public function get() * Get size of Format thumbnail requested * * @param string $format Format image (large, medium, etc...) - * @return void + * @return array Size of thumbnail requested */ private function get_thumbnail_size($format){ From aefac96cb25cfd9083abf61693a9c90a2c566da1 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 22 Nov 2023 13:29:15 +0100 Subject: [PATCH 30/45] remove debug --- .../includes/api/class-update-on-save-api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doofinder-for-woocommerce/includes/api/class-update-on-save-api.php b/doofinder-for-woocommerce/includes/api/class-update-on-save-api.php index 17325c5a..86ea7b1c 100644 --- a/doofinder-for-woocommerce/includes/api/class-update-on-save-api.php +++ b/doofinder-for-woocommerce/includes/api/class-update-on-save-api.php @@ -91,7 +91,7 @@ private function sendRequest($url, $data, $method = 'POST') ]; $response = wp_remote_request($url, $data); -exit(); + if (!is_wp_error($response) && $response['response']['code'] === 200) { $this->log->log("The update on save request has been processed correctly"); return TRUE; From fd86bcaebe7f62f483cfa550b2367094310ce645 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 22 Nov 2023 16:37:55 +0100 Subject: [PATCH 31/45] Refactor Thumb class generate --- .../includes/class-thumbnail.php | 59 +++++++++++++++---- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/doofinder-for-woocommerce/includes/class-thumbnail.php b/doofinder-for-woocommerce/includes/class-thumbnail.php index c26a368f..d745afc4 100755 --- a/doofinder-for-woocommerce/includes/class-thumbnail.php +++ b/doofinder-for-woocommerce/includes/class-thumbnail.php @@ -44,27 +44,44 @@ public function get() } $thumbnail_id = get_post_thumbnail_id($this->post); - $intermediate = image_get_intermediate_size($thumbnail_id, self::$size); - if (FALSE != $intermediate) { - return $intermediate['url']; + $thumbnail = image_get_intermediate_size($thumbnail_id, self::$size); + + if (FALSE != $thumbnail) { + return $thumbnail[0]; + } + + $img_url = $this->check_size_image_url($thumbnail_id); + if($img_url){ + return $img_url; } + $this->regenerate_thumbnail($thumbnail_id); + $thumbnail = wp_get_attachment_image_src($thumbnail_id, self::$size); + + return $thumbnail[0]; + } + + /** + * Checks if we are going to be able to generate the thumbnail from + * the original image and if it cannot then it will return the URL + * of the original image. + * + * @param string $thumbnail_id Thumb ID por check + * @return string URL of Thumb or false + */ + private function check_size_image_url($thumbnail_id){ + + //Thumb requested size $thumb_size = $this->get_thumbnail_size(self::$size); //Full img size - $img_ori = wp_get_attachment_image_src($thumbnail_id, "full"); - $img_original["w"] = $img_ori[1] ?? 0; - $img_original["h"] = $img_ori[2] ?? 0; + $img_original = $this->get_original_size($thumbnail_id); //Check if is posible generate a thumb or not if($thumb_size["w"] >= $img_original["w"] || $thumb_size["h"] >= $img_original["h"]){ - return $img_ori[0] ?? ""; + return $img_original["url"]; } - - $this->regenerate_thumbnail($thumbnail_id); - $thumbnail = wp_get_attachment_image_src($thumbnail_id, self::$size); - - return $thumbnail[0]; + return false; } /** @@ -93,6 +110,24 @@ private function get_thumbnail_size($format){ return $size; } + /** + * Get size from thumbnail_id + * + * @param string $thumbnail_id Thumbnail ID for get original size + * @return array Original IMG (w,h and url) + */ + private function get_original_size($thumbnail_id){ + + $img = array(); + $img_ori = wp_get_attachment_image_src($thumbnail_id, "full"); + + $img["url"] = $img_ori[0]; + $img["w"] = $img_ori[1]; + $img["h"] = $img_ori[2]; + + return $img; + } + /** * Regenerate thumbnails for the current post. */ From b994989d5ee0a1ad03c028b9456a640532a4c518 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 22 Nov 2023 16:40:50 +0100 Subject: [PATCH 32/45] Comments Thumb class --- doofinder-for-woocommerce/includes/class-thumbnail.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doofinder-for-woocommerce/includes/class-thumbnail.php b/doofinder-for-woocommerce/includes/class-thumbnail.php index d745afc4..0efc9251 100755 --- a/doofinder-for-woocommerce/includes/class-thumbnail.php +++ b/doofinder-for-woocommerce/includes/class-thumbnail.php @@ -44,18 +44,26 @@ public function get() } $thumbnail_id = get_post_thumbnail_id($this->post); + + //I search for the image among the wordpress autogenerated formats $thumbnail = image_get_intermediate_size($thumbnail_id, self::$size); + //If I find it, I return its URL if (FALSE != $thumbnail) { return $thumbnail[0]; } + //I check if the thumb generation is feasible with respect to the size + //of the original image. $img_url = $this->check_size_image_url($thumbnail_id); if($img_url){ return $img_url; } + //I update the image metadata with the new formats $this->regenerate_thumbnail($thumbnail_id); + + //I return the URL of the generated image in the metadata $thumbnail = wp_get_attachment_image_src($thumbnail_id, self::$size); return $thumbnail[0]; From f917eee3b2ca0e4c2f3eb3b091f9adf59ad7a3c9 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 22 Nov 2023 16:54:21 +0100 Subject: [PATCH 33/45] Check metadata image --- doofinder-for-woocommerce/includes/class-thumbnail.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doofinder-for-woocommerce/includes/class-thumbnail.php b/doofinder-for-woocommerce/includes/class-thumbnail.php index 0efc9251..0f74c21f 100755 --- a/doofinder-for-woocommerce/includes/class-thumbnail.php +++ b/doofinder-for-woocommerce/includes/class-thumbnail.php @@ -82,6 +82,12 @@ private function check_size_image_url($thumbnail_id){ //Thumb requested size $thumb_size = $this->get_thumbnail_size(self::$size); + //If I find the image I am looking for in the metadata, I return it. + $thumb_meta = wp_get_attachment_image_src($thumbnail_id, self::$size); + if($thumb_meta[0] == $thumb_size["w"] && $thumb_meta[1] == $thumb_size["h"]){ + return $thumb_meta["0"]; + } + //Full img size $img_original = $this->get_original_size($thumbnail_id); From e9c150b082a7676bed5c68b6667b2e9f27c0e4a0 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 22 Nov 2023 17:25:41 +0100 Subject: [PATCH 34/45] Refactor thumb class --- .../includes/class-thumbnail.php | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/doofinder-for-woocommerce/includes/class-thumbnail.php b/doofinder-for-woocommerce/includes/class-thumbnail.php index 0f74c21f..a4ae5111 100755 --- a/doofinder-for-woocommerce/includes/class-thumbnail.php +++ b/doofinder-for-woocommerce/includes/class-thumbnail.php @@ -45,23 +45,16 @@ public function get() $thumbnail_id = get_post_thumbnail_id($this->post); - //I search for the image among the wordpress autogenerated formats - $thumbnail = image_get_intermediate_size($thumbnail_id, self::$size); - - //If I find it, I return its URL - if (FALSE != $thumbnail) { - return $thumbnail[0]; - } - //I check if the thumb generation is feasible with respect to the size //of the original image. $img_url = $this->check_size_image_url($thumbnail_id); + if($img_url){ return $img_url; } //I update the image metadata with the new formats - $this->regenerate_thumbnail($thumbnail_id); + //$this->regenerate_thumbnail($thumbnail_id); //I return the URL of the generated image in the metadata $thumbnail = wp_get_attachment_image_src($thumbnail_id, self::$size); @@ -79,12 +72,20 @@ public function get() */ private function check_size_image_url($thumbnail_id){ + //I search for the image among the wordpress autogenerated formats + $thumbnail = image_get_intermediate_size($thumbnail_id, self::$size); + + //If I find it, I return its URL + if (FALSE != $thumbnail && $thumbnail[0] != "") { + return $thumbnail[0]; + } + //Thumb requested size $thumb_size = $this->get_thumbnail_size(self::$size); //If I find the image I am looking for in the metadata, I return it. $thumb_meta = wp_get_attachment_image_src($thumbnail_id, self::$size); - if($thumb_meta[0] == $thumb_size["w"] && $thumb_meta[1] == $thumb_size["h"]){ + if(($thumb_meta[0] >= $thumb_size["w"] || $thumb_meta[1] >= $thumb_size["h"]) && $thumb_meta["0"] != ""){ return $thumb_meta["0"]; } @@ -92,7 +93,7 @@ private function check_size_image_url($thumbnail_id){ $img_original = $this->get_original_size($thumbnail_id); //Check if is posible generate a thumb or not - if($thumb_size["w"] >= $img_original["w"] || $thumb_size["h"] >= $img_original["h"]){ + if(($thumb_size["w"] >= $img_original["w"] || $thumb_size["h"] >= $img_original["h"]) && $img_original["url"] != ""){ return $img_original["url"]; } return false; From 5f0bff5c31e9d48a36c729fb92ae91537219c15c Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 22 Nov 2023 17:27:17 +0100 Subject: [PATCH 35/45] change function name --- doofinder-for-woocommerce/includes/class-thumbnail.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doofinder-for-woocommerce/includes/class-thumbnail.php b/doofinder-for-woocommerce/includes/class-thumbnail.php index a4ae5111..e2a94005 100755 --- a/doofinder-for-woocommerce/includes/class-thumbnail.php +++ b/doofinder-for-woocommerce/includes/class-thumbnail.php @@ -47,7 +47,7 @@ public function get() //I check if the thumb generation is feasible with respect to the size //of the original image. - $img_url = $this->check_size_image_url($thumbnail_id); + $img_url = $this->get_image_url_by_size($thumbnail_id); if($img_url){ return $img_url; @@ -70,7 +70,7 @@ public function get() * @param string $thumbnail_id Thumb ID por check * @return string URL of Thumb or false */ - private function check_size_image_url($thumbnail_id){ + private function get_image_url_by_size($thumbnail_id){ //I search for the image among the wordpress autogenerated formats $thumbnail = image_get_intermediate_size($thumbnail_id, self::$size); From f1594a36f514070c5f7853c14ef5b77c154dca2d Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 22 Nov 2023 17:31:49 +0100 Subject: [PATCH 36/45] remove debug --- doofinder-for-woocommerce/includes/class-thumbnail.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doofinder-for-woocommerce/includes/class-thumbnail.php b/doofinder-for-woocommerce/includes/class-thumbnail.php index e2a94005..dc7a2a9a 100755 --- a/doofinder-for-woocommerce/includes/class-thumbnail.php +++ b/doofinder-for-woocommerce/includes/class-thumbnail.php @@ -54,7 +54,7 @@ public function get() } //I update the image metadata with the new formats - //$this->regenerate_thumbnail($thumbnail_id); + $this->regenerate_thumbnail($thumbnail_id); //I return the URL of the generated image in the metadata $thumbnail = wp_get_attachment_image_src($thumbnail_id, self::$size); From 66c47f3dc3a405c76056edbbfc09935e02b1679a Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Wed, 22 Nov 2023 18:23:08 +0100 Subject: [PATCH 37/45] setting dooplugins var in migration version --- .../doofinder-for-woocommerce.php | 4 ++-- .../includes/class-update-manager.php | 13 +++++++++++++ doofinder-for-woocommerce/readme.txt | 3 +++ package-lock.json | 4 ++-- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/doofinder-for-woocommerce/doofinder-for-woocommerce.php b/doofinder-for-woocommerce/doofinder-for-woocommerce.php index de9d367c..0f568d06 100644 --- a/doofinder-for-woocommerce/doofinder-for-woocommerce.php +++ b/doofinder-for-woocommerce/doofinder-for-woocommerce.php @@ -4,7 +4,7 @@ * Plugin Name: Doofinder WP & WooCommerce Search * License: GPLv2 or later * License URI: http://www.gnu.org/licenses/gpl-2.0.html - * Version: 2.1.0 + * Version: 2.1.1 * Requires at least: 5.6 * Requires PHP: 7.0 * Author: Doofinder @@ -35,7 +35,7 @@ class Doofinder_For_WordPress * * @var string */ - public static $version = '2.1.0'; + public static $version = '2.1.1'; /** * The only instance of Doofinder_For_WordPress diff --git a/doofinder-for-woocommerce/includes/class-update-manager.php b/doofinder-for-woocommerce/includes/class-update-manager.php index dbb15fe3..be0841a3 100644 --- a/doofinder-for-woocommerce/includes/class-update-manager.php +++ b/doofinder-for-woocommerce/includes/class-update-manager.php @@ -195,4 +195,17 @@ public static function update_020100() Migration::create_token_auth(); return true; } + + /** + * Update: 2.1.1 + * Update the woocommerce product attributes + */ + public static function update_020101() + { + $doomanager_host = Settings::get_api_host(); + $dooplugins_host = str_replace("admin", "plugins", $doomanager_host); + Settings::set_dooplugins_host($dooplugins_host); + + return true; + } } diff --git a/doofinder-for-woocommerce/readme.txt b/doofinder-for-woocommerce/readme.txt index 5261da3a..a02ef566 100644 --- a/doofinder-for-woocommerce/readme.txt +++ b/doofinder-for-woocommerce/readme.txt @@ -82,6 +82,9 @@ Just send your questions to and we will try to an == Changelog == += 2.1.1 = +Update on save refactor and add fields tu custom endpoints + = 2.1.0 = New internal endpoints to obtain products, posts, pages and custom items. Refactor in custom attributes management. diff --git a/package-lock.json b/package-lock.json index 2103366a..809f1245 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doofinder-woocommerce", - "version": "2.1.0", + "version": "2.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "doofinder-woocommerce", - "version": "2.1.0", + "version": "2.1.1", "license": "MIT", "devDependencies": { "grunt": "^1.0.1", From 286cf21fe0354c8bda013cd6586b0eec10fb58ff Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Thu, 23 Nov 2023 12:50:13 +0100 Subject: [PATCH 38/45] order by id asc --- .../includes/api/endpoints/class-endpoint-custom.php | 4 +++- .../includes/api/endpoints/class-endpoint-product.php | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php index b6196f87..43b97edc 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-custom.php @@ -296,7 +296,9 @@ private static function get_items($config_request){ 'page' => $config_request["page"], 'per_page' => $config_request["per_page"], 'lang' => $config_request["lang"], - 'include' => $config_request["ids"] + 'include' => $config_request["ids"], + "orderby" => "id", + "order" => "asc" )); $response = rest_do_request($request); $data = rest_get_server()->response_to_data($response, true); diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index d77668bb..b3307a4e 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -305,7 +305,9 @@ private static function get_products($config){ 'per_page' => $config["per_page"], 'lang' => $config["lang"], '_fields' => $config["fields"], - 'include' => $config["ids"] + 'include' => $config["ids"], + "orderby" => "id", + "order" => "asc" )); $original_response = rest_do_request($request); return $original_response->data; @@ -457,6 +459,10 @@ private static function clean_fields($product){ unset($product["name"]); unset($product["permalink"]); + if(empty($product["parent_id"])){ + unset($product["parent_id"]); + } + $product = array_filter($product, function ($value) { return $value !== '' && $value !== null; }); From 0872cd78cb98eff25573c027c6bc95eeb7949a4e Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Thu, 23 Nov 2023 13:47:39 +0100 Subject: [PATCH 39/45] change per_page default var --- .../includes/api/endpoints/class-endpoint-product.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index b3307a4e..4bbb7e31 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -39,6 +39,7 @@ class Endpoint_Product "sale_price", "short_description", "sku", + "status", "slug", "stock_status", "tags", @@ -301,13 +302,13 @@ private static function get_products($config){ // Retrieve the original product data $request = new WP_REST_Request('GET', '/wc/v3/products'); $request->set_query_params(array( - 'page' => $config["page"] ?? self::PER_PAGE, - 'per_page' => $config["per_page"], + 'page' => $config["page"], + 'per_page' => $config["per_page"] ?? self::PER_PAGE, 'lang' => $config["lang"], + 'status' => "publish", '_fields' => $config["fields"], 'include' => $config["ids"], - "orderby" => "id", - "order" => "asc" + 'orderby' => "id" )); $original_response = rest_do_request($request); return $original_response->data; From 01fdf994d6994373a798eb06a0434d7c65b09ca3 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Thu, 23 Nov 2023 14:48:40 +0100 Subject: [PATCH 40/45] order by and order --- .../includes/api/endpoints/class-endpoint-product.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 4bbb7e31..d4af0acd 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -80,6 +80,8 @@ public static function custom_product_endpoint($request, $config_request = false 'page' => $request->get_param('page') ?? 1, 'lang' => $request->get_param('lang') ?? "", 'ids' => $request->get_param('ids') ?? "", + 'orderby' => $request->get_param('orderby') ?? "id", + 'order' => $request->get_param('order') ?? "desc", 'fields' => $fields ]; } @@ -308,7 +310,8 @@ private static function get_products($config){ 'status' => "publish", '_fields' => $config["fields"], 'include' => $config["ids"], - 'orderby' => "id" + 'orderby' => $config["orderby"], + 'order' => $config["order"] )); $original_response = rest_do_request($request); return $original_response->data; From 7d9f0af0125e3dc56b37353a912884a0de415497 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Thu, 23 Nov 2023 17:34:51 +0100 Subject: [PATCH 41/45] default params --- .../includes/api/endpoints/class-endpoint-product.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index d4af0acd..74ae3521 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -90,7 +90,6 @@ public static function custom_product_endpoint($request, $config_request = false $fields = !empty($fields_param) ? explode(',', $fields_param) : []; } - // Retrieve the original product data $products = self::get_products($config_request); $custom_attr = Settings::get_custom_attributes(); @@ -304,14 +303,14 @@ private static function get_products($config){ // Retrieve the original product data $request = new WP_REST_Request('GET', '/wc/v3/products'); $request->set_query_params(array( - 'page' => $config["page"], + 'page' => $config["page"] ?? 1, 'per_page' => $config["per_page"] ?? self::PER_PAGE, - 'lang' => $config["lang"], + 'lang' => $config["lang"] ?? "", 'status' => "publish", '_fields' => $config["fields"], 'include' => $config["ids"], - 'orderby' => $config["orderby"], - 'order' => $config["order"] + 'orderby' => $config["orderby"] ?? "id", + 'order' => $config["order"] ?? "desc" )); $original_response = rest_do_request($request); return $original_response->data; From 24acbcd843a9b4a71038f5416ae5d3c3b78d9554 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Thu, 23 Nov 2023 17:37:58 +0100 Subject: [PATCH 42/45] upgrade readme --- doofinder-for-woocommerce/readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doofinder-for-woocommerce/readme.txt b/doofinder-for-woocommerce/readme.txt index a02ef566..3af67f1d 100644 --- a/doofinder-for-woocommerce/readme.txt +++ b/doofinder-for-woocommerce/readme.txt @@ -1,7 +1,7 @@ === Doofinder WP & WooCommerce Search === Contributors: Doofinder Tags: search, autocomplete -Version: 2.1.0 +Version: 2.1.1 Requires at least: 5.6 Tested up to: 6.3.1 Requires PHP: 7.0 From 57441d2a4660c5afa0f82c98615b92fa49a5a3e9 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Thu, 23 Nov 2023 17:39:23 +0100 Subject: [PATCH 43/45] upgrade version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e597eb99..371e171a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doofinder-woocommerce", - "version": "2.1.0", + "version": "2.1.1", "description": "Integrate Doofinder in your WooCommerce site with (almost) no effort.", "main": "index.js", "scripts": { From 1a196644cd9c70e638e1f2018970a8ab7718a836 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Sat, 25 Nov 2023 10:57:47 +0100 Subject: [PATCH 44/45] Fix infinite loop in categories when parent_id is empty --- .../includes/api/endpoints/class-endpoint-product.php | 3 ++- doofinder-for-woocommerce/includes/class-thumbnail.php | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 74ae3521..2cd327df 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -572,6 +572,7 @@ private static function processVariations($product) { foreach ($variations_data as &$variation) { $variation = array_merge($product, $variation, ["parent_id" => $product["id"]]); + $variation["name"] = $product["name"]; } return $variations_data; } @@ -688,7 +689,7 @@ private static function get_category_hierarchy($category_id) { $category_path = $category->name; $parent_id = $category->parent; - while ($parent_id !== 0) { + while (!empty($parent_id)) { $parent_category = get_term($parent_id, 'product_cat'); if (!is_wp_error($parent_category)) { $category_path = $parent_category->name . ' > ' . $category_path; diff --git a/doofinder-for-woocommerce/includes/class-thumbnail.php b/doofinder-for-woocommerce/includes/class-thumbnail.php index dc7a2a9a..7195d809 100755 --- a/doofinder-for-woocommerce/includes/class-thumbnail.php +++ b/doofinder-for-woocommerce/includes/class-thumbnail.php @@ -76,7 +76,7 @@ private function get_image_url_by_size($thumbnail_id){ $thumbnail = image_get_intermediate_size($thumbnail_id, self::$size); //If I find it, I return its URL - if (FALSE != $thumbnail && $thumbnail[0] != "") { + if (FALSE != $thumbnail && !empty($thumbnail[0])) { return $thumbnail[0]; } @@ -85,7 +85,7 @@ private function get_image_url_by_size($thumbnail_id){ //If I find the image I am looking for in the metadata, I return it. $thumb_meta = wp_get_attachment_image_src($thumbnail_id, self::$size); - if(($thumb_meta[0] >= $thumb_size["w"] || $thumb_meta[1] >= $thumb_size["h"]) && $thumb_meta["0"] != ""){ + if(($thumb_meta[0] >= $thumb_size["w"] || $thumb_meta[1] >= $thumb_size["h"]) && !empty($thumb_meta["0"])){ return $thumb_meta["0"]; } @@ -93,7 +93,7 @@ private function get_image_url_by_size($thumbnail_id){ $img_original = $this->get_original_size($thumbnail_id); //Check if is posible generate a thumb or not - if(($thumb_size["w"] >= $img_original["w"] || $thumb_size["h"] >= $img_original["h"]) && $img_original["url"] != ""){ + if(($thumb_size["w"] >= $img_original["w"] || $thumb_size["h"] >= $img_original["h"]) && !empty($img_original["url"])){ return $img_original["url"]; } return false; From 098c18957445cec8edbf5d445d17086e1e04d069 Mon Sep 17 00:00:00 2001 From: "vicfebo@gmail.com" Date: Mon, 27 Nov 2023 15:31:14 +0100 Subject: [PATCH 45/45] empty condition --- .../includes/api/endpoints/class-endpoint-product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php index 2cd327df..18715db9 100644 --- a/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php +++ b/doofinder-for-woocommerce/includes/api/endpoints/class-endpoint-product.php @@ -467,7 +467,7 @@ private static function clean_fields($product){ } $product = array_filter($product, function ($value) { - return $value !== '' && $value !== null; + return !empty($value); }); return $product;