Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
841685b
Implement EAV structure for product entity
Jade-GG Jul 24, 2025
78a47ec
Apply fixes from Duster
Jade-GG Jul 24, 2025
77c9a41
Fix model name
Jade-GG Jul 24, 2025
42a1a7e
Get store specific values
Jade-GG Jul 24, 2025
ee340e9
Apply fixes from Duster
Jade-GG Jul 24, 2025
9cfed19
Allow for values to be queried on, filter products based on website a…
Jade-GG Jul 24, 2025
30c975e
Apply fixes from Duster
Jade-GG Jul 24, 2025
573f3bf
Rename EavAttribute to AbstractAttribute
Jade-GG Jul 24, 2025
9184a38
Apply fixes from Duster
Jade-GG Jul 24, 2025
0cda5c0
Add stock data to products
Jade-GG Jul 24, 2025
9766b95
Apply fixes from Duster
Jade-GG Jul 24, 2025
dbe6403
Rename Datetime
Jade-GG Jul 24, 2025
e6b9338
Delete src/Models/AttributeDateTime.php
Jade-GG Jul 24, 2025
22b4949
Cast value properly when getting
Jade-GG Jul 24, 2025
521423d
Apply fixes from Duster
Jade-GG Jul 24, 2025
b6fef4c
Small fixes
Jade-GG Jul 24, 2025
24c785d
Add parent, children, super attributes & super attribute values
Jade-GG Jul 24, 2025
b72b189
Apply fixes from Duster
Jade-GG Jul 24, 2025
f5fcd82
Add consts
Jade-GG Jul 24, 2025
1ec5263
Fix sorting on super attributes & change whereValue to whereAttribute
Jade-GG Jul 24, 2025
8594af0
Apply fixes from Duster
Jade-GG Jul 24, 2025
46f1854
Rename product, use config rapidez.model, add callbacks, abstractify …
Jade-GG Aug 6, 2025
ab8aeda
Still return falsy values
Jade-GG Aug 6, 2025
0bab9eb
Remove old scopes, update HasAlternates to include rewrites relation
Jade-GG Aug 6, 2025
3f25db8
Apply fixes from Duster
Jade-GG Aug 6, 2025
98aacc5
Remove unnecessary casts
Jade-GG Aug 6, 2025
052ba64
Add URL, images, price for configurable/grouped products, move stuff …
Jade-GG Aug 6, 2025
7e934b7
Apply fixes from Duster
Jade-GG Aug 6, 2025
f310cc7
Simplify price & add specialPrice
Jade-GG Aug 6, 2025
baae5d8
Merge branch 'feature/flat-tables' of https://github.com/rapidez/core…
Jade-GG Aug 6, 2025
e42bdc5
Apply fixes from Duster
Jade-GG Aug 6, 2025
c7c4da2
Make custom attributes trait slightly more abstract, add product link…
Jade-GG Aug 7, 2025
7faf8d3
Apply fixes from Duster
Jade-GG Aug 7, 2025
0830d95
Add inverted product links
Jade-GG Aug 7, 2025
c13f98c
Add category info & use config models
Jade-GG Aug 7, 2025
f3e8018
Add minSaleQty
Jade-GG Aug 7, 2025
9c0f104
Add breadcrumb categories
Jade-GG Aug 7, 2025
c8499d0
Add reviewSummary
Jade-GG Aug 7, 2025
b50ce36
Fix bug & add toArray for indexing
Jade-GG Aug 7, 2025
d265943
Allow indexing (but slow)
Jade-GG Aug 8, 2025
5262dcf
Apply fixes from Duster
Jade-GG Aug 8, 2025
2240d05
Formatting
Jade-GG Aug 8, 2025
3947219
Add tier pricing
Jade-GG Aug 26, 2025
1097b17
Apply fixes from Duster
Jade-GG Aug 26, 2025
16993dc
Merge pull request #985 from rapidez/feature/flat-tables-tier-pricing
royduin Aug 27, 2025
9602fe3
Fix performance
Jade-GG Sep 1, 2025
cdb4c9b
Apply fixes from Duster
Jade-GG Sep 1, 2025
21a2620
Merge branch 'master' into feature/flat-tables
royduin Oct 15, 2025
ded4821
Fix product pages & improve given product data
Jade-GG Oct 16, 2025
e4ed907
Add todo
Jade-GG Oct 16, 2025
6815f9b
Apply fixes from Duster
Jade-GG Oct 16, 2025
8fac631
Fix categories & super attributes
Jade-GG Oct 16, 2025
2e535bf
Apply fixes from Duster
Jade-GG Oct 16, 2025
71abd6b
Merge branch 'feature/flat-tables' into feature/flat-tables-product-data
Jade-GG Oct 16, 2025
2523f8a
[CI] Update Snapshots
Jade-GG Oct 16, 2025
94eca16
Fix super attributes swatch data
Jade-GG Oct 16, 2025
9ad97eb
Merge branch 'feature/flat-tables-product-data' of https://github.com…
Jade-GG Oct 16, 2025
49f6c47
[CI] Update Snapshots
Jade-GG Oct 16, 2025
ae91e4d
Merge pull request #1050 from rapidez/feature/flat-tables-product-data
royduin Oct 16, 2025
18c484f
Explose stock implementation
royduin Oct 16, 2025
10d4dd1
Apply fixes from Duster
royduin Oct 16, 2025
8728146
Accessors for backwards compatiblity
royduin Oct 16, 2025
275272d
Switched the fallback method so relations can be used
royduin Oct 16, 2025
eca329b
Fixed the grouped products, relation prices and breadcrumbs for inact…
royduin Oct 16, 2025
4682610
Use the non-deprecated naming
royduin Oct 16, 2025
53a9b0f
Merge branch 'feature/flat-tables' of github.com:rapidez/core into fe…
royduin Oct 16, 2025
2f24eef
Apply fixes from Duster
royduin Oct 16, 2025
035e093
Moved the product backwards compatibile accessors to a trait
royduin Oct 16, 2025
ea83753
Partially implement super attributes & small value refactor (#1052)
Jade-GG Oct 17, 2025
77c5031
Add basic product unit tests & fix things that came out of that
Jade-GG Oct 21, 2025
0e90b38
Apply fixes from Duster
Jade-GG Oct 21, 2025
910e4a2
Fix error on PDP
Jade-GG Oct 21, 2025
e4d2be8
Model serialization: hide relations and add all attributes
royduin Oct 24, 2025
556c1e0
Merge branch 'feature/flat-tables' into feature/flat-tables-unit-tests
royduin Oct 24, 2025
d640e72
Merge pull request #1056 from rapidez/feature/flat-tables-unit-tests
royduin Oct 24, 2025
2a9d437
Index and caching improvements
royduin Oct 24, 2025
e089a97
Performance improvements
royduin Oct 29, 2025
7242ce4
Use the price index table + improved model config usage
royduin Oct 30, 2025
983b128
Apply fixes from Duster
royduin Oct 30, 2025
fdaf3c5
Unguard all models
royduin Nov 7, 2025
6918192
Todo
royduin Nov 7, 2025
c168e9b
Use database transactions for unit tests
royduin Nov 7, 2025
82c991c
Product options and views test
royduin Nov 7, 2025
a7d99a2
Apply fixes from Duster
royduin Nov 7, 2025
0382b93
Apply catalog price rules correctly everywhere
royduin Nov 7, 2025
5aee223
Merge branch 'feature/flat-tables' of github.com:rapidez/core into fe…
royduin Nov 7, 2025
f9c98ac
Apply fixes from Duster
royduin Nov 7, 2025
5302d3d
Scopes cleanup
royduin Nov 7, 2025
703f73b
Merge branch 'feature/flat-tables' of github.com:rapidez/core into fe…
royduin Nov 7, 2025
7792694
Apply fixes from Duster
royduin Nov 7, 2025
a7b0474
Implemented the visibility differently
royduin Nov 7, 2025
4b0056f
Merge branch 'feature/flat-tables' of github.com:rapidez/core into fe…
royduin Nov 7, 2025
7bf82e7
Apply fixes from Duster
royduin Nov 7, 2025
01c1202
Import
royduin Nov 7, 2025
47e2dd5
Merge branch 'feature/flat-tables' of github.com:rapidez/core into fe…
royduin Nov 7, 2025
447dc16
Todo
royduin Nov 11, 2025
060e341
Product special price fixes, exclude bundle products and seperated pr…
royduin Nov 11, 2025
77b1ede
Apply fixes from Duster
royduin Nov 11, 2025
7602422
Update CHANGELOG
royduin Nov 14, 2025
851f775
Merge branch 'master' into feature/flat-tables
royduin Nov 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions config/rapidez/attribute-models.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

return [
'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend' => Rapidez\Core\Models\AttributeModels\ArrayBackend::class,
];
8 changes: 8 additions & 0 deletions src/Models/AttributeDateTime.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Rapidez\Core\Models;

class AttributeDateTime extends EavAttribute
{
protected $casts = ['value' => 'datetime'];
}
8 changes: 8 additions & 0 deletions src/Models/AttributeDecimal.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Rapidez\Core\Models;

class AttributeDecimal extends EavAttribute
{
protected $casts = ['value' => 'float'];
}
10 changes: 10 additions & 0 deletions src/Models/AttributeInt.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Rapidez\Core\Models;

use Rapidez\Core\Models\Traits\HasAttributeOptions;

class AttributeInt extends EavAttribute
{
use HasAttributeOptions;
}
13 changes: 13 additions & 0 deletions src/Models/AttributeModels/ArrayBackend.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Rapidez\Core\Models\AttributeModels;

class ArrayBackend implements AttributeModel
{
public static function value($value, $attribute)
{
$values = explode(',', $value);

return collect($values)->map(fn ($value) => $attribute->options[$value]?->value ?? $value);
}
}
8 changes: 8 additions & 0 deletions src/Models/AttributeModels/AttributeModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Rapidez\Core\Models\AttributeModels;

interface AttributeModel
{
public static function value($value, $attribute);
}
23 changes: 23 additions & 0 deletions src/Models/AttributeOption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Rapidez\Core\Models;

use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Database\Query\JoinClause;

class AttributeOption extends Model
{
protected $table = 'eav_attribute_option';

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

static::addGlobalScope('values', function (Builder $builder) {
$builder->leftJoin('eav_attribute_option_value', function (JoinClause $join) use ($builder) {
$join->on($builder->qualifyColumn('option_id'), '=', 'eav_attribute_option_value.option_id')
->whereIn('store_id', [0, config('rapidez.store')]);
});
});
}
}
10 changes: 10 additions & 0 deletions src/Models/AttributeText.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Rapidez\Core\Models;

use Rapidez\Core\Models\Traits\HasAttributeOptions;

class AttributeText extends EavAttribute
{
use HasAttributeOptions;
}
10 changes: 10 additions & 0 deletions src/Models/AttributeVarchar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Rapidez\Core\Models;

use Rapidez\Core\Models\Traits\HasAttributeOptions;

class AttributeVarchar extends EavAttribute
{
use HasAttributeOptions;
}
58 changes: 58 additions & 0 deletions src/Models/EavAttribute.php
Comment thread
Jade-GG marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace Rapidez\Core\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Rapidez\Core\Models\Scopes\ForCurrentStoreWithoutLimitScope;

class EavAttribute extends Model
{
protected static function boot(): void
{
parent::boot();

static::addGlobalScope(new ForCurrentStoreWithoutLimitScope(['attribute_id', 'entity_id']));

static::addGlobalScope('attribute', function (Builder $builder) {
$builder->leftJoin('eav_attribute', $builder->qualifyColumn('attribute_id'), '=', 'eav_attribute.attribute_id');
});

if (isset(static::$hasAttributeOptions)) { // @phpstan-ignore-line
static::addGlobalScope('attributeOptions', function (Builder $builder) {
$builder->with('attributeOptions'); // @phpstan-ignore-line
});
}
}

public static function getCached()
{
return Cache::rememberForever('eav_attributes', function () {
return DB::table('eav_attribute')->get()->keyBy('attribute_code');
});
}

public function getTable()
{
// Overwritten to always return table, so that qualifyColumn and such work
return $this->table;
}

protected function value(): Attribute
{
return Attribute::get(function ($value) {
if ($this->frontend_input === 'select') {
return $this->options[$value]?->value ?? $value;
}

$class = config('rapidez.attribute-models')[$this->backend_model] ?? null;
if ($class) {
return $class::value($value, $this);
}

return $value;
});
}
}
53 changes: 53 additions & 0 deletions src/Models/ProductEntity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Rapidez\Core\Models;

