From 9fcab4aed16faece10aa51729751afdcb0575c35 Mon Sep 17 00:00:00 2001 From: Pete Eveleigh Date: Thu, 12 Sep 2024 09:17:49 +0100 Subject: [PATCH] composer update run qa checks --- ecs.php | 8 +- src/FosterCheckout.php | 240 +++++------ src/config.php | 158 ++++---- src/controllers/CheckoutController.php | 44 +- src/formatters/CheckoutAddressFormatter.php | 42 +- src/models/Settings.php | 96 ++--- src/services/Checkout.php | 422 ++++++++++---------- src/translations/en/foster-checkout.php | 194 ++++----- src/variables/Variables.php | 24 +- src/web/assets/checkout/CheckoutAsset.php | 12 +- 10 files changed, 620 insertions(+), 620 deletions(-) diff --git a/ecs.php b/ecs.php index 0685361..94805c1 100644 --- a/ecs.php +++ b/ecs.php @@ -5,7 +5,7 @@ use fostercommerce\ecs\ECSConfig; return ECSConfig::configure() - ->withPaths([ - __DIR__ . '/src', - __FILE__, - ]); + ->withPaths([ + __DIR__ . '/src', + __FILE__, + ]); diff --git a/src/FosterCheckout.php b/src/FosterCheckout.php index c30e91b..e9c560d 100644 --- a/src/FosterCheckout.php +++ b/src/FosterCheckout.php @@ -27,124 +27,124 @@ */ class FosterCheckout extends Plugin { - public string $schemaVersion = '1.0.0'; - - public bool $hasCpSettings = false; - - public function init(): void - { - parent::init(); - - Craft::setAlias('@fostercheckout', __DIR__); - - // Defer most setup tasks until Craft is fully initialized - Craft::$app->onInit(function (): void { - $this->registerComponents(); - $this->attachEventHandlers(); - $this->registerCustomVariables(); - }); - } - - protected function createSettingsModel(): ?Model - { - return Craft::createObject(Settings::class); - } - - protected function settingsHtml(): ?string - { - return Craft::$app->view->renderTemplate('foster-checkout/_plugin/settings.twig', [ - 'plugin' => $this, - 'settings' => $this->getSettings(), - ]); - } - - private function registerComponents(): void - { - $this->setComponents([ - 'checkout' => Checkout::class, - ]); - } - - private function registerCustomVariables(): void - { - // Register the variables - Event::on( - CraftVariable::class, - CraftVariable::EVENT_INIT, - static function (Event $event): void { - $variable = $event->sender; - $variable->set('fostercheckout', Variables::class); - } - ); - } - - private function attachEventHandlers(): void - { - Event::on( - CraftVariable::class, - CraftVariable::EVENT_INIT, - function (Event $e): void { - /** @var CraftVariable $variable */ - $variable = $e->sender; - - // Attach a service: - $variable->set('checkout', Checkout::class); - } - ); - - /* Register our plugins templates directory so Craft knows to look there */ - Event::on( - View::class, - View::EVENT_REGISTER_SITE_TEMPLATE_ROOTS, - function (RegisterTemplateRootsEvent $event): void { - $event->roots['foster-checkout'] = __DIR__ . '/templates'; - } - ); - - /* Register our site URL rules based on the plugins 'paths' setting */ - Event::on( - UrlManager::class, - UrlManager::EVENT_REGISTER_SITE_URL_RULES, - function (RegisterUrlRulesEvent $event): void { - // Get the paths from the settings - $paths = $this->checkout->paths(); - $checkoutPath = $paths['checkout'] ?? 'checkout'; - $cartPath = $paths['cart'] ?? 'cart'; - - // Define the site URL rules to route to our plugins templates - $event->rules[$checkoutPath] = [ - 'template' => 'foster-checkout/checkout/index', - ]; - $event->rules[$checkoutPath . '/email'] = [ - 'template' => 'foster-checkout/checkout/email', - ]; - $event->rules[$checkoutPath . '/address'] = [ - 'template' => 'foster-checkout/checkout/address', - ]; - $event->rules[$checkoutPath . '/shipping'] = [ - 'template' => 'foster-checkout/checkout/shipping', - ]; - $event->rules[$checkoutPath . '/payment'] = [ - 'template' => 'foster-checkout/checkout/payment', - ]; - $event->rules[$checkoutPath . '/order'] = [ - 'template' => 'foster-checkout/checkout/order', - ]; - $event->rules[$checkoutPath . '/login'] = [ - 'template' => 'foster-checkout/account/login', - ]; - $event->rules[$checkoutPath . '/register'] = [ - 'template' => 'foster-checkout/account/register', - ]; - $event->rules[$cartPath] = [ - 'template' => 'foster-checkout/cart/index', - ]; - - // TODO : Just a page to test components in isolation (remove later) - $event->rules[$checkoutPath . '/components'] = [ - 'template' => 'foster-checkout/_component-test', - ]; - } - ); - } + public string $schemaVersion = '1.0.0'; + + public bool $hasCpSettings = false; + + public function init(): void + { + parent::init(); + + Craft::setAlias('@fostercheckout', __DIR__); + + // Defer most setup tasks until Craft is fully initialized + Craft::$app->onInit(function (): void { + $this->registerComponents(); + $this->attachEventHandlers(); + $this->registerCustomVariables(); + }); + } + + protected function createSettingsModel(): ?Model + { + return Craft::createObject(Settings::class); + } + + protected function settingsHtml(): ?string + { + return Craft::$app->view->renderTemplate('foster-checkout/_plugin/settings.twig', [ + 'plugin' => $this, + 'settings' => $this->getSettings(), + ]); + } + + private function registerComponents(): void + { + $this->setComponents([ + 'checkout' => Checkout::class, + ]); + } + + private function registerCustomVariables(): void + { + // Register the variables + Event::on( + CraftVariable::class, + CraftVariable::EVENT_INIT, + static function (Event $event): void { + $variable = $event->sender; + $variable->set('fostercheckout', Variables::class); + } + ); + } + + private function attachEventHandlers(): void + { + Event::on( + CraftVariable::class, + CraftVariable::EVENT_INIT, + function (Event $e): void { + /** @var CraftVariable $variable */ + $variable = $e->sender; + + // Attach a service: + $variable->set('checkout', Checkout::class); + } + ); + + /* Register our plugins templates directory so Craft knows to look there */ + Event::on( + View::class, + View::EVENT_REGISTER_SITE_TEMPLATE_ROOTS, + function (RegisterTemplateRootsEvent $event): void { + $event->roots['foster-checkout'] = __DIR__ . '/templates'; + } + ); + + /* Register our site URL rules based on the plugins 'paths' setting */ + Event::on( + UrlManager::class, + UrlManager::EVENT_REGISTER_SITE_URL_RULES, + function (RegisterUrlRulesEvent $event): void { + // Get the paths from the settings + $paths = $this->checkout->paths(); + $checkoutPath = $paths['checkout'] ?? 'checkout'; + $cartPath = $paths['cart'] ?? 'cart'; + + // Define the site URL rules to route to our plugins templates + $event->rules[$checkoutPath] = [ + 'template' => 'foster-checkout/checkout/index', + ]; + $event->rules[$checkoutPath . '/email'] = [ + 'template' => 'foster-checkout/checkout/email', + ]; + $event->rules[$checkoutPath . '/address'] = [ + 'template' => 'foster-checkout/checkout/address', + ]; + $event->rules[$checkoutPath . '/shipping'] = [ + 'template' => 'foster-checkout/checkout/shipping', + ]; + $event->rules[$checkoutPath . '/payment'] = [ + 'template' => 'foster-checkout/checkout/payment', + ]; + $event->rules[$checkoutPath . '/order'] = [ + 'template' => 'foster-checkout/checkout/order', + ]; + $event->rules[$checkoutPath . '/login'] = [ + 'template' => 'foster-checkout/account/login', + ]; + $event->rules[$checkoutPath . '/register'] = [ + 'template' => 'foster-checkout/account/register', + ]; + $event->rules[$cartPath] = [ + 'template' => 'foster-checkout/cart/index', + ]; + + // TODO : Just a page to test components in isolation (remove later) + $event->rules[$checkoutPath . '/components'] = [ + 'template' => 'foster-checkout/_component-test', + ]; + } + ); + } } diff --git a/src/config.php b/src/config.php index d1e697e..159a4a6 100644 --- a/src/config.php +++ b/src/config.php @@ -23,96 +23,96 @@ */ return [ - // Plugin options - 'options' => [ + // Plugin options + 'options' => [ // Whether or not to show the "save for later" button - 'enableSaveForLater' => true, // true|false + 'enableSaveForLater' => true, // true|false // Whether or not to show the shipping estimator - 'enableEstimatedShipping' => true, // true|false + 'enableEstimatedShipping' => true, // true|false // Whether or not to show the free shipping message - 'enableFreeShippingMessage' => true, // true|false - ], + 'enableFreeShippingMessage' => true, // true|false + ], - // Branding Settings - 'branding' => [ - // The brand primary custom color in HEX color - 'color' => '#333333', + // Branding Settings + 'branding' => [ + // The brand primary custom color in HEX color + 'color' => '#333333', - // The Google web font (https://fonts.google.com/) family name you want to use - // (ex. 'Roboto Slab') - 'font' => 'Roboto Slab', + // The Google web font (https://fonts.google.com/) family name you want to use + // (ex. 'Roboto Slab') + 'font' => 'Roboto Slab', - // The relative path from the web root of the logo file - // (ex. '/assets/images/logo.svg') - 'logo' => '', - ], + // The relative path from the web root of the logo file + // (ex. '/assets/images/logo.svg') + 'logo' => '', + ], - // Path Settings - 'paths' => [ - // The site relative path to where the cart should be accessible - // (ex. 'cart') - 'cart' => '', + // Path Settings + 'paths' => [ + // The site relative path to where the cart should be accessible + // (ex. 'cart') + 'cart' => '', - // The site relative path to where the checkout should be accessible - // (ex. 'checkout') - 'checkout' => '', + // The site relative path to where the checkout should be accessible + // (ex. 'checkout') + 'checkout' => '', - // The path the user should be taken to if they cancel the checkout process - // (ex. '/') - 'cancel' => '', - ], + // The path the user should be taken to if they cancel the checkout process + // (ex. '/') + 'cancel' => '', + ], - // Product Settings - 'products' => [ - /* - // Add for each product type using the product type handle, to define the field handles used for the - // product and/or variant preview image to display in the cart view - 'shirts' => [ - 'image' => [ - 'product' => 'productPreviewImage', - 'variant' => 'variantPreviewImage', - ], - ], - */ - ], + // Product Settings + 'products' => [ + /* + // Add for each product type using the product type handle, to define the field handles used for the + // product and/or variant preview image to display in the cart view + 'shirts' => [ + 'image' => [ + 'product' => 'productPreviewImage', + 'variant' => 'variantPreviewImage', + ], + ], + */ + ], - // Notes that will appear in the cart, login, and checkout steps. Include the element handle (global or single) - // and the field handle in that entry that contains the content you want to display. Fields can be either plain - // text of rich text fields like Redactor - 'notes' => [ - 'cart' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'emptyCart' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'login' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'email' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'address' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'shipping' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'payment' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'order' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - ], + // Notes that will appear in the cart, login, and checkout steps. Include the element handle (global or single) + // and the field handle in that entry that contains the content you want to display. Fields can be either plain + // text of rich text fields like Redactor + 'notes' => [ + 'cart' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'emptyCart' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'login' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'email' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'address' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'shipping' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'payment' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'order' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + ], ]; diff --git a/src/controllers/CheckoutController.php b/src/controllers/CheckoutController.php index 3768cd4..843b420 100644 --- a/src/controllers/CheckoutController.php +++ b/src/controllers/CheckoutController.php @@ -11,29 +11,29 @@ */ class CheckoutController extends Controller { - protected array|int|bool $allowAnonymous = ['get-critical-data', 'get-payment-form', 'get-discounts']; + protected array|int|bool $allowAnonymous = ['get-critical-data', 'get-payment-form', 'get-discounts']; - public function actionGetCriticalData(): Response - { - return $this->asJson([ - 'countries' => FosterCheckout::getInstance()->checkout->getCountries(), - 'regions' => FosterCheckout::getInstance()->checkout->getRegions(), - 'paths' => FosterCheckout::getInstance()->getSettings()->paths, - 'gateways' => FosterCheckout::getInstance()->checkout->getGateways(), - ]); - } + public function actionGetCriticalData(): Response + { + return $this->asJson([ + 'countries' => FosterCheckout::getInstance()->checkout->getCountries(), + 'regions' => FosterCheckout::getInstance()->checkout->getRegions(), + 'paths' => FosterCheckout::getInstance()->getSettings()->paths, + 'gateways' => FosterCheckout::getInstance()->checkout->getGateways(), + ]); + } - public function actionGetPaymentForm(): Response - { - return $this->asJson([ - 'paymentForm' => FosterCheckout::getInstance()->checkout->getPaymentForm(), - ]); - } + public function actionGetPaymentForm(): Response + { + return $this->asJson([ + 'paymentForm' => FosterCheckout::getInstance()->checkout->getPaymentForm(), + ]); + } - public function actionGetDiscounts(): Response - { - return $this->asJson([ - 'discounts' => FosterCheckout::getInstance()->checkout->getDiscounts(), - ]); - } + public function actionGetDiscounts(): Response + { + return $this->asJson([ + 'discounts' => FosterCheckout::getInstance()->checkout->getDiscounts(), + ]); + } } diff --git a/src/formatters/CheckoutAddressFormatter.php b/src/formatters/CheckoutAddressFormatter.php index 26fa1b5..eaed5b8 100644 --- a/src/formatters/CheckoutAddressFormatter.php +++ b/src/formatters/CheckoutAddressFormatter.php @@ -8,29 +8,29 @@ class CheckoutAddressFormatter extends \CommerceGuys\Addressing\Formatter\DefaultFormatter { - public function format(AddressInterface $address, array $options = []): string - { - /** @var Address $address */ - if (property_exists($address, 'firstName')) { - $address->firstName = null; - } + public function format(AddressInterface $address, array $options = []): string + { + /** @var Address $address */ + if (property_exists($address, 'firstName')) { + $address->firstName = null; + } - if (property_exists($address, 'lastName')) { - $address->lastName = null; - } + if (property_exists($address, 'lastName')) { + $address->lastName = null; + } - // if the address is in the US then get the State name, otherwise use the inputted value - //$state = $address->countryCode == 'US' ? Craft::$app->getAddresses()->subdivisionRepository->get($address->administrativeArea, [$address->countryCode])->getName() : $address->administrativeArea; + // if the address is in the US then get the State name, otherwise use the inputted value + //$state = $address->countryCode == 'US' ? Craft::$app->getAddresses()->subdivisionRepository->get($address->administrativeArea, [$address->countryCode])->getName() : $address->administrativeArea; - $addressLines[] = $address->addressLine1; - $addressLines[] = $address->addressLine2; - $addressLines[] = $address->addressLine3; - $addressLines[] = $address->locality; - $addressLines[] = $address->dependentLocality; - $addressLines[] = $address->administrativeArea; - $addressLines[] = $address->postalCode; - $addressLines[] = $address->getCountry()->getName(); + $addressLines[] = $address->addressLine1; + $addressLines[] = $address->addressLine2; + $addressLines[] = $address->addressLine3; + $addressLines[] = $address->locality; + $addressLines[] = $address->dependentLocality; + $addressLines[] = $address->administrativeArea; + $addressLines[] = $address->postalCode; + $addressLines[] = $address->getCountry()->getName(); - return implode(', ', array_filter($addressLines)); - } + return implode(', ', array_filter($addressLines)); + } } diff --git a/src/models/Settings.php b/src/models/Settings.php index b052afd..3f37f8a 100644 --- a/src/models/Settings.php +++ b/src/models/Settings.php @@ -9,56 +9,56 @@ */ class Settings extends Model { - public array $options = [ - 'enableSaveForLater' => true, - ]; + public array $options = [ + 'enableSaveForLater' => true, + ]; - public array $branding = [ - 'color' => '#1F2937', - 'font' => 'Rubik', - 'logo' => '', - ]; + public array $branding = [ + 'color' => '#1F2937', + 'font' => 'Rubik', + 'logo' => '', + ]; - public array $paths = [ - 'cart' => '/cart', - 'checkout' => '/checkout', - 'cancel' => '/', - ]; + public array $paths = [ + 'cart' => '/cart', + 'checkout' => '/checkout', + 'cancel' => '/', + ]; - public array $products = []; + public array $products = []; - public array $notes = [ - 'cart' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'emptyCart' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'login' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'email' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'address' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'shipping' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'payment' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - 'order' => [ - 'elementHandle' => '', - 'fieldHandle' => '', - ], - ]; + public array $notes = [ + 'cart' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'emptyCart' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'login' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'email' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'address' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'shipping' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'payment' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + 'order' => [ + 'elementHandle' => '', + 'fieldHandle' => '', + ], + ]; } diff --git a/src/services/Checkout.php b/src/services/Checkout.php index 5ff8667..efd6542 100644 --- a/src/services/Checkout.php +++ b/src/services/Checkout.php @@ -25,215 +25,215 @@ */ class Checkout extends Component { - /* - * Gets the branding settings array - */ - public function branding(): array - { - $settings = FosterCheckout::getInstance()->getSettings(); - return $settings->branding; - } - - /* - * Gets the paths settings array - */ - public function paths(): array - { - $settings = FosterCheckout::getInstance()->getSettings(); - return $settings->paths; - } - - /** - * Gets the options settings - */ - public function options(): array - { - $settings = FosterCheckout::getInstance()->getSettings(); - return $settings->options; - } - - /** - * Gets the value of a single option from the settings - */ - public function option(string $option): string|bool|null - { - $settings = FosterCheckout::getInstance()->getSettings(); - return $settings->options[$option] ?? null; - } - - /* - * Gets the 'dist' javascript asset bundle from the plugin - * Note: We are getting it this way as running view.registerAssetBundle() in the template does not output the - * script tag with type="module" attribute - */ - public function jsBundle(): string - { - return \Craft::$app->assetManager->getPublishedUrl('@fostercheckout/web/assets/checkout/dist/js/app.js', true); - } - - /* - * Gets the custom note data based on the template page we are on - */ - public function note($page): ?string - { - // Get the data in the settings - $settings = FosterCheckout::getInstance()->getSettings(); - $notesArr = $settings->notes; - $elementHandle = $notesArr[$page]['elementHandle'] ?? null; - $fieldHandle = $notesArr[$page]['fieldHandle'] ?? null; - - $note = null; - - if ($elementHandle && $fieldHandle) { - $global = GlobalSet::find()->handle($elementHandle)->one() ?? null; - $entry = Entry::find()->section($elementHandle)->one() ?? null; - $element = $global ?? $entry; - - // Get the content field data and parse it if necessary (for rich text fields like Redactor) - if ($element) { - try { - $content = $element->getFieldValue($fieldHandle); - if ($content) { - $note = method_exists($content, 'getParsedValue') ? $content->getParsedValue() : $content; - } else { - $note = null; - } - } catch (InvalidFieldException) { - $note = null; - } - } - } - - return $note; - } - - /** - * Gets the line items image field based on the products settings - */ - public function lineItemImageField($productType): ?array - { - $settings = FosterCheckout::getInstance()->getSettings(); - $products = $settings->products; - $fieldData = null; - - if (is_string($productType)) { - if (! empty($products[$productType]['image']['product'])) { - $fieldData = [ - 'handle' => $products[$productType]['image']['product'], - 'level' => 'product', - ]; - } - - if (! empty($products[$productType]['image']['variant'])) { - $fieldData = [ - 'handle' => $products[$productType]['image']['variant'], - 'level' => 'variant', - ]; - } - } - - return $fieldData; - } - - /** - * Gets a line items image asset based on the config settings for the product type - * - * @throws InvalidConfigException - */ - public function lineItemImage(LineItem $lineItem): ?Asset - { - $image = null; - $sku = $lineItem->getSku(); - $variant = Variant::find()->sku($sku)->one(); - /** @var Product $product */ - $product = $variant->getOwner(); - - $fieldInfo = $this->lineItemImageField($product->type->handle); - - if ($fieldInfo !== null) { - try { - if ($fieldInfo['level'] === 'variant') { - $image = $variant->getFieldValue($fieldInfo['handle'])->one(); - } else { - $image = $product->getFieldValue($fieldInfo['handle'])->one(); - } - } catch (InvalidFieldException) { - // Do nothing - } - } - - return $image; - } - - /* - * Gets the available countries from Commerce - */ - public function getCountries(): array - { - try { - return Plugin::getInstance()->getStore()->getStore()->getCountriesList(); - } catch (InvalidConfigException) { - return []; - } - } - - /* - * Gets the available regions (administrative areas) from Commerce - */ - public function getRegions(): array - { - try { - return Plugin::getInstance()->getStore()->getStore()->getAdministrativeAreasListByCountryCode(); - } catch (InvalidConfigException) { - return []; - } - } - - /* - * Gets any discounts that are configured in Commerce - */ - public function getDiscounts(): array - { - try { - return Plugin::getInstance()->getDiscounts()->allDiscounts; - } catch (InvalidConfigException) { - return []; - } - } - - /* - * Gets the available gateways configured in Commerce - */ - public function getGateways(): array - { - try { - $gateways = Plugin::getInstance()->gateways->getAllCustomerEnabledGateways(); - } catch (InvalidConfigException) { - $gateways = []; - } - - $gatewaysArr = []; - foreach ($gateways as $gateway) { - $gatewaysArr[] = [ - 'id' => $gateway->id, - 'handle' => $gateway->handle, - 'name' => $gateway->name, - 'type' => $gateway->paymentType, - ]; - } - - return $gatewaysArr; - } - - /* - * Outputs a gateways payment form HTML - */ - public function getPaymentForm(): string - { - $cart = Plugin::getInstance()->getCarts()->getCart(); - - return $cart->gateway->getPaymentFormHtml([ - 'currency' => $cart->paymentCurrency, - ]); - } + /* + * Gets the branding settings array + */ + public function branding(): array + { + $settings = FosterCheckout::getInstance()->getSettings(); + return $settings->branding; + } + + /* + * Gets the paths settings array + */ + public function paths(): array + { + $settings = FosterCheckout::getInstance()->getSettings(); + return $settings->paths; + } + + /** + * Gets the options settings + */ + public function options(): array + { + $settings = FosterCheckout::getInstance()->getSettings(); + return $settings->options; + } + + /** + * Gets the value of a single option from the settings + */ + public function option(string $option): string|bool|null + { + $settings = FosterCheckout::getInstance()->getSettings(); + return $settings->options[$option] ?? null; + } + + /* + * Gets the 'dist' javascript asset bundle from the plugin + * Note: We are getting it this way as running view.registerAssetBundle() in the template does not output the + * script tag with type="module" attribute + */ + public function jsBundle(): string + { + return \Craft::$app->assetManager->getPublishedUrl('@fostercheckout/web/assets/checkout/dist/js/app.js', true); + } + + /* + * Gets the custom note data based on the template page we are on + */ + public function note($page): ?string + { + // Get the data in the settings + $settings = FosterCheckout::getInstance()->getSettings(); + $notesArr = $settings->notes; + $elementHandle = $notesArr[$page]['elementHandle'] ?? null; + $fieldHandle = $notesArr[$page]['fieldHandle'] ?? null; + + $note = null; + + if ($elementHandle && $fieldHandle) { + $global = GlobalSet::find()->handle($elementHandle)->one() ?? null; + $entry = Entry::find()->section($elementHandle)->one() ?? null; + $element = $global ?? $entry; + + // Get the content field data and parse it if necessary (for rich text fields like Redactor) + if ($element) { + try { + $content = $element->getFieldValue($fieldHandle); + if ($content) { + $note = method_exists($content, 'getParsedValue') ? $content->getParsedValue() : $content; + } else { + $note = null; + } + } catch (InvalidFieldException) { + $note = null; + } + } + } + + return $note; + } + + /** + * Gets the line items image field based on the products settings + */ + public function lineItemImageField($productType): ?array + { + $settings = FosterCheckout::getInstance()->getSettings(); + $products = $settings->products; + $fieldData = null; + + if (is_string($productType)) { + if (! empty($products[$productType]['image']['product'])) { + $fieldData = [ + 'handle' => $products[$productType]['image']['product'], + 'level' => 'product', + ]; + } + + if (! empty($products[$productType]['image']['variant'])) { + $fieldData = [ + 'handle' => $products[$productType]['image']['variant'], + 'level' => 'variant', + ]; + } + } + + return $fieldData; + } + + /** + * Gets a line items image asset based on the config settings for the product type + * + * @throws InvalidConfigException + */ + public function lineItemImage(LineItem $lineItem): ?Asset + { + $image = null; + $sku = $lineItem->getSku(); + $variant = Variant::find()->sku($sku)->one(); + /** @var Product $product */ + $product = $variant->getOwner(); + + $fieldInfo = $this->lineItemImageField($product->type->handle); + + if ($fieldInfo !== null) { + try { + if ($fieldInfo['level'] === 'variant') { + $image = $variant->getFieldValue($fieldInfo['handle'])->one(); + } else { + $image = $product->getFieldValue($fieldInfo['handle'])->one(); + } + } catch (InvalidFieldException) { + // Do nothing + } + } + + return $image; + } + + /* + * Gets the available countries from Commerce + */ + public function getCountries(): array + { + try { + return Plugin::getInstance()->getStore()->getStore()->getCountriesList(); + } catch (InvalidConfigException) { + return []; + } + } + + /* + * Gets the available regions (administrative areas) from Commerce + */ + public function getRegions(): array + { + try { + return Plugin::getInstance()->getStore()->getStore()->getAdministrativeAreasListByCountryCode(); + } catch (InvalidConfigException) { + return []; + } + } + + /* + * Gets any discounts that are configured in Commerce + */ + public function getDiscounts(): array + { + try { + return Plugin::getInstance()->getDiscounts()->allDiscounts; + } catch (InvalidConfigException) { + return []; + } + } + + /* + * Gets the available gateways configured in Commerce + */ + public function getGateways(): array + { + try { + $gateways = Plugin::getInstance()->gateways->getAllCustomerEnabledGateways(); + } catch (InvalidConfigException) { + $gateways = []; + } + + $gatewaysArr = []; + foreach ($gateways as $gateway) { + $gatewaysArr[] = [ + 'id' => $gateway->id, + 'handle' => $gateway->handle, + 'name' => $gateway->name, + 'type' => $gateway->paymentType, + ]; + } + + return $gatewaysArr; + } + + /* + * Outputs a gateways payment form HTML + */ + public function getPaymentForm(): string + { + $cart = Plugin::getInstance()->getCarts()->getCart(); + + return $cart->gateway->getPaymentFormHtml([ + 'currency' => $cart->paymentCurrency, + ]); + } } diff --git a/src/translations/en/foster-checkout.php b/src/translations/en/foster-checkout.php index b58cdb3..b2fcc4b 100644 --- a/src/translations/en/foster-checkout.php +++ b/src/translations/en/foster-checkout.php @@ -1,101 +1,101 @@ 'Cart', - 'Checkout' => 'Checkout', - 'Email' => 'Email', - 'Address' => 'Address', - 'Shipping' => 'Shipping', - 'Payment' => 'Payment', - 'Order' => 'Order', - 'Continue Shopping' => 'Continue Shopping', - 'Next Step' => 'Next Step', - 'Image of' => 'image of', - 'SKU' => 'SKU', - 'Qty' => 'Qty', - 'Quantity' => 'Quantity', - 'Remove' => 'Remove', - 'Remove from cart' => 'Remove from cart', - 'Increment quantity' => 'Increment quantity', - 'Only {qty} in stock' => 'Only {qty} in stock', - 'Decrement quantity' => 'Decrement quantity', - 'Item updated' => 'Item updated', - 'Item removed' => 'Item removed', - 'You may only purchase {qty} of this item' => 'You may only purchase {qty} of this item', - 'You must purchase at least {qty} of this item' => 'You must purchase at least {qty} of this item', - 'Save for later' => 'Save for later', - 'Clear this field' => 'Clear this field', - 'Coupon Code' => 'Coupon Code', - 'Coupon added' => 'Coupon added', - 'Submit a coupon code to get a discount on your order.' => 'Submit a coupon code to get a discount on your order.', - 'Enter your Coupon Code' => 'Enter your Coupon Code', - 'Submit' => 'Submit', - 'Estimated shipping to' => 'Estimated shipping to', - 'Get estimated shipping' => 'Get estimated shipping', - 'Postal Code' => 'Postal Code', - 'Delivery Postal Code' => 'Delivery Postal Code', - 'Update' => 'Update', - 'Close' => 'Close', - 'Your postal code helps us provide the most accurate delivery information.' => 'Your postal code helps us provide the most accurate delivery information.', - 'Order Summary' => 'Order Summary', - 'Subtotal' => 'Subtotal', - 'Discount' => 'Discount', - 'Subtotal After Discount' => 'Subtotal After Discount', - 'Add' => 'Add', - 'for FREE shipping, or choose FREE Ship to Store.' => 'for FREE shipping, or choose FREE Ship to Store.', - 'Estimated Tax' => 'Estimated Tax', - 'Estimated Total' => 'Estimated Total', - 'Select' => 'Select', - 'Optional' => 'Optional', - 'Country' => 'Country', - 'Full name' => 'Full name', - 'Enter your name' => 'Enter your name', - 'Street address' => 'Street address', - 'Apt. number, suite' => 'Apt. number, suite', - 'City' => 'City', - 'Your city' => 'Your city', - 'State / Province' => 'State / Province', - 'Your state or province' => 'Your state or province', - 'postalCodeFormat' => '00000', - 'Sign In' => 'Sign In', - 'Enter your username' => 'Enter your username', - 'Enter your email' => 'Enter your email', - 'Username' => 'Username', - 'Password' => 'Password', - 'Hide password' => 'Hide password', - 'Show password' => 'Show password', - 'Back to checkout' => 'Back to checkout', - 'Sign Up' => ' Sign Up', - 'Confirm Password' => 'Confirm Password', - 'Please address the errors noted above.' => 'Please address the errors noted above.', - 'I already have an account' => 'I already have an account', - 'There are {qty} items in your cart' => 'There are {qty} items in your cart', - 'Clear the cart' => 'Clear the cart', - 'Your cart is currently empty' => 'Your cart is currently empty', - 'to see items you might have added previously.' => 'to see items you might have added previously.', - 'Where should we send your receipt?' => 'Where should we send your receipt?', - 'Already have an account?' => 'Already have an account?', - 'User' => 'User', - 'Edit' => 'Edit', - 'Cancel' => 'Cancel', - 'Save' => 'Save', - 'Save to address book' => 'Save to your address book', - 'Ship to' => 'Ship to', - 'Method' => 'Method', - 'Item(s)' => 'Item(s)', - 'Billing address' => 'Billing address', - 'Use a different shipping address' => 'Use a different shipping address', - 'Use a different billing address' => 'Use a different billing address', - '1. Shipping address' => '1. Shipping address', - '2. Shipping method' => '2. Shipping method', - '3. Payment' => '3. Payment', - 'Place Order' => 'Place Order', - 'Thank you for your order!' => 'Thank you for your order!', - 'Your Order Number is' => 'Your Order Number is', - 'You will receive an order confirmation email shortly.' => 'You will receive an order confirmation email shortly.', - 'Order Details' => 'Order Details', - 'Date' => 'Date', - 'dateFormat' => 'n/j/y', - 'Same as shipping address' => 'Same as shipping address', - 'Use an address from your address book' => 'Use an address from your address book', + 'Cart' => 'Cart', + 'Checkout' => 'Checkout', + 'Email' => 'Email', + 'Address' => 'Address', + 'Shipping' => 'Shipping', + 'Payment' => 'Payment', + 'Order' => 'Order', + 'Continue Shopping' => 'Continue Shopping', + 'Next Step' => 'Next Step', + 'Image of' => 'image of', + 'SKU' => 'SKU', + 'Qty' => 'Qty', + 'Quantity' => 'Quantity', + 'Remove' => 'Remove', + 'Remove from cart' => 'Remove from cart', + 'Increment quantity' => 'Increment quantity', + 'Only {qty} in stock' => 'Only {qty} in stock', + 'Decrement quantity' => 'Decrement quantity', + 'Item updated' => 'Item updated', + 'Item removed' => 'Item removed', + 'You may only purchase {qty} of this item' => 'You may only purchase {qty} of this item', + 'You must purchase at least {qty} of this item' => 'You must purchase at least {qty} of this item', + 'Save for later' => 'Save for later', + 'Clear this field' => 'Clear this field', + 'Coupon Code' => 'Coupon Code', + 'Coupon added' => 'Coupon added', + 'Submit a coupon code to get a discount on your order.' => 'Submit a coupon code to get a discount on your order.', + 'Enter your Coupon Code' => 'Enter your Coupon Code', + 'Submit' => 'Submit', + 'Estimated shipping to' => 'Estimated shipping to', + 'Get estimated shipping' => 'Get estimated shipping', + 'Postal Code' => 'Postal Code', + 'Delivery Postal Code' => 'Delivery Postal Code', + 'Update' => 'Update', + 'Close' => 'Close', + 'Your postal code helps us provide the most accurate delivery information.' => 'Your postal code helps us provide the most accurate delivery information.', + 'Order Summary' => 'Order Summary', + 'Subtotal' => 'Subtotal', + 'Discount' => 'Discount', + 'Subtotal After Discount' => 'Subtotal After Discount', + 'Add' => 'Add', + 'for FREE shipping, or choose FREE Ship to Store.' => 'for FREE shipping, or choose FREE Ship to Store.', + 'Estimated Tax' => 'Estimated Tax', + 'Estimated Total' => 'Estimated Total', + 'Select' => 'Select', + 'Optional' => 'Optional', + 'Country' => 'Country', + 'Full name' => 'Full name', + 'Enter your name' => 'Enter your name', + 'Street address' => 'Street address', + 'Apt. number, suite' => 'Apt. number, suite', + 'City' => 'City', + 'Your city' => 'Your city', + 'State / Province' => 'State / Province', + 'Your state or province' => 'Your state or province', + 'postalCodeFormat' => '00000', + 'Sign In' => 'Sign In', + 'Enter your username' => 'Enter your username', + 'Enter your email' => 'Enter your email', + 'Username' => 'Username', + 'Password' => 'Password', + 'Hide password' => 'Hide password', + 'Show password' => 'Show password', + 'Back to checkout' => 'Back to checkout', + 'Sign Up' => ' Sign Up', + 'Confirm Password' => 'Confirm Password', + 'Please address the errors noted above.' => 'Please address the errors noted above.', + 'I already have an account' => 'I already have an account', + 'There are {qty} items in your cart' => 'There are {qty} items in your cart', + 'Clear the cart' => 'Clear the cart', + 'Your cart is currently empty' => 'Your cart is currently empty', + 'to see items you might have added previously.' => 'to see items you might have added previously.', + 'Where should we send your receipt?' => 'Where should we send your receipt?', + 'Already have an account?' => 'Already have an account?', + 'User' => 'User', + 'Edit' => 'Edit', + 'Cancel' => 'Cancel', + 'Save' => 'Save', + 'Save to address book' => 'Save to your address book', + 'Ship to' => 'Ship to', + 'Method' => 'Method', + 'Item(s)' => 'Item(s)', + 'Billing address' => 'Billing address', + 'Use a different shipping address' => 'Use a different shipping address', + 'Use a different billing address' => 'Use a different billing address', + '1. Shipping address' => '1. Shipping address', + '2. Shipping method' => '2. Shipping method', + '3. Payment' => '3. Payment', + 'Place Order' => 'Place Order', + 'Thank you for your order!' => 'Thank you for your order!', + 'Your Order Number is' => 'Your Order Number is', + 'You will receive an order confirmation email shortly.' => 'You will receive an order confirmation email shortly.', + 'Order Details' => 'Order Details', + 'Date' => 'Date', + 'dateFormat' => 'n/j/y', + 'Same as shipping address' => 'Same as shipping address', + 'Use an address from your address book' => 'Use an address from your address book', ]; diff --git a/src/variables/Variables.php b/src/variables/Variables.php index 8572a0a..f5534c2 100644 --- a/src/variables/Variables.php +++ b/src/variables/Variables.php @@ -7,17 +7,17 @@ class Variables { - /** - * getPath - */ - public function getPath(string $path): ?string - { - $paths = FosterCheckout::getInstance()->checkout->paths(); - return array_key_exists($path, $paths) ? Craft::$app->getSites()->getCurrentSite()->getBaseUrl() . $paths[$path] : null; - } + /** + * getPath + */ + public function getPath(string $path): ?string + { + $paths = FosterCheckout::getInstance()->checkout->paths(); + return array_key_exists($path, $paths) ? Craft::$app->getSites()->getCurrentSite()->getBaseUrl() . $paths[$path] : null; + } - public function getOption(string $option): string|bool|null - { - return FosterCheckout::getInstance()->checkout->option($option); - } + public function getOption(string $option): string|bool|null + { + return FosterCheckout::getInstance()->checkout->option($option); + } } diff --git a/src/web/assets/checkout/CheckoutAsset.php b/src/web/assets/checkout/CheckoutAsset.php index 69f0299..603412b 100644 --- a/src/web/assets/checkout/CheckoutAsset.php +++ b/src/web/assets/checkout/CheckoutAsset.php @@ -9,10 +9,10 @@ */ class CheckoutAsset extends AssetBundle { - public function init(): void - { - $this->sourcePath = __DIR__ . '/dist'; - $this->js = ['js/app.js']; - parent::init(); - } + public function init(): void + { + $this->sourcePath = __DIR__ . '/dist'; + $this->js = ['js/app.js']; + parent::init(); + } }