belongsTo(AttributeFamilyProxy::modelClass()); } /** * Get the product attribute values that owns the product. */ public function attribute_values() { return $this->hasMany(ProductAttributeValueProxy::modelClass()); } /** * Get the product variants that owns the product. */ public function variants() { return $this->hasMany(self::class, 'parent_id'); } /** * Get the product reviews that owns the product. */ public function reviews() { return $this->hasMany(ProductReviewProxy::modelClass()); } /** * Get the product that owns the product. */ public function parent() { return $this->belongsTo(self::class, 'parent_id'); } /** * The categories that belong to the product. */ public function categories() { return $this->belongsToMany(CategoryProxy::modelClass(), 'product_categories'); } /** * The inventories that belong to the product. */ public function inventories() { return $this->hasMany(ProductInventoryProxy::modelClass(), 'product_id'); } /** * The ordered inventories that belong to the product. */ public function ordered_inventories() { return $this->hasMany(ProductOrderedInventoryProxy::modelClass(), 'product_id'); } /** * The inventory sources that belong to the product. */ public function inventory_sources() { return $this->belongsToMany(InventorySourceProxy::modelClass(), 'product_inventories')->withPivot('id', 'qty'); } /** * The super attributes that belong to the product. */ public function super_attributes() { return $this->belongsToMany(AttributeProxy::modelClass(), 'product_super_attributes'); } /** * The images that belong to the product. */ public function images() { return $this->hasMany(ProductImageProxy::modelClass(), 'product_id'); } /** * The images that belong to the product. */ public function getBaseImageUrlAttribute() { $image = $this->images()->first(); return $image ? $image->url : null; } /** * The related products that belong to the product. */ public function related_products() { return $this->belongsToMany(self::class, 'product_relations', 'parent_id', 'child_id')->limit(4); } /** * The up sells that belong to the product. */ public function up_sells() { return $this->belongsToMany(self::class, 'product_up_sells', 'parent_id', 'child_id')->limit(4); } /** * The cross sells that belong to the product. */ public function cross_sells() { return $this->belongsToMany(self::class, 'product_cross_sells', 'parent_id', 'child_id')->limit(4); } /** * @param string $key * * @return bool */ public function isSaleable() { if (! $this->status) return false; if ($this->haveSufficientQuantity(1)) return true; return false; } /** * @param integer $qty * * @return bool */ public function inventory_source_qty($inventorySourceId) { return $this->inventories() ->where('inventory_source_id', $inventorySourceId) ->sum('qty'); } /** * @param integer $qty * * @return bool */ public function haveSufficientQuantity($qty) { $total = 0; $channelInventorySourceIds = core()->getCurrentChannel() ->inventory_sources() ->where('status', 1) ->pluck('id'); foreach ($this->inventories as $inventory) { if (is_numeric($index = $channelInventorySourceIds->search($inventory->inventory_source_id))) { $total += $inventory->qty; } } $orderedInventory = $this->ordered_inventories() ->where('channel_id', core()->getCurrentChannel()->id) ->first(); if ($orderedInventory) { $total -= $orderedInventory->qty; } return $qty <= $total ? true : false; } /** * Get an attribute from the model. * * @param string $key * @return mixed */ public function getAttribute($key) { if (! method_exists(self::class, $key) && ! in_array($key, ['parent_id', 'attribute_family_id']) && ! isset($this->attributes[$key])) { if (isset($this->id)) { $this->attributes[$key] = ''; $attribute = core()->getSingletonInstance(\Webkul\Attribute\Repositories\AttributeRepository::class) ->getAttributeByCode($key); $this->attributes[$key] = $this->getCustomAttributeValue($attribute); return $this->getAttributeValue($key); } } return parent::getAttribute($key); } /** * @return array */ public function attributesToArray() { $attributes = parent::attributesToArray(); $hiddenAttributes = $this->getHidden(); if (isset($this->id)) { $familyAttributes = core()->getSingletonInstance(\Webkul\Attribute\Repositories\AttributeRepository::class) ->getFamilyAttributes($this->attribute_family); foreach ($familyAttributes as $attribute) { if (in_array($attribute->code, $hiddenAttributes)) { continue; } $attributes[$attribute->code] = $this->getCustomAttributeValue($attribute); } } return $attributes; } /** * Get an product attribute value. * * @return mixed */ public function getCustomAttributeValue($attribute) { if (! $attribute) return; $channel = request()->get('channel') ?: (core()->getCurrentChannelCode() ?: core()->getDefaultChannelCode()); $locale = request()->get('locale') ?: app()->getLocale(); if ($attribute->value_per_channel) { if ($attribute->value_per_locale) { $attributeValue = $this->attribute_values()->where('channel', $channel)->where('locale', $locale)->where('attribute_id', $attribute->id)->first(); } else { $attributeValue = $this->attribute_values()->where('channel', $channel)->where('attribute_id', $attribute->id)->first(); } } else { if ($attribute->value_per_locale) { $attributeValue = $this->attribute_values()->where('locale', $locale)->where('attribute_id', $attribute->id)->first(); } else { $attributeValue = $this->attribute_values()->where('attribute_id', $attribute->id)->first(); } } return $attributeValue[ProductAttributeValue::$attributeTypeFields[$attribute->type]]; } /** * Overrides the default Eloquent query builder * * @param \Illuminate\Database\Eloquent\Builder $query * @return \Illuminate\Database\Eloquent\Builder */ public function newEloquentBuilder($query) { return new \Webkul\Product\Database\Eloquent\Builder($query); } /** * Return the product id attribute. */ public function getProductIdAttribute() { return $this->id; } /** * Return the product attribute. */ public function getProductAttribute() { return $this; } }