<?php
declare(strict_types=1);
namespace App\Twig\Extension;
use App\Model\DefaultProduct;
use App\Service\CartService;
use App\Service\ProductAttributeData;
use App\Service\ProductAttributeMapper;
use App\Service\ProductAttributeRenderer;
use App\Service\ShopService;
use Pimcore\Log\Simple;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
use Pimcore\Translation\Translator;
use App\Model\Customer;
/**
* Description of ProductExtension
*
* @author PcCom
*/
class ProductExtension extends AbstractExtension
{
/**
* @var Translator
*/
protected $translator;
/**
* @var CartService
*/
protected $cartService;
/**
* @var ShopService
*/
private $shopService;
private ProductAttributeMapper $mapper;
private ProductAttributeRenderer $renderer;
/**
* GeneralFilterExtension constructor.
*
* @param Translator $translator
* @param CartService $cartService
* @param ShopService $shopService
*/
public function __construct(
Translator $translator,
CartService $cartService,
ShopService $shopService,
ProductAttributeMapper $mapper,
ProductAttributeRenderer $renderer
)
{
$this->translator = $translator;
$this->cartService = $cartService;
$this->shopService = $shopService;
$this->mapper = $mapper;
$this->renderer = $renderer;
}
/**
* @return TwigFunction[]
*/
public function getFunctions()
{
return [
new TwigFunction('app_product_generate_link', [$this, 'generateLink']),
new TwigFunction('app_product_generate_data', [$this, 'generateData']),
new TwigFunction('app_product_attributes_rows', [$this, 'getAttributesRows']),
new TwigFunction('app_product_types_rows', [$this, 'getTypesRows']),
new TwigFunction('app_product_variants_attributes', [$this, 'getVariantsAttributes']),
new TwigFunction('app_product_variant_attribute_value', [$this, 'getVariantsAttributeValue']),
new TwigFunction('app_product_variant_prices', [$this, 'getVariantsPrices']),
new TwigFunction('app_product_related_products', [$this, 'getRelatedProducts']),
new TwigFunction('app_product_default_price',[$this,'getDefaultPrice']),
new TwigFunction('app_product_default_price_with_discount',[$this,'getDefaultPriceWithDiscount']),
new TwigFunction('app_product_price_with_discount',[$this,'getPriceWithDiscount']),
new TwigFunction('app_product_haveError',[$this,'getHaveError']),
];
}
public function generateData($product)
{
$data = new ProductAttributeData($this->mapper);
$data->initialize($product);
return $data;
}
public function getHaveError($product):bool
{
$haveError = false;
if (!$haveError){
$haveError = $this->checkVariantsWithoutPrice($product);
}
return $haveError;
}
protected function checkVariantsWithoutPrice($product):bool
{
$haveError = false;
$i = 0;
$data = $this->generateData($product);
$variants = $data->variants;
foreach ($variants as $variant){
if ($variant->getPrice()){
$i++;
}else{
Simple::log("products-with-errors", "product ID: {$variant->getId()} Error type: missing field on price");
}
}
//ERROR PRICE FIELD IS MISSING
if ($i != count($variants)){
$haveError = true;
}
return $haveError;
}
public function getAttributesRows($product, $data) : ?array
{
return $this->renderer->generateRows(get_object_vars($data), $product);
}
public function getVariantsAttributes(ProductAttributeData $data)
{
return $data->getVariantAttributes();
}
public function getTypesRows($product, $data): array
{
$typeArray = [];
$typeArray["Activador"] = $this->getActivador($product);
$typeArray["Base"] = $this->getBaseRow($product);
$typeArray["Catalizador"] = $this->getCatalizadorRow($product, $data);
$typeArray["Converter"] = $this->getConverterRow($product);
$typeArray["Disolvente"] = $this->getDisvolventeRow($product);
$typeArray["Kit"] = $this->getKitRow($product);
$typeArray["Cleaner"] = $this->getCleanerRow($product);
$typeArray["Reducer"] = $this->getReducerRow($product);
$typeArray["Complemento"] = $this->getComplement($product);
return array_filter($typeArray);
}
protected function getActivador($product): string
{
$rowString = "";
$activadors = $product->getActivador();
if (count($activadors) > 0) {
$rowString .= "<tr><td class=\"attributekey\">" . $this->translator->trans("Activador") . ":</td> ";
$rowString .= "<td class=\"attributevalue\">";
$resultString = "";
foreach ($activadors as $activador) {
$relProduct = $activador->getElement();
$resultString .= "<br/>";
if (!empty($relProduct->getBsncode())) {
$resultString .= $relProduct->getBsncode() . " - ";
}
$resultString .= $relProduct->getName();
}
$rowString .= trim($resultString, "<br/>");
$rowString .= "</td></tr>";
}
return $rowString;
}
protected function getComplement($product){
$rowString = "";
$activadors = $product->getComplement();
if (count($activadors) > 0) {
$rowString .= "<tr><td class=\"attributekey\">" . $this->translator->trans("Complemento") . ":</td> ";
$rowString .= "<td class=\"attributevalue\">";
$resultString = "";
foreach ($activadors as $activador) {
$relProduct = $activador->getElement();
$resultString .= "<br/>";
if (!empty($relProduct->getBsncode())) {
$resultString .= $relProduct->getBsncode() . " - ";
}
$resultString .= $relProduct->getName();
}
$rowString .= trim($resultString, "<br/>");
$rowString .= "</td></tr>";
}
return $rowString;
}
protected function getBaseRow($product): string
{
$rowString = "";
$bases = $product->getBase();
if (count($bases) > 0) {
$rowString .= "<tr><td class=\"attributekey\">" . $this->translator->trans("Base") . ":</td> ";
$rowString .= "<td class=\"attributevalue\">";
$resultString = "";
foreach ($bases as $base) {
$relProduct = $base->getElement();
$resultString .= "<br/>";
if (!empty($relProduct->getBsncode())) {
$resultString .= $relProduct->getBsncode() . " - ";
}
$resultString .= $relProduct->getName();
}
$rowString .= trim($resultString, "<br/>");
$rowString .= "</td></tr>";
}
return $rowString;
}
protected function getCatalizadorRow($product, $data): string
{
$rowString = "";
if (!empty($data->valuesArray["catalizador"])) {
$rowString .= "<tr><td class=\"attributekey\">" . $this->translator->trans($data->attributes["catalizador"]["title"]) . ":</td> ";
$rowString .= "<td class=\"attributevalue\">" . $this->translator->trans($data->valuesArray["catalizador"]) . "</td></tr>";
} else {
$catalizadors = $product->getCatalizador();
if (count($catalizadors) > 0) {
$rowString .= "<tr><td class=\"attributekey\">" . $this->translator->trans("Catalizador") . ":</td> ";
$rowString .= "<td class=\"attributevalue\">";
$resultString = "";
foreach ($catalizadors as $catalizador) {
$relProduct = $catalizador->getElement();
$resultString .= "<br/>";
if (!empty($relProduct->getBsncode())) {
$resultString .= $relProduct->getBsncode() . " - ";
}
$resultString .= $relProduct->getName();
}
$rowString .= trim($resultString, "<br/>");
$rowString .= "</td></tr>";
}
}
return $rowString;
}
protected function getConverterRow($product): string
{
$rowString = "";
$converters = $product->getConverter();
if (count($converters) > 0) {
$rowString .= "<tr><td class=\"attributekey\">" . $this->translator->trans("Converter") . ":</td> ";
$rowString .= "<td class=\"attributevalue\">";
$resultString = "";
foreach ($converters as $converter) {
$relProduct = $converter->getElement();
$resultString .= "<br/>";
if (!empty($relProduct->getBsncode())) {
$resultString .= $relProduct->getBsncode() . " - ";
}
$resultString .= $relProduct->getName();
}
$rowString .= trim($resultString, "<br/>");
$rowString .= "</td></tr>";
}
return $rowString;
}
protected function getDisvolventeRow($product): string
{
$rowString = "";
$disolventes = $product->getDisolvente();
if (count($disolventes) > 0) {
$rowString .= "<tr><td class=\"attributekey\">";
if ($this->translator->getLocale() == 'es') {
$rowString .= "Disolvente:";
} elseif ($this->translator->getLocale() == 'en') {
$rowString .= "Solvent:";
} else {
$rowString .= "Solvent:";
}
$rowString .= ":</td> ";
$rowString .= "<td class=\"attributevalue\">";
$resultString = "";
foreach ($disolventes as $disolvente) {
$relProduct = $disolvente->getElement();
$resultString .= "<br/>";
if (!empty($relProduct->getBsncode())) {
$resultString .= $relProduct->getBsncode() . " - ";
}
$resultString .= $relProduct->getName();
}
$rowString .= trim($resultString, "<br/>");
$rowString .= "</td></tr>";
}
return $rowString;
}
protected function getKitRow($product): string
{
$rowString = "";
$kits = $product->getKit();
if (count($kits) > 0) {
$rowString .= "<tr><td class=\"attributekey\">" . $this->translator->trans("Kit") . ":</td> ";
$rowString .= "<td class=\"attributevalue\">";
$resultString = "";
foreach ($kits as $kit) {
$relProduct = $kit->getElement();
$resultString .= "<br/>";
if (!empty($relProduct->getBsncode())) {
$resultString .= $relProduct->getBsncode() . " - ";
}
$resultString .= $relProduct->getName();
}
$rowString .= trim($resultString, "<br/>");
$rowString .= "</td></tr>";
}
return $rowString;
}
public function getCleanerRow($product): string
{
$rowString = "";
$cleaners = $product->getCleaner();
if (count($cleaners) > 0) {
$rowString .= "<tr><td class=\"attributekey\">" . $this->translator->trans("Cleaner") . ":</td> ";
$rowString .= "<td class=\"attributevalue\">";
$resultString = "";
foreach ($cleaners as $cleaner) {
$relProduct = $cleaner->getElement();
$resultString .= "<br/>";
if (!empty($relProduct->getBsncode())) {
$resultString .= $relProduct->getBsncode() . " - ";
}
$resultString .= $relProduct->getName();
}
$rowString .= trim($resultString, "<br/>");
$rowString .= "</td></tr>";
}
return $rowString;
}
protected function getReducerRow($product): string
{
$rowString = "";
$reducers = $product->getReducer();
if (count($reducers) > 0) {
$rowString .= "<tr><td class=\"attributekey\">" . $this->translator->trans("Reducer") . ":</td> ";
$rowString .= "<td class=\"attributevalue\">";
$resultString = "";
foreach ($reducers as $reducer) {
$relProduct = $reducer->getElement();
$resultString .= "<br/>";
if (!empty($relProduct->getBsncode())) {
$resultString .= $relProduct->getBsncode() . " - ";
}
$resultString .= $relProduct->getName();
}
$rowString .= trim($resultString, "<br/>");
$rowString .= "</td></tr>";
}
return $rowString;
}
public function getVariantsAttributeValue($variant, $field)
{
$data = new \stdClass();
$value = $variant->getAttributeValue($field);
$textAlign = "text-align:center;";
switch ($field["fieldtype"]) {
case "inputQuantityValue" :
case "quantityValue" :
$textAlign = "text-align:center;";
break;
}
switch ($field["name"]) {
case "color" :
$colorObj = \Pimcore\Model\DataObject\Colores::getById($value);
if ($colorObj) {
if (method_exists($colorObj, "getName")) {
$value = $colorObj->getName();
}
if (method_exists($colorObj, "getHex")) {
$hexObj = $colorObj->getHex();
if($hexObj != null){
if (method_exists($hexObj, "getHex")) {
$hexValue = $hexObj->getHex();
$classStyle = "class=\"fa fa-square\" style=\"color:" . $hexValue . "\"";
if (empty($hexValue) || ($hexValue == "#ffffff")) {
$classStyle = "class=\"fa fa-square-o\"";
}
}
}
}
}
break;
}
if (is_array($value)) {
$value = implode(" | ", $value);
}
$data->textAlign = $textAlign;
$data->value = $value;
return $data;
}
public function getVariantsPrices($variant, $iva)
{
$data = new \stdClass();
$precioReal = $variant->getPriceNumeric();
$precioIVAReal = 0;
$precioIVA = "";
$precioTotal = "";
if (!empty($precioReal)) {
$precioIVAReal = $variant->getPriceTax($iva);
$precioIVA = number_format($precioIVAReal, 2, ",", ".");
$precioTotal = number_format(((float) $precioReal) + ((float) $precioIVAReal), 2, ",", ".");
$precioReal = number_format($precioReal, 2, ",", ".");
}
$data->precioIVA = $precioIVA;
$data->precioTotal = $precioTotal;
$data->precioReal = $precioReal;
return $data;
}
public function getRelatedProducts($product)
{
$relatedProducts = [];
$attributes = $product->getAllAttributes($product);
$relatedProducts = array();
if (key_exists("relationproducts", $attributes)) {
$relationproducts = $product->getAttributeValue($attributes["relationproducts"]);
if (count($relationproducts) > 0) {
foreach ($relationproducts as $relationproduct) {
$relatedProducts[] = $relationproduct->getElement();
}
}
}
if (method_exists($product, "getGeneralrelatedproducts")) {
$relationproducts = $product->getGeneralrelatedproducts();
if (count($relationproducts) > 0) {
foreach ($relationproducts as $relationproduct) {
$relatedProducts[] = $relationproduct->getElement();
}
}
}
return $relatedProducts;
}
public function generateLink($product, array $params, array $extra): string
{
try {
/** @var DefaultProduct $linkProduct */
$linkProduct = $product->getLinkProduct();
$link = $linkProduct->getDetailUrl($params);
$authenticated = ($extra['authenticated']) ?? false;
$isProductlist = ($extra['isProductlist']) ?? false;
$isRelatedProduct = ($extra['isRelatedProduct']) ?? false;
$baseUrl = explode('?', $_SERVER['REQUEST_URI']);
$unique = "";
if (count($baseUrl) > 1) {
$unique = "?" . $baseUrl[1];
}
if ($isProductlist && !$isRelatedProduct) {
$urlArray = explode("/", $link);
$link = $baseUrl[0] . "/" . $urlArray[count($urlArray) - 1];
if ($authenticated) {
$link = $link . $unique;
}
}
}catch (\Exception $exception){
$link = '';
}
return $link;
}
//Get lower price of the product variants
public function getDefaultPriceWithDiscount($product,$userIdSage)
{
$mountOfVariants = count($product->getAllActiveVariants());
//Does it have variants?
$haveVariants = $mountOfVariants;
$optimized = ($haveVariants > 35);
if($mountOfVariants){
// START LOWER PRICE WITH DISCOUNT V2
$prices = $product->getVariantPriceAndIdList($optimized);
//replace this format 54,24 to 54.24
$prices = str_replace(',','.',$prices);
//convert string prices to float prices
$prices = array_map('floatval', $prices);
$min_value = min($prices);
$keys = array_keys($prices, $min_value);
//Calculate the discount but for one of the cheapest products found in its variants
$product = DefaultProduct::getById($keys[0]);
//END LOWER PRICE WITH DISCOUNT V2
}
return $this->shopService->getProductDiscount($product->getBsncode(), $userIdSage);
}
//Get lower price of the product variants
public function getPriceWithDiscount($product,$userIdSage): array
{
return $this->shopService->getProductDiscount($product->getBsncode(), $userIdSage);
}
public function getDefaultPrice($product)
{
$mountOfVariants = count($product->getAllActiveVariants());
$optimized = ($mountOfVariants > 35);
$prices = $product->getVariantPriceList($optimized);
if (empty($prices)) {
return 0;
}
$floatPrices = array_map(function($price) {
return floatval(str_replace(',', '.', $price));
}, $prices);
return min($floatPrices);
}
}