<?php
declare(strict_types=1);
namespace VehicleMarketBundle\Document\Areabrick;
use Knp\Component\Pager\PaginatorInterface;
use Pimcore\Extension\Document\Areabrick\AbstractTemplateAreabrick;
use Pimcore\Extension\Document\Areabrick\EditableDialogBoxConfiguration;
use Pimcore\Extension\Document\Areabrick\EditableDialogBoxInterface;
use Pimcore\Db;
use Pimcore\Model\DataObject\DealerLocation;
use Pimcore\Model\DataObject\Vehicle;
use Pimcore\Model\DataObject\VehicleFilter;
use Pimcore\Model\DataObject\VehicleFilterEntity;
use Pimcore\Model\Document\Editable;
use Pimcore\Model\Document\Editable\Area\Info;
use Symfony\Component\Form\FormFactory;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
use Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag;
use VehicleMarketBundle\Document\Form\CarListFilterFormType;
use VehicleMarketBundle\Service\CampaignSchedule;
use Pimcore\Translation\Translator;
use Pimcore\Tool\Session;
class vehicleListing extends AbstractTemplateAreabrick implements EditableDialogBoxInterface
{
/**
* @var PaginatorInterface
*/
protected $paginator;
public function getName()
{
return 'Vehicle Listing';
}
public function __construct(PaginatorInterface $paginator, Translator $translator)
{
$this->paginator = $paginator;
$this->translator = $translator;
}
/**
* @Route("/fahrzeugmarkt", name="carSearch", methods={"GET"})
*
* @param Request $request
*
* @throws \Exception
*/
public function action(Info $info)
{
$session = $info->getRequest()->getSession();
/** @var AttributeBag $bag */
$bag = $session->getBag('search_url');
$bag->set('search_url', $info->getRequest()->getRequestUri());
$carFilterURLElement = $info->getDocumentElement('carFilterURL');
$filterCount = $info->getDocumentElement('displayCount');
if (isset($carFilterURLElement) && method_exists($carFilterURLElement, 'getData') && !empty($carFilterURLElement->getData())) {
$carFilterURL = $carFilterURLElement->getData();
$parts = parse_url($carFilterURL);
if ($parts['query'] === null) {
$parts['query'] = '';
}
parse_str($parts['query'], $preselectCarFilterQuery);
} else {
$preselectCarFilterQuery = null;
}
$make = explode("/", $info->getRequest()->getPathInfo(), 3);
/**
* @var FormInterface $form
*/
$form = $this->container->get('form.factory')->create(CarListFilterFormType::class, null, ['csrf_protection' => false, 'data' => new VehicleFilter()]);
$condition = '1=1';
$joinCondition = '';
$filterBricks = [];
$sortOrder = 'asc';
$sortOrderKey = null;
$form->handleRequest($info->getRequest());
if (($form->isSubmitted() && $form->isValid())) {
$filterData = $form->getData();
if ($filterData->getSortOrder() !== null) {
switch ($filterData->getSortOrder()) {
case 'sort_price_increasing':
$filterBricks[] = "Costs";
$sortOrder = 'asc';
$sortOrderKey = 'preis';
break;
case 'sort_price_decreasing':
$filterBricks[] = "Costs";
$sortOrder = 'desc';
$sortOrderKey = 'preis';
break;
case 'sort_mileage_increasing':
$filterBricks[] = "vehicleBaseData";
$sortOrder = 'asc';
$sortOrderKey = 'kilometer';
break;
case 'sort_mileage_decreasing':
$filterBricks[] = "vehicleBaseData";
$sortOrder = 'desc';
$sortOrderKey = 'kilometer';
break;
case 'sort_rate_increasing':
$filterBricks[] = "vehicleBaseData";
$sortOrder = 'asc';
$sortOrderKey = 'filterRate';
break;
case 'sort_rate_decreasing':
$filterBricks[] = "vehicleBaseData";
$sortOrder = 'desc';
$sortOrderKey = 'filterRate';
break;
}
}
if ($filterData->getCarMake() || !empty($preselectCarFilterQuery['car_list_filter_form']['car_make'])) {
$filterBricks[] = "vehicleBaseData";
$carMake = empty($preselectCarFilterQuery['car_list_filter_form']['car_make']) || $filterData->getCarMake() ? $filterData->getCarMake() : $preselectCarFilterQuery['car_list_filter_form']['car_make'];
$condition .= " and vehicleBaseData.marke LIKE '" . $carMake . "' ";
}
if ($filterData->getCarModel()) {
$filterBricks[] = "vehicleBaseData";
if(str_contains($filterData->getCarModel(), 'alle ')) {
switch ($filterData->getCarModel()) {
case 'alle 1er':
$condition .= " and vehicleBaseData.modellbasis LIKE '1%' ";
break;
case 'alle 2er':
$condition .= " and vehicleBaseData.modellbasis LIKE '2%' ";
break;
case 'alle 3er':
$condition .= " and vehicleBaseData.modellbasis LIKE '3%' ";
break;
case 'alle 4er':
$condition .= " and vehicleBaseData.modellbasis LIKE '4%' ";
break;
case 'alle 5er':
$condition .= " and vehicleBaseData.modellbasis LIKE '5%' ";
break;
case 'alle 6er':
$condition .= " and vehicleBaseData.modellbasis LIKE '6%' ";
break;
case 'alle 7er':
$condition .= " and vehicleBaseData.modellbasis LIKE '7%' ";
break;
case 'alle 8er':
$condition .= " and vehicleBaseData.modellbasis LIKE '8%' ";
break;
case 'alle i-Modelle':
$condition .= " and vehicleBaseData.modellbasis LIKE 'i%' ";
break;
case 'alle M-Modelle':
$condition .= " and vehicleBaseData.modellbasis LIKE 'M%' ";
break;
case 'alle X-Modelle':
$condition .= " and vehicleBaseData.modellbasis LIKE 'X%' ";
break;
case 'alle Z-Modelle':
$condition .= " and vehicleBaseData.modellbasis LIKE 'Z%' ";
break;
}
} else {
$condition .= " and vehicleBaseData.modellbasis LIKE '" . $filterData->getCarModel() . "' ";
}
}
if ($filterData->getCarType()) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.kategorie LIKE '" . $filterData->getCarType() . "' ";
}
if ($filterData->getCarAgeType()) {
$filterBricks[] = "vehicleBaseData";
switch ($filterData->getCarAgeType()) {
case 'Jahreswagen':
$condition .= " and vehicleBaseData.jahreswagen = 1 ";
break;
case 'Vorführfahrzeug':
$condition .= " and vehicleBaseData.vorfuehrfahrzeug = 1 ";
break;
case 'Neufahrzeug':
$condition .= " and vehicleBaseData.neufahrzeug = 1 ";
break;
case 'Gebrauchtfahrzeug':
$condition .= " and vehicleBaseData.neufahrzeug = 0 ";
break;
}
}
if ($filterData->getRegistrationYearStart()) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.ezYear >= '" . $filterData->getRegistrationYearStart() . "' ";
}
if ($filterData->getRegistrationYearEnd()) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.ezYear <= '" . $filterData->getRegistrationYearEnd() . "' ";
}
if ($filterData->getMonthlyRateMin()) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and filterRate >= '" . $filterData->getMonthlyRateMin() . "' ";
}
if ($filterData->getMonthlyRateMax()) {
$filterBricks[] = "vehicleBaseData";
// `filterRate > 0` because 0 means "no bookable rate", not "free": without it a
// "up to 300 EUR/month" filter returns every vehicle that has no leasing rate at
// all. 391 of 923 vehicles currently carry 0 and another 123 carry NULL.
// The MIN filter needs no counterpart - 0 and NULL both fail `>= <min>` already.
$condition .= " and filterRate > 0 and filterRate <= '" . $filterData->getMonthlyRateMax() . "' ";
}
if ($filterData->getKmDriven()) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.kilometer <= '" . $filterData->getKmDriven() . "' ";
}
if ($filterData->getFuel()) {
$filterBricks[] = "TechnicalData";
$condition .= " and TechnicalData.kraftstoffart LIKE '" . $filterData->getFuel() . "' ";
}
if ($filterData->getTransmission()) {
$filterBricks[] = "TechnicalData";
$condition .= " and TechnicalData.getriebeart LIKE '" . $filterData->getTransmission() . "' ";
}
if ($filterData->getColor()) {
$filterBricks[] = "Exterieur";
$condition .= " and Exterieur.grundfarbeAussen LIKE '" . $filterData->getColor() . "' ";
}
if ($filterData->getCarLocation()) {
$location = DealerLocation::getList()->filterByName($filterData->getCarLocation())->current();
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.filialId = '" . $location->getLocationId() . "' ";
}
if ($filterData->getCarAvailability()) {
$filterBricks[] = "vehicleBaseData";
if ($filterData->getCarAvailability() === 'now') {
$condition .= " and STR_TO_DATE(vehicleBaseData.lieferdatum, \"%d.%m.%Y\") < NOW() ";
} else {
$condition .= " and STR_TO_DATE(vehicleBaseData.lieferdatum, \"%d.%m.%Y\") >= NOW() ";
}
}
if ($filterData->getQualityBadge()) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.qualitaetssiegel LIKE '" . $filterData->getQualityBadge() . "' ";
}
if ($filterData->getCampaignName()) {
$filterBricks[] = "vehicleBaseData";
$condition .= $this->campaignCondition($filterData->getCampaignName());
}
} elseif ($preselectCarFilterQuery !== null) {
if (isset($preselectCarFilterQuery['car_list_filter_form'])) {
$filterData = $preselectCarFilterQuery['car_list_filter_form'];
if (!$form->isSubmitted()) {
$form->setData($filterData);
}
}
// dd($filterData);
if ($filterData['sort_order'] !== null) {
switch ($filterData['sort_order']) {
case 'sort_price_increasing':
$filterBricks[] = "Costs";
$sortOrder = 'asc';
$sortOrderKey = 'preis';
break;
case 'sort_price_decreasing':
$filterBricks[] = "Costs";
$sortOrder = 'desc';
$sortOrderKey = 'preis';
break;
case 'sort_mileage_increasing':
$filterBricks[] = "vehicleBaseData";
$sortOrder = 'asc';
$sortOrderKey = 'kilometer';
break;
case 'sort_mileage_decreasing':
$filterBricks[] = "vehicleBaseData";
$sortOrder = 'desc';
$sortOrderKey = 'kilometer';
break;
case 'sort_rate_increasing':
$filterBricks[] = "vehicleBaseData";
$sortOrder = 'asc';
$sortOrderKey = 'filterRate';
break;
case 'sort_rate_decreasing':
$filterBricks[] = "vehicleBaseData";
$sortOrder = 'desc';
$sortOrderKey = 'filterRate';
break;
}
}
if ($filterData['car_make']) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.marke LIKE '" . $filterData['car_make'] . "' ";
}
if ($filterData['car_model']) {
$filterBricks[] = "vehicleBaseData";
if(str_contains($filterData['car_model'], 'alle ')) {
switch ($filterData['car_model']) {
case 'alle 1er':
$condition .= " and vehicleBaseData.modellbasis LIKE '1%' ";
break;
case 'alle 2er':
$condition .= " and vehicleBaseData.modellbasis LIKE '2%' ";
break;
case 'alle 3er':
$condition .= " and vehicleBaseData.modellbasis LIKE '3%' ";
break;
case 'alle 4er':
$condition .= " and vehicleBaseData.modellbasis LIKE '4%' ";
break;
case 'alle 5er':
$condition .= " and vehicleBaseData.modellbasis LIKE '5%' ";
break;
case 'alle 6er':
$condition .= " and vehicleBaseData.modellbasis LIKE '6%' ";
break;
case 'alle 7er':
$condition .= " and vehicleBaseData.modellbasis LIKE '7%' ";
break;
case 'alle 8er':
$condition .= " and vehicleBaseData.modellbasis LIKE '8%' ";
break;
case 'alle i-Modelle':
$condition .= " and vehicleBaseData.modellbasis LIKE 'i%' ";
break;
case 'alle M-Modelle':
$condition .= " and vehicleBaseData.modellbasis LIKE 'M%' ";
break;
case 'alle X-Modelle':
$condition .= " and vehicleBaseData.modellbasis LIKE 'X%' ";
break;
case 'alle Z-Modelle':
$condition .= " and vehicleBaseData.modellbasis LIKE 'Z%' ";
break;
}
} else {
$condition .= " and vehicleBaseData.modellbasis LIKE '" . $filterData['car_model'] . "' ";
}
}
if ($filterData['car_type']) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.kategorie LIKE '" . $filterData['car_type'] . "' ";
}
if ($filterData['car_age_type']) {
$filterBricks[] = "vehicleBaseData";
switch ($filterData['car_age_type']) {
case 'Jahreswagen':
$condition .= " and vehicleBaseData.jahreswagen = 1 ";
break;
case 'Vorführfahrzeug':
$condition .= " and vehicleBaseData.vorfuehrfahrzeug = 1 ";
break;
case 'Neufahrzeug':
$condition .= " and vehicleBaseData.neufahrzeug = 1 ";
break;
case 'Gebrauchtfahrzeug':
$condition .= " and vehicleBaseData.neufahrzeug = 0 ";
break;
}
}
if ($filterData['registration_year_start']) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.ezYear >= '" . $filterData['registration_year_start'] . "' ";
}
if ($filterData['registration_year_end']) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.ezYear <= '" . $filterData['registration_year_end'] . "' ";
}
if ($filterData['monthly_rate_min']) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and filterRate >= '" . $filterData['monthly_rate_min'] . "' ";
}
if ($filterData['monthly_rate_max']) {
$filterBricks[] = "vehicleBaseData";
// See the same filter on the form path above: 0 means "no bookable rate".
$condition .= " and filterRate > 0 and filterRate <= '" . $filterData['monthly_rate_max'] . "' ";
}
if ($filterData['km_driven']) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.kilometer <= '" . $filterData['km_driven'] . "' ";
}
if ($filterData['fuel']) {
$filterBricks[] = "TechnicalData";
$condition .= " and TechnicalData.kraftstoffart LIKE '" . $filterData['fuel'] . "' ";
}
if ($filterData['transmission']) {
$filterBricks[] = "TechnicalData";
$condition .= " and TechnicalData.getriebeart LIKE '" . $filterData['transmission'] . "' ";
}
if ($filterData['color']) {
$filterBricks[] = "Exterieur";
$condition .= " and Exterieur.grundfarbeAussen LIKE '" . $filterData['color'] . "' ";
}
if ($filterData['car_location']) {
$location = DealerLocation::getList()->filterByName($filterData['car_location'])->current();
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.filialId = '" . $location->getLocationId() . "' ";
}
if ($filterData['car_availability']) {
$filterBricks[] = "vehicleBaseData";
if ($filterData['car_availability'] === 'now') {
$condition .= " and STR_TO_DATE(vehicleBaseData.lieferdatum, \"%d.%m.%Y\") < NOW() ";
} else {
$condition .= " and STR_TO_DATE(vehicleBaseData.lieferdatum, \"%d.%m.%Y\") >= NOW() ";
}
}
if ($filterData['quality_badge']) {
$filterBricks[] = "vehicleBaseData";
$condition .= " and vehicleBaseData.qualitaetssiegel LIKE '" . $filterData['quality_badge'] . "' ";
}
if ($filterData['campaign_name']) {
$filterBricks[] = "vehicleBaseData";
$condition .= $this->campaignCondition($filterData['campaign_name']);
}
}
// if (isset($make[2])) {
// $filterBricks[] = "vehicleBaseData";
// $condition .= " and vehicleBaseData.marke LIKE '" . $make[2] . "' ";
// }
//
$filterBricks = array_unique($filterBricks);
if (count($filterBricks) == 0) {
$cars = Vehicle::getList();
} else {
$cars = Vehicle::getList([
"objectbricks" => $filterBricks,
"condition" => $condition,
"orderKey" => $sortOrderKey,
"order" => $sortOrder
]);
}
$this->keepRatelessVehiclesLast($cars, $sortOrderKey, $sortOrder);
if ($info->getRequest()->get('json') == 1) {
return new JsonResponse(
['count' => $cars->getCount()]
);
}
//dd($cars->getQueryBuilder()->getSQL());
$paginator = $this->paginator->paginate(
$cars,
intval($info->getRequest()->get('page', 1)),
9
);
$info->setParam('paginatedCars', $paginator);
$info->setParam('paginationVariables', $paginator->getPaginationData());
$info->setParam('form', $form->createView());
$info->setParam('isBackendUser', (Session::getReadOnly()->get("user")));
}
/**
* SQL fragment for the Kampagne filter.
*
* `campaignNames` is a multiselect stored as ",A,B," in the query table, so membership is a
* LIKE on the comma-delimited value.
*
* A campaign that is not running today matches nothing. The dropdown only offers running
* campaigns (see CarListFilterFormType), but a bookmarked or shared URL can still carry an
* ended or not-yet-started one - and a vehicle's campaignNames keeps every campaign automedia
* delivered, including announced ones. Ignoring the filter instead would silently show the
* full inventory as if the promotion still applied.
*/
protected function campaignCondition(string $campaignName): string
{
if (!(new CampaignSchedule())->isRunning($campaignName)) {
return ' and 1 = 0 ';
}
return ' and vehicleBaseData.campaignNames LIKE ' . Db::get()->quote('%,' . $campaignName . ',%') . ' ';
}
/**
* Sorting by rate ascending must not put the vehicles that have no rate first.
*
* `filterRate` is 0 for a vehicle with no bookable leasing rate and NULL for one the ingest
* never touched - currently 391 and 123 of 923 vehicles. Plain `ORDER BY filterRate asc`
* therefore fills the first 514 places of "cheapest rate first" with vehicles that show no
* rate at all, before the cheapest real offer appears.
*
* Fixed by ordering, not by filtering: a sort order must not change which vehicles are in the
* result. The leading term is a boolean - 0 for "has a rate", 1 for "has none" - so the rated
* vehicles come first, ascending by rate, and the rest keep their place at the end.
* `setOrderKey(..., false)` passes the expression through unquoted, and Pimcore appends the
* direction to the whole string (Model\Listing\Dao\QueryBuilderHelperTrait::applyOrderByToQueryBuilder),
* which is why this is one string and not two keys.
*
* Descending needs no help: there, 0 and NULL already sort last.
*/
protected function keepRatelessVehiclesLast(Vehicle\Listing $cars, ?string $sortOrderKey, string $sortOrder): void
{
if ($sortOrderKey !== 'filterRate' || strtolower($sortOrder) !== 'asc') {
return;
}
$cars->setOrderKey('IFNULL(filterRate, 0) = 0, filterRate', false);
}
protected function filterFuelTypes(Vehicle $entries, array $search)
{
if (!empty($search['kraftstoff'])) {
$query = '';
$fuelTypeParams = [];
for ($i = 0; $i < count($search['kraftstoff']); $i++) {
$query .= ' kraftstoffart = :f_type' . $i . ' OR ';
$fuelTypeParams['f_type' . $i] = $search['kraftstoff'][$i];
}
$query = substr($query, 0, -4);
$entries->addConditionParam($query, $fuelTypeParams, 'AND');
}
return $entries;
}
public function getDescription()
{
return 'A component for rendering a list of cars';
}
public function getEditableDialogBoxConfiguration(Editable $area, ?Info $info): EditableDialogBoxConfiguration
{
$cars = Vehicle::getList();
return (new EditableDialogBoxConfiguration())
->setItems([
[
'type' => 'input',
'label' => $this->translator->trans('Url to filter the list:', [], 'admin'),
'name' => 'carFilterURL'
],
[
'type' => 'relation',
'label' => $this->translator->trans('Path to the vehicle details page:', [], 'admin'),
'name' => 'carDetailPageUrl'
],
[
'type' => 'select',
'name' => 'car-list-filter',
'label' => $this->translator->trans('Show filters for the list?', [], 'admin'),
'config' => [
'store' => [
[true, $this->translator->trans('Yes', [], 'admin'),],
[false, $this->translator->trans('No', [], 'admin'),],
],
'defaultValue' => true
]
],
[
'type' => 'select',
'name' => 'car-list-available-from',
'label' => $this->translator->trans('Show Car available from?', [], 'admin'),
'config' => [
'store' => [
[true, $this->translator->trans('Yes', [], 'admin'),],
[false, $this->translator->trans('No', [], 'admin'),],
],
'defaultValue' => true
]
]
// ,
// [
// 'type' => 'numeric',
// 'label' => 'Display-Count',
// 'name' => 'displayCount'
// ]
])
->setHeight(460)
->setReloadOnClose(true);
}
function process_something($cars)
{
$myArray = array();
foreach ($cars as $b) {
$myArray[] = array($b->getStammdaten()->getVehicleBaseData()->getMarke(), $b->getStammdaten()->getVehicleBaseData()->getMarke());
}
return $myArray;
}
public function getHtmlTagOpen(Info $info)
{
return '';
}
public function getHtmlTagClose(Info $info)
{
return '';
}
public function getTemplateLocation()
{
return static::TEMPLATE_LOCATION_BUNDLE;
}
}