<?php
namespace App\Service\Filter;
use App\Env;
use App\Entity\Cat;
use App\Entity\Prod;
use App\Service\Auth\Auth;
use cijic\phpMorphy\Morphy;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Contracts\Cache\TagAwareCacheInterface;
class Prods
{
private RequestStack $rs;
private Auth $Auth;
private EntityManagerInterface $em;
private TagAwareCacheInterface $Cache;
private Cats $Cats;
private Env $Env;
private Morphy $phpMorphy;
private $prods = [];
private $pc = [];
private $prod_count = 0;
public function __construct(RequestStack $rs, Auth $Auth, EntityManagerInterface $em, TagAwareCacheInterface $appCache, Env $Env, Cats $Cats, Security $security)
{
$this->rs = $rs;
$this->Auth = $Auth;
$this->Auth->setUser($security->getUser());
$this->em = $em;
$this->Cache = $appCache;
$this->Env = $Env;
$this->Cats = $Cats;
}
public function getFromDb(int $cat = 0, string $spec = '', string $q = '', int $id = 0)
{
$request = $this->rs->getCurrentRequest();
$test = $request->get('test');
$q = $q ? $q : $request->get('q');
$prods_temp_q = $prods_temp = [];
$opt = $this->Auth->isOpt() ? 'opt' : '';
$where = "visible = 1 and (num > 0 or num2 > 0 or num3 > 0)";
if ($cat) {
$where .= " and ".$this->Cats->getCatTreeWhere($cat);
}
switch($spec) {
case 'new':
$where .= " and `new` = 1";
break;
case 'pop':
$where .= " and `pop` = 1";
break;
case 'onsale':
$where .= " and `onsale` = 1";
break;
case 'mix':
$where .= " and `mix` = 1";
break;
case 'action':
if($this->Auth->isOpt()) $where .= " and `skidkaopt` > 0";
else $where .= " and `skidka` > 0";
break;
case 'search':
$lang = 'ru';
$this->phpMorphy = new Morphy($lang);
$words = preg_split("/[\s\.,\-\=\+!\'\"%\&\(\)]/", $q, -1, PREG_SPLIT_NO_EMPTY);
foreach ($words as $k => $v) {
$r = $this->getRoot($v);
$where .= " and (`art` like '%$r%' or `tags` like '%$r%')";
}
break;
}
$select = "id, cat, intname, name, art, price, price2, price3, priceopt, priceopt2, priceopt3, skidka, skidka2, skidka3, skidkaopt, skidkaopt2, skidkaopt3, numdiscount, numdiscount2, numdiscount3, chars, numdiscountopt, numdiscountopt2, numdiscountopt3, num, num2, num3, weight, weight2, weight3, inpack, inpack2, inpack3, pop, new, mix, action, onsale, prior, ordered, changed, colors";
if ($id) {
$q = "SELECT $select FROM prod WHERE id = $id";
$prods_temp = $this->em->getConnection()->prepare($q)->executeQuery()->fetchAllAssociative();
} elseif ($q) {
$q = "SELECT $select FROM prod WHERE $where";
$prods_temp_q = $this->em->getConnection()->prepare($q)->executeQuery()->fetchAllAssociative();
} else {
$q = "SELECT $select FROM prod WHERE $where";
$prods_temp = $this->em->getConnection()->prepare($q)->executeQuery()->fetchAllAssociative();
}
$this->pc = [];
$this->prods = [];
if (is_array($prods_temp) && count($prods_temp)) {
foreach ($prods_temp as $kc => $p) {
$p['colors'] = json_decode($p['colors'], true);
$this->prods[$p['id']] = $p;
$chars = explode(";", $p['chars']);
foreach ($chars as $char) {
$cv = explode(":", $char);
if ($cv[0] != 'onsale' && $cv[0] != 'pop' && $cv[0] != 'action' && $cv[0] != 'new' && $cv[0] != 'mix' && isset($cv[1]) && $cv[1] > 0) {
$this->pc[$cv[0]][] = $cv[1];
}
}
}
unset($prods_temp);
}
if (is_array($prods_temp_q) && count($prods_temp_q)) {
foreach ($prods_temp_q as $kc => $p) {
$p['colors'] = json_decode($p['colors'], true);
$this->prods[$p['id']] = $p;
$chars = explode(";", $p['chars']);
foreach ($chars as $char) {
$cv = explode(":", $char);
if ($cv[0] != 'onsale' && $cv[0] != 'pop' && $cv[0] != 'action' && $cv[0] != 'new' && $cv[0] != 'mix' && isset($cv[1]) && $cv[1] > 0) {
$this->pc[$cv[0]][] = $cv[1];
}
}
}
unset($prods_temp_q);
}
// $prod_ids = [];
// foreach ($this->prods as $k => $v) {
// $prod_ids[] = $v['id'];
// }
// //TODO Alex
// $this->prods = $this->em->createQuery('SELECT p from App\Entity\Prod p WHERE p.id in (:ids)')
// ->setParameter('ids', $prod_ids)
// //->setMaxResults(50)
// ->getResult();
return $this->prods;
}
public function getProd($id = 0)
{
$prods = $this->getFromDb(0, '', '', $id);
if ($prods) {
return reset($prods);
} else {
return [];
}
}
public function getProds(int $cat = 0, string $spec = '', string $search = ''): array
{
if (empty($this->prods)) {
return $this->getFromDb($cat, $spec, $search);
}
return $this->prods;
}
public function getPC(int $cat = 0, string $spec = ''): array
{
if (empty($this->pc)) {
$this->getFromDb($cat, $spec);
}
return $this->pc;
}
public function getTagsFromName(string $name): array
{
$tags = [];
$words = preg_split("/[\s\.,\-\=\+!\'\"%\&\(\)\:\;]/", $name, -1, PREG_SPLIT_NO_EMPTY);
foreach ($words as $k => $v) {
$r = $this->getRoot($v);
$tags[] = $r;
}
return $tags;
}
public function getRoot(string $word): string
{
$shortest = '';
$data = $this->phpMorphy->getPseudoRoot(mb_strtoupper($word));
if ($data == null) {
return $word;
} elseif (count($data) > 1) {
$lengths = array_map('strlen', $data);
$lengths = array_flip($lengths);
sort($lengths);
$k = array_pop($lengths);
$shortest = mb_strtolower($data[$k]);
} else {
$shortest = mb_strtolower($data[0]);
}
return $shortest;
}
public function getLemma(string $word): string
{
$l = $this->phpMorphy->lemmatize($word);
if (is_array($l)) {
return $l[0];
} elseif (is_string($l)) {
return $l;
} else {
return $word;
}
}
public function getchars(array $get_params)
{
$filter = [];
foreach ($get_params as $k => $v) {
if ($k == 'getnum' || $k == 'filter' || $k == 'q') {
continue;
}
if (isset($get_params[$k]) && is_array($get_params[$k])) {
$filter[str_replace('char', '', $k)] = [];
foreach ($get_params[$k] as $vvv) {
array_push($filter[str_replace('char', '', $k)], $vvv);
}
} else {
$filter[str_replace('char', '', $k)] = $v;
}
}
return $filter;
}
/**
*
* @param array $get_params
* @param \App\Entity\Prod[] $prods
* @param array $chars
* @return array
*/
public function filter (array $get_params, array $prods, array $chars = array()) {
$qwe = '';
if (empty($chars)) {
$filter = $this->getchars($get_params);
} else {
$filter = $chars;
}
foreach($filter as $k => $char) {
if($char == 'action' && $this->Auth->isOpt()) {
$filter[$k] = 'actionopt';
}
}
if (isset($filter['sale']) && $filter['sale'] == 1) {
$filter[$filter['sale']] = "1";
unset($filter['sale']);
}
$ids = array();
if (empty($filter)) {
return $prods;
}
$fc = count($filter);
foreach ($prods as $k => $prod) {
if (empty($prod->getChars())) {
continue;
}
$filter_vals_founded = 0;
foreach ($filter as $c => $cv) {
if (is_array($cv) && count($cv) > 1) { // Выбрано нескольно значений одной характеристики
foreach ($cv as $ccv) {
if (strstr($prod->getChars(), $c.":".$ccv.";")) { // Если хотя бы одно значение найдено, то значение считается найдено
$qwe .= $c.":".$ccv.";";
$filter_vals_founded++;
break;
}
}
} else { // Выбрано ОДНО значение одной характеристики
if (is_array($cv)) {
$cv = $cv[0];
}
if (strstr($prod->getChars(), $c.":".$cv.";")) {
$filter_vals_founded++;
}
}
}
if ($filter_vals_founded >= $fc) { // Если найдены все значения характеристик, помещаем товар в массив
$ids[] = $prod;
}
}
return $ids;
}
/**
*
* @param \App\Entity\Prod[] $prods
* @param array $chars
* @param mixed $char
* @param mixed $charval
* @return int
*/
public function prodcount (array $prods, array $chars, $char, $charval)
{
$filter = $chars;
$fc = count($filter);
$cnt = 0;
$qwe = '';
if ($char == 'action' && $this->Auth->isOpt()) {
$char = 'actionopt';
}
if (isset($filter['sale'])) {
$filter[$filter['sale']] = "1";
unset($filter['sale']);
}
foreach ($prods as $k => $prod) {
if (empty($prod['chars'])) {
continue;
}
if (!empty($filter)) {
$filter_vals_founded = 0;
foreach ($filter as $c => $cv) {
if (is_array($cv) && count($cv) > 1) { // Выбрано нескольно значений одной характеристики
foreach ($cv as $ccv) {
if (strstr($prod['chars'], $c.":".$ccv.";") || $c == $char) { // Если хотя бы одно значение найдено, то значение считается найдено
$qwe .= $c.":".$ccv.";";
$filter_vals_founded++;
break;
}
}
} else { // Выбрано ОДНО значение одной характеристики
if (is_array($cv)) {
$cv = $cv[0];
}
if (strstr($prod['chars'], $c.":".$cv.";") || $c == $char) {
$filter_vals_founded++;
}
}
}
if (strstr($prod['chars'], $char.":".$charval.";") && $filter_vals_founded >= $fc) { // Прибавляем 1 к значению характеристики в фильтре с учетом того, что она соответствуюе всем остальным условиям
$cnt++;
}
} else { // фильтр не задан
if (strstr($prod['chars'], $char.":".$charval.";")) {
$cnt++;
}
}
}
return $cnt;
}
}