Product system performance optimization
This commit is contained in:
parent
2790a6e1ff
commit
a5a1111484
|
|
@ -206,6 +206,23 @@ class AttributeRepository extends Repository
|
|||
return $attributes[$code] = $this->findOneByField('code', $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get attribute by id.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Webkul\Attribute\Contracts\Attribute
|
||||
*/
|
||||
public function getAttributeById($id)
|
||||
{
|
||||
static $attributes = [];
|
||||
|
||||
if (array_key_exists($id, $attributes)) {
|
||||
return $attributes[$id];
|
||||
}
|
||||
|
||||
return $attributes[$id] = $this->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get family attributes.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -367,6 +367,8 @@ class CartRule
|
|||
|
||||
$cart->save();
|
||||
|
||||
Cart::setCart($cart);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -430,6 +432,8 @@ class CartRule
|
|||
$cart->applied_cart_rule_ids = join(',', $cartAppliedCartRuleIds);
|
||||
|
||||
$cart->save();
|
||||
|
||||
Cart::setCart($cart);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ class Cart
|
|||
{
|
||||
}
|
||||
|
||||
protected $cart;
|
||||
/**
|
||||
* Returns cart.
|
||||
*
|
||||
|
|
@ -56,20 +57,31 @@ class Cart
|
|||
*/
|
||||
public function getCart(): ?\Webkul\Checkout\Contracts\Cart
|
||||
{
|
||||
$cart = null;
|
||||
if ($this->cart) {
|
||||
return $this->cart;
|
||||
}
|
||||
|
||||
if (auth()->guard()->check()) {
|
||||
$cart = $this->cartRepository->findOneWhere([
|
||||
$this->cart = $this->cartRepository->findOneWhere([
|
||||
'customer_id' => auth()->guard()->user()->id,
|
||||
'is_active' => 1,
|
||||
]);
|
||||
} else if (session()->has('cart')) {
|
||||
$cart = $this->cartRepository->find(session()->get('cart')->id);
|
||||
$this->cart = $this->cartRepository->find(session()->get('cart')->id);
|
||||
}
|
||||
|
||||
$this->removeInactiveItems($cart);
|
||||
$this->removeInactiveItems($this->cart);
|
||||
|
||||
return $cart;
|
||||
return $this->cart;
|
||||
}
|
||||
/**
|
||||
* Returns cart.
|
||||
*
|
||||
* @return \Webkul\Checkout\Contracts\Cart|null
|
||||
*/
|
||||
public function setCart($cart)
|
||||
{
|
||||
$this->cart = $cart;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -158,6 +170,8 @@ class Cart
|
|||
}
|
||||
}
|
||||
|
||||
$this->setCart($cart);
|
||||
|
||||
Event::dispatch('checkout.cart.add.after', $cart);
|
||||
|
||||
$this->collectTotals();
|
||||
|
|
@ -280,6 +294,8 @@ class Cart
|
|||
if (session()->has('cart')) {
|
||||
session()->forget('cart');
|
||||
}
|
||||
|
||||
$this->setCart(null);
|
||||
}
|
||||
|
||||
Shipping::collectRates();
|
||||
|
|
@ -313,7 +329,9 @@ class Cart
|
|||
$this->removeItem($item->id);
|
||||
}
|
||||
|
||||
Event::dispatch('checkout.cart.delete.all.after', $cart);
|
||||
$this->setCart(null);
|
||||
|
||||
Event::dispatch('checkout.cart.delete.all.after', null);
|
||||
|
||||
return $cart;
|
||||
}
|
||||
|
|
@ -341,6 +359,8 @@ class Cart
|
|||
if (session()->has('cart')) {
|
||||
session()->forget('cart');
|
||||
}
|
||||
|
||||
$this->setCart(null);
|
||||
}
|
||||
|
||||
session()->flash('info', __('shop::app.checkout.cart.item.inactive'));
|
||||
|
|
@ -377,6 +397,8 @@ class Cart
|
|||
|
||||
$cart->save();
|
||||
|
||||
$this->setCart($cart);
|
||||
|
||||
$this->collectTotals();
|
||||
|
||||
return true;
|
||||
|
|
@ -401,6 +423,8 @@ class Cart
|
|||
$cart->shipping_method = $shippingMethodCode;
|
||||
$cart->save();
|
||||
|
||||
$this->setCart($cart);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -492,6 +516,8 @@ class Cart
|
|||
|
||||
$cart->save();
|
||||
|
||||
$this->setCart($cart);
|
||||
|
||||
Event::dispatch('checkout.cart.collect.totals.after', $cart);
|
||||
}
|
||||
|
||||
|
|
@ -543,6 +569,8 @@ class Cart
|
|||
$item->save();
|
||||
}
|
||||
|
||||
$this->setCart($cart);
|
||||
|
||||
Event::dispatch('checkout.cart.calculate.items.tax.after', $cart);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,6 @@ class CheckoutServiceProvider extends ServiceProvider
|
|||
return new Cart();
|
||||
});
|
||||
|
||||
$this->app->bind('cart', \Webkul\Checkout\Cart::class);
|
||||
$this->app->singleton('cart', \Webkul\Checkout\Cart::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ trait CartCoupons
|
|||
|
||||
$cart->save();
|
||||
|
||||
$this->setCart($cart);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -41,6 +43,8 @@ trait CartCoupons
|
|||
|
||||
$cart->save();
|
||||
|
||||
$this->setCart($cart);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
@ -68,6 +68,8 @@ trait CartTools
|
|||
|
||||
$this->cartRepository->delete($guestCart->id);
|
||||
|
||||
$this->setCart($cart);
|
||||
|
||||
session()->forget('cart');
|
||||
}
|
||||
}
|
||||
|
|
@ -239,6 +241,8 @@ trait CartTools
|
|||
|
||||
if (! $cart->items->count()) {
|
||||
$this->cartRepository->delete($cart->id);
|
||||
|
||||
$this->setCart(null);
|
||||
}
|
||||
|
||||
$this->collectTotals();
|
||||
|
|
|
|||
|
|
@ -55,12 +55,18 @@ class ConfigurableOption extends AbstractProduct
|
|||
/**
|
||||
* Get allowed attributes.
|
||||
*
|
||||
* @param \Webkul\Product\Contracts\Product|\Webkul\Product\Contracts\ProductFlat $product
|
||||
* @param \W\Webkul\Product\Contracts\ProductFlat $product
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function getAllowAttributes($product)
|
||||
{
|
||||
return $product->product->super_attributes;
|
||||
static $productSuperAttributes = [];
|
||||
|
||||
if (isset($productSuperAttributes[$product->id])) {
|
||||
return $productSuperAttributes[$product->id];
|
||||
}
|
||||
|
||||
return $productSuperAttributes[$product->id] = $product->product->super_attributes()->with(['translation', 'options', 'options.translation'])->get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -151,33 +151,7 @@ class ProductController extends Controller
|
|||
*/
|
||||
public function update(ProductForm $request, $id)
|
||||
{
|
||||
$data = request()->all();
|
||||
|
||||
$multiselectAttributeCodes = [];
|
||||
|
||||
$productAttributes = $this->productRepository->findOrFail($id);
|
||||
|
||||
foreach ($productAttributes->attribute_family->attribute_groups as $attributeGroup) {
|
||||
$customAttributes = $productAttributes->getEditableAttributes($attributeGroup);
|
||||
|
||||
if (count($customAttributes)) {
|
||||
foreach ($customAttributes as $attribute) {
|
||||
if ($attribute->type == 'multiselect' || $attribute->type == 'checkbox') {
|
||||
array_push($multiselectAttributeCodes, $attribute->code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($multiselectAttributeCodes)) {
|
||||
foreach ($multiselectAttributeCodes as $multiselectAttributeCode) {
|
||||
if (! isset($data[$multiselectAttributeCode])) {
|
||||
$data[$multiselectAttributeCode] = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->productRepository->update($data, $id);
|
||||
$this->productRepository->update(request()->all(), $id);
|
||||
|
||||
session()->flash('success', trans('admin::app.response.update-success', ['name' => 'Product']));
|
||||
|
||||
|
|
|
|||
|
|
@ -13,13 +13,6 @@ use Webkul\Product\Models\ProductAttributeValue;
|
|||
|
||||
class ProductFlat
|
||||
{
|
||||
/**
|
||||
* Attribute Object
|
||||
*
|
||||
* @var \Webkul\Attribute\Contracts\Attribute
|
||||
*/
|
||||
protected $attribute;
|
||||
|
||||
/**
|
||||
* Attribute codes that can be fill during flat creation.
|
||||
*
|
||||
|
|
@ -50,6 +43,11 @@ class ProductFlat
|
|||
'checkbox' => 'text',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $flatColumns = [];
|
||||
|
||||
/**
|
||||
* Create a new listener instance.
|
||||
*
|
||||
|
|
@ -66,6 +64,7 @@ class ProductFlat
|
|||
protected ProductAttributeValueRepository $productAttributeValueRepository
|
||||
)
|
||||
{
|
||||
$this->flatColumns = Schema::getColumnListing('product_flat');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -82,10 +81,11 @@ class ProductFlat
|
|||
|
||||
if (! $attribute->use_in_flat) {
|
||||
$this->afterAttributeDeleted($attribute->id);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('product_flat', $attribute->code)) {
|
||||
if (! in_array($attribute->code, $this->flatColumns)) {
|
||||
Schema::table('product_flat', function (Blueprint $table) use($attribute) {
|
||||
$table->{$this->attributeTypeFields[$attribute->type]}($attribute->code)->nullable();
|
||||
|
||||
|
|
@ -105,8 +105,8 @@ class ProductFlat
|
|||
public function afterAttributeDeleted($attributeId)
|
||||
{
|
||||
$attribute = $this->attributeRepository->find($attributeId);
|
||||
|
||||
if (Schema::hasColumn('product_flat', strtolower($attribute->code))) {
|
||||
|
||||
if (in_array(strtolower($attribute->code), $this->flatColumns)) {
|
||||
Schema::table('product_flat', function (Blueprint $table) use($attribute) {
|
||||
$table->dropColumn($attribute->code);
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ class ProductFlat
|
|||
}
|
||||
});
|
||||
|
||||
$this->productFlatRepository->updateAttributeColumn( $attribute , $this );
|
||||
$this->productFlatRepository->updateAttributeColumn( $attribute , $this);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -150,8 +150,8 @@ class ProductFlat
|
|||
|
||||
static $superAttributes = [];
|
||||
|
||||
if (! array_key_exists($product->attribute_family->id, $familyAttributes)) {
|
||||
$familyAttributes[$product->attribute_family->id] = $product->attribute_family->custom_attributes;
|
||||
if (! array_key_exists($product->attribute_family_id, $familyAttributes)) {
|
||||
$familyAttributes[$product->attribute_family_id] = $product->attribute_family->custom_attributes;
|
||||
}
|
||||
|
||||
if ($parentProduct && ! array_key_exists($parentProduct->id, $superAttributes)) {
|
||||
|
|
@ -161,72 +161,69 @@ class ProductFlat
|
|||
if (isset($product['channels'])) {
|
||||
foreach ($product['channels'] as $channel) {
|
||||
$channel = app('Webkul\Core\Repositories\ChannelRepository')->findOrFail($channel);
|
||||
|
||||
$channels[] = $channel['code'];
|
||||
}
|
||||
} elseif (isset($parentProduct['channels'])){
|
||||
} else if (isset($parentProduct['channels'])){
|
||||
foreach ($parentProduct['channels'] as $channel) {
|
||||
$channel = app('Webkul\Core\Repositories\ChannelRepository')->findOrFail($channel);
|
||||
|
||||
$channels[] = $channel['code'];
|
||||
}
|
||||
} else {
|
||||
$channels[] = core()->getDefaultChannelCode();
|
||||
}
|
||||
|
||||
$attributeValues = $product->attribute_values()->get();
|
||||
|
||||
foreach (core()->getAllChannels() as $channel) {
|
||||
if (in_array($channel->code, $channels)) {
|
||||
foreach ($channel->locales as $locale) {
|
||||
$productFlat = $this->productFlatRepository->findOneWhere([
|
||||
$productFlat = $this->productFlatRepository->updateOrCreate([
|
||||
'product_id' => $product->id,
|
||||
'channel' => $channel->code,
|
||||
'locale' => $locale->code,
|
||||
]);
|
||||
|
||||
if (! $productFlat) {
|
||||
$productFlat = $this->productFlatRepository->create([
|
||||
'product_id' => $product->id,
|
||||
'channel' => $channel->code,
|
||||
'locale' => $locale->code,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($familyAttributes[$product->attribute_family->id] as $attribute) {
|
||||
if ($parentProduct && ! in_array($attribute->code, array_merge($superAttributes[$parentProduct->id], $this->fillableAttributeCodes))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($attribute->code, ['tax_category_id'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('product_flat', $attribute->code)) {
|
||||
foreach ($familyAttributes[$product->attribute_family_id] as $attribute) {
|
||||
if (($parentProduct
|
||||
&& ! in_array($attribute->code, array_merge($superAttributes[$parentProduct->id], $this->fillableAttributeCodes)))
|
||||
|| in_array($attribute->code, ['tax_category_id'])
|
||||
|| ! in_array($attribute->code, $this->flatColumns)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($attribute->value_per_channel) {
|
||||
if ($attribute->value_per_locale) {
|
||||
$productAttributeValue = $product->attribute_values()
|
||||
->where('channel', $channel->code)
|
||||
->where('locale', $locale->code)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
$productAttributeValue = $attributeValues
|
||||
->where('channel', $channel->code)
|
||||
->where('locale', $locale->code)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
} else {
|
||||
$productAttributeValue = $product->attribute_values()
|
||||
->where('channel', $channel->code)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
$productAttributeValue = $attributeValues
|
||||
->where('channel', $channel->code)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
}
|
||||
} else {
|
||||
if ($attribute->value_per_locale) {
|
||||
$productAttributeValue = $product->attribute_values()->where('locale', $locale->code)->where('attribute_id', $attribute->id)->first();
|
||||
$productAttributeValue = $attributeValues
|
||||
->where('locale', $locale->code)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
} else {
|
||||
$productAttributeValue = $product->attribute_values()->where('attribute_id', $attribute->id)->first();
|
||||
$productAttributeValue = $attributeValues
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
}
|
||||
}
|
||||
|
||||
$productFlat->{$attribute->code} = $productAttributeValue[ProductAttributeValue::$attributeTypeFields[$attribute->type]] ?? null;
|
||||
|
||||
if ($attribute->type == 'select') {
|
||||
$attributeOption = $this->attributeOptionRepository->find($product->{$attribute->code});
|
||||
$attributeOption = $this->getAttributeOptions($productFlat->{$attribute->code});
|
||||
|
||||
if ($attributeOption) {
|
||||
if ($attributeOptionTranslation = $attributeOption->translate($locale->code)) {
|
||||
|
|
@ -236,10 +233,10 @@ class ProductFlat
|
|||
}
|
||||
}
|
||||
} elseif ($attribute->type == 'multiselect') {
|
||||
$attributeOptionIds = explode(',', $product->{$attribute->code});
|
||||
$attributeOptionIds = explode(',', $productFlat->{$attribute->code});
|
||||
|
||||
if (count($attributeOptionIds)) {
|
||||
$attributeOptions = $this->attributeOptionRepository->findWhereIn('id', $attributeOptionIds);
|
||||
$attributeOptions = $this->getAttributeOptions($productFlat->{$attribute->code});
|
||||
|
||||
$optionLabels = [];
|
||||
|
||||
|
|
@ -256,10 +253,6 @@ class ProductFlat
|
|||
}
|
||||
}
|
||||
|
||||
$productFlat->created_at = $product->created_at;
|
||||
|
||||
$productFlat->updated_at = $product->updated_at;
|
||||
|
||||
$productFlat->min_price = $product->getTypeInstance()->getMinimalPrice();
|
||||
|
||||
$productFlat->max_price = $product->getTypeInstance()->getMaximamPrice();
|
||||
|
|
@ -294,4 +287,29 @@ class ProductFlat
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttributeOptions($value)
|
||||
{
|
||||
if (! $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
static $attributeOptions = [];
|
||||
|
||||
if (array_key_exists($value, $attributeOptions)) {
|
||||
return $attributeOptions[$value];
|
||||
}
|
||||
|
||||
if (is_numeric($value)) {
|
||||
return $attributeOptions[$value] = $this->attributeOptionRepository->find($value);
|
||||
} else {
|
||||
$attributeOptionIds = explode(',', $value);
|
||||
|
||||
return $attributeOptions[$value] = $this->attributeOptionRepository->findWhereIn('id', $attributeOptionIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -441,19 +441,17 @@ class Product extends Model implements ProductContract
|
|||
*/
|
||||
public function getAttribute($key)
|
||||
{
|
||||
|
||||
if (! method_exists(static::class, $key)
|
||||
&& ! in_array($key, [
|
||||
'pivot',
|
||||
'parent_id',
|
||||
'attribute_family_id',
|
||||
])
|
||||
&& ! isset($this->attributes[$key])) {
|
||||
&& ! isset($this->attributes[$key])
|
||||
) {
|
||||
if (isset($this->id)) {
|
||||
$this->attributes[$key] = '';
|
||||
|
||||
$attribute = core()
|
||||
->getSingletonInstance(AttributeRepository::class)
|
||||
->getAttributeByCode($key);
|
||||
$attribute = $this->checkInLoadedFamilyAttributes()->where('code', $key)->first();
|
||||
|
||||
$this->attributes[$key] = $this->getCustomAttributeValue($attribute);
|
||||
|
||||
|
|
@ -500,25 +498,25 @@ class Product extends Model implements ProductContract
|
|||
|
||||
if ($attribute->value_per_channel) {
|
||||
if ($attribute->value_per_locale) {
|
||||
$attributeValue = $this->attribute_values()
|
||||
$attributeValue = $this->attribute_values
|
||||
->where('channel', $channel)
|
||||
->where('locale', $locale)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
} else {
|
||||
$attributeValue = $this->attribute_values()
|
||||
$attributeValue = $this->attribute_values
|
||||
->where('channel', $channel)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
}
|
||||
} else {
|
||||
if ($attribute->value_per_locale) {
|
||||
$attributeValue = $this->attribute_values()
|
||||
$attributeValue = $this->attribute_values
|
||||
->where('locale', $locale)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
} else {
|
||||
$attributeValue = $this->attribute_values()
|
||||
$attributeValue = $this->attribute_values
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class ProductFlat extends Model implements ProductFlatContract
|
|||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $timestamps = false;
|
||||
// public $timestamps = false;
|
||||
|
||||
/**
|
||||
* Get the index name for the model.
|
||||
|
|
@ -137,16 +137,6 @@ class ProductFlat extends Model implements ProductFlatContract
|
|||
return $this->hasMany(static::class, 'parent_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the attributes for the attribute groups.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getImagesAttribute()
|
||||
{
|
||||
return $this->images()->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* The images that belong to the product.
|
||||
*
|
||||
|
|
@ -165,18 +155,7 @@ class ProductFlat extends Model implements ProductFlatContract
|
|||
*/
|
||||
public function videos()
|
||||
{
|
||||
return $this->product->videos()
|
||||
->orderBy('position');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the reviews for the attribute groups.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getReviewsAttribute()
|
||||
{
|
||||
return $this->reviews()->get();
|
||||
return $this->product->videos()->orderBy('position');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -9,21 +9,6 @@ use Webkul\Product\Models\ProductAttributeValueProxy;
|
|||
|
||||
class ProductAttributeValueRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* Create a new reposotory instance.
|
||||
*
|
||||
* @param \Webkul\Attribute\Repositories\AttributeRepository $attributeRepository
|
||||
* @param \Illuminate\Container\Container $app
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
protected AttributeRepository $attributeRepository,
|
||||
App $app
|
||||
)
|
||||
{
|
||||
parent::__construct($app);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify Model class name
|
||||
*
|
||||
|
|
@ -34,27 +19,6 @@ class ProductAttributeValueRepository extends Repository
|
|||
return 'Webkul\Product\Contracts\ProductAttributeValue';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return \Webkul\Product\Contracts\ProductAttributeValue
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
if (isset($data['attribute_id'])) {
|
||||
$attribute = $this->attributeRepository->find($data['attribute_id']);
|
||||
} else {
|
||||
$attribute = $this->attributeRepository->findOneByField('code', $data['attribute_code']);
|
||||
}
|
||||
|
||||
if (! $attribute) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data[ProductAttributeValueProxy::modelClass()::$attributeTypeFields[$attribute->type]] = $data['value'];
|
||||
|
||||
return $this->model->create($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $attributeId
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class ProductRepository extends Repository
|
|||
{
|
||||
Event::dispatch('catalog.product.update.before', $id);
|
||||
|
||||
$product = $this->find($id);
|
||||
$product = $this->findOrFail($id);
|
||||
|
||||
$product = $product->getTypeInstance()->update($data, $id, $attribute);
|
||||
|
||||
|
|
|
|||
|
|
@ -177,6 +177,10 @@ abstract class AbstractType
|
|||
$data[$attribute->code] = isset($data[$attribute->code]) && $data[$attribute->code] ? 1 : 0;
|
||||
}
|
||||
|
||||
if ($attribute->type == 'multiselect' || $attribute->type == 'checkbox') {
|
||||
$data[$attribute->code] = isset($data[$attribute->code]) ? implode(',', $data[$attribute->code]) : null;
|
||||
}
|
||||
|
||||
if (! isset($data[$attribute->code])) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -189,38 +193,50 @@ abstract class AbstractType
|
|||
$data[$attribute->code] = null;
|
||||
}
|
||||
|
||||
if ($attribute->type === 'multiselect' || $attribute->type === 'checkbox') {
|
||||
$data[$attribute->code] = implode(',', $data[$attribute->code]);
|
||||
}
|
||||
|
||||
if ($attribute->type === 'image' || $attribute->type === 'file') {
|
||||
$data[$attribute->code] = gettype($data[$attribute->code]) === 'object'
|
||||
? request()->file($attribute->code)->store('product/' . $product->id)
|
||||
: null;
|
||||
}
|
||||
|
||||
$attributeValue = $this->attributeValueRepository->findOneWhere([
|
||||
'product_id' => $product->id,
|
||||
'attribute_id' => $attribute->id,
|
||||
'channel' => $attribute->value_per_channel ? $data['channel'] : null,
|
||||
'locale' => $attribute->value_per_locale ? $data['locale'] : null,
|
||||
]);
|
||||
if ($attribute->value_per_channel) {
|
||||
if ($attribute->value_per_locale) {
|
||||
$productAttributeValue = $product->attribute_values
|
||||
->where('channel', $attribute->value_per_channel ? $data['channel'] : null)
|
||||
->where('locale', $attribute->value_per_locale ? $data['locale'] : null)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
} else {
|
||||
$productAttributeValue = $product->attribute_values
|
||||
->where('channel', $attribute->value_per_channel ? $data['channel'] : null)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
}
|
||||
} else {
|
||||
if ($attribute->value_per_locale) {
|
||||
$productAttributeValue = $product->attribute_values
|
||||
->where('locale', $attribute->value_per_locale ? $data['locale'] : null)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
} else {
|
||||
$productAttributeValue = $product->attribute_values
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
}
|
||||
}
|
||||
|
||||
if (! $attributeValue) {
|
||||
$columnName = ProductAttributeValue::$attributeTypeFields[$attribute->type];
|
||||
|
||||
if (! $productAttributeValue) {
|
||||
$this->attributeValueRepository->create([
|
||||
'product_id' => $product->id,
|
||||
'attribute_id' => $attribute->id,
|
||||
'value' => $data[$attribute->code],
|
||||
$columnName => $data[$attribute->code],
|
||||
'channel' => $attribute->value_per_channel ? $data['channel'] : null,
|
||||
'locale' => $attribute->value_per_locale ? $data['locale'] : null,
|
||||
]);
|
||||
} else {
|
||||
$this->attributeValueRepository->update(
|
||||
[
|
||||
ProductAttributeValue::$attributeTypeFields[$attribute->type] => $data[$attribute->code],
|
||||
],
|
||||
$attributeValue->id
|
||||
);
|
||||
$productAttributeValue->update([$columnName => $data[$attribute->code]]);
|
||||
|
||||
if ($attribute->type == 'image' || $attribute->type == 'file') {
|
||||
Storage::delete($attributeValue->text_value);
|
||||
|
|
@ -271,6 +287,28 @@ abstract class AbstractType
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttributeByCode($code)
|
||||
{
|
||||
return core()
|
||||
->getSingletonInstance(AttributeRepository::class)
|
||||
->getAttributeByCode($code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttributeById($id)
|
||||
{
|
||||
return core()
|
||||
->getSingletonInstance(AttributeRepository::class)
|
||||
->getAttributeById($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns children ids.
|
||||
*
|
||||
|
|
@ -413,7 +451,7 @@ abstract class AbstractType
|
|||
}
|
||||
}
|
||||
|
||||
$orderedInventory = $this->product->ordered_inventories()
|
||||
$orderedInventory = $this->product->ordered_inventories
|
||||
->where('channel_id', core()->getCurrentChannel()->id)->first();
|
||||
|
||||
if ($orderedInventory) {
|
||||
|
|
@ -535,6 +573,12 @@ abstract class AbstractType
|
|||
*/
|
||||
public function haveSpecialPrice($qty = null)
|
||||
{
|
||||
static $haveSpecialPrice = null;
|
||||
|
||||
if (! is_null($haveSpecialPrice)) {
|
||||
return $haveSpecialPrice;
|
||||
}
|
||||
|
||||
$customerGroupPrice = $this->getCustomerGroupPrice($this->product, $qty);
|
||||
|
||||
$rulePrice = app('Webkul\CatalogRule\Helpers\CatalogRuleProductPrice')->getRulePrice($this->product);
|
||||
|
|
@ -715,7 +759,7 @@ abstract class AbstractType
|
|||
|
||||
if ($taxCategory = $this->getTaxCategory()) {
|
||||
if ($address === null && auth()->guard('customer')->check()) {
|
||||
$address = auth()->guard('customer')->user()->addresses()->where('default_address', 1)->first();
|
||||
$address = auth()->guard('customer')->user()->addresses->where('default_address', 1)->first();
|
||||
}
|
||||
|
||||
if ($address === null) {
|
||||
|
|
@ -959,9 +1003,7 @@ abstract class AbstractType
|
|||
if (auth()->guard()->check()) {
|
||||
$customerGroupId = auth()->guard()->user()->customer_group_id;
|
||||
} else {
|
||||
$customerGroupRepository = app('Webkul\Customer\Repositories\CustomerGroupRepository');
|
||||
|
||||
if ($customerGuestGroup = $customerGroupRepository->findOneByField('code', 'guest')) {
|
||||
if ($customerGuestGroup = app(CustomerGroupRepository::class)->findOneByField('code', 'guest')) {
|
||||
$customerGroupId = $customerGuestGroup->id;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ class Configurable extends AbstractType
|
|||
$super_attributes = [];
|
||||
|
||||
foreach ($data['super_attributes'] as $attributeCode => $attributeOptions) {
|
||||
$attribute = $this->attributeRepository->findOneByField('code', $attributeCode);
|
||||
$attribute = $this->getAttributeByCode($attributeCode);
|
||||
|
||||
$super_attributes[$attribute->id] = $attributeOptions;
|
||||
|
||||
|
|
@ -233,69 +233,92 @@ class Configurable extends AbstractType
|
|||
'sku' => $data['sku'],
|
||||
]);
|
||||
|
||||
$attributeValues = [];
|
||||
|
||||
foreach ($this->fillableTypes as $attributeCode) {
|
||||
if (! isset($data[$attributeCode])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attribute = $this->attributeRepository->findOneByField('code', $attributeCode);
|
||||
$attribute = $this->getAttributeByCode($attributeCode);
|
||||
|
||||
$attributeTypeFields = $this->getAttributeTypeValues($attribute->type, $data[$attributeCode]);
|
||||
|
||||
if ($attribute->value_per_channel) {
|
||||
if ($attribute->value_per_locale) {
|
||||
foreach (core()->getAllChannels() as $channel) {
|
||||
foreach (core()->getAllLocales() as $locale) {
|
||||
$this->attributeValueRepository->create([
|
||||
$attributeValues[] = array_merge($attributeTypeFields, [
|
||||
'product_id' => $variant->id,
|
||||
'attribute_id' => $attribute->id,
|
||||
'channel' => $channel->code,
|
||||
'locale' => $locale->code,
|
||||
'value' => $data[$attributeCode],
|
||||
]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach (core()->getAllChannels() as $channel) {
|
||||
$this->attributeValueRepository->create([
|
||||
$attributeValues[] = array_merge($attributeTypeFields, [
|
||||
'product_id' => $variant->id,
|
||||
'attribute_id' => $attribute->id,
|
||||
'channel' => $channel->code,
|
||||
'value' => $data[$attributeCode],
|
||||
'locale' => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($attribute->value_per_locale) {
|
||||
foreach (core()->getAllLocales() as $locale) {
|
||||
$this->attributeValueRepository->create([
|
||||
$attributeValues[] = array_merge($attributeTypeFields, [
|
||||
'product_id' => $variant->id,
|
||||
'attribute_id' => $attribute->id,
|
||||
'channel' => null,
|
||||
'locale' => $locale->code,
|
||||
'value' => $data[$attributeCode],
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
$this->attributeValueRepository->create([
|
||||
$attributeValues[] = array_merge($attributeTypeFields, [
|
||||
'product_id' => $variant->id,
|
||||
'attribute_id' => $attribute->id,
|
||||
'value' => $data[$attributeCode],
|
||||
'channel' => null,
|
||||
'locale' => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($permutation as $attributeId => $optionId) {
|
||||
$this->attributeValueRepository->create([
|
||||
$attribute = $this->getAttributeById($attributeId);
|
||||
|
||||
$attributeValues[] = array_merge($this->getAttributeTypeValues($attribute->type, $optionId), [
|
||||
'product_id' => $variant->id,
|
||||
'attribute_id' => $attributeId,
|
||||
'value' => $optionId,
|
||||
'channel' => null,
|
||||
'locale' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->attributeValueRepository->insert($attributeValues);
|
||||
|
||||
$this->productInventoryRepository->saveInventories($data, $variant);
|
||||
|
||||
return $variant;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $attributeType
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributeTypeValues($attributeType, $value)
|
||||
{
|
||||
$attributeTypeFields = array_fill_keys(array_values(ProductAttributeValue::$attributeTypeFields), null);
|
||||
|
||||
$attributeTypeFields[ProductAttributeValue::$attributeTypeFields[$attributeType]] = $value;
|
||||
|
||||
return $attributeTypeFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update variant.
|
||||
*
|
||||
|
|
@ -314,27 +337,46 @@ class Configurable extends AbstractType
|
|||
continue;
|
||||
}
|
||||
|
||||
$attribute = $this->attributeRepository->findOneByField('code', $attributeCode);
|
||||
$attribute = $this->getAttributeByCode($attributeCode);
|
||||
|
||||
$attributeValue = $this->attributeValueRepository->findOneWhere([
|
||||
'product_id' => $id,
|
||||
'attribute_id' => $attribute->id,
|
||||
'channel' => $attribute->value_per_channel ? $data['channel'] : null,
|
||||
'locale' => $attribute->value_per_locale ? $data['locale'] : null,
|
||||
]);
|
||||
if ($attribute->value_per_channel) {
|
||||
if ($attribute->value_per_locale) {
|
||||
$productAttributeValue = $variant->attribute_values
|
||||
->where('channel', $attribute->value_per_channel ? $data['channel'] : null)
|
||||
->where('locale', $attribute->value_per_locale ? $data['locale'] : null)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
} else {
|
||||
$productAttributeValue = $variant->attribute_values
|
||||
->where('channel', $attribute->value_per_channel ? $data['channel'] : null)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
}
|
||||
} else {
|
||||
if ($attribute->value_per_locale) {
|
||||
$productAttributeValue = $variant->attribute_values
|
||||
->where('locale', $attribute->value_per_locale ? $data['locale'] : null)
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
} else {
|
||||
$productAttributeValue = $variant->attribute_values
|
||||
->where('attribute_id', $attribute->id)
|
||||
->first();
|
||||
}
|
||||
}
|
||||
|
||||
if (! $attributeValue) {
|
||||
$columnName = ProductAttributeValue::$attributeTypeFields[$attribute->type];
|
||||
|
||||
if (! $productAttributeValue) {
|
||||
$this->attributeValueRepository->create([
|
||||
'product_id' => $id,
|
||||
'product_id' => $variant->id,
|
||||
'attribute_id' => $attribute->id,
|
||||
'value' => $data[$attribute->code],
|
||||
$columnName => $data[$attribute->code],
|
||||
'channel' => $attribute->value_per_channel ? $data['channel'] : null,
|
||||
'locale' => $attribute->value_per_locale ? $data['locale'] : null,
|
||||
]);
|
||||
} else {
|
||||
$this->attributeValueRepository->update([
|
||||
ProductAttributeValue::$attributeTypeFields[$attribute->type] => $data[$attribute->code],
|
||||
], $attributeValue->id);
|
||||
$productAttributeValue->update([$columnName => $data[$attribute->code]]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -457,7 +499,11 @@ class Configurable extends AbstractType
|
|||
*/
|
||||
public function getMinimalPrice($qty = null)
|
||||
{
|
||||
$minPrices = [];
|
||||
static $minPrice = null;
|
||||
|
||||
if (! is_null($minPrice)) {
|
||||
return $minPrice;
|
||||
}
|
||||
|
||||
/* method is calling many time so using variable */
|
||||
$tablePrefix = DB::getTablePrefix();
|
||||
|
|
@ -471,6 +517,9 @@ class Configurable extends AbstractType
|
|||
->where('product_flat.channel', core()->getCurrentChannelCode())
|
||||
->get();
|
||||
|
||||
|
||||
$minPrices = [];
|
||||
|
||||
foreach ($result as $price) {
|
||||
$minPrices[] = $price->min_price;
|
||||
}
|
||||
|
|
@ -479,7 +528,7 @@ class Configurable extends AbstractType
|
|||
return 0;
|
||||
}
|
||||
|
||||
return min($minPrices);
|
||||
return $minPrice = min($minPrices);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -489,6 +538,12 @@ class Configurable extends AbstractType
|
|||
*/
|
||||
public function getOfferPrice()
|
||||
{
|
||||
static $offerPrice = null;
|
||||
|
||||
if (! is_null($offerPrice)) {
|
||||
return $offerPrice;
|
||||
}
|
||||
|
||||
$rulePrices = $customerGroupPrices = [];
|
||||
|
||||
foreach ($this->product->variants as $variant) {
|
||||
|
|
@ -502,10 +557,10 @@ class Configurable extends AbstractType
|
|||
}
|
||||
|
||||
if ($rulePrices || $customerGroupPrices) {
|
||||
return min(array_merge($rulePrices, $customerGroupPrices));
|
||||
return $offerPrice = min(array_merge($rulePrices, $customerGroupPrices));
|
||||
}
|
||||
|
||||
return [];
|
||||
return $offerPrice = [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -515,16 +570,11 @@ class Configurable extends AbstractType
|
|||
*/
|
||||
public function haveOffer()
|
||||
{
|
||||
$haveOffer = false;
|
||||
|
||||
$offerPrice = $this->getOfferPrice();
|
||||
$minPrice = $this->getMinimalPrice();
|
||||
|
||||
if ($offerPrice < $minPrice) {
|
||||
$haveOffer = true;
|
||||
if ($this->getOfferPrice() < $this->getMinimalPrice()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $haveOffer;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -534,6 +584,12 @@ class Configurable extends AbstractType
|
|||
*/
|
||||
public function getMaximamPrice()
|
||||
{
|
||||
static $maxPrice = null;
|
||||
|
||||
if (! is_null($maxPrice)) {
|
||||
return $maxPrice;
|
||||
}
|
||||
|
||||
$productFlat = ProductFlat::join('products', 'product_flat.product_id', '=', 'products.id')
|
||||
->distinct()
|
||||
->where('products.parent_id', $this->product->id)
|
||||
|
|
@ -542,7 +598,7 @@ class Configurable extends AbstractType
|
|||
->where('product_flat.locale', app()->getLocale())
|
||||
->first();
|
||||
|
||||
return $productFlat ? $productFlat->max_price : 0;
|
||||
return $maxPrice = $productFlat ? $productFlat->max_price : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -823,7 +879,7 @@ class Configurable extends AbstractType
|
|||
$total = 0;
|
||||
|
||||
$channelInventorySourceIds = core()->getCurrentChannel()
|
||||
->inventory_sources()
|
||||
->inventory_sources
|
||||
->where('status', 1)
|
||||
->pluck('id');
|
||||
|
||||
|
|
@ -834,7 +890,7 @@ class Configurable extends AbstractType
|
|||
}
|
||||
}
|
||||
|
||||
$orderedInventory = $variant->ordered_inventories()
|
||||
$orderedInventory = $variant->ordered_inventories
|
||||
->where('channel_id', core()->getCurrentChannel()->id)
|
||||
->first();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue