| @@ -3,8 +3,9 @@ | ||
| 3 | 3 | namespace FluentCart\App\Models; |
| 4 | 4 | |
| 5 | 5 | use FluentCart\Api\ModuleSettings; |
| 6 | 6 | use FluentCart\App\App; |
| 7 | +use FluentCart\App\Helpers\AttributeHelper; | |
| 7 | 8 | use FluentCart\App\Helpers\Helper; |
| 8 | 9 | use FluentCart\App\Helpers\Status; |
| 9 | 10 | use FluentCart\App\Models\Concerns\CanSearch; |
| 10 | 11 | use FluentCart\App\Models\Concerns\CanUpdateBatch; |
| @@ -127,8 +128,67 @@ | ||
| 127 | 128 | |
| 128 | 129 | public function shippingClass(): \FluentCart\Framework\Database\Orm\Relations\BelongsTo |
| 129 | 130 | { |
| 130 | 131 | return $this->belongsTo(ShippingClass::class, 'shipping_class', 'id'); |
| 132 | + } | |
| 133 | + | |
| 134 | + /** | |
| 135 | + * Labeled attribute combination for this variation, e.g. "Color: Red | Size: XS". | |
| 136 | + * | |
| 137 | + * Uses the batched `variation_display_title` when | |
| 138 | + * AttributeHelper::attachVariationDisplayTitles() has already resolved it, | |
| 139 | + * and otherwise resolves on demand — so callers get a correct value either | |
| 140 | + * way, and a correctly batched caller costs no extra queries. | |
| 141 | + * | |
| 142 | + * @return string Falls back to the stored variation title. | |
| 143 | + */ | |
| 144 | + public function getVariationLabel(): string | |
| 145 | + { | |
| 146 | + $resolved = (string) ($this->variation_display_title ?? ''); | |
| 147 | + | |
| 148 | + if ($resolved !== '') { | |
| 149 | + return $resolved; | |
| 150 | + } | |
| 151 | + | |
| 152 | + $variationType = $this->product_detail ? $this->product_detail->variation_type : ''; | |
| 153 | + | |
| 154 | + $label = AttributeHelper::getDisplayAttributesString( | |
| 155 | + AttributeHelper::getProductItemAttributes($this->id, $this->post_id), | |
| 156 | + [ | |
| 157 | + 'title' => $this->variation_title, | |
| 158 | + 'variation_type' => $variationType, | |
| 159 | + 'other_info' => ['variation_type' => $variationType], | |
| 160 | + ], | |
| 161 | + 'order_item' | |
| 162 | + ); | |
| 163 | + | |
| 164 | + return $label !== '' ? $label : (string) $this->variation_title; | |
| 165 | + } | |
| 166 | + | |
| 167 | + /** | |
| 168 | + * Full display title for this variation: "<product> - <attribute combination>". | |
| 169 | + * | |
| 170 | + * The catalogue-side counterpart to OrderItem::getDisplayTitle(), which | |
| 171 | + * composes the same shape from a frozen line item. Product feeds, plan | |
| 172 | + * names and CLI output all need the product name alongside the variation, | |
| 173 | + * and each was concatenating it themselves. | |
| 174 | + * | |
| 175 | + * @return string | |
| 176 | + */ | |
| 177 | + public function getDisplayTitle(): string | |
| 178 | + { | |
| 179 | + $label = $this->getVariationLabel(); | |
| 180 | + $productTitle = $this->product ? (string) $this->product->post_title : ''; | |
| 181 | + | |
| 182 | + if ($productTitle === '' || $productTitle === $label) { | |
| 183 | + return $label; | |
| 184 | + } | |
| 185 | + | |
| 186 | + if ($label === '') { | |
| 187 | + return $productTitle; | |
| 188 | + } | |
| 189 | + | |
| 190 | + return $productTitle . ' - ' . $label; | |
| 131 | 191 | } |
| 132 | 192 | |
| 133 | 193 | /** |
| 134 | 194 | * One2One: Product Variation belongs to one Product detail |