<?php
namespace Slivki\Controller\Admin;
use Slivki\Bundle\SubscriptionBundle\Request\Query\GetSubscriberHistoryQueryStringBuilder;
use Slivki\Bundle\SubscriptionBundle\Services\SubscriptionHistoryServiceInterface;
use Slivki\Dao\Statistic\User\UserBoughtCodesHistoryDaoInterface;
use Slivki\Entity\MailingCampaignType;
use Slivki\Entity\MediaType;
use Slivki\Entity\OfferCode;
use Slivki\Entity\OfferOrder;
use Slivki\Entity\OfferOrderDetails;
use Slivki\Entity\User;
use Slivki\Entity\UserActivity;
use Slivki\Entity\UserBalanceActivity;
use Slivki\Entity\UserBalanceActivityType;
use Slivki\Entity\UserConfirmation;
use Slivki\Entity\UserGroup;
use Slivki\Entity\UserProperty;
use Slivki\Message\Query\Profile\GetBalanceHistoryQuery;
use Slivki\Messenger\Query\QueryBusInterface;
use Slivki\Repository\BatchCodes\BatchCodesPlanRepositoryInterface;
use Slivki\Services\Mailer;
use Slivki\Services\Subscription\SubscriptionService;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class UserController extends AdminController
{
private const USER_BALANCE_ACTIVITY_LIMIT = 25;
private const USER_BOUGHT_OFFER_CODES_HISTORY_LIMIT = 50;
/**
* @Route("/admin/users")
*/
public function ajaxUsers(Request $request) {
if (!$request->isXmlHttpRequest()) {
return $this->redirect("/admin");
}
return $this->render('Slivki/admin/users/index.html.twig');
}
/**
* @Route("/admin/user/search")
*/
public function userSearchAction(
Request $request,
BatchCodesPlanRepositoryInterface $batchCodesPlanRepository,
SubscriptionService $subscriptionService,
QueryBusInterface $queryBus,
UserBoughtCodesHistoryDaoInterface $userBoughtCodesHistoryDao
): Response {
if (!$request->isMethod("POST")) {
return new Response();
}
$entityManager = $this->getDoctrine()->getManager('admin');
$searchType = $request->request->get('userSearchType');
$user = null;
if ($searchType == 'id') {
$user = $entityManager->find(User::class, $request->request->get('id'));
} else {
if ($searchType == 'email') {
$dql = 'select user from Slivki:User user where lower(user.email) = :query';
$query = strtolower($request->request->get('email', ''));
} else if ($searchType == 'phone') {
$dql = 'select user from Slivki:User user join user.phones phone where phone.confirmed = true and phone.phoneNumber = :query';
$query = $request->request->get('phone', '');
}
$users = $entityManager->createQuery($dql)->setParameter("query", $query)->getResult();
if (count($users) == 1) {
$user = $users[0];
} else if (count($users) > 1) {
return $this->render('Slivki/admin/users/found_user_list.html.twig', ['users' => $users]);
} else if (count($users) == 0) {
$dql = 'select email from Slivki:UserEmailHistory email where lower(email.email) = :query';
$query = strtolower($request->request->get('email', ''));
$emails = $entityManager->createQuery($dql)->setParameter("query", $query)->getResult();
if (count($emails) > 0) {
$user = $entityManager->find(User::class, $emails[0]->getUserID());
}
}
}
if (!$user) {
return new Response("<strong>Клиенты с такими параметрами отсутствуют</strong>");
}
$userGroups = $user->getUserGroups();
$userRepository = $entityManager->getRepository(User::class);
$subscription = $subscriptionService->getSubscription($user);
$subscriptionPlan = $subscriptionService->getCurrentSubscriptionPlan($user);
if (null !== $subscription && $subscription->isSharedSubscription()) {
$parentSubscriber = $subscriptionService->getParentSubscriber($user);
$data['parentSubscriberPhone'] = $parentSubscriber->getPhone();
}
foreach ($user->getUserGroups() as $group) {
if ($group->getID() == UserGroup::ROLE_ADMIN_ID) {
$data['adminUser'] = true;
}
if ($group->getID() == UserGroup::ROLE_BANNED_USER_COMMENT_ID) {
$data['bannedUserComment'] = true;
}
}
if ($user->getStatus() == User::STATUS_LOCKED) {
$data['bannedUser'] = true;
}
$data['user'] = $user;
$data['offerOrders'] = $userBoughtCodesHistoryDao->findUserBoughtCodesHistory(
$user->getID(),
self::USER_BOUGHT_OFFER_CODES_HISTORY_LIMIT
);
$data['userGroups'] = $userGroups;
$data['subscriptionPlan'] = $subscriptionPlan;
$data['allowedCodesCount'] = null !== $subscription ? $subscription->getNumberOfCodes() : null;
$data['subscribedTill'] = null;
if (null !== $subscriptionPlan) {
$data['subscribedTill'] = (new \DateTimeImmutable())->setTimestamp($subscription->getNextDateOfWriteOff());
}
$data['userBalanceActivities'] = $queryBus->handle(new GetBalanceHistoryQuery(
1,
self::USER_BALANCE_ACTIVITY_LIMIT,
$user->getID(),
))->getItems();
$data['batchCodesPlanList'] = $batchCodesPlanRepository->findAllActive();
$data['emailHistory'] = $userRepository->getUserEmailHistory($user);
return $this->render('Slivki/admin/users/user_block.html.twig', $data);
}
/**
* @Route("/admin/user/avatar_remove")
*/
public function userAvatarRemove(Request $request) {
if (!$request->isMethod("POST")) {
return new Response();
}
$entityManager = $this->getDoctrine()->getManager();
$media = $this->getMediaRepository()->findOneBy(array('entityID' => $request->request->get("userID"), 'typeID' => MediaType::TYPE_PROFILE_IMAGE_ID));
if($media) {
$entityManager->remove($media);
$entityManager->flush();
}
return new Response();
}
/** @Route("/admin/user/subscription/code/remove/{offerCodeID}") */
public function subscriptionCodeRemoveAction(Request $request, $offerCodeID) {
$offerCodeID = (int)$offerCodeID;
if (!$offerCodeID) {
return new Response();
}
$entityManager = $this->getEntityManager();
$offerCode = $entityManager->find(OfferCode::class, $offerCodeID);
if (!$offerCode) {
return new Response();
}
$offerOrder = $offerCode->getOfferOrder();
$code = $offerCode->getCode();
$codeCount = $offerOrder->getCodesCount() - 1;
$offerOrder->setCodesCount($codeCount);
if (!$codeCount) {
$offerOrder->setStatus(OfferOrder::STATUS_INIT);
}
/** @var OfferOrderDetails $detail */
foreach ($offerOrder->getOfferOrderDetails() as $detail) {
if ($detail->getCode() == $code) {
$detail->setCode(null);
}
}
$entityManager->remove($offerCode);
$entityManager->flush();
return new Response();
}
/**
* @Route("/admin/users/nonactive")
*/
public function ajaxUsersNonactive(Request $request) {
if (!$request->isXmlHttpRequest()) {
return $this->redirect("/admin");
}
$requestEmail = $request->request->get('email');
$requestDateFrom = $request->request->get('user-registered-since');
$requestDateTo = $request->request->get('user-registered-till');
$from = $requestDateFrom ? date('d.m.Y', strtotime($requestDateFrom)) : date('d.m.Y');
$to = $requestDateTo ? date('d.m.Y', strtotime($requestDateTo)) : date('d.m.Y', strtotime('+1 days'));
$dateFrom = date_create_from_format('d.m.Y', $from);
$dateTo = date_create_from_format('d.m.Y', $to);
$userRepository = $this->getUserRepository();
$query = $userRepository->createQueryBuilder('user');
$query->where("user.status = :status");
if($requestEmail && trim($requestEmail) != '') {
$query->andWhere("user.email = :email");
$query->setParameter(":email", $requestEmail);
} else {
$query->andWhere("user.createdOn >= :dateFrom");
$query->andWhere("user.createdOn < :dateTo");
$query->setParameter(":dateFrom", $dateFrom);
$query->setParameter(":dateTo", $dateTo);
}
$query->setParameter(":status", User::STATUS_REGISTERED);
$query->orderBy("user.createdOn", "desc");
$nonActiveUsers = $query->getQuery()->getResult();
$data = [
'nonActiveUsers' => $nonActiveUsers,
'dateFrom' => $dateFrom,
'dateTo' => $dateTo
];
return $this->render('Slivki/admin/users/activation.html.twig', $data);
}
/**
* @Route("/admin/user/activate/{userID}")
*/
public function ajaxActivateUser($userID) {
$entityManager = $this->getDoctrine()->getManager();
$userRepository = $entityManager->getRepository(User::class);
$user = $userRepository->find($userID);
if(!$user) {
return new Response();
}
$user->setStatus(User::STATUS_CONFIRMED);
$mainMailingCampaignType = $entityManager->getRepository(MailingCampaignType::class)->find(MailingCampaignType::MAIN_ID);
$user->addMailingCampaignTypes($mainMailingCampaignType);
$entityManager->flush();
$userConfirmationRepository = $entityManager->getRepository(UserConfirmation::class);
$userConfirmations = $userConfirmationRepository->findByUserID($userID);
foreach ($userConfirmations as $userConfirmation) {
$entityManager->remove($userConfirmation);
}
$entityManager->flush();
$userRepository->addActivity($user, UserActivity::SUBSCRIBE_ACTION, $mainMailingCampaignType);
return new Response();
}
/**
* @Route("/admin/user/replenishment_balance")
*/
public function ajaxReplenishmentBalanceUser(Request $request){
if (!$request->isXmlHttpRequest()) {
return $this->redirect("/admin");
}
$userID = $request->request->get("userID");
$replenishmentAmount = (float) $request->request->get("amount");
if($replenishmentAmount < 0) {
$result['success'] = "false";
$result['message'] = "Введите положительное число";
return new Response(json_encode($result));
}
$isReplenishment = $request->request->get("isReplenishment");
$entityManager = $this->getDoctrine()->getManager();
$userRepository = $entityManager->getRepository(User::class);
$user = $userRepository->findOneBy(["ID" => $userID]);
$currentBalance = $user->getBalance();
$result['userEmail'] = $user->getEmail();
if($isReplenishment == "true") {
$currentBalance += $replenishmentAmount;
$user->setBalance($currentBalance);
$entityManager->flush($user);
$result['newBalance'] = $currentBalance;
$result['success'] = "true";
} else {
if ($currentBalance - $replenishmentAmount >= 0) {
$currentBalance -= $replenishmentAmount;
$user->setBalance($currentBalance);
$entityManager->flush($user);
$result['success'] = "true";
$result['newBalance'] = $currentBalance;
} else {
$result['success'] = "false";
$result['message'] = "Баланс пользователя не может быть отрицательным";
return new Response(json_encode($result));
}
}
$balanceActivity = new UserBalanceActivity();
$result['createdOn'] = date('d.m.Y H:i', $balanceActivity->getCreatedOn()->getTimestamp());
$replenishmentAmount = number_format($replenishmentAmount, 2);
$result['replenishmentAmount'] = $replenishmentAmount;
if ($isReplenishment === 'true') {
$type = UserBalanceActivity::TYPE_REPLENISHMENT_BY_OPERATOR;
} else {
$type = UserBalanceActivity::TYPE_WITHDRAW_BY_OPERATOR;
$replenishmentAmount *= -1;
}
$balanceActivityType = $entityManager->getRepository(UserBalanceActivityType::class)->find($type);
$balanceActivity->setType($balanceActivityType);
$balanceActivity->setUser($user);
$balanceActivity->setAmount($replenishmentAmount);
$balanceActivity->setOperatorID($this->getUser()->getID());
$entityManager->persist($balanceActivity);
$entityManager->flush($balanceActivity);
$user->addBalanceActivity($balanceActivity);
$result['status'] = $balanceActivityType->getName();
return new Response(json_encode($result));
}
/**
* @Route("/admin/user/send_code")
*/
public function ajaxSendCode(Request $request, Mailer $mailer){
if (!$request->isXmlHttpRequest()) {
return $this->redirect("/admin");
}
$orderID = $request->request->get("orderID");
$order = $this->getOfferOrderRepository()->findOneBy(['ID' => $orderID]);
$result = [];
if ($order) {
$this->sendCode($mailer, $order);
$result['success'] = "true";
$result['message'] = "Код успешно выслан на почту " . $order->getUser()->getEmail();
} else {
$result['success'] = "false";
$result['message'] = "Заказ не найден";
}
return new Response(json_encode($result));
}
/**
* @Route("/admin/user/change_password")
*/
public function ajaxChangePassword(Request $request, Mailer $mailer){
if(!$request->isXmlHttpRequest()){
return $this->redirect("/admin");
}
$userID = $request->request->get("userID");
$entityManager = $this->getDoctrine()->getManager();
$user = $entityManager->getRepository(User::class)->findOneBy(["ID" => $userID]);
$password = $request->request->get("newPassword");
$sendEmail = $request->request->get("sendEmail");
$result = [];
if(mb_strlen($password) >= 6) {
$user->encryptPassword($password);
} else {
$result['success'] = "false";
$result['message'] = "Пароль не может быть меньше 6 символов";
return new Response(json_encode($result));
}
if($sendEmail == "true"){
$message = $mailer->createMessage();
$message->setSubject('Slivki.by - смена пароля')
->setFrom('info@slivki.by', 'Slivki.by')
->setTo($user->getEmail())
->setBody(
$this->get('twig')->render(
'Slivki/emails/change_password_by_operator.html.twig',
array('password' => $password)
),
'text/html'
);
$mailer->send($message);
$result['success'] = "true";
$result['message'] = "Новый пароль был отправлен на почту пользователя" . " (" . $user->getEmail() . ")";
$entityManager->flush($user);
return new Response(json_encode($result));
}
$result['success'] = "true";
$result['message'] = "Пароль пользователя " . $user->getEmail() . "был успешно изменен";
$entityManager->flush($user);
return new Response(json_encode($result));
}
/**
* @Route("/admin/user/allow-x2-bonus/{userID}/{bonusAllowed}")
*/
public function allowX2BonusAction(Mailer $mailer, $userID, $bonusAllowed) {
$bonusAllowed = $bonusAllowed == 'true';
$entityManager = $this->getDoctrine()->getManager('admin');
$user = $this->getUserRepository()->find($userID);
if ($user) {
$bonusProperty = $user->getPropertyByName(UserProperty::NAME_BONUS_X2);
if ($bonusProperty && !$bonusAllowed) {
$entityManager->remove($bonusProperty);
} else if (!$bonusProperty && $bonusAllowed) {
$bonusProperty = new UserProperty();
$bonusProperty->setName(UserProperty::NAME_BONUS_X2);
$user->addProperty($bonusProperty);
$bonusProperty->setUser($user);
$message = $mailer->createMessage();
$message->setSubject('Акция! Ваш счет удвоится в течение первых 24 часов!')
->setFrom('info@slivki.by', 'Slivki.by')
->setTo($user->getEmail())
->setBody($this->get('twig')->render('Slivki/emails/double_replenishment.html.twig'), 'text/html');
$mailer->send($message);
}
$entityManager->flush();
}
return new Response();
}
/**
* @Route("/admin/user/change_group")
*/
public function userChangeGroupAction(Request $request) {
if(!$request->isXmlHttpRequest()){
return $this->redirect("/admin");
}
if ('volga@slivki.by' !== $this->getUser()->getEmail()) {
throw $this->createAccessDeniedException();
}
$userID = $request->request->get("userID");
$groupID = $request->request->get("groupID");
// $action = true - add group, false - remove group;
$action = $request->request->get("action") == 'true';
$entityManager = $this->getDoctrine()->getManager('admin');
$userRepository = $this->getUserRepository();
if ($groupID == User::STATUS_LOCKED) {
$user = $userRepository->find($userID);
if ($action) {
$user->setStatus(User::STATUS_LOCKED);
} else {
$user->setStatus(User::STATUS_CONFIRMED);
}
$entityManager->flush($user);
return new Response();
}
$user = $userRepository->find($userID);
if(!$user) {
return new Response();
}
$userGroup = $entityManager->getRepository(UserGroup::class)->find($groupID);
if(!$userGroup) {
return new Response();
}
if($action) {
$user->addUserGroup($userGroup);
} else {
$user->removeUserGroup($userGroup);
}
$entityManager->flush();
return new Response();
}
/**
* @Route("/admin/user/subscribe/{userID}/{subscribed}/{totally}")
*/
public function unsubscribeAction($userID, $subscribed, $totally) {
$entityManager = $this->getDoctrine()->getManager();
$user = $entityManager->find(User::class, $userID);
$subscribed = $subscribed == 'true';
if ($totally == 'true') {
$user->setTotallyUnsubscribed($subscribed);
} else {
$user->setAcceptNewsletter($subscribed);
}
$entityManager->flush($user);
return new Response();
}
/**
* @Route("/admin/user/get_permission")
*/
public function userGetPermissionAction(Request $request) {
if (!$request->isXmlHttpRequest()){
return $this->redirect("/admin");
}
$userID = $request->request->getInt("userID");
if ($userID == 0) {
throw $this->createNotFoundException("User not selected");
}
$entityManager = $this->getEntityManager();
$userRepository = $this->getUserRepository();
$user = $userRepository->find($userID);
$data['groupsPermitted'] = $user->getUserGroups();
$data['groupsAll'] = $entityManager->getRepository(UserGroup::class)->findByHidden(false);
return $this->render('Slivki/admin/users/list_user_group.html.twig', $data);
}
/**
* @Route("/admin/user/set_permission")
*/
public function userSetPermissionAction(Request $request) {
if (!$request->isXmlHttpRequest()){
return $this->redirect("/admin");
}
$userID = $request->request->getInt("userID");
if ($userID == 0) {
throw $this->createNotFoundException("User not selected");
}
$groupList = $request->request->get("groupList", []);
$entityManager = $this->getEntityManager();
$userRepository = $this->getUserRepository();
$userGroupRepository = $entityManager->getRepository(UserGroup::class);
$user = $userRepository->find($userID);
$userGroups = $user->getUserGroups();
foreach($userGroups as $groupRemoved) {
if (!$groupRemoved->isHidden()) {
$user->removeUserGroup($groupRemoved);
}
}
foreach ($groupList as $groupID) {
$group = $userGroupRepository->find((int)$groupID);
if (!$group) {
continue;
}
$user->addUserGroup($group);
}
$entityManager->flush();
return new Response();
}
/**
* @Route("/admin/user/manager-name/save")
*/
public function saveManagerName(Request $request) {
if (!$request->isXmlHttpRequest()){
return $this->redirect("/admin");
}
$userID = $request->request->getInt("userID");
if (!$this->isGranted('ROLE_ADMIN') && !($userID == $this->getUser()->getID())) {
return new Response();
}
$entityManager = $this->getEntityManager();
$user = $entityManager->find(User::class, $userID);
$user->setManagerName($request->request->get('managerName'));
$entityManager->flush();
return new Response('1');
}
/**
* @Route("/admin/user/subscribe/history")
*/
public function getUserSubscribeHistory(
Request $request,
SubscriptionHistoryServiceInterface $subscriptionHistoryService
) {
if (!$request->isXmlHttpRequest()){
return $this->redirect("/admin");
}
$entityManager = $this->getEntityManager();
$userID = $request->request->getInt("userID");
$user = $entityManager->find(User::class, $userID);
if (!$user) {
return new Response("Пользователь не найден");
}
$result = null !== $user->getToken()
? $subscriptionHistoryService->getSubscriberHistory(
(new GetSubscriberHistoryQueryStringBuilder())
->withPage(1)
->withPerPage(50),
$user->getToken())
: null;
if (null !== $result && 0 === \count($result->getItems())) {
return new Response('История пустая');
}
return $this->render('Slivki/admin/users/subscribe_history_table.html.twig', ['result' => $result]);
}
}