<?php
namespace App\AtechNet\CoreBundle\Controller;
use App\AtechNet\CoreBundle\Entity\Product;
use App\AtechNet\CoreBundle\Helper\Furbify\Image;
use App\AtechNet\CoreBundle\Helper\Furbify\ProductHelper;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class WizardController extends AbstractController
{
public const MAIN_CATEGORY_LAPTOP = 5;
// 1.
public const L_OFFICE = 21;
// 2.
public const L_TRAVEL = 22;
public const L_INTERNET = 87;
public const L_SENIOR = 43;
// 3.
public const L_WORKSTATION = 113;
public const L_GAMER = 24;
public const MAIN_CATEGORY_PC = 4;
// 1.
public const PC_OFFICE = 116;
public const PC_AIO = 84;
// 2.
public const PC_SENIOR = 15;
public const PC_INTERNET = 86;
// 3.
public const PC_WORKSTATION = 14;
// + AIO
// 4.
public const PC_GAMER = 17;
private const WIZARD_ELEMENTS = [
'title' => 'wizard_pc_or_laptop_question',
'description' => 'wizard_select_one',
'nextSteps' => [
'title' => 'wizard_question_for_using',
'description' => 'wizard_select_max_two',
'items' => [
'laptop' => [
'cId' => self::MAIN_CATEGORY_LAPTOP, // cID => category ID
'type' => 'mc', // mc => main category
'value' => 'laptop', // value => for checkbox value attribute
'title' => 'wizard_c_laptop', // this will be passed to translator->trans()
'description' => 'product count goes here', // in maic category select, this string will be replaced to product count number
'icon' => 'wizard_laptop_default.svg', // checkbox icon
'nextSteps' => [
'office' => [
'cId' => [self::L_OFFICE],
'badges' => ['work'],
'type' => 'sc', // sc => sub category
'value' => 'office',
'title' => 'wizard_sc_laptop_office_title',
'description' => 'wizard_sc_laptop_office_description',
'icon' => 'wizard_laptop_office_work.svg',
'filters' => [
// pl: cpu => [i3, i7] <== any filter can be added in this format
142 => ['1357', '1359'],
],
// at last page what questions to ask before price filtering,
// these values are references for this->lastParams object items
'lastParams' => ['screen_size'],
],
'standard' => [
'cId' => [self::L_TRAVEL, self::L_INTERNET, self::L_SENIOR],
'badges' => ['travel', 'internet', 'senior'],
'type' => 'sc',
'value' => 'standard',
'title' => 'wizard_sc_laptop_standard_title',
'description' => 'wizard_sc_laptop_standard_description',
'icon' => 'wizard_laptop_pc_home_use-2.svg',
'filters' => [],
'lastParams' => ['screen_size'],
],
'powerful' => [
'cId' => [self::L_WORKSTATION, self::L_GAMER],
'badges' => ['workstation', 'gamer'],
'type' => 'sc',
'value' => 'powerful',
'title' => 'wizard_sc_laptop_powerful_title',
'description' => 'wizard_sc_laptop_powerful_description',
'icon' => 'wizard-laptop-icon-workstation.svg',
'filters' => [],
'lastParams' => ['screen_size'],
],
],
],
'pc' => [
'cId' => self::MAIN_CATEGORY_PC,
'type' => 'mc',
'value' => 'pc',
'title' => 'wizard_c_pc',
'description' => 'count',
'icon' => 'wizard_pc_default.svg',
'nextSteps' => [
'standard' => [
'cId' => [self::PC_SENIOR, self::PC_INTERNET],
'badges' => ['senior', 'internet'],
'type' => 'sc',
'value' => 'standard',
'title' => 'wizard_sc_pc_standard_title',
'description' => 'wizard_sc_pc_standard_description',
'icon' => 'wizard_laptop_pc_home_use-2.svg',
'filters' => [],
'lastParams' => ['case_size'],
],
'office' => [
'cId' => [self::PC_OFFICE, self::PC_AIO],
'badges' => ['work'],
'type' => 'sc',
'value' => 'office',
'title' => 'wizard_sc_pc_office_title',
'description' => 'wizard_sc_pc_office_description',
'icon' => 'wizard_pc_default.svg',
'filters' => [],
'lastParams' => ['case_size'],
],
'powerFul' => [
'cId' => [self::PC_WORKSTATION, self::PC_AIO],
'badges' => ['workstation'],
'type' => 'sc',
'value' => 'powerFul',
'title' => 'wizard_sc_pc_powerful_title',
'description' => 'wizard_sc_pc_powerful_description',
'icon' => 'wizard-pc-workstation.svg',
'filters' => [],
'lastParams' => ['case_size'],
],
'gamer' => [
'cId' => [self::PC_GAMER],
'badges' => ['gamer'],
'type' => 'sc',
'value' => 'gamer',
'title' => 'wizard_sc_pc_gamer_title',
'description' => 'wizard_sc_pc_gamer_description',
'icon' => 'wizard-laptop-pc-gamer.svg', // if empty, placeholder will be inserted
'filters' => [],
'lastParams' => ['case_size'],
],
],
],
],
],
];
private const LAST_PARAMS = [
'screen_size' => [
'title' => 'wizard_screen_size_question', // for translator->trans()
'description' => 'wizard_screen_size_description', // for translator->trans()
'filterKey' => '12', // the screen filtering key
'items' => [
'colTo14' => [
'type' => 'screen_size',
'value' => 'colTo14', // checkbox value
'title' => 'wizard_smaller_screen',
'description' => 'wizard_smaller_screen_description',
'icon' => 'wizard-laptop-icon-mini.svg',
'filters' => [609, 1219, 193, 398, 194],
],
'col14' => [
'type' => 'screen_size',
'value' => 'col14',
'title' => 'wizard_col14_screen',
'description' => 'wizard_col14_screen_description',
'icon' => 'wizard-laptop-icon-medium.svg',
'filters' => [195, 196],
],
'colFrom15' => [
'type' => 'screen_size',
'value' => 'colFrom15',
'title' => 'wizard_from_col15_screen',
'description' => 'wizard_from_col15_screen_description',
'icon' => 'wizard-laptop-icon-large.svg',
'filters' => [251, 674],
],
],
],
'case_size' => [
'title' => 'wizard_case_size_question',
'description' => 'wizard_screen_size_description',
'filterKey' => '1',
'items' => [
'mini' => [
'type' => 'case_size',
'value' => 'mini',
'title' => 'wizard_minipc',
'description' => 'wizard_minipc_description',
'icon' => 'wizard-pc-mini-pc.svg',
'filters' => [1273, 3, 685],
],
'sff' => [
'type' => 'case_size',
'value' => 'sff',
'title' => 'wizard_sffpc',
'description' => 'wizard_sffpc_description',
'icon' => 'wizard-pc-sff.svg',
'filters' => [1, 2],
],
'tower' => [
'type' => 'case_size',
'value' => 'tower',
'title' => 'wizard_towerpc',
'description' => 'wizard_towerpc_description',
'icon' => 'wizard-pc-tower.svg',
'filters' => [4, 5, 250],
],
],
],
];
private const MAX_STEP_NUMBER = 4;
/**
* @Route("/wizard", name="wizard_home", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/wizard", name="wizard_home_locale", defaults={"_locale":""})
* @param Request $request
* @return Response
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public function indexAction(Request $request): Response
{
return $this->redirectToRoute('wizard_steps', [
'step' => 1,
]);
}
/**
* @Route("/wizard/steps", name="wizard_steps", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/wizard/steps", name="wizard_steps_locale", defaults={"_locale":""})
* @param Request $request
* @return Response
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public function stepsAction(Request $request): Response
{
$step = $request->query->all()['step'] ?? 0;
if ($step === 0) {
return $this->redirectToRoute('wizard_home');
}
if ($this->getEnvironment() == 'prod') {
\Sentry\configureScope(function (\Sentry\State\Scope $scope): void {
$scope->setUser([
'ip_address' => $_SERVER['REMOTE_ADDR'],
]);
});
}
$data['seoTitle'] = 'Furbify Wizard ' . $step;
$data['header'] = $this->getHeader($request);
$data['footer'] = $this->getFooter($request);
$data['step'] = $step;
$data['stepsOptions'] = [
'currentStep' => $step,
'count' => self::MAX_STEP_NUMBER,
];
$multiStore = $this->getMultiStoreHelper($request);
$domain = $multiStore->getDomain();
$translator = $this->getTranslator();
$data['currentWizardPage'] = [];
switch ($step) {
case 1:
$laptopCount = $this->getProductHelper($request)->getTotalByFilters([
'filterCategoryId' => self::MAIN_CATEGORY_LAPTOP,
]);
$pcCount = $this->getProductHelper($request)->getTotalByFilters([
'filterCategoryId' => self::MAIN_CATEGORY_PC,
]);
$wizardElements = self::WIZARD_ELEMENTS;
// Insert each main categories prouduct count
$wizardElements['nextSteps']['items']['laptop']['description'] = $laptopCount . ' ' . $translator->trans('wizard_count_product');
$wizardElements['nextSteps']['items']['pc']['description'] = $pcCount . ' ' . $translator->trans('wizard_count_product');
$data['currentWizardPage'] = $wizardElements;
break;
case 2:
$mainCategory = $request->query->all()['mc'];
$data['currentWizardPage']['title'] = self::WIZARD_ELEMENTS['nextSteps']['title'];
$data['currentWizardPage']['description'] = self::WIZARD_ELEMENTS['nextSteps']['description'];
$data['currentWizardPage']['nextSteps']['items'] = self::WIZARD_ELEMENTS['nextSteps']['items'][$mainCategory]['nextSteps'];
$data['currentWizardPage']['mc'] = $mainCategory;
break;
case 3:
$mainCategory = $request->query->all()['mc'];
$subCategory = $request->query->all()['sc'];
$data['currentWizardPage']['title'] = self::WIZARD_ELEMENTS['nextSteps']['title'];
$data['currentWizardPage']['description'] = self::WIZARD_ELEMENTS['nextSteps']['description'];
$data['currentWizardPage']['mc'] = $mainCategory;
$data['currentWizardPage']['sc'] = $subCategory;
$lastParams = self::WIZARD_ELEMENTS['nextSteps']['items'][$mainCategory]['nextSteps'][$subCategory]['lastParams'];
$priceFilters = [
'domainId' => $domain->getId(),
'categoryIds' => self::WIZARD_ELEMENTS['nextSteps']['items'][$mainCategory]['nextSteps'][$subCategory]['cId'],
'filterPriceMin' => null,
'filterPriceMax' => null,
];
$subCategory = self::WIZARD_ELEMENTS['nextSteps']['items'][$mainCategory]['nextSteps'][$subCategory];
$priceFilters['categoryIds'] = $subCategory['cId'];
$priceFilters['filterBadge'] = implode(',', $subCategory['badges']);
foreach ($lastParams as $key => $value) {
$data['currentWizardPage']['lastParams'][$value] = self::LAST_PARAMS[$value];
}
$data['currentWizardPage']['nextSteps']['items'] = self::WIZARD_ELEMENTS['nextSteps']['items'][$mainCategory]['nextSteps'];
break;
case 4:
$mainCategory = $request->query->get('mc');
$subCategory = $request->query->get('sc');
$selectedAttr = $request->query->get('filterAttr');
$selectedParam = $request->query->get('filter')[0];
$filters = [];
$data['currentWizardPage']['mc'] = $mainCategory;
$data['currentWizardPage']['sc'] = $subCategory;
$data['currentWizardPage']['selectedAttribute'] = $selectedAttr;
$data['currentWizardPage']['attributeValue'] = $selectedParam;
$lastParams = self::WIZARD_ELEMENTS['nextSteps']['items'][$mainCategory]['nextSteps'][$subCategory]['lastParams'];
$priceFilters = [
'domainId' => $domain->getId(),
'categoryIds' => self::WIZARD_ELEMENTS['nextSteps']['items'][$mainCategory]['nextSteps'][$subCategory]['cId'],
'filterPriceMin' => null,
'filterPriceMax' => null,
'filterAttribute' => [
self::LAST_PARAMS[$selectedAttr]['filterKey'] => implode(',', self::LAST_PARAMS[$selectedAttr]['items'][$selectedParam]['filters']),
],
];
$subCategory = self::WIZARD_ELEMENTS['nextSteps']['items'][$mainCategory]['nextSteps'][$subCategory];
$priceFilters['categoryIds'] = $subCategory['cId'];
$priceFilters['filterBadge'] = implode(',', $subCategory['badges']);
$productRepo = $this->getEntityManager()->getRepository(Product::class);
$priceFilters['filterType'] = $productRepo->getProductTypeIds($priceFilters['categoryIds']);
$filters = $this->getProductHelper($request)->buildPriceFilterForWizard($priceFilters);
$data['filterPriceMin'] = null;
$data['filterPriceMax'] = null;
$data['filtersAttrs'] = $filters;
break;
}
$data['currency'] = $domain->getCurrency();
if ($step == self::MAX_STEP_NUMBER) {
// return rendered view
return $this->render('AtechNetCoreBundle/Wizard/lastStep.html.twig', $data);
}
// return rendered view
return $this->render('AtechNetCoreBundle/Wizard/step.html.twig', $data);
}
/**
* @Route("/wizard/result", name="wizard_result", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/wizard/result", name="wizard_result_locale", defaults={"_locale":""})
* @param Request $request
* @return Response
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public function productResultAction(Request $request): Response
{
$multiStore = $this->getMultiStoreHelper($request);
$domain = $multiStore->getDomain();
$mainCategory = $request->query->all()['mc'] ?? 0;
if ($mainCategory === 0) {
return $this->redirectToRoute('wizard_home');
}
$subCategory = $request->get('sc');
$checkedFilters = (array) $request->get('filtersAttrs');
$priceMin = $request->get('setterPriceMin');
$pricemax = $request->get('setterPricemax');
$sort = $request->get('sort') ?? 'price';
$order = $request->get('order') ?? 'asc';
$filters = [];
if (!empty($checkedFilters)) {
foreach ($checkedFilters as $key => $value) {
$v = json_decode(str_replace("'", '"', $value), true);
$this->updateFilters($v, $key, $filters);
}
}
$data = [];
$filters['limit'] = $data['limit'] = $request->get('limit') ?? 24;
// Sort By
$data['sortOrders'] = [];
$translator = $this->getTranslator();
$data['sortOrders'] = [
[
'text' => $translator->trans('low to high'),
'value' => 'price-asc',
'sort' => 'price',
'order' => 'asc',
], [
'text' => $translator->trans('high to low'),
'value' => 'price-desc',
'sort' => 'price',
'order' => 'desc',
], [
'text' => $translator->trans('Last added products'),
'value' => 'created-desc',
'sort' => 'created',
'order' => 'desc',
], [
'text' => $translator->trans('By name'),
'value' => 'name-asc',
'sort' => 'name',
'order' => 'asc',
],
];
$limits = [12, 24, 48, 96];
foreach ($limits as $value) {
$data['limits'][] = [
'text' => $value,
'value' => $value,
];
}
$filters['filterPriceMin'] = str_replace(' ', '', $priceMin);
$filters['filterPriceMax'] = str_replace(' ', '', $pricemax);
$filters['sort'] = $data['sort'] = $sort;
$filters['order'] = $data['order'] = $order;
$this->addFiltersFromSelectedWizardElement($mainCategory, $subCategory, $filters);
$filters['subCategory'] = $subCategory;
$filters['mainCategory'] = $mainCategory;
$data['filterData'] = $filters;
$data['seoTitle'] = 'Wizard result';
$data['header'] = $this->getHeader($request);
$data['footer'] = $this->getFooter($request);
$data['currency'] = $domain->getCurrency();
$data['precision'] = $domain->getPricePrecision();
foreach ($checkedFilters as $key => $value) {
$checkedFilters[$key] = str_replace('"', "'", $value);
}
$data['filterData']['filtersAttrs'] = $checkedFilters;
$totalCount = $this->getProductList($request, $subCategory, $mainCategory, true, $domain->getId(), $filters);
$page = $request->get('page') ?? 1;
$data['filterData']['total'] = $totalCount;
$data['filterData']['page'] = $page;
$data['checkedFilters'] = $checkedFilters;
$data['pagination'] = [
'total' => $totalCount,
'page' => $page,
'limit' => $data['limit'],
'moreButton' => true,
'url' => $this->url($request)->link('category', $filters),
];
$data['contentTitle'] = $totalCount > 0 ? $translator->trans('wizard_search_result_title') . ': ' . $totalCount : $translator->trans('No results');
return $this->render('AtechNetCoreBundle/Wizard/productResult.html.twig', $data);
}
/**
* @Route("/wizard/productCount", name="product_count", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/wizard/productCount", name="product_count_locale", defaults={"_locale":""})
* @param Request $request
* @return JsonResponse
*/
public function productCountAction(Request $request): JsonResponse
{
$json = [];
$mainCategory = $request->request->get('mc');
$subCategory = $request->request->get('sc');
$checkedFilters = $request->request->get('filtersAttrs');
$filters = [];
if (!empty($checkedFilters) && $checkedFilters != 0) {
foreach ($checkedFilters as $key => $value) {
$this->updateFilters($value, $key, $filters);
}
}
$this->addFiltersFromSelectedWizardElement($mainCategory, $subCategory, $filters);
$price = $request->request->get('price');
if (!empty($price)) {
$filters['filterPriceMin'] = str_replace(' ', '', $price['min']);
$filters['filterPriceMax'] = str_replace(' ', '', $price['max']);
}
if (!is_null($subCategory)) {
$multiStore = $this->getMultiStoreHelper($request);
$domain = $multiStore->getDomain();
$json = [
'productCount' => $this->getProductList($request, $subCategory, $mainCategory, true, $domain->getId(), $filters),
];
}
return new JsonResponse($json);
}
/**
* @param string $subCategory
* @param string $mainCategory
* @param array $filters
* @param bool $count
* @param Request $request
* @param int $domainId
* @return array|int|void
* @throws \Exception
*/
private function getProductList(Request $request, string $subCategory, string $mainCategory, bool $count, int $domainId, array $filters = [])
{
$subCategory = self::WIZARD_ELEMENTS['nextSteps']['items'][$mainCategory]['nextSteps'][$subCategory];
$filters['categoryIds'] = $subCategory['cId'];
$filters['filterBadge'] = implode(',', $subCategory['badges']);
$productRepo = $this->getEntityManager()->getRepository(Product::class);
$filters['filterType'] = $productRepo->getProductTypeIds($filters['categoryIds']);
$productCount = $this->getProductHelper($request)->getCountForWizard($filters);
// returns with product-count if param $count is set TRUE
if ($count) {
return $productCount;
}
$placeholder = $this->getImage('placeholder.png', '')->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
$filters['start'] = $filters['page'] > 1 ? ($filters['page'] - 1) * $filters['limit'] : 0;
$productList = $this->getProductHelper($request)->getStructuredDataByFilters($filters);
$i = 0;
$products = [];
foreach ($productList as $result) {
$image = $placeholder;
if (is_object($result['images'])) {
$image = $this->getImage($result['images'], 'product/' . $result['code'])->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
}
$products[] = [
'id' => $result['id'],
'code' => $result['code'],
'title' => ProductHelper::getHeadingTitle($result, true),
'vendor' => $result['vendor'],
'vendorId' => $result['vendorId'],
'labels' => $result['badges'],
'rawPrice' => $result['rawPrice'],
'price' => $result['vatPrice'],
'rawSpecial' => ($result['isDiscounted'] ? $result['rawDiscountPrice'] : false),
'special' => ($result['isDiscounted'] ? $result['discountVatPrice'] : false),
'image' => $image,
'attributes' => $result['attributes'],
'attributesListTxt' => $result['attributesListTxt'],
'available' => $result['availableQty'],
'type' => $result['productType'],
'typeId' => $result['productTypeId'],
'href' => $this->url($request)->link('product', [
'product_id' => $result['id'],
'isBazaar' => $result['isBazaar'] ?? 0
]),
'active' => $result['active'],
'timedSalesActive' => $result['timedSalesActive'],
'reviewCount' => $result['reviewCount'],
'reviewStars' => $result['reviewStars'],
'reviews' => $result['reviews'],
'freeShipping' => $result['freeShipping'],
'warrantyYear' => $this->getWarrantyForProductType($domainId, $result['productTypeId'])['year'],
'labelOS' => $this->getProductHelper($request)->getOSLabel($result),
];
$i++;
}
return $products;
}
/**
* merge all filter attributes from items[], implodes array items to string and pushes the created filter-string under $filters[filterAttribute]
* @param array $items
* @param string $paramName
* @param array &$filters
* @return void
*/
private function updateFilters(array $items, string $paramName, array &$filters): void
{
$attributes = [];
foreach ($items as $key => $value) {
array_push($attributes, self::LAST_PARAMS[$paramName]['items'][$value]['filters']);
}
$attributes = array_merge([], ...$attributes);
$filters['filterAttribute'][self::LAST_PARAMS[$paramName]['filterKey']] = implode(",", $attributes);
}
/**
* loops over in $subCategoryArray(selected subcategories) and uses defined filters[] items to create/update $filters[filterAttribute]
* @param string $mainCategory
* @param string $subCategory
* @param array &$filters
* @return void
*/
private function addFiltersFromSelectedWizardElement(string $mainCategory, string $subCategory, array &$filters): void
{
$wizardElements = self::WIZARD_ELEMENTS;
$actualScFilters = $wizardElements['nextSteps']['items'][$mainCategory]['nextSteps'][$subCategory]['filters'];
if (!empty($actualScFilters)) {
$fa = $filters['filterAttribute'] ?? [];
foreach ($actualScFilters as $key => $fValues) {
$fResultValues = $fValues;
// if filter['filterAttribute'] has key => explode > merge > arrray_unique > implode
if (isset($fa[$key])) {
$actualFilterKey = explode(",", $fa[$key]);
$fResultValues = array_unique(array_merge([], $actualFilterKey, $fValues));
}
$fa[$key] = implode(",", $fResultValues);
}
$filters['filterAttribute'] = $fa;
}
}
/**
* @Route("/wizard/get/product-list-ajax", name="wizard_product_list_ajax", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/wizard/get/product-list-ajax", name="wizard_product_list_ajax_locale", defaults={"_locale":""})
* @param Request $request
* @return JsonResponse
* @throws \Exception
*/
public function productListAjaxAction(Request $request): JsonResponse
{
$domain = $this->getMultiStoreHelper($request)->getDomain();
$filterData = $request->query->all();
$checkedFilters = $request->get('checkedFilters') ?? null;
$data['products'] = [];
$productsCacheKey = 'wizard.products.' . $domain->getId() . '.' . $domain->getLanguage()->getCode() . '.' . md5(serialize($filterData));
$cacheItem = $this->cache->getItem($productsCacheKey);
if ($cacheItem->isHit()) {
$data['products'] = $cacheItem->get();
} else {
$data['products'] = $this->getProductList($request, $filterData['subCategory'], $filterData['mainCategory'], false, $domain->getId(), $filterData);
$cacheItem->set($data['products']);
$cacheItem->expiresAfter(self::CACHE_LIFETIME_30_MINUTES);
$this->cache->save($cacheItem);
}
$data['currency'] = $domain->getCurrency();
$data['precision'] = $domain->getPricePrecision();
$arguments = [
'mc' => $filterData['mainCategory'],
'sc' => $filterData['subCategory'],
'setterPriceMin' => $filterData['filterPriceMin'],
'setterPricemax' => $filterData['filterPriceMax'],
'sort' => $filterData['sort'],
'order' => $filterData['order'],
'filtersAttrs' => $checkedFilters,
'step' => 4,
];
$arguments['page'] = '{page}';
$data['pagination'] = [
'total' => $filterData['total'],
'page' => $request->get('page') ?? 1,
'limit' => $filterData['limit'],
'moreButton' => true,
'url' => $this->url($request)->link('wizard_result', $arguments),
];
$data['col'] = 3;
return new JsonResponse($data);
}
}