use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Rapidez\Core\Models\Scopes\Product\ForCurrentWebsiteScope;
use Rapidez\Core\Models\Traits\HasCustomAttributes;

class ProductEntity extends Model
{
use HasCustomAttributes;

protected $table = 'catalog_product_entity';
protected $primaryKey = 'entity_id';

protected $casts = [
self::UPDATED_AT => 'datetime',
self::CREATED_AT => 'datetime',
];

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

static::addGlobalScope(ForCurrentWebsiteScope::class);
static::addGlobalScope('customAttributes', fn (Builder $builder) => $builder->withCustomAttributes());
static::addGlobalScope('onlyEnabled', fn (Builder $builder) => $builder->whereValue('status', 1));
}

public function gallery(): BelongsToMany
{
return $this->belongsToMany(
config('rapidez.models.product_image'),
'catalog_product_entity_media_gallery_value_to_entity',
'entity_id',
'value_id',
);
}

public function getAttribute($key)
{
if (! $key) {
return;
}

if ($value = parent::getAttribute($key)) {
return $value;
}

return $this->getCustomAttribute($key)?->value;
}
}
10 changes: 10 additions & 0 deletions src/Models/ProductStock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Rapidez\Core\Models;

use Illuminate\Database\Eloquent\Model;

class ProductStock extends Model
{
protected $table = 'cataloginventory_stock_item';
}
28 changes: 21 additions & 7 deletions src/Models/Scopes/ForCurrentStoreWithoutLimitScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Support\Facades\DB;

