<?php
namespace Slivki\Controller;
use Doctrine\ORM\Query\ResultSetMapping;
use Imagine\Gd\Imagine;
use Imagine\Image\Box;
use Imagine\Image\Point;
use Slivki\Dto\User\OrderHistory\Factory\TireOrderHistoryDtoFactory;
use Slivki\Entity\City;
use Slivki\Entity\MailingCampaign;
use Slivki\Entity\Subscriber;
use Slivki\Entity\UserEmailHistory;
use Slivki\Enum\Order\PaymentType;
use Slivki\Factory\User\OrderHistory\FoodOrderHistoryDtoFactory;
use Slivki\Handler\User\CreditCard\RemoveCreditCardHandler;
use Slivki\Repository\Offer\DeliveryZoneRepositoryInterface;
use Slivki\Repository\User\UserAddressRepositoryInterface;
use Slivki\Response\Admin\Offer\CoordinatesResponse;
use Slivki\Services\GiftCertificateService;
use Slivki\Services\MapProviders\CoordinatesYandex;
use Slivki\Services\OfferExtension\FoodOfferExtensionImageService;
use Slivki\Services\Sms\Security\SmsLimiterService;
use Slivki\Services\User\AccountMerger;
use Slivki\Services\User\AuthorizationCodeSender;
use Slivki\Services\User\UserPhoneService;
use Slivki\Services\UserGetter;
use Slivki\Util\Iiko\SushiVesla;
use Doctrine\Persistence\ManagerRegistry;
use Slivki\Util\Iiko\Tokiny;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\Routing\Annotation\Route;
use Slivki\Entity\Comment;
use Slivki\Entity\DeliveryLocation;
use Slivki\Entity\FoodOrder;
use Slivki\Entity\GiftCertificateOrder;
use Slivki\Entity\MailingCampaignType;
use Slivki\Entity\MailingCampaignUnsubscribe;
use Slivki\Entity\Media;
use Slivki\Entity\Media\OfferExtensionMedia;
use Slivki\Entity\MediaType;
use Slivki\Entity\Offer;
use Slivki\Entity\OfferOrder;
use Slivki\Entity\OfferOrderDetails;
use Slivki\Entity\Referral;
use Slivki\Entity\SocialAccount;
use Slivki\Entity\Street;
use Slivki\Entity\SubscriptionOrder;
use Slivki\Entity\TireOrder;
use Slivki\Entity\User;
use Slivki\Entity\UserActivity;
use Slivki\Entity\UserAddress;
use Slivki\Entity\UserBalanceActivity;
use Slivki\Entity\UserBalanceActivityType;
use Slivki\Entity\UserConfirmation;
use Slivki\Entity\UserGroup;
use Slivki\Entity\UserPhone;
use Slivki\Repository\CityRepository;
use Slivki\Services\Encoder;
use Slivki\Services\ImageService;
use Slivki\Services\Mailer;
use Slivki\Services\Subscription\SubscriptionService;
use Slivki\Util\Amplitude;
use Slivki\Util\CommonUtil;
use Slivki\Util\Iiko\AbstractDelivery;
use Slivki\Util\Iiko\IikoUtil;
use Slivki\Util\Logger;
use Slivki\Util\OAuth2Client\AbstractOAuth2Client;
use Slivki\Util\OAuth2Client\UserData;
use Slivki\Util\SoftCache;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use function sprintf;
class UserController extends SiteController
{
private ManagerRegistry $managerRegistry;
private TireOrderHistoryDtoFactory $tireOrderHistoryDtoFactory;
private FoodOrderHistoryDtoFactory $foodOrderHistoryDtoFactory;
public function __construct(
KernelInterface $kernel,
ManagerRegistry $managerRegistry,
TireOrderHistoryDtoFactory $tireOrderHistoryDtoFactory,
FoodOrderHistoryDtoFactory $foodOrderHistoryDtoFactory
) {
parent::__construct($kernel);
$this->managerRegistry = $managerRegistry;
$this->tireOrderHistoryDtoFactory = $tireOrderHistoryDtoFactory;
$this->foodOrderHistoryDtoFactory = $foodOrderHistoryDtoFactory;
}
/**
* @Route("/login")
*/
public function loginPageAction(Request $request) {
$session = $this->container->get('session');
$key = 'returnUrl';
$data['tab'] = $request->query->get('tab', 'login');
$path = urldecode($request->query->get('path', '/'));
if ($path != '/') {
$session->set($key, $path);
} else {
$referer = $request->headers->get('referer');
$path = parse_url($referer, PHP_URL_PATH);
if ($path != '/login' && $path != $session->get($key)) {
$query = parse_url($referer, PHP_URL_QUERY);
if ($query != "") {
$path .= "?$query";
}
$session->set($key, $path);
}
}
if ($path == '' || $path == '/login') {
$path = CityRepository::$mainPageURL;
}
if ($this->getUser()) {
return $this->redirect($path);
}
$data['email'] = $this->get('session')->get('restoredEmail', '');
$data['afterLoginRedirectUri'] = strpos($path, 'http') === false ? $request->getSchemeAndHttpHost() . $path : $path;
$flashBag = $session->getFlashBag();
$data['registrationError'] = $flashBag->get('registrationError');
$data['registeredEmailSent'] = $flashBag->get('registeredEmailSent');
$data['registeredEmailSentRaw'] = $flashBag->get('registeredEmailSentRaw');
return $this->render('Slivki/mobile/login.html.twig', $data);
}
/**
* @Route("/register", name="register")
*/
public function registerAction(Request $request, Mailer $mailer, ValidatorInterface $validator) {
$isMobileDevice = CommonUtil::isMobileDevice($request);
if ($request->getMethod() != "POST") {
if ($isMobileDevice) {
return $this->redirect("/login");
}
return $this->redirect("/");
}
$utmSource = $this->getUtmSourceCookie($request);
$user = new User();
$user->setAcceptNewsletter(true);
$user->setStatus(User::STATUS_REGISTERED);
$email = mb_strtolower(trim($request->request->get("email")));
$userRepository = $this->getDoctrine()->getRepository(User::class);
if ($userRepository->loadUserByUsername($email, false)) {
return new JsonResponse(['message' =>"Пользователь с таким e-mail-ом уже зарегистрирован"]);
}
$user->setEmail($email);
/** @var \Symfony\Component\Validator\ConstraintViolationList $errorList */
$errorList = $validator->validate($user);
if ($errorList->count() > 0) {
return new JsonResponse(['message' =>$errorList->get(0)->getMessage()]);
}
$password = trim($request->get("password"));
if (strlen($password) < 6) {
return new JsonResponse(['message' =>"Пароль не может быть меньше 6 символов"]);
}
if ($password != trim($request->get("confirmPassword"))) {
return new JsonResponse(['message' =>"Пароли не совпадают"]);
}
$user->encryptPassword($password);
$cityName = $request->get("city");
$cityRepository = $this->getDoctrine()->getRepository(City::class);
$city = $cityRepository->findOneBy(array("name" => $cityName));
if (!$city) {
$city = $cityRepository->findOneBy(array(), array("ID" => "asc"));
}
$user->setCity($city);
if ($utmSource) {
$user->setRegisteredFromUtmSource($utmSource['utmSource']);
}
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$userRepository->addDirectorGroupToUserByUser($user);
$entityManager->flush($user);
$this->checkUserIsSupplier($user);
$userConfirmation = new UserConfirmation();
$userConfirmation->setUserID($user->getID());
$userConfirmation->setReturnUrl($request->request->get('registerReturnUrl'));
$entityManager->persist($userConfirmation);
$this->subscriberRemove($email);
$entityManager->flush();
$this->checkReferer($request, $user);
$eventData = ['city' => $cityName, 'ip' => $request->getClientIp()];
$userData = [
'userID' => $user->getID(),
'email' => $user->getEmail(),
'phone' => '',
'social' => '',
'user_type' => 'general',
'active' => true,
'region' => $cityName,
'date_created' => $user->getCreatedOn()->format('Y-m-d H:i:s')
];
$utmData = $this->getUtmSourceCookie($request);
if ($utmData) {
if (isset($utmData[$utmData['utmSource']])) {
$utmData['utm_source'] = $utmData['utmSource'];
unset($utmData['utmSource']);
}
if (isset($utmData['period'])) {
unset($utmData['period']);
}
}
$amplitude = new Amplitude($user);
$amplitude->sendEvent('NewUserRegistered', $eventData, $utmSource, $userData);
$this->sendConfirm($mailer, $user);
$data = [
'id' => 'modalAccountActivation',
'email' => $email,
'link' => Encoder::encodeString($user->getEmail(), $user->getSalt())
];
$view = $isMobileDevice ? 'Slivki/mobile_account_activation.html.twig' : 'Slivki/popups/account_activation_popup.html.twig';
$popup = $this->get('twig')->render($view, $data);
return new JsonResponse(['popup' => $popup]);
}
/**
* @Route("/social-login/{socialNetwork}", name="socialLogin")
*/
public function socialLoginAction(Request $request, $socialNetwork) {
$redirectUri = $request->query->get('state', CityRepository::$mainPageURL);
$className = 'Slivki\Util\OAuth2Client\Provider\\' . ucfirst($socialNetwork) . 'Client';
/** @var AbstractOAuth2Client $oAuthProvider */
$oAuthProvider = new $className();
$accessToken = $oAuthProvider->getAccessToken($request);
if (!$accessToken) {
return $this->redirect($redirectUri);
}
/** @var UserData $userData */
$userData = $oAuthProvider->getUserData($accessToken);
if (!$userData->getEmail()) {
return $this->redirect($redirectUri);
}
$entityManager = $this->getDoctrine()->getManager();
$socialAccount = $entityManager->getRepository(SocialAccount::class)->findOneBy([
'network' => $userData->getNetwork(),
'identity' => $userData->getID()
]);
if ($socialAccount) {
$user = $socialAccount->getUser();
} else {
$user = $entityManager->getRepository(User::class)->findOneByEmail($userData->getEmail());
}
if (!$user) {
// Register new user
$utmSource = $this->getUtmSourceCookie($request);
$user = new User();
$user->setAcceptNewsletter(true);
$user->setStatus(User::STATUS_CONFIRMED);
$user->setEmail($userData->getEmail());
$user->setLastName($userData->getLastName());
$user->setFirstName($userData->getFirstName());
$password = substr(md5(microtime()), 0, 5);
$user->encryptPassword($password);
if ($utmSource != '') {
$user->setRegisteredFromUtmSource($utmSource);
}
$entityManager->persist($user);
$mainMailingCampaignType = $entityManager->getRepository(MailingCampaignType::class)->find(MailingCampaignType::MAIN_ID);
$user->addMailingCampaignTypes($mainMailingCampaignType);
$userRepository = $this->getUserRepository();
$userRepository->addDirectorGroupToUserByUser($user);
$entityManager->flush($user);
$userRepository->addActivity($user, UserActivity::SUBSCRIBE_ACTION, $mainMailingCampaignType);
$this->checkReferer($request, $user);
$this->checkUserIsSupplier($user);
$this->subscriberRemove($user->getEmail() );
}
$linked = false;
foreach($user->getSocialAccounts()->toArray() as $value) {
if ($userData->getNetwork() == $value->getNetwork() && $userData->getID() == $value->getIdentity()) {
$linked = true;
break;
}
}
// Add social account
if (!$linked) {
$socialAccount = new SocialAccount();
$socialAccount->setNetwork($userData->getNetwork());
$socialAccount->setIdentity($userData->getID());
$socialAccount->setUser($user);
$user->addSocialAccount($socialAccount);
}
$entityManager->flush();
$entityManager->clear();
$user = $this->getUserRepository()->find($user->getID());
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->get('security.token_storage')->setToken($token);
return $this->redirect($redirectUri);
}
private function checkUserIsSupplier(User $user) {
$entityManager = $this->getDoctrine()->getManager();
$director = $this->getUserRepository()->getDirector($user);
if ($director) {
$supplierUserGroup = $entityManager->getRepository(UserGroup::class)->find(UserGroup::ROLE_SUPPLIER_ID);
$user->addUserGroup($supplierUserGroup);
$entityManager->flush();
}
}
/**
* @Route("/sendconfirm", name="sendconfirm")
*/
public function sendConfirmAction(Request $request, Mailer $mailer) {
$email = Encoder::decodeString($request->query->get('email'), User::SALT);
$user = $this->getDoctrine()->getRepository(User::class)->findOneByEmail(pg_escape_string($email));
if (!$user){
if (self::getMobileDevice($request)) {
return $this->redirect("/login");
}
return $this->redirect("/");
}
if ($this->sendConfirm($mailer, $user)) {
$this->addFlash("registeredEmailSent", Encoder::encodeString($user->getEmail(), User::SALT));
$this->addFlash("registeredEmailSentRaw", $user->getEmail());
}
if (self::getMobileDevice($request)) {
return $this->redirect("/login");
}
return $this->redirect("/");
}
/**
* @Route("/lostpassword/{email}", name="lostpassword")
*/
public function lostPasswordAction(Request $request, Mailer $mailer, $email = null){
if ($request->getMethod() != "POST") {
if (self::getMobileDevice($request)) {
return $this->render('Slivki/mobile/profile/restore_password.html.twig', ['email' => $email]);
}
return $this->redirect("/");
}
$result = [
'type' => 'error',
'html' => 'Введенный e-mail не найден'
];
if ($this->sendPassword($mailer, $request->request->get('email'))) {
$result = [
'type' => 'success',
'html' => '<p>Пароль отправлен на ваш электронный ящик</p>'
.'<a href="/login" class="btn btn-success bg-slivki btn-block text-dark border-0">Войти</a>'
];
$this->get('session')->set('restoredEmail', $request->request->get('email'));
if (!self::getMobileDevice($request)) {
$result['html'] = '<p>Пароль отправлен на ваш электронный ящик</p>';
}
}
return new JsonResponse($result);
}
/**
* @Route("/profile/login", name="login")
*/
public function loginAction(Request $request, AuthenticationUtils $utils) {
if (self::getMobileDevice($request)) {
return $this->redirect('/');
}
$redirectUri = $request->headers->get('referer', CityRepository::$mainPageURL);
$authError = $utils->getLastAuthenticationError();
$this->addFlash("openLoginPopup", "true");
if ($authError) {
$this->addFlash("authError", $authError);
}
// if the user is disabled, show the link to send a confirmation letter
if (is_a($authError, "Symfony\Component\Security\Core\Exception\DisabledException")) {
$this->addFlash("confirmEmail", Encoder::encodeString($authError->getToken()->getUserName(), User::SALT));
}
return $this->redirect($redirectUri);
}
/**
* @Route("/profile", name="profile")
*/
public function profileAction(
Request $request,
ImageService $imageService,
SubscriptionService $subscriptionService,
UserGetter $userGetter
) {
ini_set('memory_limit', '1G'); // TODO: need refactoring
$entityManager = $this->getDoctrine()->getManager();
$user = $userGetter->get();
$limit = 32;
// mark offer orders as seen by user
$notSeenOfferOrders = $user->getNotSeenOfferOrders();
/** @var OfferOrder $offerOrder */
foreach($notSeenOfferOrders as $offerOrder) {
$offerOrder->setSeenByUser(true);
}
$entityManager->flush();
$mobileDevice = CommonUtil::isMobileDevice($request);
$data['siteSettings'] = $this->getSiteSettings();
$bonusTypeBalanceActivityList = '(' . implode(',', UserBalanceActivityType::BONUS_ACTIVITIES) . ')';
$sql = "select coalesce(sum(amount), 0) from user_balance_activity where type in $bonusTypeBalanceActivityList and user_id = " . $this->getUser()->getID();
$data['totalBonus'] = number_format($entityManager->getConnection()->executeQuery($sql)->fetchColumn(), 2, '.', '');
$data['totalBonusCodes'] = (int)($data['totalBonus'] / $data['siteSettings']->getCodeCost());
$data['allOfferOrders'] = $this->getCodesHistory($limit, 0,false);
$data['deliveryOrders'] = $this->getCodesHistory($limit, 0,false, true);
$deliveryOrdersHistory = $this->getAllUserHistory($request, $imageService, $data['deliveryOrders'], $limit, 0, false);
$data['deliveryOrdersHistory'] = $deliveryOrdersHistory['html'];
$data['deliveryOrdersHistoryShowMoreButton'] = count($data['deliveryOrders']) >= $limit;
$data['promocodesHistory'] = $this->getCodesHistoryHtml($request, $data['allOfferOrders']);
$data['promocodesHistoryShowMoreButton'] = count($data['allOfferOrders']) >= $limit;
$balanceActivity = $this->getBalanceActivity($limit, 0);
$all = array_merge($data['allOfferOrders'], $balanceActivity);
$allUserHistory = $this->getAllUserHistory($request, $imageService, $all, $limit);
$data['allUserHistory'] = $allUserHistory['html'];
$data['balanceActivityHtml'] = $this->getBalanceActivityHtml($balanceActivity);
$data['balanceActivityShowMoreButton'] = count($balanceActivity) >= $limit;
$data['allShowMoreButton'] = $allUserHistory['count'] >= $limit;
$data['cities'] = $entityManager->getRepository(City::class)->findBy([], ['name' => 'asc']);
$data['mailingCampaignTypeList'] = $entityManager->getRepository(MailingCampaignType::class)->findBy([], ['ID' => 'ASC']);
$data['shareUrl'] = $request->getSchemeAndHttpHost() . '?ref=' . $user->getID();
$data['user'] = $entityManager->merge($user);
$data['referralBonus'] = $this->getSiteSettings()->getReferralBonus();
$data['subscribed'] = $subscriptionService->isSubscriber($user);
$data['subscription'] = $subscriptionService->getSubscription($user);
$data['currentSubscriptionPlan'] = $subscriptionService->getCurrentSubscriptionPlan($user);
if ($mobileDevice) {
return $this->render('Slivki/mobile/profile/index.html.twig', $data);
}
return $this->render('Slivki/profile/index.html.twig', $data);
}
/**
* @Route("/profile/ajax_get_more_codes")
*/
public function ajaxGetMoreCodesAction(
Request $request,
ImageService $imageService
) {
if (!$request->isXmlHttpRequest()) {
return $this->redirect("/profile");
}
$offset = $request->query->get('offset');
$type = $request->query->get('type');
$limit = $request->query->get('limit');
$result = [
'html' => '',
'hideShowMoreButton' => 0
];
switch($type) {
case 'all':
$balanceActivity = $this->getBalanceActivity(null, 0);
$activeCodes = $this->getCodesHistory(null, 0,false);
$all = array_merge($balanceActivity, $activeCodes);
$allUserHistory = $this->getAllUserHistory($request, $imageService, $all, $limit, $offset);
$result = [
'html' => $allUserHistory['html'],
'hideShowMoreButton' => $allUserHistory['count'] < $limit ? '1' : '0'
];
break;
case 'balanceActivity':
$balanceActivity = $this->getBalanceActivity($limit, $offset);
$result = [
'html' => $this->getBalanceActivityHtml($balanceActivity),
'hideShowMoreButton' => count($balanceActivity) < $limit ? '1' : '0'
];
break;
case 'deliveryOrdersHistory':
$deliveryOrdersHistory = $this->getCodesHistory($limit, 0,false, true);
$deliveryOrdersHistoryHtml = $this->getAllUserHistory($request, $imageService, $deliveryOrdersHistory, $limit, $offset, false);
$result = [
'html' => $deliveryOrdersHistoryHtml['html'],
'hideShowMoreButton' => count($deliveryOrdersHistory) < (int)$offset + (int)$limit ? '1' : '0'
];
break;
case 'promocodesHistory':
$promocodesHistory = $this->getCodesHistory($limit, $offset, false);
$result = [
'html' => $this->getCodesHistoryHtml($request, $promocodesHistory),
'hideShowMoreButton' => count($promocodesHistory) < $limit ? '1' : '0'
];
break;
}
return new Response(json_encode($result));
}
private function getCodesHistory($limit, $offset, $onlyActive = true, $onlyFoodOrders = false) {
$userID = $this->getUser()->getID();
$onlyActiveCondition = $onlyActive ? "AND offerOrderDetails.codeActiveTill >= CURRENT_TIMESTAMP() + '-1 day'" : "";
$onlyFoodOrdersCondition = $onlyFoodOrders ? "and (offerOrder instance of " . FoodOrder::class
. " or offerOrder instance of " . TireOrder::class . " or offerOrder instance of " . GiftCertificateOrder::class . ")" : "";
$entityManager = $this->getDoctrine()->getManager();
$dql = "SELECT offerOrder, offer, teaserMedia
FROM Slivki:OfferOrder offerOrder
join offerOrder.offer offer
left join offer.teaserMedias teaserMedia
WHERE offerOrder.user = $userID and offerOrder.status > 0
$onlyActiveCondition
$onlyFoodOrdersCondition
ORDER BY offerOrder.ID DESC";
$query = $entityManager->createQuery($dql);
if ($limit) {
$query->setMaxResults($limit);
}
$query->setFirstResult($offset);
return $query->getResult();
}
private function getCodesHistoryHtml(Request $request, $codesHistory)
{
/** @var User $user */
$user = $this->getUser();
$offerRepository = $this->getOfferRepository();
$codesHistoryHtml = '';
$mobileDevice = CommonUtil::isMobileDevice($request);
$view = $mobileDevice ? 'Slivki/mobile/profile/code_item.html.twig' : 'Slivki/profile/codes/codes_item.html.twig';
foreach($codesHistory as $item) {
if ($item->getOfferOrderDetails()->count() == 0 || ($item instanceof FoodOrder) || ($item instanceof TireOrder)) {
continue;
}
$data['isTotalTab'] = false;
if ($mobileDevice) {
$offer = $item->getOffer();
$data['offer'] = $offer;
$codeCost = $offerRepository->getCodeCost($offer);
$offerIsFreeForUser = $this->getOfferRepository()->isOfferFreeForUser($offer, $user);
$data['payLink'] = '/oplata-balance/' . $offer->getID();
if (!$offerIsFreeForUser && $user->getFullBalance() < $codeCost) {
$data['payLink'] = '/oplata/' . $offer->getID();
}
if ($offer->getID() == Offer::PETROL_OFFER_ID) {
$data['payLink'] = '/oplata-promokoda-azs';
}
}
$data['offerOrder'] = $item;
$codesHistoryHtml .= $this->renderView($view, $data);
}
return $codesHistoryHtml;
}
private function getBalanceActivity($limit, $offset) {
$userID = $this->getUser()->getID();
$entityManager = $this->getDoctrine()->getManager();
$user = $this->getUser();
$userRegistrationBonusCancel = $user->getBalanceActivityByType($entityManager->find(UserBalanceActivityType::class, UserBalanceActivity::TYPE_REGISTRATION_BONUS_CANCEL));
$userRegistrationBonusCancelCondition = '';
if ($userRegistrationBonusCancel->count() > 0) {
$userRegistrationBonusCancelCondition = ' AND UserBalanceActivity.type != ' . UserBalanceActivity::TYPE_REGISTRATION_BONUS
. 'AND UserBalanceActivity.type != ' . UserBalanceActivity::TYPE_REGISTRATION_BONUS_CANCEL;
}
$dql = "SELECT UserBalanceActivity
FROM Slivki:UserBalanceActivity UserBalanceActivity
WHERE UserBalanceActivity.user = $userID $userRegistrationBonusCancelCondition
AND UserBalanceActivity.type != :resetBalanceForInactiveUserType
ORDER BY UserBalanceActivity.createdOn DESC";
$query = $entityManager->createQuery($dql);
$query->setParameter('resetBalanceForInactiveUserType', UserBalanceActivity::TYPE_RESET_BALANCE_FOR_INACTIVE_USER);
if ($limit) {
$query->setMaxResults($limit);
}
$query->setFirstResult($offset);
$balanceActivity = $query->getResult();
return $balanceActivity;
}
private function getBalanceActivityHtml($balanceActivityList) {
$balanceActivityHtml = '';
$bonusTypeBalanceActivityList = UserBalanceActivityType::BONUS_ACTIVITIES;
/** @var UserBalanceActivity $balanceActivity */
foreach ($balanceActivityList as $balanceActivity) {
if (in_array($balanceActivity->getType()->getID(), $bonusTypeBalanceActivityList)) {
$balanceActivityHtml .= $this->get('twig')->render('Slivki/profile/codes/bonus_item.html.twig', ['bonus' => $balanceActivity, 'siteSettings' => $this->getSiteSettings()]);
} else {
$balanceActivityHtml .= $this->get('twig')->render('Slivki/profile/codes/payments_item.html.twig', ['payment' => $balanceActivity]);
}
}
return $balanceActivityHtml;
}
private function getAllUserHistory(Request $request, ImageService $imageService, $all, $limit, $offset = 0, $isTotalTab = true) {
$isMobile = self::getMobileDevice($request);
$siteSettings = $this->getSiteSettings();
usort($all, function ($item1, $item2) {
return $item2->getCreatedOn()->format('U') - $item1->getCreatedOn()->format('U');
});
$all = array_slice($all, $offset, $limit);
$bonusTypeBalanceActivityList = UserBalanceActivityType::BONUS_ACTIVITIES;
$result = [
'html' => '',
'count' => count($all)
];
/** @var User $user */
$user = $this->getUser();
$offerRepository = $this->getOfferRepository();
$standardCodeCost = $siteSettings->getCodeCost();
$seoRepository = $this->getSeoRepository();
foreach ($all as $item) {
if ($item instanceof SubscriptionOrder) {
continue;
}
if ($item instanceof OfferOrder) {
$data = [];
$data['isTotalTab'] = $isTotalTab;
$view = 'Slivki/profile/codes/codes_item.html.twig';
if ($item instanceof FoodOrder) {
if ($isMobile && $isTotalTab) {
continue;
}
$data['foodOrder'] = $this->foodOrderHistoryDtoFactory->create($item);
$view = 'Slivki/profile/codes/food_item.html.twig';
} elseif ($item instanceof TireOrder) {
$data['tireOrder'] = $this->tireOrderHistoryDtoFactory->create($item);
$view = 'Slivki/profile/codes/tire_item.html.twig';
} elseif ($item instanceof GiftCertificateOrder) {
$view = 'Slivki/profile/codes/gift_certificate_item.html.twig';
}
if ($isMobile) {
if ($item instanceof FoodOrder) {
$view = 'Slivki/mobile/profile/food_item.html.twig';
} elseif ($item instanceof TireOrder) {
$view = 'Slivki/mobile/profile/tire_item.html.twig';
} elseif ($item instanceof GiftCertificateOrder) {
$view = 'Slivki/mobile/profile/gift_certificate_item.html.twig';
} else {
$view = 'Slivki/mobile/profile/code_item.html.twig';
}
$offer = $item->getOffer();
$data['offer'] = $offer;
$codeCost = $offerRepository->getCodeCost($offer);
$offerIsFreeForUser = $this->getOfferRepository()->isOfferFreeForUser($offer, $user);
$data['payLink'] = '/oplata-balance/' . $offer->getID();
if ($user->getFullBalance() < $codeCost && !$offerIsFreeForUser) {
$data['payLink'] = '/oplata/' . $offer->getID();
}
if ($offer->getID() == Offer::PETROL_OFFER_ID) {
$data['payLink'] = '/oplata-promokoda-azs';
} else if ($codeCost != $standardCodeCost || ($item->getOfferOrderDetails()->count() > 0 && $item->getOfferOrderDetails()->first()->getOfferExtension())) {
$data['payLink'] = $seoRepository->getOfferURL($offer->getID())->getMainAlias();
}
}
$data['offerOrder'] = $item;
$result['html'] .= $this->renderView($view, $data);
} else {
if (!$isMobile) {
if (in_array($item->getType()->getID(), $bonusTypeBalanceActivityList)) {
$result['html'] .= $this->renderView('Slivki/profile/codes/bonus_item.html.twig', ['bonus' => $item, 'siteSettings' => $siteSettings]);
} else {
$result['html'] .= $this->renderView('Slivki/profile/codes/payments_item.html.twig', ['payment' => $item]);
}
}
}
}
return $result;
}
/**
* @Route("/profile/ajax_use_code/{codeID}")
*/
public function ajaxUseCode($codeID) {
$code = $this->getOfferOrderDetailsRepository()->find($codeID);
if (!$code) {
return new Response();
}
if ($code->getOfferOrder()->getUser() != $this->getUser()) {
return new Response();
}
$code->setUsed(true);
$this->getDoctrine()->getManager()->flush();
return new Response();
}
/**
* @Route("/profile/ajax_unuse_code/{codeID}")
*/
public function ajaxUnuseCode($codeID) {
$code = $this->getOfferOrderDetailsRepository()->find($codeID);
if (!$code) {
return new Response();
}
if ($code->getOfferOrder()->getUser() != $this->getUser()) {
return new Response();
}
$code->setUsed(false);
$this->getDoctrine()->getManager()->flush();
return new Response();
}
/**
* @Route("/ajax_get_user_social_accounts")
*/
public function ajaxGetUserSocialAccounts() {
$user = $this->getUser();
$result = '';
$socialAccounts = $user->getSocialAccounts();
foreach ($socialAccounts as $socialAccount) {
$result .= $socialAccount->getNetwork() . ' ';
}
return new Response($result);
}
/**
* @Route("/accept_newsletter")
*/
public function acceptNewsletter(Request $request, SubscriptionService $subscriptionService)
{
$entityManager = $this->getDoctrine()->getManager();
$user = $this->getUser();
$requestMailingCampaignTypeIDList = $request->request->get('newsletter', []);
foreach ($user->getMailingCampaignTypes() as $mailingCampaignType) {
if (!in_array($mailingCampaignType->getID(), $requestMailingCampaignTypeIDList)) {
$user->removeMailingCampaignType($mailingCampaignType);
$this->getUserRepository()->addActivity($user, UserActivity::UNSUBSCRIBE_ACTION, $mailingCampaignType);
}
}
$subscribe = false;
foreach ($requestMailingCampaignTypeIDList as $mailingCampaignTypeID) {
if (!$user->hasMailingCampaignType($mailingCampaignTypeID)) {
$mailingCampaignType = $entityManager->getRepository(MailingCampaignType::class)->find($mailingCampaignTypeID);
if ($mailingCampaignType) {
$user->addMailingCampaignTypes($mailingCampaignType);
$this->getUserRepository()->addActivity($user, UserActivity::SUBSCRIBE_ACTION, $mailingCampaignType);
$subscribe = true;
}
}
}
if ($subscribe) {
$limitDate = new \DateTime('2017-09-20');
$activityType = $entityManager->find(UserBalanceActivityType::class, UserBalanceActivity::TYPE_SUBSCRIBE_PROMO_BONUS);
$activityCount = 0;
if ($user->getBalanceActivityByType($activityType)->count() == 0) {
foreach ($user->getUserActivity() as $activity) {
if ($activity->getCreatedOn() > $limitDate) {
$activityCount++;
}
}
if ($activityCount < 2) {
$entityManager->getRepository(User::class)->addBonus(
$subscriptionService,
$user,
UserBalanceActivity::TYPE_SUBSCRIBE_PROMO_BONUS,
1.5
);
}
}
}
$entityManager->flush($user);
return $this->redirect("/profile#profile_subscribe");
}
/**
* @Route("/unsubscribe")
*/
public function unsubscribeNewsletters(Request $request) {
$entityManager = $this->getDoctrine()->getManager();
if ($request->isMethod('POST')) {
$email = $request->request->get('email', '');
$mailingCampaignID = $request->request->getInt('mailingCampaignID');
if ($email == '') {
return $this->redirect("/");
}
$userRepository = $this->getUserRepository();
$user = $userRepository->findOneByEmail($email);
if (!$user) {
return $this->redirect("/");
}
$requestMailingCampaignTypeIDList = $request->request->get('newsletter', []);
$unsubscribed = false;
foreach ($user->getMailingCampaignTypes() as $mailingCampaignType) {
if (!in_array($mailingCampaignType->getID(), $requestMailingCampaignTypeIDList)) {
$user->removeMailingCampaignType($mailingCampaignType);
$userRepository->addActivity($user, UserActivity::UNSUBSCRIBE_ACTION, $mailingCampaignType);
$unsubscribed = true;
}
}
if ($unsubscribed) {
$mailingCampaign = $entityManager->find(MailingCampaign::class, $mailingCampaignID);
if ($mailingCampaign) {
$mailingCampaignUnsubscribe = $entityManager->getRepository(MailingCampaignUnsubscribe::class)->findBy(['user' => $user, 'mailingCampaign' => $mailingCampaign]);
if (empty($mailingCampaignUnsubscribe)) {
$mailingCampaignUnsubscribe = new MailingCampaignUnsubscribe();
$mailingCampaignUnsubscribe->setUser($user);
$mailingCampaignUnsubscribe->setMailingCampaign($mailingCampaign);
$entityManager->persist($mailingCampaignUnsubscribe);
$entityManager->flush();
}
}
}
foreach ($requestMailingCampaignTypeIDList as $mailingCampaignTypeID) {
if (!$user->hasMailingCampaignType($mailingCampaignTypeID)) {
$mailingCampaignType = $entityManager->getRepository(MailingCampaignType::class)->find($mailingCampaignTypeID);
if ($mailingCampaignType) {
$user->addMailingCampaignTypes($mailingCampaignType);
$userRepository->addActivity($user, UserActivity::SUBSCRIBE_ACTION, $mailingCampaignType);
}
}
}
$entityManager->flush($user);
return $this->render('Slivki/unsubscribe_results.html.twig');
}
$email = $request->query->get('email', '');
$subscriber = $entityManager->getRepository(Subscriber::class)->findOneByEmail($email);
if ($subscriber) {
$entityManager->remove($subscriber);
$entityManager->flush($subscriber);
return $this->render('Slivki/unsubscribe_results.html.twig');
}
$data = [];
if ($email == '') {
return $this->redirect("/");
}
$userRepository = $this->getUserRepository();
$user = $userRepository->findOneByEmail($email);
if (!$user) {
return $this->redirect("/");
}
$mailingCampaignID = $request->query->getInt('mc');
if ($mailingCampaignID) {
$data['mailingCampaignID'] = $mailingCampaignID;
}
$data['user'] = $user;
$data['mailingCampaignTypeList'] = $entityManager->getRepository(MailingCampaignType::class)->findBy([], ['ID' => 'ASC']);
return $this->render('Slivki/unsubscribe.html.twig', $data);
}
/**
* @Route("/profile_image_upload")
*/
public function profileImageUpload(
Request $request,
ImageService $imageService,
KernelInterface $kernel,
SubscriptionService $subscriptionService
) {
$actionRequest = $request->query->get('actionRequest');
$error = 'true';
$result = '';
$user = $this->getUser();
$entityManager = $this->getDoctrine()->getManager();
$media = $user->getProfileImageMedia();
switch ($actionRequest) {
case 'uploadFile':
$imageFolder = $kernel->getProjectDir() . '/public' . User::MEDIA_PATH;
$uploadedFile = $request->files->get('profileImageUpload');
if ($uploadedFile) {
if (!in_array(mb_strtolower($uploadedFile->getClientOriginalExtension()), ['jpg', 'png', 'gif', 'jpeg'])) {
return new Response("error=true;result=Разрешены только .jpg, .jpeg, .png или .gif изображения");
};
$fs = new Filesystem();
$newFileName = time() . '_' . $uploadedFile->getClientOriginalName();
while ($fs->exists($imageFolder . $newFileName)) {
$newFileName = time() . '_' . $newFileName;
}
$uploadedFile->move($imageFolder, $newFileName);
if (!$media) {
$media = new Media\ProfileImageMedia();
$media->setMediaType($entityManager->getRepository(MediaType::class)->find(MediaType::TYPE_PROFILE_IMAGE_ID));
$media->setPath(MediaType::TYPE_PROFILE_IMAGE_PATH);
$entityManager->persist($media);
}
$media->setName($newFileName);
$user->setProfileImageMedia($media);
$entityManager->flush();
// Add bonus for avatar upload
$siteSettings = $this->getSiteSettings();
$userRepository = $entityManager->getRepository(User::class);
if(!$userRepository->hasUserAvatarBonus($user)) {
$userRepository->addBonus(
$subscriptionService,
$user,
UserBalanceActivity::TYPE_PROFILE_IMAGE_BONUS,
$siteSettings->getAvatarBonus()
);
}
$result = User::MEDIA_PATH . $newFileName;
$error = 'false';
}
break;
case 'cropImage':
$cropCoordinates = $request->request->get('cropCoordinates');
$cropCoordinates = json_decode($cropCoordinates);
$originalMediaPath = $kernel->getProjectDir() . '/public/znijki-media/initial' . $media->getPath() . $media->getName();
$imagine = new Imagine();
$image = $imagine->open($originalMediaPath);
$image->crop(new Point($cropCoordinates->x, $cropCoordinates->y), new Box($cropCoordinates->w, $cropCoordinates->h));
$image->save($originalMediaPath);
$softCache = new SoftCache(ImageService::CACHE_NAME);
$mediaSizeList = $media->getSizes();
foreach ($mediaSizeList->toArray() as $mediaSize) {
$cacheKey = $media->getID() . "-url-" . $mediaSize->getWidth() . "x" . $mediaSize->getHeight();
$softCache->set($cacheKey, null, 1);
$imageService->resizeImage($media, $mediaSize->getWidth(), $mediaSize->getHeight());
}
$result = $imageService->getImageURL($media, 250, 250);
$error = 'false';
break;
case 'deleteImage':
$entityManager->remove($media);
$entityManager->flush();
$error = 'false';
break;
}
return new Response("error=$error;result=$result");
}
/**
* @Route("/ajax_profile_save")
*/
public function ajaxProfileSave(Request $request, ValidatorInterface $validator) {
$user = $this->getUser();
$result['error'] = '';
$entityManager = $this->getDoctrine()->getManager();
/** @var \Symfony\Component\Validator\ConstraintViolationList $errorList */
$errorList = $validator->validate($user);
if ($errorList->count() > 0) {
$result['error'] .= $errorList->get(0)->getMessage();
}
if($request->request->get('user_name') == '') {
$result['error'] .= 'Поле "Имя" не может быть пустым!<br>';
}
$requestPassword = trim($request->request->get('user_new_pass'));
if(strlen($requestPassword) > 0) {
if (strlen($requestPassword) < 6) {
$result['error'] .= 'Пароль не может быть меньше 6 символов';
}
if($requestPassword != $request->request->get('user_confirm_pass')) {
$result['error'] .= 'Введенные пароли не совпадают!<br>';
}
$user->encryptPassword($requestPassword, $user->getSalt());
}
$user->setFirstName($request->request->get('user_name'));
$user->setLastName($request->request->get('user_last_name'));
$city = $entityManager->getRepository(City::class)->find($request->request->get('city'));
$user->setCity($city);
if($result['error'] == '') {
$entityManager->flush($user);
}
return new Response(json_encode($result));
}
/**
* @Route("/confirm/{code}", name="confirm")
*/
public function confirmAction(Request $request, $code) {
$code = pg_escape_string($code);
$entityManager = $this->getDoctrine()->getManager();
$resultMapping = new ResultSetMapping();
$resultMapping->addEntityResult(UserConfirmation::class, "UserConfirmation");
$resultMapping->addFieldResult("UserConfirmation", "user_id", "userID");
$resultMapping->addFieldResult("UserConfirmation", "id", "ID");
$resultMapping->addFieldResult("UserConfirmation", "return_url", "returnUrl");
$query = $entityManager->createNativeQuery("select user_id, id, return_url from user_confirmation where md5(id::text || user_id::text)=?", $resultMapping);
$query->setParameter(1, $code);
$confirmation = $query->getResult();
$returnUrl = '/';
if ($confirmation) {
$userID = $confirmation[0]->getUserID();
$user = $entityManager->getRepository(User::class)->find($userID);
if (!$user) {
$data['lastComments'] = $this->getDoctrine()->getRepository(Comment::class)->findBy(["hidden" => false], ["createdOn" => "desc"], 3);
return $this->render('Slivki/register_confirm_error.html.twig', $data);
}
$user->setStatus(User::STATUS_CONFIRMED);
$mainMailingCampaignType = $entityManager->getRepository(MailingCampaignType::class)->find(MailingCampaignType::MAIN_ID);
$user->addMailingCampaignTypes($mainMailingCampaignType);
foreach ($confirmation as $item) {
$entityManager->remove($item);
}
$entityManager->flush();
$amplitude = new Amplitude($user);
$amplitude->sendEvent('NewUserConfirmed', []);
$userRepository = $this->getUserRepository();
$userRepository->addActivity($user, UserActivity::SUBSCRIBE_ACTION, $mainMailingCampaignType);
$returnUrl = $confirmation[0]->getReturnUrl() ? $confirmation[0]->getReturnUrl() : '/';
} else {
$data['lastComments'] = $this->getDoctrine()->getRepository(Comment::class)->findBy(["hidden" => false], ["createdOn" => "desc"], 3);
return $this->render('Slivki/register_confirm_error.html.twig', $data);
}
$this->addFlash("openThanksForRegisterPopup", "true");
// Login user
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->get('security.token_storage')->setToken($token);
return $this->redirect($returnUrl);
}
private function checkReferer(Request $request, User $user) {
$refererID = $request->cookies->get('refID');
if (!$refererID) {
return;
}
$entityManager = $this->getDoctrine()->getManager();
$referer = $entityManager->find(User::class, $refererID);
if (!$referer) {
return;
}
$referral = $entityManager->getRepository(Referral::class)->findBy(['email' => $user->getEmail()]);
if (!$referral) {
$referral = new Referral();
$entityManager->persist($referral);
} else {
$referral = $referral[0];
}
$referral->setReferral($user);
$referral->setReferer($referer);
$referral->setStatus(Referral::STATUS_REGISTERED);
$referer->addReferral($referral);
$entityManager->flush();
}
/**
* @Route("/ajax_set_favourite")
*/
public function ajaxSetFavourite(Request $request) {
if (!$request->isXmlHttpRequest()) {
return $this->redirect("/");
}
$action = $request->query->get('action');
$offerID = $request->query->get('offerID');
$entityManager = $this->getDoctrine()->getManager();
$user = $this->getUser();
$offer = $this->getOfferRepository()->find($offerID);
switch ($action) {
case 'addToFavourites':
$user->addFavouriteOffer($offer);
$entityManager->flush();
$amplitude = new Amplitude($user);
$amplitude->sendEvent('PromotionAddedToFavorite', ['promotion_id' => $offerID]);
break;
case 'deleteFromFavourites':
$user->deleteFavouriteOffer($offer);
$entityManager->flush();
break;
}
return new Response('');
}
private function subscriberRemove($email) {
$entityManager = $this->getDoctrine()->getManager();
$subscriber = $entityManager->getRepository(Subscriber::class)->findOneByEmail($email);
if ($subscriber) {
$entityManager->remove($subscriber);
$entityManager->flush($subscriber);
}
}
/**
* @Route("/profile/refresh_user_balance")
*/
public function refreshUserBalance() {
return new Response($this->getUser()->getBalance());
}
/** @Route("/user/offer-rate/defer") */
public function deferOfferRateAction() {
$sql = "update offer_rate_schedule set show_on = show_on + '7 days' where user_id = " . (int)$this->getUser()->getID() . ';';
$this->getDoctrine()->getManager()->getConnection()->executeQuery($sql);
return new Response();
}
/** @Route("/user/offer-rate-popup/disable") */
public function disableOfferRatePopup() {
$entityManager = $this->getDoctrine()->getManager();
$user = $entityManager->merge($this->getUser());
$user->setNotShowRatePopupTill(new \DateTime('+30 days'));
$entityManager->flush();
return new Response();
}
/**
* @Route("/mobile-logout")
*/
public function mobileLogoutPageAction(Request $request) {
if ($this->getUser() and self::getMobileDevice($request)) {
return $this->render('Slivki/mobile_logout.html.twig');
} else {
return $this->redirect("/login");
}
}
/**
* @Route("/profile/ajax_get_favorite")
*/
public function ajaxGetFavorite(Request $request) {
if (!$request->isXmlHttpRequest()) {
return $this->redirect("/profile");
}
$entityManager = $this->getDoctrine()->getManager();
$user = $this->getUser();
$data['allFavouriteOffers'] = $user->getFavouriteOffers()->toArray();
$data['activeFavouriteOffers'] = [];
$data['pastFavouriteOffers'] = [];
$mediaRepository = $entityManager->getRepository(Media::class);
foreach ($data['allFavouriteOffers'] as $favouriteOffer) {
if ($favouriteOffer->getActiveTill()->format('U') > time()) {
$data['activeFavouriteOffers'][] = $favouriteOffer;
} else {
$data['pastFavouriteOffers'][] = $favouriteOffer;
}
}
$view = self::getMobileDevice($request) ? 'Slivki/mobile/profile/favorites.html.twig' : 'Slivki/profile/favorites/index.html.twig';
return $this->render($view, $data);
}
/** @Route("/profile/invite/send") */
public function sendInviteAction(Request $request, Mailer $mailer, ValidatorInterface $validator) {
$emailList = $request->request->get('inviteTo');
if (!$emailList) {
return new JsonResponse(['message' => 'Введите адрес получателя']);
}
$emailList = explode(',', $emailList);
$entityManager = $this->getDoctrine()->getManager();
$sql = "select count(*) from referral where referer_id = " . $this->getUser()->getID() . " and created_on > now() + '-1 day'";
$invitesSentCount = $entityManager->getConnection()->executeQuery($sql)->fetchColumn();
if ($invitesSentCount + count($emailList) > 10) {
return new JsonResponse(['message' => 'Превышен суточный лимит отправки приглашений']);
}
$emailConstraint = new \Symfony\Component\Validator\Constraints\Email();
foreach ($emailList as $email) {
$error = $validator->validate($email, $emailConstraint);
if ($error->count() > 0) {
return new JsonResponse(['message' => 'Неверный формат адреса электронной почты']);
}
}
$referer = $entityManager->merge($this->getUser());
$inviteFrom = $request->request->get('inviteFrom');
foreach ($emailList as $email) {
$email = mb_strtolower(trim($email));
$referral = new Referral();
$referral->setEmail($email);
$referral->setReferer($referer);
$referral->setStatus(Referral::STATUS_WAIT);
$entityManager->persist($referral);
$referer->addReferral($referral);
$entityManager->flush();
$message = $mailer->createMessage();
$message->setTo($email);
$message->setFrom('info@slivki.by', $inviteFrom);
$message->returnPath($inviteFrom);
$message->replyTo($inviteFrom);
$message->setSubject('Рекомендую Slivki.by');
$message->setBody($request->request->get('inviteText'));
$mailer->send($message);
}
return new JsonResponse(['result' => true, 'message' => 'Приглашение отправлено']);
}
/** @Route("/profile/card", name = "profileMobileCardList") */
public function creditCardAction(Request $request) {
if (!self::getMobileDevice($request)) {
return new Response();
}
return $this->render('Slivki/mobile/profile/card.html.twig');
}
/** @Route("/profile/card/add-form", name = "profileMobileCardAdd") */
public function addCreditCardAction(Request $request) {
if (!self::getMobileDevice($request)) {
return new Response();
}
return $this->render('Slivki/mobile/profile/card_add.html.twig');
}
/**
* @Route("/profile/card/remove/{cardID}")
*/
public function cardRemoveAction(
RemoveCreditCardHandler $removeCreditCardHandler,
int $cardID
) {
$removeCreditCardHandler->handle($this->getUser(), $cardID);
return new Response();
}
/**
* @Route("/profile/gift_certificates/pdf/{offerOrderDetailsID}")
*/
public function giftCertificatesPdf(Request $request, KernelInterface $kernel, $offerOrderDetailsID) {
$action = $request->query->get('action');
/** @var OfferOrderDetails $offerOrderDetails */
$offerOrderDetails = $this->getOfferOrderDetailsRepository()->find($offerOrderDetailsID);
if (!$offerOrderDetails) {
return new Response();
}
if ($offerOrderDetails->getOfferOrder()->getUser() != $this->getUser()) {
return new Response();
}
$mpdf = $this->getGiftCertificateMpdf($kernel, $offerOrderDetails);
if (!$mpdf) {
return new Response();
}
if ($action == 'save') {
$mpdf->Output('certificate'.$offerOrderDetailsID.'.pdf', 'D');
} else {
$mpdf->Output();
}
}
/** @Route("/profile/phone/confirm", name="phoneConfirm") */
public function phoneConfirmAction(Request $request) {
$user = $this->getUser();
$userPhone = $user->getCurrentPhone();
if ($userPhone && $userPhone->isConfirmed() && $userPhone->isBelorussian()) {
return $this->redirectToRoute('homepage');
}
return $this->render(CommonUtil::isMobileDevice($request) ? 'Slivki/mobile/profile/phone_confirm.html.twig'
: 'Slivki/profile/phone_confirm.html.twig');
}
/**
* @Route("/profile/phone/sendsms", name="profile_phone_sendsms")
*/
public function phoneSendSmsAction(
Request $request,
AuthorizationCodeSender $authorizationCodeSender,
UserPhoneService $userPhoneService
): Response {
$phoneNumber = $request->request->get('userPhone', '');
if (strlen($phoneNumber) != 12) {
return new Response('Wrong phone number!');
}
$entityManager = $this->getDoctrine()->getManager();
$user = $this->getUser();
$userPhone = $user->getCurrentPhone();
if ($userPhone && $userPhone->getPhoneNumber() == $phoneNumber && $userPhone->isConfirmed()) {
return new Response('Allready confirmed!');
}
$existUserPhone = $entityManager->getRepository(UserPhone::class)->findBy([
'confirmed' => true,
'phoneNumber' => $phoneNumber
]);
if ($existUserPhone) {
return new Response("Номер телефона $phoneNumber уже зарегистрирован!");
}
if (!$userPhone || !($userPhone->getPhoneNumber() == $phoneNumber)) {
$userPhoneService->addUserPhone($user, $phoneNumber);
}
$smsCode = random_int(1000, 9999);
$this->get('session')->set('confirmPhoneNumber', $phoneNumber);
$this->get('session')->set('confirmPhoneSmsCode', $smsCode);
$authorizationCodeSender->send($phoneNumber, $smsCode, $request->getHost());
return new Response();
}
/** @Route("/profile/phone/checkcode") */
public function phoneCheckCodeAction(
Request $request,
Mailer $mailer,
UserPhoneService $userPhoneService
): Response {
$requestCode = $request->request->get('smsCode', '');
$code = $this->get('session')->get('confirmPhoneSmsCode');
$phoneNumber = $this->get('session')->get('confirmPhoneNumber');
if ($requestCode != $code) {
return new Response();
}
$user = $this->getUser();
$userPhone = $user->getCurrentPhone();
if ($userPhone && $userPhone->getPhoneNumber() == $phoneNumber) {
$userPhoneService->confirmUserPhone($userPhone);
$comments = $this->getCommentRepository()->findBy(['user' => $user, 'confirmedPhone' => false], ['ID' => 'DESC']);
if (isset($comments[0])) {
$comments[0]->setConfirmedPhone(true);
if ($comments[0]->getTypeID() == Comment::TYPE_OFFER_COMMENT) {
$offer = $this->getOfferRepository()->find($comments[0]->getEntityID());
if ($offer) {
$this->sendOfferCommentNotice($mailer, $offer, $comments[0], $comments[0]->getParentComment());
}
}
}
$this->getDoctrine()->getManager()->flush();
if (isset($comments[0])) {
$this->resetCommentsCache($comments[0]->getEntityID(), $comments[0]->getTypeID());
}
return new Response('1');
}
return new Response();
}
/**
* @Route("/user/create/from-order", methods={"POST"}, name="user_create_from_order")
*/
public function userCreateFromOrder(Request $request, Mailer $mailer, ValidatorInterface $validator) {
$entityManager = $this->getDoctrine()->getManager();
$order = $entityManager->find(Offer::class, $request->request->get('orderID'));
if (!$order) {
return new Response('Произошла ошибка');
}
$email = mb_strtolower(trim($request->request->get('email')));
$user = $entityManager->getRepository(User::class)->findByEmail($email);
if ($user) {
return new JsonResponse(['error' => true, 'message' => 'Пользователь с таким email уже зарегистрирован']);
}
$password = rand(11111, 99999);
$user = new User();
$user->setEmail($email);
$user->encryptPassword($password);
$order->setUser($user);
$user->setStatus(User::STATUS_CONFIRMED);
/** @var \Symfony\Component\Validator\ConstraintViolationList $errorList */
$errorList = $validator->validate($user);
if ($errorList->count() > 0) {
return new JsonResponse(['error' => true, 'message' => $errorList->get(0)->getMessage()]);
}
$order->setUser($user);
$entityManager->persist($user);
$entityManager->getRepository(User::class)->addDirectorGroupToUserByUser($user);
$entityManager->flush();
$message = $mailer->createMessage();
$message->setTo($email);
$message->setFrom('info@slivki.by', 'Slivki.by');
$message->setSubject('Мы позаботились о том, чтобы вы не забыли');
$message->setBody($this->renderView('Slivki/emails/code.html.twig', ['offerOrder' => $order, 'userCreated' => true]), 'text/html');
$mailer->send($message);
return new JsonResponse(['error' => false, 'message' => 'Письмо с кодом отправлено на Ваш адрес']);
}
/**
* @Route("/profile/delivery/address/add")
*/
public function addAddressAction(
Request $request,
CoordinatesYandex $coordinatesYandex,
SubscriptionService $subscriptionService,
DeliveryZoneRepositoryInterface $deliveryZoneRepository
): JsonResponse {
$entityManager = $this->getDoctrine()->getManager();
$orderID = $request->request->getInt('orderID');
/** @var FoodOrder $order */
$order = $entityManager->find(FoodOrder::class, $orderID);
$offer = $order->getOffer();
$offerID = $offer->getID();
$iikoUtil = IikoUtil::instance($offer);
$iikoUtil->setContainer($this->kernel->getContainer());
if ($request->request->getBoolean('isStreetSelect')) {
$street = $entityManager->find(Street::class, $request->request->getInt('streetID'));
} else {
$streetName = $request->request->get('streetID');
$deliveryLocationID = $request->request->getInt('deliveryLocationID');
$deliveryLocation = null;
$streetFindByParameters = [
'name' => $streetName,
'offerID' => $offerID,
];
if (0 !== $deliveryLocationID) {
$deliveryLocation = $entityManager->find(DeliveryLocation::class, $deliveryLocationID);
$city = $deliveryLocation->getName();
$streetFindByParameters['city'] = $city;
}
$street = $entityManager->getRepository(Street::class)->findOneBy($streetFindByParameters);
if (!$street) {
$street = new Street();
$street->setOfferID($offerID);
$street->setName($streetName);
$entityManager->persist($street);
if (null !== $deliveryLocation) {
$street->setDeliveryLocation($deliveryLocation);
$street->setCity($city);
}
}
}
$address = new UserAddress();
$address->setName($request->request->get('name'));
$address->setStreet($street);
$address->setHouse($request->request->get('house'));
$address->setBlock($request->request->get('block'));
$address->setAppartment($request->request->get('appartment'));
$address->setEntrance($request->request->get('entrance'));
$address->setFloor($request->request->get('floor'));
$address->setDoorphone($request->request->get('doorphone'));
$address->setOfferID($order->getOffer()->getID());
$address->setActive(true);
$address->setIsOnlineGift($request->request->getBoolean('isOnlineGift'));
$address->setCompletedPurchase(false);
$order->setDeliveryTime($request->request->get('deliveryTime'));
$this->getUser()->addDeliveryAddress($address);
$phone = $request->request->get('phone');
if ($phone) {
$address->setPhone($phone);
}
$order->setDeliveryAddress($address);
if (!($iikoUtil instanceof Tokiny)) {
$order->setPaymentType($request->request->getInt('paymentType', PaymentType::ONLINE));
}
$result = $this->getCheckAddressResponse($iikoUtil->checkOrder($entityManager, $order, $subscriptionService));
if ($result['status'] === 'error') {
return new JsonResponse([
'status' => $result['status'],
'message' => $result['message'],
], Response::HTTP_OK);
}
$entityManager->flush();
$offerDeliveryZone = $order->getOffer()->getOfferDeliveryZone();
if (null !== $offerDeliveryZone && $offerDeliveryZone->count() > 0) {
$points = $address->getCoordinatesForDeliveryZone() ?? $coordinatesYandex->getGeoCoordinates(
$address->buildFullAddress(),
['offerId' => (int)$order->getOffer()->getID()]
);
$deliveryZone = $deliveryZoneRepository->getPolygonByPoint($order->getOffer(), $points);
if (null !== $deliveryZone) {
$result['deliveryPrice'] = 0;
$coordinates = explode(' ', $points);
$result['coordinates'] = new CoordinatesResponse(
$coordinates[1],
$coordinates[0],
);
if (null === $address->getCoordinatesForDeliveryZone()) {
$address->setLatitude($coordinates[1]);
$address->setLongitude($coordinates[0]);
}
}
}
if (isset($result['deliveryPrice']) && 0 !== (int) $result['deliveryPrice']) {
$order->setDeliveryCost($result['deliveryPrice']);
}
$result['deliveryPrice'] = $order->getDeliveryCost();
$entityManager->flush();
$view = CommonUtil::isMobileDevice($request) ? 'Slivki/mobile/delivery/address_block.html.twig' : 'Slivki/delivery/address_block.html.twig';
$result['html']['address'] = $this->renderView($view, ['address' => $address, 'checked' => ' checked', 'offerID' => $offerID]);
return new JsonResponse($result, Response::HTTP_OK);
}
/**
* @Route("/profile/devivery/address/delete/{addressID}/{offerID}", name="deleteDeliveryAddress", methods={"GET"})
*/
public function deleteAddressAction(UserAddressRepositoryInterface $userAddressRepository, int $addressID, int $offerID): JsonResponse
{
$userAddress = $userAddressRepository->getByUserIdAndAddressId($this->getUser()->getID(), $addressID);
if ($userAddress instanceof UserAddress) {
$userAddress->disable();
$userAddressRepository->save($userAddress);
}
return new JsonResponse(
['countDeliveryAddresses' => \count($this->getUser()->getAvailableUserAddresses($offerID))],
Response::HTTP_OK,
);
}
/** @Route("/profile/crt/{offerOrderDetailsID}", name="profileGetCrtPdf") */
public function profileGetCrtPdfAction($offerOrderDetailsID, KernelInterface $kernel, GiftCertificateService $giftCertificateService) {
$entityManager = $this->getDoctrine()->getManager();
$dql = "select offerOrderDetails from Slivki:OfferOrderDetails offerOrderDetails
join offerOrderDetails.giftCertificate giftCertificate
join offerOrderDetails.offerOrder offerOrder
join offerOrder.offer offer
where offerOrder.status > 0 and offerOrder.user = :user and offerOrderDetails.ID = :offerOrderDetailsID
";
$offerOrderDetails = $entityManager->createQuery($dql)
->setParameter('user', $this->getUser())
->setParameter('offerOrderDetailsID', $offerOrderDetailsID)
->getOneOrNullResult();
if (!$offerOrderDetails) {
die;
return new Response();
}
$giftCertificateService->getCertificatePdf($kernel, $offerOrderDetails);
die;
}
/**
* @Route("/profile/logout", name="app_logout", methods={"GET"})
*/
public function logout() {
// controller can be blank: it will never be executed!
throw new \Exception('Don\'t forget to activate logout in security.yaml');
}
/**
* @Route("/login/check-code/{code}", name="login_check_code")
*/
public function checkCode(
Request $request,
SmsLimiterService $smsLimiterService,
UserPhoneService $userPhoneService,
$code
) {
$session = $request->getSession();
$logger = Logger::instance('PHONEAUTH');
$logger->info($code);
$logger->info($session->get('loginPhoneCode', 'empty'));
if ((string)$session->get('loginPhoneCode', 'empty') != (string)$code) {
$atemptsCount = $session->get('loginAtemptsCount', 0);
if ($atemptsCount> 10) {
$session->remove('loginPhoneCode');
} else {
$session->set('loginAtemptsCount', $atemptsCount++);
}
$logger->info('ERROR');
return new JsonResponse(['error' => true, 'message' => 'Неверный код']);
}
$phoneNumber = $session->get('loginPhoneNumber');
$entityManager = $this->getDoctrine()->getManager();
$userPhone = $entityManager->getRepository(UserPhone::class)->findOneBy(['phoneNumber' => $phoneNumber, 'confirmed' => true]);
$proposeAccountsMerge = false;
if (!$userPhone) {
$proposeAccountsMerge = true;
$user = new User();
$token = uniqid($user->getID(), true);
$user->setToken($token);
$user->setStatus(User::STATUS_CONFIRMED);
$user->setDefaultPassword();
$entityManager->persist($user);
$userPhone = $userPhoneService->addUserPhone($user, $phoneNumber);
$userPhoneService->confirmUserPhone($userPhone);
$entityManager->flush();
}
/** @var User $user */
$user = $userPhone->getUser();
Logger::instance('DEBUG')->info($user->getPasswordEncoded());
if ($user->getPasswordEncoded() == '' || $user->getPasswordEncoded() == null) {
$user->encryptPassword('111');
$entityManager->flush();
}
Logger::instance('DEBUG')->info($user->getPassword());
$token = $user->getToken();
if (!$token) {
$token = uniqid($user->getID(), true);
$user->setToken($token);
$entityManager->flush();
}
Logger::instance('DEBUG')->info('token');
Logger::instance('DEBUG')->info($token);
$this->addFlash("openMergeProfilePopup", "true");
$cookie = Cookie::create(self::USER_TOKEN_COOKIE, $token, time() + 315360000, '/', $this->getParameter('base_domain'));
$response = new JsonResponse(['error' => false, 'proposeAccountsMerge' => $proposeAccountsMerge]);
$response->headers->setCookie($cookie);
if ($request->getClientIp() !== null) {
$smsLimiterService->clearCache($request->getClientIp());
}
return $response;
}
/** @Route("/login/send-code-email") */
public function sendCodeEmailAction(Request $request, Mailer $mailer) {
$email = $request->request->get('email');
if (!$email) {
return new Response('', 500);
}
$code = rand(1111, 9999);
$email = mb_strtolower($email);
$entityManager = $this->getDoctrine()->getManager();
$this->log($email);
$currentUser = $user = $this->getUser();
if ($user && $currentUser->getEmail()) {
return new Response('', 500);
}
$alreadyMerged = $entityManager->getRepository(User::class)->findOneByEmail($email . "-merged");
if ($alreadyMerged) {
return new Response('', 500);
}
$session = $request->getSession();
$session->set('mergeAcccountEmail', $email);
$userConfirmation = new UserConfirmation();
$userConfirmation->setEmail($email);
$userConfirmation->setAuthCode($code);
$entityManager->persist($userConfirmation);
$entityManager->flush();
$body = $this->renderView('Slivki/emails/mail.html.twig', ['content' => $code]);
$message = $mailer->createMessage('Код для привязки аккаунта', $body, 'html');
$message->setFrom('info@slivki.by', 'Slivki.by');
$this->log($email);
$message->setTo($email);
$mailer->send($message);
return new Response();
}
/**
* @Route("/login/check-code-mail/{code}", name="user_login_check_code_mail")
*/
public function checkEmailCodeAction(
Request $request,
Mailer $mailer,
AccountMerger $mergeAccount,
$code
) {
$entityManager = $this->getDoctrine()->getManager();
$session = $request->getSession();
if ($request->getSession()->get('mergeAcccountEmail')) {
$userConfirmation = $entityManager->getRepository(UserConfirmation::class)->findOneBy([
'authCode' => $code,
'email' => $request->getSession()->get('mergeAcccountEmail')
]);
if ($userConfirmation) {
$userRepository = $this->getDoctrine()->getManager('admin')->getRepository(User::class);
$emailUser = $userRepository->findOneByEmail($userConfirmation->getEmail());
if (!$emailUser) {
$this->getUser()->setEmail($request->getSession()->get('mergeAcccountEmail'));
$entityManager->flush();
} else {
$mergeAccount->merge($this->getUser(), $emailUser);
}
$session->set('mergeAcccountEmail', null);
return new JsonResponse(['domain' => $this->getParameter('base_domain')]);
}
} else if ($request->getSession()->get('changeAcccountEmail')) {
$email = $request->getSession()->get('changeAcccountEmail');
$userConfirmation = $entityManager->getRepository(UserConfirmation::class)->findOneBy([
'authCode' => $code,
'email' => $email
]);
if ($userConfirmation) {
$user = $this->getUser();
if (!$user) {
return new Response('', 404);
}
$oldEmail = $user->getEmail();
$userEmails = new UserEmailHistory();
$userEmails->setEmail($oldEmail);
$userEmails->setCreatedOn(new \DateTime());
$userEmails->setUserID($user->getID());
$entityManager->persist($userEmails);
$user->setEmail($email);
$entityManager->flush();
$body = "Добрый день.<br>Уведомляем Вас о том, что почта вашего аккаунта на сайте Slivki.by изменена на $email.<br>С уважением, команда Slivki.by";
$message = $mailer->createMessage('Код для привязки аккаунта', $body, 'html');
$message->setFrom('info@slivki.by', 'Slivki.by');
$this->log($oldEmail);
$message->setTo($oldEmail);
$mailer->send($message);
$session->set('changeAcccountEmail', null);
return new Response('', 200);
}
}
return new Response('', 404);
}
/** @Route("/change/send-code-email") */
public function changeCodeEmailAction(Request $request, Mailer $mailer) {
$email = $request->request->get('email');
if (!$email) {
return new Response('', 500);
}
$code = rand(1111, 9999);
$email = mb_strtolower($email);
$entityManager = $this->getDoctrine()->getManager();
$user = $entityManager->getRepository(User::class)->findOneByEmail($email);
$this->log($email);
if ($user) {
return new Response('', 500);
}
$session = $request->getSession();
$session->set('changeAcccountEmail', $email);
$userConfirmation = new UserConfirmation();
$userConfirmation->setEmail($email);
$userConfirmation->setAuthCode($code);
$entityManager->persist($userConfirmation);
$entityManager->flush();
$body = $this->renderView('Slivki/emails/mail.html.twig', ['content' => $code]);
$message = $mailer->createMessage('Код для привязки аккаунта', $body, 'html');
$message->setFrom('info@slivki.by', 'Slivki.by');
$this->log($email);
$message->setTo($email);
$mailer->send($message);
return new Response();
}
}