<?php
// src/Controller/DefaultController.php
namespace App\Controller;
use App\Entity\ProductCategory;
use App\Entity\ProductConstructor;
use App\Entity\ProductSpecificationValue;
use App\Entity\ProductType;
use App\Entity\SeoFormula;
use App\Entity\StaticPage;
use App\Repository\FaqRepository;
use App\Services\SeoFormulaService;
use App\ZorrovAdmin\ApiBundle\Services\ConstructorCreateImageService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
class FrontendConstructorController extends AbstractController
{
/**
* @Route("/app/constructor/{main}/{category}/{type}", name="app_constructor")
*/
public function constructorCategoryTypection(FaqRepository $faqRepository, $main=null, $category=null, $type=null, Request $request)
{
// // If this is the first visit to the site, the default language is set to 'ua'
// if (!$request->hasPreviousSession() and $request->getLocale() == 'ru') {
// return $this->redirectToRoute('app_constructor', ['_locale' => 'ua', 'main'=>$main,'category'=>$category,'type'=>$type]);
// }
$staticPage = $this->getDoctrine()->getRepository(StaticPage::class)->findOneBy(['systemName' => 'constructor']);
$faqs = $faqRepository->getByPage('constructor');
$typeObject = $this->getDoctrine()->getRepository(ProductType::class)
->findBySystemName($type);
$categoryObj = $this->getDoctrine()->getRepository(ProductCategory::class)
->findOneBy(array('slug'=>$category));
//test construсtor temprorary fix
$url = 'app_constructor';
$template = 'frontend/constructor/constructor.html.twig';
if($main == 'caps'
or $main == 'mirror'
or $main == 'badges'
or $main == 'puzzle'
or $main == 'christmas-toys'
or $main == 'paintings'
or $main == 'covers'
or $main == 'apron'
or $main == 'mouse-pad'
or $main == 'pillows'
or $main == 'holders'
or $main == 'notebook'
or $main == 'bags'
or $main == 'magnets'
// or $main == 'thermos'
or $main == 'thermal-stickers'
or $main == 'tattoo'
or $main == 'longsleeves'
or $main == 'hoodie-sweatshirts'
or $main == 't-shirts'
or $main == 'case'
or $main == null
or ($main == 'mugs' and $category == 'test-cup')
){
$url = 'app_canvas_constructor';
$template = 'frontend/constructor/canvas-constructor.html.twig';
}
//end of test construсtor temprorary fix
if($category and $type){
$constructor = $this->getDoctrine()->getRepository(ProductConstructor::class)->
findOneByCategoryAndType($category,$type);
if(!empty($constructor) and !$constructor[0]->getInStock()){
return $this->redirect($this->generateUrl($url));
}
}
$categoryTitle = '';
if($typeObject and $main != 'case'){
$metaTitle = ($typeObject->translate()->getTitleForTypePage()) ? $typeObject->translate()->getTitleForTypePage() : $typeObject->translate()->getTitle();
$metaDescription = ($typeObject->translate()->getSeoDescription())? $typeObject->translate()->getSeoDescription() : $metaTitle;
}
elseif ($main == 'case') {
if($categoryObj){
$categoryTitle = $categoryObj->getParent()->translate()->getTitleForProduct().' '.$categoryObj->translate()->getTitleForProduct();
$metaTitle = '【Создать Свой Чехол на Телефон '.$categoryTitle.'】 Конструктор Чехлов | Сделать Чехол со Своим Дизайном, Принтом, Фото Онлайн в Украине';
$metaDescription = 'Создайте свой уникальный чехол на телефон '.$categoryTitle.' при помощи специального конструктора на сайте zorrov.com! Вы можете использовать любой дизайн, принт, фото, чтобы подчеркнуть свою индивидуальность!';
}
}
else{
$metaTitle = null;
$metaDescription = null;
}
$canonicalUrl = $this->generateUrl($url);
if($category and $main != 'case'){
if($categoryObj and $categoryObj->getParent() and
!$categoryObj->getParent()->getShowChildrenOnWebsite()){
$canonicalUrl = $this->generateUrl('app_constructor_category', array('slug'=>$categoryObj->getParent()->getSlug()));
}
else{
$canonicalUrl = $this->generateUrl('app_constructor_category', array('slug'=>$category));
}
}
return $this->render($template, [
'metaTitle'=>$metaTitle,
'metaDescription'=>$metaDescription,
'main'=>$main,
'category'=>$category,
'categoryTitle'=>$categoryTitle,
'staticPage'=>$staticPage,
'type'=>$type,
'canonicalUrl'=>$canonicalUrl,
'faqs'=>$faqs
]);
}
/**
* @Route("/app/test/constructor/{main}/{category}/{type}", name="app_canvas_constructor")
*/
public function testConstructorCategoryTypection(FaqRepository $faqRepository, $main=null, $category=null, $type=null)
{
$staticPage = $this->getDoctrine()->getRepository(StaticPage::class)->findOneBy(['systemName' => 'constructor']);
$faqs = $faqRepository->getByPage('constructor');
$typeObject = $this->getDoctrine()->getRepository(ProductType::class)
->findBySystemName($type);
$categoryObj = $this->getDoctrine()->getRepository(ProductCategory::class)
->findOneBy(array('slug'=>$category));
if($category and $type){
$constructor = $this->getDoctrine()->getRepository(ProductConstructor::class)->
findOneByCategoryAndType($category,$type);
if(!empty($constructor) and !$constructor[0]->getInStock()){
return $this->redirect($this->generateUrl('app_canvas_constructor'));
}
}
$categoryTitle = '';
if($typeObject and $main != 'case'){
$metaTitle = ($typeObject->translate()->getTitleForTypePage()) ? $typeObject->translate()->getTitleForTypePage() : $typeObject->translate()->getTitle();
$metaDescription = ($typeObject->translate()->getSeoDescription())? $typeObject->translate()->getSeoDescription() : $metaTitle;
}
elseif ($main == 'case') {
if($categoryObj){
$categoryTitle = $categoryObj->getParent()->translate()->getTitleForProduct().' '.$categoryObj->translate()->getTitleForProduct();
$metaTitle = '【Создать Свой Чехол на Телефон '.$categoryTitle.'】 Конструктор Чехлов | Сделать Чехол со Своим Дизайном, Принтом, Фото Онлайн в Украине';
$metaDescription = 'Создайте свой уникальный чехол на телефон '.$categoryTitle.' при помощи специального конструктора на сайте zorrov.com! Вы можете использовать любой дизайн, принт, фото, чтобы подчеркнуть свою индивидуальность!';
}
}
else{
$metaTitle = null;
$metaDescription = null;
}
$canonicalUrl = $this->generateUrl('app_canvas_constructor');
if($category and $main != 'case'){
if($categoryObj and $categoryObj->getParent() and
!$categoryObj->getParent()->getShowChildrenOnWebsite()){
$canonicalUrl = $this->generateUrl('app_constructor_category', array('slug'=>$categoryObj->getParent()->getSlug()));
}
else{
$canonicalUrl = $this->generateUrl('app_constructor_category', array('slug'=>$category));
}
}
return $this->render('frontend/constructor/canvas-constructor.html.twig', [
'metaTitle'=>$metaTitle,
'metaDescription'=>$metaDescription,
'main'=>$main,
'category'=>$category,
'categoryTitle'=>$categoryTitle,
'staticPage'=>$staticPage,
'type'=>$type,
'canonicalUrl'=>$canonicalUrl,
'faqs'=>$faqs
]);
}
/**
* @Route("/constructor-categories/", name="app_constructor_categories")
*/
public function constructorCategoriesAction(SeoFormulaService $seoFormulaService)
{
$categories = $this->getDoctrine()->getRepository(ProductCategory::class)
->findTopCategoriesForConstructorMenu();
$staticPage = $this->getDoctrine()->getRepository(StaticPage::class)->findOneBy(array('systemName'=>'constructor-categories'));
return $this->render('frontend/constructor/categories.html.twig', [
'seo'=>$staticPage,
'categories'=>$categories,
]);
}
/**
* @Route("/constructor-category/{slug}/{filters}", name="app_constructor_category")
*/
public function constructorCategoryAction($slug,
SeoFormulaService $seoFormulaService,
TranslatorInterface $translator,
$filters = '')
{
$category = $this->getDoctrine()->getRepository(ProductCategory::class)
->findOneBy(array('slug'=>$slug));
$main = $category->getMain()->getSlug();
$descedants = $category->getDescendants();
$descedantIds = array();
foreach ($descedants as $descedant){
$descedantIds[] = $descedant->getId();
}
$filterStr = $filters;
// dump($filterStr); die();
$filters = $this->prepareFilters($filters);
if(!$filters)
throw $this->createNotFoundException('Filters does not exist');
$constructors = $this->getDoctrine()->getRepository(ProductConstructor::class)
->findByCategoryIds($descedants);
$constructorProducts = array();
$catTitle = str_replace($translator->trans('constructor.case_for',[],'translation'), '',$category->translate()->getH1());
$dropshipper = ($this->getUser() and $this->getUser()->getIsDropShipper());
// if ($this->getUser() and $this->getUser()->getUsername()=='admin'){
// dump($constructors); die();
// }
$typeIds = array();
foreach ($constructors as $constructor){
// $element = $constructors[$innerCategory['category']->getSlug()];
$preview = $constructor->getPreview();
if(!$preview){
if($constructor->getConstructorBackground()){
$preview = $constructor->getConstructorBackground();
}
else{
$preview = $constructor->getCategory()->getConstructorBackground();
}
}
$type = $constructor->getType();
$typeIds[] = $type->getId();
$title = ($type->translate()->getTitleForTypePage()) ?
str_replace('%category%', $catTitle,$type->translate()->getTitleForTypePage()) :
$type->translate()->getTitle();
if($dropshipper and $type->getDropshipperConstructorPrice()){
$price = (int)round($type->getDropshipperConstructorPrice(),0);
$originalPrice = $price;
}
else{
$price = (int)round($type->getConstructorPrice(),0);
$originalPrice = (int)round($type->getConstructorOriginalPrice(),0);
}
$secondPreview = '';
if(count($type->getConstructorGalleryImages())){
$secondPreview = $type->getConstructorGalleryImages()->first()->getImage();
}
$constructorProducts[] = array(
'id' => $constructor->getId(),
'preview' => $preview,
'secondPreview' => $secondPreview,
'inStock' => $constructor->getInStock(),
'title' => $title,
'link' => $this->generateUrl('app_constructor_product',array('id'=>$constructor->getId())),
'price' => $price,
'originalPrice' => $originalPrice,
'constructorLink' => $this->generateUrl('app_constructor',
array('main'=>$main,'category'=>$constructor->getCategory()->getSlug(),'type'=>$type->getSystemName())),
);
}
// dump($typeIds);
// dump($descedantIds); die();
// $productsSpecValues =
// $productsSpecValuesCount = $productHasSpecificationValueRepository->countAllProductsBySpecificationValues($produ
$productsSpecValues = $this->getProductSpecificationValuesForConstructorProduct($descedantIds,$typeIds);
$specifications = $this->prepareSpecificationArray($productsSpecValues, $filters['filters'], $constructors);
dump($specifications); die();
$seo = $this->seoConstructorCategoryData($category,$seoFormulaService);
// dump($constructorProducts); die();
$filterStr = $this->prepareFilterStr($filterStr);
return $this->render('frontend/constructor/category.html.twig', [
'seo'=>$seo,
'category'=>$category,
'filters' => $filters,
'filterStr' => $filterStr,
'constructorProducts'=>$constructorProducts,
]);
}
/**
* @Route("/constructor-category-filters-apply/{slug}/{sort}", name="app_constructor_category_filters_apply")
*/
public function constructorCategoryFiltersApplyAction($slug, $sort, Request $request)
{
$filterStr = $this->filtersApply($request, $sort);
return $this->redirectToRoute('app_category_show', ['slug' => $slug, 'filters' => $filterStr]);
}
/**
* @Route("/constructor-product/{id}", name="app_constructor_product")
*/
public function constructorProductAction($id, Request $request, TranslatorInterface $translator,
ConstructorCreateImageService $constructorService,
SeoFormulaService $seoFormulaService)
{
$constructor = $this->getDoctrine()->getRepository(ProductConstructor::class)
->find($id);
if(!$constructor){
throw $this->createNotFoundException('The constructor does not exist');
}
$type = $constructor->getType();
$category = $constructor->getCategory();
if(!$type->getShowOnWebsite()){
return $this->redirect($this->generateUrl('app_homepage'));
}
$main = $category->getMain()->getSlug();
$title = $constructorService->createPreviewTitle($category, $type, $request->getLocale());
$catTitle = str_replace($translator->trans('constructor.case_for',[],'translation'), '',$category->translate()->getH1());
$metaTitle = ($type->translate()->getTitleForTypePage()) ? $type->translate()->getTitleForTypePage() : $type->translate()->getTitle();
$metaTitle = str_replace('%category%', $catTitle, $metaTitle);
$preview = $constructor->getPreview();
$dropshipper = ($this->getUser() and $this->getUser()->getIsDropShipper());
if($dropshipper and $type->getDropshipperConstructorPrice()){
$price = $type->getDropshipperConstructorPrice();
$originalPrice = $price;
}
else{
$price = $type->getConstructorPrice();
$originalPrice = $type->getConstructorOriginalPrice();
}
if(!$preview){
if($constructor->getConstructorBackground()){
$preview = $constructor->getConstructorBackground();
}
else{
$preview = $constructor->getCategory()->getConstructorBackground();
}
}
$wholesalePrices = $type->hasWholesalePrices() ? $type->getWholesalePrices() : array();
$specificationValues = $this->getConstructorProductsSpecification($category, $type);
$parentCategory = ($category->getAncestors()->count()) ? $category->getAncestors()->last(): $category;
$info = $this->getInfo($type, $request->getLocale());
$constructorProduct = array(
'id' => $id,
'title' => $title,
'parentCategory' => $parentCategory->translate()->getTitle(),
'description' => $type->translate()->getDescription(),
'metaTitle' => $metaTitle,
'metaDescription' => ($type->translate()->getSeoDescription())? $type->translate()->getSeoDescription() : $metaTitle,
'image' => $preview,
'price' => $price,
'originalPrice' => $originalPrice,
'wholesalePrices' => $wholesalePrices,
'object' => $type,
'info' => $info,
'inStock' => $constructor->getInStock(),
'gallery' => $type->getConstructorGalleryImages(),
'constructorLink' => $this->generateUrl('app_constructor',
array('main'=>$main,'category'=>$constructor->getCategory()->getSlug(),'type'=>$type->getSystemName())),
);
$seo = $this->seoConstructorCategoryData($category,$seoFormulaService);
return $this->render('frontend/constructor/product.html.twig', [
'seo'=>$seo,
'category'=>$category,
'constructor'=>$constructorProduct,
'specificationValues'=>$specificationValues,
]);
}
private function seoConstructorCategoryData($category,$seoFormulaService)
{
$seo = array();
$seoFormula = $category->getTreeSeoFormula();
if(!$seoFormula){
$seoFormula = $this->getDoctrine()->getRepository(SeoFormula::class)
->findMainFormula()[0];
}
$categoryTitleFields = array(
'h1' => $category->translate()->getH1(),
'title' => $category->translate()->getTitle(),
'titleForProductCyrillic' => $category->translate()->getTitleForProductCyrillic(),
);
$seo['title'] = $seoFormulaService->getTitleForCustom($seoFormula,$categoryTitleFields);
$categoryDescriptionFields = array(
'title' => $category->translate()->getTitle(),
'h1' => $category->translate()->getH1(),
);
$seo['seo_description'] = $seoFormulaService->getSeoDescriptionForCustom($seoFormula,$categoryDescriptionFields);
$categoryOnThePageFields = array(
'parentTitleForProduct' => $category->getParent() ? $category->getParent()->translate()->getTitleForProduct() : $category->translate()->getTitleForProduct(),
'titleForProduct' => $category->translate()->getTitleForProduct(),
);
$seo['h1'] = $seoFormulaService->getH1ForCustom($seoFormula,$categoryOnThePageFields);
$seo['h1_second'] = $seoFormulaService->getH1SecondForCustom($seoFormula,$categoryOnThePageFields);
$seo['description'] = $seoFormulaService->getDescriptionForCustom($seoFormula,$categoryOnThePageFields);
return $seo;
}
private function getConstructorProductsSpecification($category, $type){
$specificationValues = array();
$ancestors = $category->getAncestors();
$ancestors = array_reverse($ancestors->toArray());
$ancestors[] = $category;
if($category->hasTreeSpecificationValues()){
$specificationValues['category'] = array();
foreach (array_reverse($ancestors) as $category){
if(!$category->getSpecificationValues()->isEmpty()){
foreach ($category->getSpecificationValues() as $catSpecValue){
if($catSpecValue->getProductSpecification()->getShowOnWebsite() and $catSpecValue->getProductSpecificationValue()){
$specificationValues['category'][$catSpecValue->getProductSpecification()->getId()] = array(
'specification'=>$catSpecValue->getProductSpecification()->translate()->getTitle(),
'values'=>array(
$catSpecValue->getProductSpecificationValue()->translate()->getValue(),
)
);
}
}
}
}
if(empty($specificationValues['category'])){
unset($specificationValues['category']);
}
}
if($type->hasSpecificationValues()){
$specificationValues['product-type'] = array();
foreach ($type->getSpecificationValues() as $typeSpecValue){
if($typeSpecValue->getProductSpecification()->getShowOnWebsite()) {
$id = $typeSpecValue->getProductSpecification()->getId();
if (empty($specificationValues['product-type'][$id])) {
$specificationValues['product-type'][$id] = array(
'specification' => $typeSpecValue->getProductSpecification()->translate()->getTitle(),
'values' => array(
$typeSpecValue->getProductSpecificationValue()->translate()->getValue(),
)
);
} else {
$specificationValues['product-type'][$id]['values'][] = $typeSpecValue->getProductSpecificationValue()->translate()->getValue();
}
}
}
if(empty($specificationValues['product-type'])){
unset($specificationValues['product-type']);
}
}
return $specificationValues;
}
private function getProductSpecificationValuesForConstructorProduct($catIds, $typeIds)
{
$catValues = $this->getDoctrine()->getRepository(ProductSpecificationValue::class)->findAllByCategories($catIds);
$catValuesIds = array_keys($catValues);
$typeValues = $this->getDoctrine()->getRepository(ProductSpecificationValue::class)->findAllByTypes($typeIds);
foreach ($typeValues as $typeValue){
if(!in_array($typeValue->getId(),$catValuesIds)){
$catValues[$typeValue->getId()] = $typeValue;
}
}
return $catValues;
}
private function getInfo($type, $locale)
{
$info = null;
if($type and $type->getInfo()
and $type->getInfo()->getInfoItems()){
$info = array(
'title'=>$type->getInfo()->getTitle(),
'items'=>array()
);
foreach ($type->getInfo()->getInfoItems() as $item){
if($item->translate($locale)->getValue()){
$info = $this->getInfoItem($info, $item, $locale);
}
else{
$info = $this->getInfoItem($info, $item, 'ru');
}
}
}
return $info;
}
private function getInfoItem($info, $item, $locale){
$values = explode('/',$item->translate($locale)->getValue());
if(count($values) == 2 and $item->translate($locale)->getParameter()){
$info['items'][] = array(
'label'=>$item->translate($locale)->getParameter(),
'min'=>$values[0],
'max'=>$values[1],
);
}
return $info;
}
private function prepareFilterStr($filterStr)
{
$filterStr = trim(explode('page=',$filterStr)[0],';');
$filterStr = trim(explode('sort=',$filterStr)[0],';');
return $filterStr;
}
private function prepareFilters($filters)
{
$notFound = !empty($filters);
$prepared = array(
'page' => 1,
'sort' => $this->getParameter('default_sort'),
'filters' => array(),
);
return $prepared;
$filterArr = explode(';', $filters);
// dump($filterArr);
// die();
$filterTexts = array();
foreach ($filterArr as $filterItem){
if(strpos($filterItem,'page') !== false) {
$prepared['page'] = (int)str_replace('page=', '', $filterItem);
$notFound = false;
continue;
}
if(strpos($filterItem,'sort') !== false) {
$prepared['sort'] = str_replace('sort=', '', $filterItem);
$notFound = false;
continue;
}
$filterParts = explode('=', $filterItem);
if(count($filterParts) == 2){
if(empty($filterTexts[$filterParts[0]])){
$filterTexts[$filterParts[0]] = array();
}
$filterTexts[$filterParts[0]] = explode(',', $filterParts[1]);
$notFound = false;
}
}
if($filterTexts){
foreach ($filterTexts as $systemName=>$filter){
$values = $this->getDoctrine()->getRepository(ProductSpecificationValue::class)
->findBySystemNamesAndSpecSystemName($systemName,$filter);
$prepared['filters'] = array_merge($prepared['filters'], array_keys($values));
}
}
if($notFound) return null;
return $prepared;
}
private function filtersApply($request, $sort)
{
$filterIds = $request->request->get('specifications');
dump($filterIds); die();
// dump($filterIds); die();
// foreach ($filterIds as $filterId){
// if(is_string($filterId)){
// return $this->redirectToRoute('app_category_show', ['slug' => $filterId]);
// }
// }
$filtersMin = $this->getDoctrine()->getRepository(ProductSpecificationValue::class)
->findByIdsMinimized($filterIds);
$filters = array();
foreach ($filtersMin as $filterRow){
if(empty($filters[$filterRow['productSpecification']['systemName']])){
$filters[$filterRow['productSpecification']['systemName']] = array();
}
$filters[$filterRow['productSpecification']['systemName']][] = $filterRow['systemName'];
}
// $filters = array_column($filtersMin, 'systemName');
$filterStr = '';
foreach($filters as $key => $filter){
if($filter)
$filterStr .= $key.'='.implode(",", $filter).';';
}
$filterStr = rtrim($filterStr, ";");
// dump($filtersMin);
// dump($filterStr); die();
// $filterStr = ($filters) ? implode(";", $filters) : '';
if($sort and $sort != $this->getParameter('default_sort')){
if($filterStr)
$filterStr .= ';sort='.$sort;
else
$filterStr = 'sort='.$sort;
}
return $filterStr;
}
private function prepareSpecificationArray($values, $filters, $constructors)
{
$filters = [];
$specifications = array();
// $productsSpecValuesCountArr = $this->prepareValuesConstructorCountArray(array_keys($values),$constructors);
foreach ($values as $value){
$specification = $value->getProductSpecification();
if(empty($specifications[$specification->getId()])){
$specifications[$specification->getId()] = array(
'title' => $specification->translate()->getTitle(),
'position' => $specification->getPosition() ? $specification->getPosition() : 0,
'values' => array()
);
}
// if(!empty($productsSpecValuesCountArr[$value->getId()])){
$specifications[$specification->getId()]['values'][$value->translate()->getValue()] = array(
'id' => $value->getId(),
'value' => $value->translate()->getValue(),
// 'count' => $productsSpecValuesCountArr[$value->getId()],
'checked' => in_array($value->getId(), $filters)
);
// }
}
$result = $specifications;
foreach ($specifications as $key => $specification){
ksort($specification['values']);
$result[$key]['values'] = $specification['values'];
}
//to sort specifications by position
$price = array_column($result, 'position');
array_multisort($price, SORT_DESC, $result);
return $result;
}
private function prepareValuesConstructorCountArray($values,$constructors)
{
$countArr = array();
dump($values);
foreach ($values as $valueId){
foreach ($constructors as $constructor){
$type = $constructor->getType();
$contain = $type->productContainsProductSpecificationValueId($valueId);
if($contain){
if(empty($countArr[$valueId])){
$countArr[$valueId] = 1;
}
else{
$countArr[$valueId]++;
}
}
}
}
dump($countArr); die();
return $countArr;
}
// public function constructorImages(
// $categorySlug,$typeName,
// ProductConstructorRepository $productConstructorRepository
// )
// {
// $constructor = $productConstructorRepository->findOneByCategoryAndType($categorySlug,$typeName);
// dump($constructor); die();
// $categories = $this->getDoctrine()->getRepository(ProductCategory::class)
// ->findCategoriesForConstructorMenu('case');
// return $this->render('frontend/parts/top_constructor_menu.html.twig', [
// 'categories' => $categories
// ]);
// }
}