<?php
/**
* Created by simpson <simpsonwork@gmail.com>
* Date: 2019-04-05
* Time: 20:11
*/
namespace App\Controller;
use App\Entity\Location\City;
use App\Form\SearchProfileForm;
use App\Service\ProfileList;
use App\Specification\ElasticSearch\Spec;
use App\Specification\Profile\ProfileIsProvidingMostOfServices;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Response;
class ProfileSearchController extends AbstractController
{
use ExtendedPaginationTrait;
const ENTRIES_ON_PAGE = 36;
private int $cookieTime;
public function __construct(
ParameterBagInterface $parameterBag
) {
$this->cookieTime = (int)$parameterBag->get('search.form_cookie_time') ?: 1200;
}
#[ParamConverter("city", converter: "city_converter")]
public function page(Request $request, City $city, ProfileList $profileList): Response
{
$isAjax = $request->isXmlHttpRequest();
$formFields = null;
if($isAjax) {
$content = json_decode($request->getContent(), true);
parse_str($content['form'], $data);
$formFields = current($data);
} else {
$requestedPage = $request->attributes->get('page');
//если просто рефрешнули страницу с результатами после нажатия кнопки "Показать еще"
/*if($requestedPage > 1 && ($savedForm = $request->cookies->get('search_form'))) {
$formFields = json_decode($savedForm, true);
}*/
}
$form = $this->createForm(SearchProfileForm::class, null, [
'action' => $this->generateUrl('profile_search.page', ['city' => $city->getUriIdentity()]),
'csrf_protection' => false,
'city' => $city,
]);
if($formFields) {
$this->cleanAndCastFormFields($formFields, $form, true);
$form->submit($formFields);
} else {
$form->handleRequest($request);
}
if ($form->isSubmitted() && $form->isValid()) {
$additionalSpecs = [];
/** @var ProfileIsProvidingMostOfServices $servicesSpec */
if(($servicesSpec = $form->getViewData()['services']) != null) {
$additionalSpecs[] = $servicesSpec;
}
$profiles = $profileList->listActiveWithinCityOrderedByStatusWithSpec($city, $form->getData(), $additionalSpecs);
}
if($isAjax) {
$response = $this->render('ProfileList/list.profiles.html.twig', [
'profiles' => $profiles ?? null,
]);
$content = preg_replace('/\s{2,}/', ' ', $response->getContent());
$response->setContent($content);
return $response;
} else {
$response = $this->render('ProfileSearch/list.html.twig', [
'profiles' => $profiles ?? null,
'form' => $form->createView(),
'recommendationSpec' => Spec::andX(),
]);
if($form->isSubmitted() && $request->request->get($form->getName())) {
$formFields = $request->request->get($form->getName());
$this->cleanAndCastFormFields($formFields, $form, false);
//$response->headers->setCookie(new Cookie('search_form', json_encode($formFields), mktime() + $this->cookieTime));
}
return $response;
}
}
protected function cleanAndCastFormFields(array &$fields, FormInterface $form, bool $cast): void
{
//если значение пустое - удаляем соотв. ключ, оставляя тольно заполненные поля
//если значение массив - проходимся внутри, пустые массивы в результате удаляем
//если в форме это поле чекбокс - конвертим в bool
foreach ($fields as $k=>$v) {
if ($v === '')
unset($fields[$k]);
if (is_array($v) && $this->isAssociativeArray($v)) {
$this->cleanAndCastFormFields($v, $form->get($k), $cast);
if (empty($v))
unset($fields[$k]);
}
if($cast && $form->get($k)->getConfig()->getType()->getInnerType() instanceof CheckboxType)
$fields[$k] = (bool)$fields[$k];
}
}
protected function isAssociativeArray(array $arr): bool
{
if (array() === $arr) return false;
return array_keys($arr) !== range(0, count($arr) - 1);
}
}