Skip to content
2 changes: 1 addition & 1 deletion src/Http/Controllers/ProductController.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public function show(int $productId)
$productModel = config('rapidez.models.product');
$product = $productModel::selectForProductPage()
->withEventyGlobalScopes('productpage.scopes')
->with('options')
->with('options', 'attrs')
->findOrFail($productId);

$attributes = [
Expand Down
8 changes: 5 additions & 3 deletions src/Models/OptionValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@ class OptionValue extends Model

protected $primaryKey = 'value_id';

public static function getCachedByOptionId(int $optionId): string
public static function getCachedByOptionId(int $optionId, ?int $attributeId = null, mixed $default = false): string
{
$cacheKey = 'optionvalues.' . config('rapidez.store');
$cache = Cache::store('rapidez:multi')->get($cacheKey, []);

if (! isset($cache[$optionId])) {
$cache[$optionId] = html_entity_decode(self::where('option_id', $optionId)
$cache[$optionId] = html_entity_decode(self::where('eav_attribute_option_value.option_id', $optionId)
->whereIn('store_id', [config('rapidez.store'), 0])
->join('eav_attribute_option', 'eav_attribute_option.option_id', '=', 'eav_attribute_option_value.option_id')
->orderByDesc('store_id')
->when($attributeId, fn ($query) => $query->where('attribute_id', $attributeId))
->first('value')
->value ?? false);
->value ?? $default);
Cache::store('rapidez:multi')->forever($cacheKey, $cache);
}

Expand Down
56 changes: 56 additions & 0 deletions src/Models/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,62 @@ public function getThumbnailAttribute($image): ?string
return $this->getImageAttribute($image);
}

public function attrs(): HasMany
{
return $this->hasMany(
ProductAttribute::class,
'entity_id',
'entity_id',
);
}

public function getAttribute($key)
{
if (($value = parent::getAttribute($key)) !== null || $this->hasAttribute($key)) {
return $value;
}

// TOOD: Not sure if this is very efficient, first we're
// searching for the attribute by code for the id and
// after that we're searching for the attribute id
// between the product attributes for the value.
$attributeModel = config('rapidez.models.attribute');
$attributes = $attributeModel::getCachedWhere(function ($attribute) use ($key) {
return $attribute['code'] == $key;
});

if (! count($attributes) || ! $attribute = reset($attributes)) {
return null;
}

$this->loadMissing('attrs');
// TODO: Check for a custom value for a store. So if store 1 overwrites store 0.
if (! $value = optional($this->attrs->firstWhere('attribute_id', $attribute['id']))->value) {
return null;
}

if ($attribute['input'] == 'multiselect') {
foreach (explode(',', $value) as $optionValueId) {
$values[] = OptionValue::getCachedByOptionId($optionValueId, $attribute['id'], $optionValueId);
}
$this->setAttribute($key, $values);

return $values;
}

if ($attribute['input'] == 'select' && $attribute['type'] == 'int' && ! ($attribute['system'] ?? false)) {
$value = OptionValue::getCachedByOptionId($value, $attribute['id'], $value);
}

if ($key == 'url_key') {
return '/' . ($value ? $value . Rapidez::config('catalog/seo/product_url_suffix') : 'catalog/product/view/id/' . $this->entity_id);
}

$this->setAttribute($key, $value);

return $value;
}

protected function breadcrumbCategories(): Attribute
{
return Attribute::make(
Expand Down
35 changes: 35 additions & 0 deletions src/Models/ProductAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Rapidez\Core\Models;

use Illuminate\Database\Eloquent\Builder;

class ProductAttribute extends Model
{
protected $table = 'catalog_product_entity_varchar';

protected static function boot(): void
{
parent::boot();

static::addGlobalScope('unions', function (Builder $builder) {
$builder
->select([
'entity_id',
'attribute_id',
'store_id',
'value',
])
->whereIn('store_id', [config('rapidez.store'), 0])
->whereNotNull('value');

$baseQuery = clone $builder->getQuery();
foreach (['int', 'text', 'decimal'] as $type) {
$typeTable = 'catalog_product_entity_' . $type;
$typeQuery = (clone $baseQuery)->from($typeTable);
$typeQuery->wheres[0]['column'] = $typeTable . '.entity_id';
$builder->unionAll($typeQuery);
}
});
}
}
2 changes: 1 addition & 1 deletion src/Models/Traits/Product/SelectAttributeScopes.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function scopeSelectForProductPage(Builder $query): Builder
{
$attributeModel = config('rapidez.models.attribute');
$this->attributesToSelect = Arr::pluck($attributeModel::getCachedWhere(function ($attribute) {
return $attribute['productpage'] || in_array($attribute['code'], [
return ($attribute['flat'] || $attribute['type'] === 'select') && $attribute['productpage'] || in_array($attribute['code'], [
'name',
'meta_title',
'meta_description',
Expand Down