sarga/packages/Webkul/Core/src/Helpers/Laravel5Helper.php

454 lines
14 KiB
PHP
Raw Normal View History

2020-01-17 13:42:47 +00:00
<?php
2020-01-17 13:42:47 +00:00
namespace Webkul\Core\Helpers;
// here you can define custom actions
// all public methods declared in helper class will be available in $I
use StdClass;
use Faker\Factory;
use Codeception\Module\Laravel;
use Webkul\Checkout\Models\Cart;
use Webkul\Product\Models\Product;
use Illuminate\Support\Facades\DB;
use Webkul\Checkout\Models\CartItem;
use Webkul\Customer\Models\Customer;
use Illuminate\Support\Facades\Event;
use Webkul\Attribute\Models\Attribute;
use Webkul\Checkout\Models\CartAddress;
use Webkul\Customer\Models\CustomerAddress;
use Webkul\Product\Models\ProductInventory;
use Webkul\Attribute\Models\AttributeOption;
use Webkul\BookingProduct\Models\BookingProduct;
use Webkul\Product\Models\ProductAttributeValue;
use Webkul\Product\Models\ProductDownloadableLink;
use Webkul\BookingProduct\Models\BookingProductEventTicket;
use Webkul\Product\Models\ProductDownloadableLinkTranslation;
2020-01-17 13:42:47 +00:00
/**
* Class Laravel5Helper
*
* @package Webkul\Core\Helpers
*/
class Laravel5Helper extends Laravel
2020-01-17 13:42:47 +00:00
{
public const SIMPLE_PRODUCT = 1;
public const VIRTUAL_PRODUCT = 2;
public const DOWNLOADABLE_PRODUCT = 3;
public const BOOKING_EVENT_PRODUCT = 4;
2020-01-17 13:42:47 +00:00
/**
* Returns the field name of the given attribute in which a value should be saved inside
* the 'product_attribute_values' table. Depends on the type.
2020-01-17 13:42:47 +00:00
*
* @param string $type
2020-01-17 13:42:47 +00:00
*
* @return string|null
* @part ORM
*/
public static function getAttributeFieldName(string $type): ?string
2020-01-17 13:42:47 +00:00
{
$possibleTypes = [
'text' => 'text_value',
'select' => 'integer_value',
'boolean' => 'boolean_value',
'textarea' => 'text_value',
'price' => 'float_value',
'date' => 'date_value',
'checkbox' => 'text_value',
2020-01-17 13:42:47 +00:00
];
return $possibleTypes[$type];
2020-01-17 13:42:47 +00:00
}
public function prepareCart(array $options = []): array
{
$faker = Factory::create();
$I = $this;
$product = $I->haveProduct(self::SIMPLE_PRODUCT, $options['productOptions'] ?? []);
if (isset($options['customer'])) {
$customer = $options['customer'];
} else {
$customer = $I->have(Customer::class);
}
$I->have(CustomerAddress::class, [
'default_address' => 1,
'customer_id' => $customer->id,
'first_name' => $customer->first_name,
'last_name' => $customer->last_name,
'company_name' => $faker->company,
]);
2020-03-02 08:08:51 +00:00
if (isset($options['payment_method'])
&& $options['payment_method'] === 'free_of_charge') {
2021-10-06 12:26:08 +00:00
$grand_total = '0.0000';
$base_grand_total = '0.0000';
} else {
2021-10-06 12:26:08 +00:00
$grand_total = (string)$faker->numberBetween(1, 666);
$base_grand_total = $grand_total;
}
$cart = $I->have(Cart::class, [
'customer_id' => $customer->id,
'customer_first_name' => $customer->first_name,
'customer_last_name' => $customer->last_name,
'customer_email' => $customer->email,
'is_active' => $options['is_active'] ?? 1,
'channel_id' => $options['channel_id'] ?? 1,
'grand_total' => $grand_total,
'base_grand_total' => $base_grand_total,
]);
$cartAddress = $I->have(CartAddress::class, ['cart_id' => $cart->id]);
2020-03-31 12:35:01 +00:00
$type = $options['product_type'] ?? 'simple';
$totalQtyOrdered = 0;
$cartItems = [];
$generatedCartItems = random_int(3, 10);
for ($i = 2; $i <= $generatedCartItems; $i++) {
$quantity = random_int(1, 10);
$cartItem = $I->have(CartItem::class, [
'type' => $type,
'quantity' => $quantity,
'cart_id' => $cart->id,
'product_id' => $product->id,
]);
$totalQtyOrdered += $quantity;
$cartItems[] = $cartItem;
}
// actually set the cart to the user's session
// when in an functional test:
2021-10-06 12:26:08 +00:00
$stub = new StdClass();
$stub->id = $cart->id;
$I->setSession(['cart' => $stub]);
return [
'cart' => $cart,
'product' => $product,
'customer' => $customer,
'cartAddress' => $cartAddress,
'cartItems' => $cartItems,
'totalQtyOrdered' => $totalQtyOrdered,
];
}
/**
* Set all session with the given key and value in the array.
*
* @param array $keyValue
*/
public function setSession(array $keyValue): void
{
session($keyValue);
}
/**
* Flush the session data and regenerate the ID
* A logged in user will be logged off.
*/
public function invalidateSession(): void
{
session()->invalidate();
}
2020-01-17 13:42:47 +00:00
/**
* Helper function to generate products for testing.
*
* By default, the product will be generated as saleable, this means it has a price,
* weight, is active and has a positive inventory stock, if necessary.
*
* @param int $productType see constants in this class for usage
* @param array $configs
* @param array $productStates
2020-01-17 13:42:47 +00:00
*
* @return \Webkul\Product\Models\Product
* @part ORM
2020-01-17 13:42:47 +00:00
*/
public function haveProduct(int $productType, array $configs = [], array $productStates = []): Product
{
2020-01-17 13:42:47 +00:00
$I = $this;
switch ($productType) {
case self::BOOKING_EVENT_PRODUCT:
$product = $I->haveBookingEventProduct($configs, $productStates);
break;
case self::DOWNLOADABLE_PRODUCT:
$product = $I->haveDownloadableProduct($configs, $productStates);
break;
case self::VIRTUAL_PRODUCT:
$product = $I->haveVirtualProduct($configs, $productStates);
break;
case self::SIMPLE_PRODUCT:
default:
$product = $I->haveSimpleProduct($configs, $productStates);
}
if ($product !== null) {
Event::dispatch('catalog.product.create.after', $product);
}
return $product;
}
private function haveSimpleProduct(array $configs = [], array $productStates = []): Product
{
$I = $this;
if (!in_array('simple', $productStates)) {
$productStates = array_merge($productStates, ['simple']);
}
$product = $I->createProduct($configs['productAttributes'] ?? [], $productStates);
2020-08-27 11:14:31 +00:00
$I->createAttributeValues($product, $configs['attributeValues'] ?? []);
$I->createInventory($product->id, $configs['productInventory'] ?? []);
return $product->refresh();
}
private function haveVirtualProduct(array $configs = [], array $productStates = []): Product
{
$I = $this;
if (!in_array('virtual', $productStates)) {
$productStates = array_merge($productStates, ['virtual']);
}
$product = $I->createProduct($configs['productAttributes'] ?? [], $productStates);
2020-08-27 11:14:31 +00:00
$I->createAttributeValues($product, $configs['attributeValues'] ?? []);
$I->createInventory($product->id, $configs['productInventory'] ?? []);
return $product->refresh();
}
private function haveDownloadableProduct(array $configs = [], array $productStates = []): Product
{
$I = $this;
if (!in_array('downloadable', $productStates)) {
$productStates = array_merge($productStates, ['downloadable']);
}
$product = $I->createProduct($configs['productAttributes'] ?? [], $productStates);
2020-08-27 11:14:31 +00:00
$I->createAttributeValues($product, $configs['attributeValues'] ?? []);
$I->createDownloadableLink($product->id);
return $product->refresh();
}
private function haveBookingEventProduct(array $configs = [], array $productStates = []): Product
{
$I = $this;
2021-10-06 13:52:20 +00:00
if (! in_array('booking', $productStates)) {
$productStates = array_merge($productStates, ['booking']);
}
$product = $I->createProduct($configs['productAttributes'] ?? [], $productStates);
2020-08-27 11:14:31 +00:00
$I->createAttributeValues($product, $configs['attributeValues'] ?? []);
$I->createBookingEventProduct($product->id);
return $product->refresh();
}
private function createProduct(array $attributes = [], array $states = []): Product
{
return Product::factory()
->state(function () use ($states) {
return [
'type' => $states[0],
];
})
->create($attributes);
}
private function createInventory(int $productId, array $inventoryConfig = []): void
{
$I = $this;
$I->have(ProductInventory::class, array_merge($inventoryConfig, [
'product_id' => $productId,
'inventory_source_id' => 1,
]));
}
private function createDownloadableLink(int $productId): void
{
2021-10-06 12:26:08 +00:00
$I = $this;
$link = $I->have(ProductDownloadableLink::class, [
'product_id' => $productId,
]);
$I->have(ProductDownloadableLinkTranslation::class, [
'product_downloadable_link_id' => $link->id,
]);
}
private function createBookingEventProduct(int $productId): void
{
2021-10-06 12:26:08 +00:00
$I = $this;
$bookingProduct = $I->have(BookingProduct::class, [
'product_id' => $productId,
]);
$I->have(BookingProductEventTicket::class, [
'booking_product_id' => $bookingProduct->id,
]);
}
2020-08-27 11:14:31 +00:00
private function createAttributeValues(Product $product, array $attributeValues = []): void
2020-01-17 13:42:47 +00:00
{
$I = $this;
$faker = Factory::create();
$brand = Attribute::query()
->where(['code' => 'brand'])
->firstOrFail(); // usually 25
if (!AttributeOption::query()
->where(['attribute_id' => $brand->id])
->exists()) {
AttributeOption::create([
'admin_name' => 'Webkul Demo Brand (c) 2020',
'attribute_id' => $brand->id,
]);
}
/**
* Some defaults that should apply to all generated products.
* By defaults products will be generated as saleable.
* If you do not want this, this defaults can be overriden by $attributeValues.
*/
$defaultAttributeValues = [
2020-08-27 11:14:31 +00:00
'name' => $faker->words(3, true),
'description' => $faker->sentence,
'short_description' => $faker->sentence,
2020-08-27 11:14:31 +00:00
'sku' => $product->sku,
'url_key' => $faker->slug,
'status' => true,
'guest_checkout' => true,
'visible_individually' => true,
'special_price_from' => null,
'special_price_to' => null,
'special_price' => null,
'price' => $faker->randomFloat(2, 1, 1000),
'weight' => '1.00',
// necessary for shipping
'brand' => AttributeOption::query()
->firstWhere('attribute_id', $brand->id)->id,
2020-01-17 13:42:47 +00:00
];
2020-02-19 12:26:12 +00:00
$attributeValues = array_merge($defaultAttributeValues, $attributeValues);
2020-02-19 12:26:12 +00:00
/** @var array $possibleAttributeValues list of the possible attributes a product can have */
$possibleAttributeValues = DB::table('attributes')
->select('id', 'code', 'type')
->get()
->toArray();
2020-03-31 12:35:01 +00:00
foreach ($possibleAttributeValues as $attributeSet) {
$data = [
2020-08-27 11:14:31 +00:00
'product_id' => $product->id,
2020-03-31 12:35:01 +00:00
'attribute_id' => $attributeSet->id,
];
2020-03-31 12:35:01 +00:00
$fieldName = self::getAttributeFieldName($attributeSet->type);
2020-03-31 12:35:01 +00:00
$data[$fieldName] = $attributeValues[$attributeSet->code] ?? null;
2020-08-27 11:14:31 +00:00
$data = $this->appendAttributeDependencies($attributeSet->code, $data);
$I->have(ProductAttributeValue::class, $data);
2020-01-17 13:42:47 +00:00
}
}
2020-08-27 11:14:31 +00:00
/**
* @param string $attributeCode
* @param array $data
2020-08-27 11:14:31 +00:00
*
* @return array
*/
private function appendAttributeDependencies(string $attributeCode, array $data): array
{
2021-10-06 12:26:08 +00:00
$locale = core()->getCurrentLocale()->code;
2020-08-27 11:14:31 +00:00
$channel = core()->getCurrentChannelCode();
$attributeSetDependencies = [
'name' => [
'locale',
'channel',
],
'tax_category_id' => [
2020-08-27 11:14:31 +00:00
'channel',
],
'short_description' => [
'locale',
'channel',
],
'description' => [
'locale',
'channel',
],
'cost' => [
'channel',
],
'special_price_from' => [
'channel',
],
'special_price_to' => [
'channel',
],
'meta_title' => [
'locale',
'channel',
],
'meta_keywords' => [
'locale',
'channel',
],
'meta_description' => [
'locale',
'channel',
],
'custom_sale_badge' => [
'locale',
],
];
if (array_key_exists($attributeCode, $attributeSetDependencies)) {
foreach ($attributeSetDependencies[$attributeCode] as $key) {
if ($key === 'locale') {
$data['locale'] = $locale;
}
if ($key === 'channel') {
$data['channel'] = $channel;
}
}
}
return $data;
}
}