Merge pull request #4906 from devansh-webkul/variants-issue

Configurable product required filled generated and image repository enhanced #4901
This commit is contained in:
Glenn Hermans 2021-06-01 21:02:40 +02:00 committed by GitHub
commit 49f3be17e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 146 additions and 96 deletions

View File

@ -2,28 +2,26 @@
namespace Webkul\Product\Repositories;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\Http\UploadedFile;
use Webkul\Core\Eloquent\Repository;
use Illuminate\Support\Facades\Storage;
use Illuminate\Container\Container as App;
use Webkul\Product\Repositories\ProductRepository;
class ProductImageRepository extends Repository
{
/**
* ProductRepository object
* Product repository object.
*
* @return Object
* @var Webkul\Product\Repositories\ProductRepository
*/
protected $productRepository;
/**
* Create a new repository instance.
*
* @param \Webkul\Product\Repositories\ProductRepository $productRepository
* @param \Illuminate\Container\Container $app
*
* @param \Webkul\Product\Repositories\ProductRepository $productRepository
* @param \Illuminate\Container\Container $app
* @return void
*/
public function __construct(
@ -36,51 +34,70 @@ class ProductImageRepository extends Repository
}
/**
* Specify Model class name
* Specify model class name.
*
* @return mixed
* @return string
*/
function model()
public function model(): string
{
return 'Webkul\Product\Contracts\ProductImage';
}
/**
* Get product directory.
*
* @param Webkul\Product\Models\Product $variant
*/
public function getProductDirectory($product): string
{
return 'product/' . $product->id;
}
/**
* Upload images.
*
* @param array $data
* @param \Webkul\Product\Contracts\Product $product
* @param \Webkul\Product\Models\Product $product
* @return void
*/
public function uploadImages($data, $product)
public function uploadImages($data, $product): void
{
$previousImageIds = $product->images()->pluck('id');
$this->upload($product, $data['images'] ?? null);
if (isset($data['images'])) {
foreach ($data['images'] as $imageId => $image) {
$file = 'images.' . $imageId;
$dir = 'product/' . $product->id;
if (isset($data['variants'])) {
$this->uploadVariantImages($data['variants']);
}
}
/**
* Upload.
*
* @param Webkul\Product\Models\Product $product
* @param array
* @return void
*/
public function upload($product, $images): void
{
$previousVariantImageIds = $product->images()->pluck('id');
if ($images) {
foreach ($images as $imageId => $image) {
if ($image instanceof UploadedFile) {
if (request()->hasFile($file)) {
$this->create([
'path' => request()->file($file)->store($dir),
'product_id' => $product->id,
]);
}
$this->create([
'path' => $image->store($this->getProductDirectory($product)),
'product_id' => $product->id,
]);
} else {
if (is_numeric($index = $previousImageIds->search($imageId))) {
$previousImageIds->forget($index);
if (is_numeric($index = $previousVariantImageIds->search($imageId))) {
$previousVariantImageIds->forget($index);
}
}
}
}
if (isset($data['variants'])) {
$this->uploadVariantImages($data['variants']);
}
foreach ($previousImageIds as $imageId) {
if ($imageModel = $this->find($imageId)) {
Storage::delete($imageModel->path);
foreach ($previousVariantImageIds as $imageId) {
if ($image = $this->find($imageId)) {
Storage::delete($image->path);
$this->delete($imageId);
}
@ -88,42 +105,21 @@ class ProductImageRepository extends Repository
}
/**
* Upload variant images.
*
* @param array $variants
* @return void
*/
public function uploadVariantImages($variants)
public function uploadVariantImages($variants): void
{
foreach ($variants as $variantsId => $variant) {
$product = $this->productRepository->findOrFail($variantsId);
$previousVariantImageIds = $product->images()->pluck('id');
$product = $this->productRepository->find($variantsId);
if (isset($variant['images'])) {
foreach ($variant['images'] as $imageId => $image) {
$file = 'variants.' . $product->id .'.'. 'images.' . $imageId;
$dir = 'product/' . $product->id;
if ($image instanceof UploadedFile) {
if (request()->hasFile($file)) {
$this->create([
'path' => request()->file($file)->store($dir),
'product_id' => $product->id,
]);
}
} else {
if (is_numeric($index = $previousVariantImageIds->search($imageId))) {
$previousVariantImageIds->forget($index);
}
}
}
if (! $product) {
break;
}
foreach ($previousVariantImageIds as $imageId) {
if ($imageModel = $this->find($imageId)) {
Storage::delete($imageModel->path);
$this->delete($imageId);
}
}
$this->upload($product, $variant['images'] ?? null);
}
}
}

View File

@ -2,26 +2,32 @@
namespace Webkul\Product\Type;
use Webkul\Customer\Contracts\CartItem;
use Webkul\Product\Datatypes\CartItemValidationResult;
use Webkul\Product\Models\ProductAttributeValue;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use Webkul\Product\Models\ProductFlat;
use Webkul\Product\Facades\ProductImage;
use Illuminate\Support\Str;
use Webkul\Product\Models\ProductAttributeValue;
use Webkul\Checkout\Models\CartItem as CartItemModel;
use Illuminate\Support\Facades\DB;
use Webkul\Product\Datatypes\CartItemValidationResult;
class Configurable extends AbstractType
{
/**
* Skip attribute for downloadable product type
* Skip attribute for configurable product type.
*
* @var array
*/
protected $skipAttributes = ['price', 'cost', 'special_price', 'special_price_from', 'special_price_to', 'length', 'width', 'height', 'weight'];
/**
* These blade files will be included in product edit page
* These are the types which can be fillable when generating variant.
*
* @var array
*/
protected $fillableTypes = ['sku', 'name', 'url_key', 'short_description', 'description', 'price', 'weight', 'status'];
/**
* These blade files will be included in product edit page.
*
* @var array
*/
@ -35,32 +41,34 @@ class Configurable extends AbstractType
];
/**
* Is a composite product type
* Is a composite product type.
*
* @var boolean
*/
protected $isComposite = true;
/**
* Show quantity box
* Show quantity box.
*
* @var boolean
*/
protected $showQuantityBox = true;
/**
* Has child products aka variants
* Has child products i.e. variants.
*
* @var boolean
*/
protected $hasVariants = true;
/**
* product options
* Product options.
*/
protected $productOptions = [];
/**
* Create configurable product.
*
* @param array $data
* @return \Webkul\Product\Contracts\Product
*/
@ -88,8 +96,10 @@ class Configurable extends AbstractType
}
/**
* @param array $data
* @param int $id
* Update configurable product.
*
* @param array $data
* @param int $id
* @param string $attribute
* @return \Webkul\Product\Contracts\Product
*/
@ -110,7 +120,9 @@ class Configurable extends AbstractType
$permutation[$superAttribute->id] = $variantData[$superAttribute->code];
}
$this->createVariant($product, $permutation, $variantData);
$variant = $this->createVariant($product, $permutation, $variantData);
$this->productImageRepository->upload($variant, $variantData['images'] ?? null);
} else {
if (is_numeric($index = $previousVariantIds->search($variantId))) {
$previousVariantIds->forget($index);
@ -133,6 +145,8 @@ class Configurable extends AbstractType
}
/**
* Create variant.
*
* @param \Webkul\Product\Contracts\Product $product
* @param array $permutation
* @param array $data
@ -151,6 +165,8 @@ class Configurable extends AbstractType
];
}
$data = $this->fillRequiredFields($data);
$typeOfVariants = 'simple';
$productInstance = app(config('product_types.' . $product->type . '.class'));
@ -165,7 +181,11 @@ class Configurable extends AbstractType
'sku' => $data['sku'],
]);
foreach (['sku', 'name', 'price', 'weight', 'status'] as $attributeCode) {
foreach ($this->fillableTypes as $attributeCode) {
if (! isset($data[$attributeCode])) {
continue;
}
$attribute = $this->attributeRepository->findOneByField('code', $attributeCode);
if ($attribute->value_per_channel) {
@ -225,8 +245,10 @@ class Configurable extends AbstractType
}
/**
* Update variant.
*
* @param array $data
* @param int $id
* @param int $id
* @return \Webkul\Product\Contracts\Product
*/
public function updateVariant(array $data, $id)
@ -235,7 +257,11 @@ class Configurable extends AbstractType
$variant->update(['sku' => $data['sku']]);
foreach (['sku', 'name', 'price', 'weight', 'status'] as $attributeCode) {
foreach ($this->fillableTypes as $attributeCode) {
if (! isset($data[$attributeCode])) {
continue;
}
$attribute = $this->attributeRepository->findOneByField('code', $attributeCode);
$attributeValue = $this->attributeValueRepository->findOneWhere([
@ -266,6 +292,27 @@ class Configurable extends AbstractType
}
/**
* Fill required fields.
*
* @param array $data
* @param int $id
* @return \Webkul\Product\Contracts\Product
*/
public function fillRequiredFields(array $data): array
{
/**
* Name field is not present when variant is created so adding sku.
*/
return array_merge($data, [
'url_key' => $data['sku'],
'short_description' => $data['sku'],
'description' => $data['sku']
]);
}
/**
* Check variant option availability.
*
* @param array $data
* @param \Webkul\Product\Contracts\Product $product
* @return bool
@ -300,7 +347,7 @@ class Configurable extends AbstractType
}
/**
* Returns children ids
* Returns children ids.
*
* @return array
*/
@ -310,6 +357,8 @@ class Configurable extends AbstractType
}
/**
* Is item have quantity.
*
* @param \Webkul\Checkout\Contracts\CartItem $cartItem
* @return bool
*/
@ -319,7 +368,7 @@ class Configurable extends AbstractType
}
/**
* Returns validation rules
* Return validation rules.
*
* @return array
*/
@ -334,7 +383,7 @@ class Configurable extends AbstractType
}
/**
* Return true if item can be moved to cart from wishlist
* Return true if item can be moved to cart from wishlist.
*
* @param \Webkul\Customer\Contracts\Wishlist $item
* @return bool
@ -349,7 +398,7 @@ class Configurable extends AbstractType
}
/**
* Get product minimal price
* Get product minimal price.
*
* @param int $qty
* @return float
@ -382,7 +431,7 @@ class Configurable extends AbstractType
}
/**
* Get product offer price
* Get product offer price.
*
* @return float
*/
@ -407,7 +456,7 @@ class Configurable extends AbstractType
}
/**
* Check for offer
* Check for offer.
*
* @return bool
*/
@ -425,7 +474,7 @@ class Configurable extends AbstractType
}
/**
* Get product maximam price
* Get product maximum price.
*
* @return float
*/
@ -443,7 +492,7 @@ class Configurable extends AbstractType
}
/**
* Get product minimal price
* Get product minimal price.
*
* @return string
*/
@ -515,6 +564,7 @@ class Configurable extends AbstractType
}
/**
* Compare options.
*
* @param array $options1
* @param array $options2
@ -536,7 +586,7 @@ class Configurable extends AbstractType
}
/**
* Returns additional information for items
* Return additional information for items.
*
* @param array $data
* @return array
@ -559,7 +609,7 @@ class Configurable extends AbstractType
}
/**
* Get actual ordered item
* Get actual ordered item.
*
* @param \Webkul\Checkout\Contracts\CartItem $item
* @return \Webkul\Checkout\Contracts\CartItem|\Webkul\Sales\Contracts\OrderItem|\Webkul\Sales\Contracts\InvoiceItem|\Webkul\Sales\Contracts\ShipmentItem|\Webkul\Customer\Contracts\Wishlist
@ -570,7 +620,7 @@ class Configurable extends AbstractType
}
/**
* Get product base image
* Get product base image.
*
* @param \Webkul\Customer\Contracts\Wishlist|\Webkul\Checkout\Contracts\CartItem $item
* @return array
@ -584,7 +634,7 @@ class Configurable extends AbstractType
$product = $item->product;
}
} else {
if ($item instanceof \Webkul\Customer\Contracts\CartItem) {
if ($item instanceof \Webkul\Checkout\Contracts\CartItem) {
$product = $item->child->product;
} else {
if (count($item->child->product->images)) {
@ -599,7 +649,7 @@ class Configurable extends AbstractType
}
/**
* Validate cart item product price
* Validate cart item product price.
*
* @param \Webkul\Product\Type\CartItem $item
*
@ -648,6 +698,8 @@ class Configurable extends AbstractType
}
/**
* Is product have sufficient quantity.
*
* @param int $qty
* @return bool
*/
@ -667,7 +719,7 @@ class Configurable extends AbstractType
}
/**
* Return true if this product type is saleable
* Return true if this product type is saleable.
*
* @return bool
*/
@ -683,6 +735,8 @@ class Configurable extends AbstractType
}
/**
* Return total quantity.
*
* @return int
*/
public function totalQuantity()
@ -690,9 +744,9 @@ class Configurable extends AbstractType
$total = 0;
$channelInventorySourceIds = core()->getCurrentChannel()
->inventory_sources()
->where('status', 1)
->pluck('id');
->inventory_sources()
->where('status', 1)
->pluck('id');
foreach ($this->product->variants as $variant) {
foreach ($variant->inventories as $inventory) {
@ -702,8 +756,8 @@ class Configurable extends AbstractType
}
$orderedInventory = $variant->ordered_inventories()
->where('channel_id', core()->getCurrentChannel()->id)
->first();
->where('channel_id', core()->getCurrentChannel()->id)
->first();
if ($orderedInventory) {
$total -= $orderedInventory->qty;