diff --git a/config/environments/development.php b/config/environments/development.php index cfacfcb8..df784947 100755 --- a/config/environments/development.php +++ b/config/environments/development.php @@ -8,6 +8,7 @@ declare(strict_types=1); use Roots\WPConfig\Config; +use function base64_encode; use function Env\env; Config::define('SAVEQUERIES', true); @@ -25,6 +26,10 @@ Config::define('DISALLOW_FILE_MODS', false); // WooCommerce Config::define('WOOCOMMERCE_API_CONSUMER_KEY', env('WOOCOMMERCE_API_CONSUMER_KEY')); Config::define('WOOCOMMERCE_API_CONSUMER_SECRET', env('WOOCOMMERCE_API_CONSUMER_SECRET')); +Config::define( + 'WOOCOMMERCE_API_AUTH_STRING', + base64_encode(env('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . env('WOOCOMMERCE_API_CONSUMER_SECRET')), +); // Stripe Config::define('STRIPE_API_SECRET', env('STRIPE_API_SECRET')); diff --git a/config/environments/production.php b/config/environments/production.php index 93b792c3..0047176f 100755 --- a/config/environments/production.php +++ b/config/environments/production.php @@ -8,6 +8,7 @@ declare(strict_types=1); use Roots\WPConfig\Config; +use function base64_encode; use function Env\env; Config::define('WP_DEBUG', true); @@ -20,6 +21,10 @@ Config::define('DISALLOW_FILE_MODS', false); Config::define('WOOCOMMERCE_API_CONSUMER_KEY', env('WOOCOMMERCE_API_CONSUMER_KEY')); Config::define('WOOCOMMERCE_API_CONSUMER_SECRET', env('WOOCOMMERCE_API_CONSUMER_SECRET')); +Config::define( + 'WOOCOMMERCE_API_AUTH_STRING', + base64_encode(env('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . env('WOOCOMMERCE_API_CONSUMER_SECRET')), +); // Stripe Config::define('STRIPE_API_SECRET', env('STRIPE_API_SECRET')); diff --git a/config/environments/staging.php b/config/environments/staging.php index 1651c055..0f7ba42b 100755 --- a/config/environments/staging.php +++ b/config/environments/staging.php @@ -8,8 +8,13 @@ declare(strict_types=1); use Roots\WPConfig\Config; +use function base64_encode; use function Env\env; Config::define('DISALLOW_INDEXING', true); Config::define('WOOCOMMERCE_API_CONSUMER_KEY', env('WOOCOMMERCE_API_CONSUMER_KEY')); Config::define('WOOCOMMERCE_API_CONSUMER_SECRET', env('WOOCOMMERCE_API_CONSUMER_SECRET')); +Config::define( + 'WOOCOMMERCE_API_AUTH_STRING', + base64_encode(env('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . env('WOOCOMMERCE_API_CONSUMER_SECRET')), +); diff --git a/web/app/themes/haiku-atelier-2024/archive-product.php b/web/app/themes/haiku-atelier-2024/archive-product.php index 2a97be56..a2b49c0f 100755 --- a/web/app/themes/haiku-atelier-2024/archive-product.php +++ b/web/app/themes/haiku-atelier-2024/archive-product.php @@ -17,7 +17,6 @@ use WC_Product; use function add_action; use function array_map; use function assert; -use function base64_encode; use function is_string; use function wc_get_products; use function wp_create_nonce; @@ -33,12 +32,7 @@ $products = array_map(callback: Product::from_wc_product(...), array: $wc_produc $context['products'] = $products; // Injecte les états initiaux des données du Produit sous forme de JSON dans le contexte. -$page_states = [ - 'nonce' => wp_create_nonce('wc_store_api'), - 'authString' => base64_encode( - Config::get('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . Config::get('WOOCOMMERCE_API_CONSUMER_SECRET'), - ), -] +$page_states = ['authString' => Config::get('WOOCOMMERCE_API_AUTH_STRING'), 'nonce' => wp_create_nonce('wc_store_api')] |> wp_json_encode(...); assert(is_string($page_states)); $context['page_states'] = $page_states; diff --git a/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php b/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php index 479b02e7..adb6c205 100755 --- a/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php @@ -131,7 +131,8 @@ function retire_merdes_wc(): void { */ function genere_balises_img_dans_produit_dans_reponse_rest( WP_REST_Response $response, - mixed $_product, + WC_Data $_product, + WP_REST_Request $_request, ): WP_REST_Response { // Vérifie que la Réponse a des données if (empty($response->data)) { @@ -169,37 +170,34 @@ function genere_balises_img_dans_produit_dans_reponse_rest( return $response; } -add_filter('woocommerce_rest_prepare_product_object', 'genere_balises_img_dans_produit_dans_reponse_rest', 10, 2); - /** * TODO. */ function genere_prix_maximal_produit_variable_dans_reponse_rest( - WP_REST_Response $reponse, - WC_Data $_produit, + WP_REST_Response $response, + WC_Data $_product, + WP_REST_Request $_request, ): WP_REST_Response { // Vérifie que la Réponse a des données - if (empty($reponse->data)) { - return $reponse; + if (empty($response->data)) { + return $response; } // Si le Produit n'est pas Variable, assigner le prix du Produit comme prix maximal - if ('variable' !== $reponse->data['type']) { - $reponse->data['prix_maximal'] = $reponse->data['regular_price']; + if ('variable' !== $response->data['type']) { + $response->data['prix_maximal'] = $response->data['regular_price']; - return $reponse; + return $response; } // Assigne le prix de la Variation la plus chère dans la Réponse - $reponse->data['prix_maximal'] = collect($reponse->data['variations']) + $response->data['prix_maximal'] = collect($response->data['variations']) ->map(wc_get_product(...)) ->map(static fn($p) => $p->get_price())->max(); - return $reponse; + return $response; } -add_filter('woocommerce_rest_prepare_product_object', 'genere_prix_maximal_produit_variable_dans_reponse_rest', 10, 2); - /** * Retire la propagande commerciale de WooCommerce du menu. */ @@ -216,3 +214,8 @@ add_action('init', 'retire_script_galerie'); add_action('template_redirect', 'retire_merdes_wc'); add_action('wp_enqueue_scripts', 'dequeue_woocommerce_styles_scripts'); add_filter('woocommerce_enqueue_styles', '__return_empty_array'); +add_filter('woocommerce_rest_prepare_product_object', 'genere_balises_img_dans_produit_dans_reponse_rest', 10, 3); +add_filter('woocommerce_rest_prepare_product_object', 'genere_prix_maximal_produit_variable_dans_reponse_rest', 10, 3); + +// DEBUG +// add_filter('woocommerce_store_api_disable_nonce_check', '__return_true'); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts b/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts index a928ba02..55764889 100644 --- a/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts @@ -1,4 +1,4 @@ -import { Console, Context, Effect, Layer, Match, pipe, References, Schedule, Schema, SchemaIssue } from "effect"; +import { Console, Context, Effect, Layer, Match, pipe, Schedule, Schema, SchemaIssue } from "effect"; import type { SchemaError } from "effect/Schema"; import type { HttpClientError, @@ -13,6 +13,7 @@ import { HttpClientErrorSchema } from "effect/unstable/http/HttpClientError"; import type { CartProduct, GetProducts } from "../schemas/api.ts"; import { Product } from "../schemas/api.ts"; import { WooCommerceCart } from "../schemas/cart.ts"; +import { AppConfig, Provider } from "./config.ts"; /** Le nombre maximal d'essais pour une Requête. */ const MAX_RETRIES = 3; @@ -81,6 +82,8 @@ class APIClient extends Context.Service()("haikuatelier.fr/APIClient" }), ); + const config = yield* AppConfig.parse(Provider); + const matchAPIError = (error: HttpClientError.HttpClientError | SchemaError): APIError => { if (error._tag === "SchemaError") { return new APIRequestError({ @@ -126,9 +129,6 @@ class APIClient extends Context.Service()("haikuatelier.fr/APIClient" Effect.flatMap(HttpClientResponse.schemaBodyJson(WooCommerceCart)), Effect.mapError(error => matchAPIError(error)), Effect.tapError(error => printErrorAsSuccinctMessage(error)), - // Effect.catchTag("APIResponseError", error => { - // if (error.cause.) - // }), ); return response; @@ -142,8 +142,8 @@ class APIClient extends Context.Service()("haikuatelier.fr/APIClient" HttpClientRequest.setHeader("Nonce", nonce), // TODO: Utiliser l'environnement HttpClientRequest.basicAuth( - "ck_ed966a2265099a6dfe9915db692cbd2450cceed6", - "cs_a046c91647af95188a3e39a736ebe02f2024e430", + config.WOOCOMMERCE_API_CONSUMER_KEY, + config.WOOCOMMERCE_API_CONSUMER_SECRET, ), // Le corps de la Requête a été validée en amont, on peut utiliser Unsafe. HttpClientRequest.setUrlParams(queryParams), diff --git a/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/config.ts b/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/config.ts new file mode 100644 index 00000000..a93efad2 --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/config.ts @@ -0,0 +1,17 @@ +/** + * `Config` décrit la Configuration nécessaire. `ConfigProvider` est le _backend_ qui la charge. Par défault, la Configuration est lue depuis les variables d'environnement, mais d'autres sources peuvent être utilisées. + */ + +import { Config, ConfigProvider } from "effect"; + +const AppConfig = Config.all({ + WOOCOMMERCE_API_CONSUMER_KEY: Config.redacted("WOOCOMMERCE_API_CONSUMER_KEY"), + WOOCOMMERCE_API_CONSUMER_SECRET: Config.redacted("WOOCOMMERCE_API_CONSUMER_SECRET"), +}); + +const Provider = ConfigProvider.fromUnknown({ + WOOCOMMERCE_API_CONSUMER_KEY: "ck_329c944b248aa7cc837c7662d9c6e09d638802df", + WOOCOMMERCE_API_CONSUMER_SECRET: "cs_5687d0c694bd519b231145afa7177c0c987f7155", +}); + +export { AppConfig, Provider }; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts index 5ae434cd..7a70370b 100644 --- a/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts @@ -11,7 +11,7 @@ const ShopPageRuntime = ManagedRuntime.make( Layer.provideMerge(ShopPageMessages.Live), Layer.provideMerge(ShopPageElements.Live), Layer.provide(APIClient.Live), - Layer.tapError(error => Console.error("ProductPageRuntime", "Impossible de créer le Layer :", error)), + Layer.tapError(error => Console.error("ProductPageRuntime", "Impossible de créer le Layer :", error.message)), ), ); export default ShopPageRuntime; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts index 6639ae12..62090246 100644 --- a/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts @@ -1,6 +1,5 @@ import { Array as FxArray, - Console, Context, Effect, Layer, @@ -118,8 +117,6 @@ class ShopPageDOM extends Context.Service()("haikuatelier.fr/Shop/S }; const onMoreProductsWantedHandler = Effect.fn("onMoreProductsWantedHandler")(function*() { - yield* Console.debug("onMoreProductsWantedHandler"); - /** Le numéro de page souhaitée. */ const newPageNumber = yield* Ref.updateAndGet(PageNumber, pageNumber => pageNumber + 1); /** L'ID de la Catégorie de Produits affichée dans la page si elle existe. */ @@ -137,7 +134,6 @@ class ShopPageDOM extends Context.Service()("haikuatelier.fr/Shop/S yield* SubscriptionRef.set(ShowMoreButtonText, "Getting Products..."); const newProducts = yield* API.GetProducts(nonce, requestBody); - yield* Console.debug("onMoreProductsWantedHandler", newProducts); // Rétablis le texte du Bouton et réactive les interactions. yield* SubscriptionRef.set(ShowMoreButtonText, "Show more"); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts index 9d516e2d..00c73df4 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts @@ -9,17 +9,14 @@ import ShopPageElements from "./page-boutique/service-elements.ts"; import ShopPageMessages from "./page-boutique/service-messages.ts"; document.addEventListener("DOMContentLoaded", (): void => { - console.debug("scripts-page-boutique"); // initialisePageBoutique(); ShopPageRuntime.runFork(Effect.gen(function*() { const Elements = yield* ShopPageElements; const DOM = yield* ShopPageDOM; const Messages = yield* ShopPageMessages; - yield* Effect.all([DOM.initLoadMoreProductsOnButtonClick(), Messages.initShowMoreButtonUpdates()], { + yield* Effect.all([DOM.initMoreProductsOnButtonClick(), Messages.initShowMoreButtonUpdates()], { concurrency: "unbounded", }).pipe(Effect.tapCause(Console.error)); - - console.debug(Elements.ProductsGrid); })); });