/**
* Remove results from the default store when store view specific is found.
*/
class ForCurrentStoreWithoutLimitScope implements Scope
{
public function __construct(public $uniquePerStoreKey, public $storeIdColumn = 'store_id') {}
public array $uniquePerStoreKeys;

public function __construct(string|array $uniquePerStoreKey, public $storeIdColumn = 'store_id')
{
$this->uniquePerStoreKeys = is_array($uniquePerStoreKey) ? $uniquePerStoreKey : [$uniquePerStoreKey];
}

public function apply(Builder $query, Model $model)
{
Expand All @@ -20,18 +26,26 @@ public function apply(Builder $query, Model $model)
->where($query->qualifyColumn($this->storeIdColumn), 0);
}

$scope = $this;

return $query
// Pre-filter results to be default and current store only.
->whereIn($query->qualifyColumn($this->storeIdColumn), [0, config('rapidez.store')])
// Remove values from the default store where values for the current store exist.
->where(fn ($query) => $query
// Remove values where we already have values in the current store.
->whereNotIn($query->qualifyColumn($this->uniquePerStoreKey), fn ($query) => $query
->select($model->qualifyColumn($this->uniquePerStoreKey))
->from($model->getTable())
->whereColumn($model->qualifyColumn($this->uniquePerStoreKey), $model->qualifyColumn($this->uniquePerStoreKey))
->where($model->qualifyColumn($this->storeIdColumn), config('rapidez.store'))
)
->where(function ($query) use ($scope, $model) {
$query
->whereNotExists(function ($query) use ($scope, $model) {
$query
->select(DB::raw(1))
->from($model->getTable() . ' as comparison')
->where('comparison.' . $this->storeIdColumn, config('rapidez.store'));
foreach ($scope->uniquePerStoreKeys as $uniquePerStoreKey) {
$query->whereColumn('comparison.' . $uniquePerStoreKey, $model->qualifyColumn($uniquePerStoreKey));
}
});
})
// Unless the value IS the current store.
->orWhere($query->qualifyColumn($this->storeIdColumn), config('rapidez.store'))
);
Expand Down
16 changes: 16 additions & 0 deletions src/Models/Scopes/Product/ForCurrentWebsiteScope.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rapidez\Core\Models\Scopes\Product;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

class ForCurrentWebsiteScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder->leftJoin('catalog_product_website', 'product_id', '=', $model->getQualifiedKeyName());
$builder->where('website_id', config('rapidez.website'));
}
}
26 changes: 26 additions & 0 deletions src/Models/Traits/HasAttributeOptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Rapidez\Core\Models\Traits;

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Rapidez\Core\Models\AttributeOption;

trait HasAttributeOptions
{
protected static $hasAttributeOptions = true;

protected function options(): Attribute
{
// Sort by store_id first to always get the higher store id if there are two.
return Attribute::get(fn () => $this->attributeOptions
->sortBy('store_id')
->keyBy('option_id')
);
}

public function attributeOptions(): HasMany
{
return $this->hasMany(AttributeOption::class, 'attribute_id', 'attribute_id');
}
}
Loading