at the end of the day, it was inevitable
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Command;
|
||||
|
||||
use AppBundle\Command\AbstractSingleCopyCommand;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Repository\UserRepository;
|
||||
use UserBundle\Entity\Plan;
|
||||
|
||||
/**
|
||||
* Class CancelSubscriptionCommand
|
||||
*
|
||||
* @package UserBundle\Command
|
||||
*/
|
||||
class CancelSubscriptionCommand extends AbstractSingleCopyCommand
|
||||
{
|
||||
|
||||
const NAME = 'socialhose:cancel-subscription';
|
||||
|
||||
/**
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* CancelSubscriptionCommand constructor.
|
||||
*
|
||||
* @param EntityManagerInterface $em A EntityManagerInterface instance.
|
||||
* @param LoggerInterface $logger A LoggerInterface instance.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $em, LoggerInterface $logger)
|
||||
{
|
||||
parent::__construct(self::NAME, $logger);
|
||||
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the current command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setDescription('Cancel subscription');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input An InputInterface instance.
|
||||
* @param OutputInterface $output An OutputInterface instance.
|
||||
*
|
||||
* @return null|integer
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$repository = $this->em->getRepository(User::class);
|
||||
$currentDate = date('Y-m-d');
|
||||
$users = $repository->getAllUserBillingSubscription($currentDate);
|
||||
foreach ($users as $user) {
|
||||
$repository = $this->em->getRepository(Plan::class);
|
||||
$planObj = $repository->findOneBy([ 'title' => 'Free' ]);
|
||||
|
||||
$plan = $user->getBillingSubscription()->getPlan();
|
||||
$plan->setTitle($user->getCompanyName());
|
||||
$plan->setInnerName('Starter');
|
||||
$plan->setPrice(0);
|
||||
$plan->setNews($planObj->isNews());
|
||||
$plan->setBlog($planObj->isBlog());
|
||||
$plan->setReddit($planObj->isReddit());
|
||||
$plan->setInstagram($planObj->isInstagram());
|
||||
$plan->setTwitter($planObj->isTwitter());
|
||||
$plan->setAnalytics($planObj->isAnalytics());
|
||||
$plan->setSearchesPerDay($planObj->getSearchesPerDay());
|
||||
$plan->setSavedFeeds($planObj->getSavedFeeds());
|
||||
$plan->setMasterAccounts($planObj->getMasterAccounts());
|
||||
$plan->setSubscriberAccounts($planObj->getSubscriberAccounts());
|
||||
$plan->setAlerts($planObj->getAlerts());
|
||||
$plan->setNewsLetters($planObj->getNewsLetters());
|
||||
$plan->setWebFeeds($planObj->getWebFeeds());
|
||||
$plan->setAlerts($planObj->getAlerts());
|
||||
$plan->setIsPlanDowngrade(false);
|
||||
|
||||
$this->em->persist($plan);
|
||||
$this->em->flush();
|
||||
|
||||
$subscription = $user->getBillingSubscription();
|
||||
$subscription->setIsSubscriptionCancelled(false);
|
||||
$this->em->persist($subscription);
|
||||
$this->em->flush();
|
||||
|
||||
}
|
||||
$io->success('Cancel Subscription Successfully.');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Command;
|
||||
|
||||
use AppBundle\Command\AbstractSingleCopyCommand;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use UserBundle\Entity\Subscription\AbstractSubscription;
|
||||
use UserBundle\Repository\SubscriptionRepository;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Repository\UserRepository;
|
||||
use UserBundle\Entity\Plan;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Class DowngradeSubscriptionPlanCommand
|
||||
*
|
||||
* @package UserBundle\Command
|
||||
*/
|
||||
class DowngradeSubscriptionPlanCommand extends AbstractSingleCopyCommand
|
||||
{
|
||||
|
||||
const NAME = 'socialhose:downgrade-subscription-plan';
|
||||
|
||||
/**
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* DowngradeSubscriptionPlanCommand constructor.
|
||||
*
|
||||
* @param EntityManagerInterface $em A EntityManagerInterface instance.
|
||||
* @param LoggerInterface $logger A LoggerInterface instance.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $em, LoggerInterface $logger,ContainerInterface $container)
|
||||
{
|
||||
parent::__construct(self::NAME, $logger);
|
||||
|
||||
$this->em = $em;
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the current command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setDescription('Downgrade subscription plan');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input An InputInterface instance.
|
||||
* @param OutputInterface $output An OutputInterface instance.
|
||||
*
|
||||
* @return null|integer
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$repository = $this->em->getRepository(User::class);
|
||||
$currentDate = date('Y-m-d');
|
||||
$users = $repository->getAllUserBillingSubscriptionPlanDowngrade($currentDate);
|
||||
foreach ($users as $user) {
|
||||
$repository = $this->em->getRepository(Plan::class);
|
||||
$planObj = $repository->findOneBy(['isPlanDowngrade' => true, 'user' => $user->getId()], ['id'=>'desc']);
|
||||
|
||||
$subscription = $user->getBillingSubscription();
|
||||
$subscription->setIsPlanDowngrade(false);
|
||||
$subscription->setPlan($planObj);
|
||||
$this->em->persist($subscription);
|
||||
$this->em->flush();
|
||||
$this->downgradePlanInStripe($user,$planObj);
|
||||
}
|
||||
$io->success('Downgrade Subscription Plan Successfully.');
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function downgradePlanInStripe($user, $planObj)
|
||||
{
|
||||
$stripe = $this->container->get('stripe.service');
|
||||
$stripe->setApiKey();
|
||||
$customer = $stripe->getCustomer(
|
||||
$user->getStripeUserId()
|
||||
);
|
||||
$customerArray = [];
|
||||
if ($customer instanceof ApiErrorException) {
|
||||
$customerArray = ['paymentError' => 1,'data'=>$customer,'message'=>'Customer not found'];
|
||||
$this->logger->info(sprintf(
|
||||
'Error cron job downgrade \'%s\'',
|
||||
json_encode($customerArray)
|
||||
));
|
||||
}
|
||||
if (isset($customer['id'])) {
|
||||
$price = $stripe->addPrice(
|
||||
[
|
||||
'unit_amount' => !empty($planObj->getPrice()) ? $planObj->getPrice() * 100 : 0,
|
||||
'currency' => 'usd',
|
||||
'recurring' => ['interval' => 'month'],
|
||||
'product' => $customer['metadata']['productId']
|
||||
]
|
||||
);
|
||||
if ($price instanceof ApiErrorException) {
|
||||
$priceArray = ['paymentError' => 1,'data'=>$price,'message'=>'Price not found'];
|
||||
$this->logger->info(sprintf(
|
||||
'Error cron job downgrade \'%s\'',
|
||||
json_encode($priceArray)
|
||||
));
|
||||
return $this->generateResponse($priceArray, 400);
|
||||
}
|
||||
if (isset($price['id'])) {
|
||||
//Add subscription
|
||||
$subscription = $stripe->getSubscription(
|
||||
$customer['metadata']['subscriptionId']
|
||||
);
|
||||
|
||||
if ($subscription instanceof ApiErrorException) {
|
||||
$subscriptionArray = ['paymentError' => 1,'data'=>$subscription,'message'=>'Subscribtion get failed'];
|
||||
$this->logger->info(sprintf(
|
||||
'Error cron job downgrade \'%s\'',
|
||||
json_encode($subscriptionArray)
|
||||
));
|
||||
return $this->generateResponse($subscriptionArray, 400);
|
||||
}
|
||||
|
||||
if (isset($subscription['id'])) {
|
||||
//Add subscription item
|
||||
$subscriptionItem = $stripe->updateSubscriptionItem($subscription['items']['data'][0]['id'],
|
||||
[
|
||||
'price' => $price['id'],
|
||||
]
|
||||
);
|
||||
if ($subscriptionItem instanceof ApiErrorException) {
|
||||
$subscriptionItemArray = ['paymentError' => 1,'data'=>$subscriptionItem,'message'=>'Subscribtion Item failed'];
|
||||
$this->logger->info(sprintf(
|
||||
'Error cron job downgrade \'%s\'',
|
||||
json_encode($subscriptionItemArray)
|
||||
));
|
||||
return $this->generateResponse($subscriptionItemArray, 400);
|
||||
}
|
||||
//update customer metadata
|
||||
$customer = $stripe->updateCustomer($customer['id'],
|
||||
[
|
||||
'metadata' => [
|
||||
'priceId' => $price['id'],
|
||||
'subscriptionId' => $subscription['id'],
|
||||
'subStartDate' => $subscription['current_period_start'],
|
||||
'subEndDate' => $subscription['current_period_end'],
|
||||
]
|
||||
]
|
||||
);
|
||||
if ($customer instanceof ApiErrorException) {
|
||||
$customerArray = ['paymentError' => 1,'data'=>$customer,'message'=>'Customer update meta data failed'];
|
||||
$this->logger->info(sprintf(
|
||||
'Error cron job downgrade \'%s\'',
|
||||
json_encode($customerArray)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Command;
|
||||
|
||||
use AppBundle\Command\AbstractSingleCopyCommand;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use UserBundle\Entity\Subscription\AbstractSubscription;
|
||||
use UserBundle\Repository\SubscriptionRepository;
|
||||
|
||||
/**
|
||||
* Class RenewSearchLimitsCommand
|
||||
*
|
||||
* @package UserBundle\Command
|
||||
*/
|
||||
class RenewSearchLimitsCommand extends AbstractSingleCopyCommand
|
||||
{
|
||||
|
||||
const NAME = 'socialhose:renew-search-limits';
|
||||
|
||||
/**
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* RenewSearchLimitsCommand constructor.
|
||||
*
|
||||
* @param EntityManagerInterface $em A EntityManagerInterface instance.
|
||||
* @param LoggerInterface $logger A LoggerInterface instance.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $em, LoggerInterface $logger)
|
||||
{
|
||||
parent::__construct(self::NAME, $logger);
|
||||
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the current command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setDescription('Set all searchPerDay limits to zero');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input An InputInterface instance.
|
||||
* @param OutputInterface $output An OutputInterface instance.
|
||||
*
|
||||
* @return null|integer
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
/** @var SubscriptionRepository $repository */
|
||||
$repository = $this->em->getRepository(AbstractSubscription::class);
|
||||
$repository->renewSearchLimits();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\Developing;
|
||||
|
||||
use AppBundle\AppBundleServices;
|
||||
use AppBundle\Configuration\ConfigurationInterface;
|
||||
use CacheBundle\Entity\Comment;
|
||||
use CacheBundle\Entity\Document;
|
||||
use Faker\Factory;
|
||||
use IndexBundle\Index\Strategy\IndexStrategyInterface;
|
||||
use IndexBundle\Index\Strategy\HoseIndexStrategy;
|
||||
use IndexBundle\Model\ArticleDocument;
|
||||
use IndexBundle\Model\ArticleDocumentInterface;
|
||||
use IndexBundle\Model\Generator\ExternalDocumentGenerator;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\Notification\NotificationTheme;
|
||||
use UserBundle\Entity\Notification\NotificationThemeOptions;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Enum\ThemeOptionsUserCommentsEnum;
|
||||
use UserBundle\Enum\ThemeTypeEnum;
|
||||
use UserBundle\Manager\Notification\Model\FeedData;
|
||||
use UserBundle\Manager\Notification\SendableNotification;
|
||||
use UserBundle\Manager\Notification\SendableNotificationConfig;
|
||||
|
||||
/**
|
||||
* Class EmailController
|
||||
*
|
||||
* For developing ant testing email's only.
|
||||
*
|
||||
* @package UserBundle\Controller\Developing
|
||||
*
|
||||
* @Route("/emails")
|
||||
*/
|
||||
class EmailController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \Faker\Generator
|
||||
*/
|
||||
private $faker;
|
||||
|
||||
/**
|
||||
* @var IndexStrategyInterface
|
||||
*/
|
||||
private $strategy;
|
||||
|
||||
/**
|
||||
* EmailController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->strategy = new HoseIndexStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/plain", methods={ "GET" })
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function plainAction()
|
||||
{
|
||||
$notification = $this->generateNotification(Notification::create()->setThemeType(ThemeTypeEnum::plain()));
|
||||
|
||||
$notification->setPlainThemeOptionsDiff([
|
||||
// 'summary' => '<p>Summary</p>',
|
||||
// 'conclusion' => '<p>Conclusion</p>',
|
||||
//
|
||||
// 'header.imageUrl' => ThemeOptionHeader::DEFAULT_IMAGE,
|
||||
// 'header.logoLink' => 'http://ya.ru',
|
||||
//
|
||||
// 'content.showInfo.images' => true,
|
||||
// 'content.showInfo.sectionDivider' => true,
|
||||
// 'content.showInfo.sourceCountry' => true,
|
||||
// 'content.showInfo.articleCount' => true,
|
||||
// 'content.showInfo.tableOfContents' => ThemeOptionsTableOfContentsEnum::SOURCE_HEADLINE_DATE,
|
||||
'content.showInfo.userComments' => ThemeOptionsUserCommentsEnum::WITHOUT_AUTHOR_DATE,
|
||||
//
|
||||
// 'colors.text.articleHeadline' => 'yellow',
|
||||
// 'colors.text.source' => 'green',
|
||||
// 'colors.text.articleContent' => 'red',
|
||||
// 'colors.text.author' => '#fdfdfd',
|
||||
// 'colors.text.publishDate' => '#23fa1f',
|
||||
//
|
||||
// 'fonts.tableOfContents.size' => 18,
|
||||
// 'fonts.tableOfContents.family' => 'Courier New',
|
||||
// 'fonts.tableOfContents.style.bold' => true,
|
||||
// 'fonts.tableOfContents.style.italic' => true,
|
||||
// 'fonts.tableOfContents.style.underline' => true,
|
||||
//
|
||||
// 'fonts.feedTitle.size' => 18,
|
||||
// 'fonts.feedTitle.family' => 'Courier New',
|
||||
// 'fonts.feedTitle.style.bold' => true,
|
||||
// 'fonts.feedTitle.style.italic' => true,
|
||||
// 'fonts.feedTitle.style.underline' => true,
|
||||
//
|
||||
// 'fonts.articleHeadline.size' => 10,
|
||||
// 'fonts.articleHeadline.family' => 'Courier New',
|
||||
// 'fonts.articleHeadline.style.bold' => true,
|
||||
// 'fonts.articleHeadline.style.italic' => true,
|
||||
// 'fonts.articleHeadline.style.underline' => true,
|
||||
//
|
||||
// 'fonts.source.size' => 10,
|
||||
// 'fonts.source.family' => 'Courier New',
|
||||
// 'fonts.source.style.bold' => true,
|
||||
// 'fonts.source.style.italic' => true,
|
||||
// 'fonts.source.style.underline' => true,
|
||||
//
|
||||
// 'fonts.author.size' => 6,
|
||||
// 'fonts.author.family' => 'Courier New',
|
||||
// 'fonts.author.style.bold' => true,
|
||||
// 'fonts.author.style.italic' => true,
|
||||
// 'fonts.author.style.underline' => true,
|
||||
//
|
||||
// 'fonts.date.size' => 14,
|
||||
// 'fonts.date.family' => 'Courier New',
|
||||
// 'fonts.date.style.bold' => true,
|
||||
// 'fonts.date.style.italic' => true,
|
||||
// 'fonts.date.style.underline' => true,
|
||||
//
|
||||
// 'fonts.articleContent.size' => 6,
|
||||
// 'fonts.articleContent.family' => 'Courier New',
|
||||
// 'fonts.articleContent.style.bold' => true,
|
||||
// 'fonts.articleContent.style.italic' => true,
|
||||
// 'fonts.articleContent.style.underline' => true,
|
||||
]);
|
||||
|
||||
/** @var ConfigurationInterface $configuration */
|
||||
$configuration = $this->get(AppBundleServices::CONFIGURATION);
|
||||
|
||||
$sendableNotification = new SendableNotification(
|
||||
SendableNotificationConfig::fromConfiguration($configuration),
|
||||
$notification,
|
||||
$this->generateFeeds(3)
|
||||
);
|
||||
|
||||
return new Response($sendableNotification->render($this->get('templating')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/enhanced", methods={ "GET" })
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function enhancedAction()
|
||||
{
|
||||
$notification = $this->generateNotification(Notification::create()->setThemeType(ThemeTypeEnum::enhanced()));
|
||||
|
||||
$notification->setEnhancedThemeOptionsDiff([
|
||||
// 'summary' => '<p>Summary</p>',
|
||||
// 'conclusion' => '<p>Conclusion</p>',
|
||||
//
|
||||
// 'header.imageUrl' => ThemeOptionHeader::DEFAULT_IMAGE,
|
||||
// 'header.logoLink' => 'http://ya.ru',
|
||||
//
|
||||
// 'content.showInfo.sectionDivider' => true,
|
||||
// 'content.showInfo.sourceCountry' => true,
|
||||
// 'content.showInfo.articleCount' => true,
|
||||
// 'content.showInfo.tableOfContents' => ThemeOptionsTableOfContentsEnum::HEADLINE_SOURCE_DATE,
|
||||
'content.showInfo.userComments' => ThemeOptionsUserCommentsEnum::WITH_AUTHOR_DATE,
|
||||
//
|
||||
// 'colors.background.header' => '#541dab',
|
||||
// 'colors.background.accent' => '#df10bc',
|
||||
// 'colors.background.emailBody' => '#eeeeee',
|
||||
//
|
||||
// 'colors.text.header' => '#12fdfd',
|
||||
// 'colors.text.articleHeadline' => 'yellow',
|
||||
// 'colors.text.source' => 'green',
|
||||
// 'colors.text.articleContent' => 'red',
|
||||
// 'colors.text.author' => '#fdfdfd',
|
||||
// 'colors.text.publishDate' => '#23fa1f',
|
||||
//
|
||||
// 'fonts.header.size' => 18,
|
||||
// 'fonts.header.family' => 'Courier New',
|
||||
// 'fonts.header.style.bold' => true,
|
||||
// 'fonts.header.style.italic' => true,
|
||||
// 'fonts.header.style.underline' => true,
|
||||
//
|
||||
// 'fonts.tableOfContents.size' => 32,
|
||||
// 'fonts.tableOfContents.family' => 'Courier New',
|
||||
// 'fonts.tableOfContents.style.bold' => true,
|
||||
// 'fonts.tableOfContents.style.italic' => true,
|
||||
// 'fonts.tableOfContents.style.underline' => true,
|
||||
//
|
||||
// 'fonts.feedTitle.size' => 18,
|
||||
// 'fonts.feedTitle.family' => 'Courier New',
|
||||
// 'fonts.feedTitle.style.bold' => true,
|
||||
// 'fonts.feedTitle.style.italic' => true,
|
||||
// 'fonts.feedTitle.style.underline' => true,
|
||||
//
|
||||
// 'fonts.articleHeadline.size' => 10,
|
||||
// 'fonts.articleHeadline.family' => 'Courier New',
|
||||
// 'fonts.articleHeadline.style.bold' => true,
|
||||
// 'fonts.articleHeadline.style.italic' => true,
|
||||
// 'fonts.articleHeadline.style.underline' => true,
|
||||
//
|
||||
// 'fonts.source.size' => 10,
|
||||
// 'fonts.source.family' => 'Courier New',
|
||||
// 'fonts.source.style.bold' => true,
|
||||
// 'fonts.source.style.italic' => true,
|
||||
// 'fonts.source.style.underline' => true,
|
||||
//
|
||||
// 'fonts.author.size' => 6,
|
||||
// 'fonts.author.family' => 'Courier New',
|
||||
// 'fonts.author.style.bold' => true,
|
||||
// 'fonts.author.style.italic' => true,
|
||||
// 'fonts.author.style.underline' => true,
|
||||
//
|
||||
// 'fonts.date.size' => 14,
|
||||
// 'fonts.date.family' => 'Courier New',
|
||||
// 'fonts.date.style.bold' => true,
|
||||
// 'fonts.date.style.italic' => true,
|
||||
// 'fonts.date.style.underline' => true,
|
||||
//
|
||||
// 'fonts.articleContent.size' => 12,
|
||||
// 'fonts.articleContent.family' => 'Courier New',
|
||||
// 'fonts.articleContent.style.bold' => true,
|
||||
// 'fonts.articleContent.style.italic' => true,
|
||||
// 'fonts.articleContent.style.underline' => true,
|
||||
]);
|
||||
|
||||
/** @var ConfigurationInterface $configuration */
|
||||
$configuration = $this->get(AppBundleServices::CONFIGURATION);
|
||||
|
||||
$feeds = $this->generateFeeds(3);
|
||||
|
||||
$sendableNotification = new SendableNotification(
|
||||
SendableNotificationConfig::fromConfiguration($configuration),
|
||||
$notification,
|
||||
$feeds
|
||||
);
|
||||
|
||||
return new Response($sendableNotification->render($this->get('templating')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate notification.
|
||||
*
|
||||
* @param Notification $notification A Notification instance.
|
||||
*
|
||||
* @return Notification
|
||||
*/
|
||||
private function generateNotification(Notification $notification)
|
||||
{
|
||||
$faker = $this->getFaker();
|
||||
|
||||
$user = User::create('some@email.com')
|
||||
->setFirstName('John')
|
||||
->setLastName('Due');
|
||||
|
||||
$defaultOptions = NotificationThemeOptions::createDefault();
|
||||
|
||||
return $notification
|
||||
->setSubject(ucfirst($faker->word))
|
||||
->setName($faker->word)
|
||||
->setOwner($user)
|
||||
->setTheme(NotificationTheme::create()
|
||||
->setName('Some')
|
||||
->setEnhanced($defaultOptions)
|
||||
->setPlain($defaultOptions)
|
||||
->setDefault(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $count Number of generated feeds.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
private function generateFeeds($count = 2)
|
||||
{
|
||||
$feeds = [];
|
||||
$faker = $this->getFaker();
|
||||
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
$documentCount = random_int(1, 3);
|
||||
|
||||
$feeds[] = new FeedData(
|
||||
$faker->word,
|
||||
$this->generateDocuments($documentCount)
|
||||
);
|
||||
}
|
||||
|
||||
return $feeds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate documents for notification rendering.
|
||||
*
|
||||
* @param integer $count Number of documents.
|
||||
*
|
||||
* @return ArticleDocumentInterface[]
|
||||
*/
|
||||
private function generateDocuments($count)
|
||||
{
|
||||
$documents = [];
|
||||
$generator = new ExternalDocumentGenerator();
|
||||
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
$documentEntity = $this->generateComments($generator->generate()->toDocumentEntity());
|
||||
$data = $documentEntity->getData();
|
||||
$data['comments'] = $documentEntity->getComments()->toArray();
|
||||
$data['commentsCount'] = count($data['comments']);
|
||||
|
||||
$documents[] = new ArticleDocument(
|
||||
$this->strategy,
|
||||
$this->strategy->createDocument($data)->getNormalizedData()
|
||||
);
|
||||
}
|
||||
|
||||
return $documents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate comments for documents.
|
||||
*
|
||||
* @param Document $document A Document entity instance.
|
||||
*
|
||||
* @return Document
|
||||
*/
|
||||
private function generateComments(Document $document)
|
||||
{
|
||||
$faker = $this->getFaker();
|
||||
|
||||
$commentsCount = random_int(0, 3);
|
||||
for ($i = 0; $i < $commentsCount; ++$i) {
|
||||
$user = User::create($faker->email, '')
|
||||
->setFirstName($faker->firstName)
|
||||
->setLastName($faker->lastName);
|
||||
|
||||
$document->addComment(new Comment(
|
||||
$user,
|
||||
$faker->text,
|
||||
$faker->optional(0.4, '')->word
|
||||
));
|
||||
}
|
||||
|
||||
return $document;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Faker\Generator
|
||||
*/
|
||||
private function getFaker()
|
||||
{
|
||||
if ($this->faker === null) {
|
||||
$this->faker = Factory::create();
|
||||
}
|
||||
|
||||
return $this->faker;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\Security;
|
||||
|
||||
use ApiBundle\Controller\AbstractApiController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
|
||||
/**
|
||||
* Class CostCalculationController
|
||||
* @package UserBundle\Controller\Security
|
||||
*
|
||||
* @Route("/cost_calculation", service="user.controller.cost_calculation")
|
||||
*/
|
||||
class CostCalculationController extends AbstractApiController
|
||||
{
|
||||
|
||||
/**
|
||||
* @Route("", methods={ "POST" })
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function costCalculationAction(Request $request, $isCallContoller = false)
|
||||
{
|
||||
$data = $request->request->all();
|
||||
$mtPrice = 0;
|
||||
$totalPrice = 0;
|
||||
$responseData = [];
|
||||
//echo '<pre>'; print_r($data); die;
|
||||
if(!empty($data)){
|
||||
if(isset(
|
||||
$data['news'],
|
||||
$data['blog'],
|
||||
$data['reddit'],
|
||||
$data['instagram'],
|
||||
$data['twitter'],
|
||||
$data['searchesPerDay'],
|
||||
$data['savedFeeds'],
|
||||
$data['subscriberAccounts'],
|
||||
$data['webFeeds'],
|
||||
$data['alerts'],
|
||||
$data['analytics']
|
||||
)
|
||||
){
|
||||
//die('hello');
|
||||
$mtPrice += ($data['news'] == true) ? 20 : 0;
|
||||
$mtPrice += ($data['blog'] == true) ? 15 : 0;
|
||||
$mtPrice += ($data['reddit'] == true) ? 1 : 0;
|
||||
$mtPrice += ($data['instagram'] == true) ? 3 : 0;
|
||||
$mtPrice += ($data['twitter'] == true) ? 3 : 0;
|
||||
$responseData['selectedMediaTypeCost'] = $mtPrice;
|
||||
$searchPerDayPrice = ($data['searchesPerDay'] > 10) ? ($data['searchesPerDay'] - 10)/10 : 0;
|
||||
$searchPerDayPrice = $searchPerDayPrice ? ($searchPerDayPrice * $mtPrice) : 0;
|
||||
$responseData['searchPerDayPrice'] = $searchPerDayPrice;
|
||||
|
||||
$savedFeedsPrice = $data['savedFeeds'] ? ($data['savedFeeds'] * $mtPrice) : 0;
|
||||
$responseData['savedFeedsPrice'] = $savedFeedsPrice;
|
||||
|
||||
$subscriberAccountsPrice = $data['subscriberAccounts'] > 1 ? (($data['subscriberAccounts'] - 1) * 15) : 0; // Fixed price $15 per account
|
||||
$responseData['subscriberAccountsPrice'] = $subscriberAccountsPrice;
|
||||
|
||||
$webFeedsPrice = $data['webFeeds'] > 0 ? ($data['webFeeds'] * 5) : 0; // Fixed price $5 per export/webFeeds
|
||||
$responseData['webFeedsPrice'] = $webFeedsPrice;
|
||||
|
||||
$alertsPrice = $data['alerts'] ? ($data['alerts'] * 5) : 0; // Fixed price $5 per alerts
|
||||
$responseData['alertsPrice'] = $alertsPrice;
|
||||
|
||||
$analyticsPrice = $data['analytics'] ? ($data['savedFeeds'] * 15) : 0; // Fixed price $15 if analytics field comes true in request
|
||||
$responseData['analyticsPrice'] = $analyticsPrice;
|
||||
|
||||
$totalPrice = $searchPerDayPrice + $savedFeedsPrice + $subscriberAccountsPrice + $webFeedsPrice + $alertsPrice + $analyticsPrice;
|
||||
$responseData['totalPrice'] = $totalPrice;
|
||||
if ($isCallContoller) {
|
||||
return ['price' => $totalPrice];
|
||||
}
|
||||
return $this->generateResponse($responseData, 200);
|
||||
} else {
|
||||
return $this->generateResponse("Invalid request", 400);
|
||||
}
|
||||
} else {
|
||||
return $this->generateResponse("Something went wrong in the request.", 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\Security;
|
||||
|
||||
use ApiBundle\Controller\AbstractApiController;
|
||||
use FOS\UserBundle\Util\TokenGeneratorInterface;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use UserBundle\Form\HubSpotRegistrationType;
|
||||
use UserBundle\Manager\User\UserManagerInterface;
|
||||
|
||||
/**
|
||||
* Class HubSpotRegistrationController
|
||||
* @package UserBundle\Controller\Security
|
||||
*
|
||||
* @Route("/hubspot-registration", service="user.controller.hubspot_registration")
|
||||
*/
|
||||
class HubSpotRegistrationController extends AbstractApiController
|
||||
{
|
||||
|
||||
/**
|
||||
* Register new user.
|
||||
* Return empty response.
|
||||
*
|
||||
* @Route("", methods={ "POST" })
|
||||
*
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return array|\ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function registerAction(Request $request)
|
||||
{
|
||||
/** @var $userManager UserManagerInterface */
|
||||
$userManager = $this->get('fos_user.user_manager');
|
||||
/** @var \UserBundle\Entity\User $user */
|
||||
$user = $userManager->createUser();
|
||||
$user->setEnabled(true);
|
||||
$form = $this->createForm(HubSpotRegistrationType::class, $user);
|
||||
|
||||
$form->submit($request->request->all());
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$user->setPassword('');
|
||||
/** @var TokenGeneratorInterface $tokenGenerator */
|
||||
$tokenGenerator = $this->container->get('fos_user.util.token_generator');
|
||||
$user->setConfirmationToken($tokenGenerator->generateToken());
|
||||
|
||||
$userManager->updateUser($user);
|
||||
|
||||
return $this->generateResponse([
|
||||
'code' => $user->getConfirmationToken(),
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->generateResponse($form, 400);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\Security;
|
||||
|
||||
use ApiBundle\Controller\AbstractApiController;
|
||||
use PaymentBundle\Enum\PaymentGatewayEnum;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use UserBundle\Entity\Plan;
|
||||
use UserBundle\Entity\Subscription\AbstractSubscription;
|
||||
use UserBundle\Form\PlanType;
|
||||
use UserBundle\Repository\PlanRepository;
|
||||
use UserBundle\Repository\SubscriptionRepository;
|
||||
|
||||
/**
|
||||
* Class PlanController
|
||||
* @package UserBundle\Controller\Security
|
||||
*
|
||||
* @Route("/plans", service="user.controller.plan")
|
||||
*/
|
||||
class PlanController extends AbstractApiController
|
||||
{
|
||||
/**
|
||||
* @Route("", methods={ "GET" })
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
|
||||
$repository = $this->getManager()->getRepository(Plan::class);
|
||||
|
||||
$qb = $repository->createQueryBuilder('p');
|
||||
$query = $qb
|
||||
->where('p.is_default = true')
|
||||
->andwhere('p.title != :title')
|
||||
->setParameters(array(
|
||||
'title' => 'Free'
|
||||
));
|
||||
$query = $query->getQuery();
|
||||
$plans = $query->getResult();
|
||||
|
||||
if (count($plans) === 0) {
|
||||
return $this->generateResponse("Can't find plans.", 404);
|
||||
}
|
||||
|
||||
return $this->generateResponse($plans, 200, [
|
||||
'id',
|
||||
'plan'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,441 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\Security;
|
||||
|
||||
use ApiBundle\Controller\AbstractApiController;
|
||||
use AppBundle\AppBundleServices;
|
||||
use AppBundle\Configuration\ConfigurationInterface;
|
||||
use AppBundle\Configuration\ParametersName;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use FOS\UserBundle\Util\TokenGeneratorInterface;
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use PaymentBundle\Enum\PaymentGatewayEnum;
|
||||
use PaymentBundle\Gateway\Factory\PaymentGatewayFactoryInterface;
|
||||
use PaymentBundle\Model\BillingSubscription;
|
||||
use PaymentBundle\Model\PaymentData;
|
||||
use PaymentBundle\PaymentBundleServices;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use UserBundle\Entity\Organization;
|
||||
use UserBundle\Entity\Plan;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Form\PaymentDataType;
|
||||
use UserBundle\Form\RegistrationType;
|
||||
use UserBundle\Manager\User\UserManagerInterface;
|
||||
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use FOS\UserBundle\FOSUserEvents;
|
||||
use FOS\UserBundle\Event\FormEvent;
|
||||
use FOS\UserBundle\Event\FilterUserResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use FOS\UserBundle\Event\GetResponseUserEvent;
|
||||
use UserBundle\Mailer\MailerInterface;
|
||||
use Stripe\Exception\ApiErrorException;
|
||||
use UserBundle\Security\CostCalculationController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Class RegistrationController
|
||||
* @package UserBundle\Controller\Security
|
||||
*
|
||||
* @Route("/registration", service="user.controller.registration")
|
||||
*/
|
||||
class RegistrationController extends AbstractApiController
|
||||
{
|
||||
|
||||
/**
|
||||
* Max organization rep response.
|
||||
*/
|
||||
const DEFAULT_LIMIT = 10;
|
||||
|
||||
/**
|
||||
* Register new user.
|
||||
* Return empty response.
|
||||
*
|
||||
* @Route("", methods={ "POST" })
|
||||
*
|
||||
* @ApiDoc(
|
||||
* resource="Registration",
|
||||
* section="Security",
|
||||
* input={
|
||||
* "class"="UserBundle\Form\RegistrationType",
|
||||
* "name"=false
|
||||
* },
|
||||
* output={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* "message"={
|
||||
* "dataType"="string",
|
||||
* "description"="Registration success message"
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="Register successfully."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
* @param UserPasswordEncoderInterface $encoder
|
||||
*
|
||||
* @return array|\ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function registerAction(Request $request)
|
||||
{
|
||||
/** @var $userManager UserManagerInterface */
|
||||
$userManager = $this->get('fos_user.user_manager');
|
||||
$dispatcher = $this->get('event_dispatcher');
|
||||
/** @var \UserBundle\Entity\User $user */
|
||||
$user = $userManager->createUser();
|
||||
$user->setEnabled(true);
|
||||
$form = $this->createForm(RegistrationType::class, $user, array(
|
||||
'paymentID' => $request->request->get('paymentID'),
|
||||
));
|
||||
$form->submit($request->request->all());
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$passwordEncoder = $this->get('security.password_encoder');
|
||||
$encoded = $passwordEncoder->encodePassword($user, $form['password']->getData());
|
||||
$user->setPassword($encoded);
|
||||
|
||||
// if (!empty($user->getBillingSubscription()->getPlan()->isFree())) {
|
||||
// $user->getBillingSubscription()->setPayed(true);
|
||||
// $userManager->updateUser($user);
|
||||
|
||||
// /** @var ConfigurationInterface $configuration */
|
||||
// $configuration = $this->get(AppBundleServices::CONFIGURATION);
|
||||
|
||||
// return $this->generateResponse([
|
||||
// 'message' => $configuration->getParameter(ParametersName::REGISTRATION_PAYMENT_AWAITING),
|
||||
// ]);
|
||||
// }
|
||||
|
||||
/** @var TokenGeneratorInterface $tokenGenerator */
|
||||
$tokenGenerator = $this->container->get('fos_user.util.token_generator');
|
||||
$user->setConfirmationToken($tokenGenerator->generateToken());
|
||||
|
||||
//stripe register user
|
||||
if (isset($form['paymentID'])) {
|
||||
$stripe = $this->get('stripe.service');
|
||||
$stripe->setApiKey();
|
||||
|
||||
$customer = $stripe->createCustomer(
|
||||
[
|
||||
'email' => $form['email']->getData(),
|
||||
'name' => $form['firstName']->getData().' '.$form['lastName']->getData(),
|
||||
]
|
||||
);
|
||||
|
||||
$customerArray = [];
|
||||
if ($customer instanceof ApiErrorException) {
|
||||
$customerArray = ['paymentError' => 1,'data'=>$customer,'message'=>'Customer failed'];
|
||||
return $this->generateResponse($customerArray, 400);
|
||||
}
|
||||
if (isset($customer['id'])) {
|
||||
$user->setStripeUserId($customer['id']);
|
||||
|
||||
//Add card atatch to customer
|
||||
$cardAttach = $stripe->paymentMethodAttachToCustomer($form['paymentID']->getData(),
|
||||
['customer' => $customer['id']]
|
||||
);
|
||||
|
||||
if ($cardAttach instanceof ApiErrorException) {
|
||||
$cardAttachArray = ['paymentError' => 1,'data'=>$cardAttach,'message'=>'Card attached to customer failed'];
|
||||
return $this->generateResponse($cardAttachArray, 500);
|
||||
}
|
||||
|
||||
//Add product
|
||||
$product = $stripe->addProduct(
|
||||
[
|
||||
'name' => 'SOCIALHOSE.IO Media Monitoring Subscription',
|
||||
'metadata' => (array)$customer['id']
|
||||
]
|
||||
);
|
||||
if ($product instanceof ApiErrorException) {
|
||||
$productArray = ['paymentError' => 1,'data'=>$product,'message'=>'Product failed'];
|
||||
return $this->generateResponse($productArray, 400);
|
||||
}
|
||||
|
||||
if (isset($product['id'])) {
|
||||
|
||||
//Call cost calculation plan
|
||||
$costCalculation = $this->get('cost.calculation');
|
||||
$response = $costCalculation->costCalculationAction($request, true);
|
||||
//Add plan
|
||||
// $plan = $stripe->addPlan(
|
||||
// [
|
||||
// 'amount' => isset($response['price']) ? $response['price'] * 100 : 0,
|
||||
// 'currency' => 'usd',
|
||||
// 'interval' => 'month',
|
||||
// 'product' => $product['id']
|
||||
// ]
|
||||
// );
|
||||
// if ($plan instanceof ApiErrorException) {
|
||||
// $planArray = ['paymentError' => 1,'data'=>[],'message'=>'Plan failed'];
|
||||
// return $this->generateResponse($planArray, 500);
|
||||
// }
|
||||
|
||||
$price = $stripe->addPrice(
|
||||
[
|
||||
'unit_amount' => isset($response['price']) ? $response['price'] * 100 : 0,
|
||||
'currency' => 'usd',
|
||||
'recurring' => ['interval' => 'month'],
|
||||
'product' => $product['id']
|
||||
]
|
||||
);
|
||||
if ($price instanceof ApiErrorException) {
|
||||
$priceArray = ['paymentError' => 1,'data'=>$price,'message'=>'Price add failed'];
|
||||
return $this->generateResponse($priceArray, 400);
|
||||
}
|
||||
|
||||
//Plan subscription code
|
||||
if (isset($price['id'])) {
|
||||
//Add plan
|
||||
$subscription = $stripe->createSubscription(
|
||||
[
|
||||
'customer' => $customer['id'],
|
||||
'items' => [['price' => $price['id']]],
|
||||
'default_payment_method' => $form['paymentID']->getData()
|
||||
]
|
||||
);
|
||||
if ($subscription instanceof ApiErrorException) {
|
||||
$subscriptionArray = ['paymentError' => 1,'data'=>$subscription,'message'=>'Subscribtion failed'];
|
||||
return $this->generateResponse($subscriptionArray, 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
$mailer = $this->get('user.mailer.default');
|
||||
$baseurl = $request->getScheme() . '://' . $request->getHttpHost() . $request->getBasePath();
|
||||
$mailer->sendEmailMessage($user, $baseurl);
|
||||
$userManager->updateUser($user);
|
||||
|
||||
return $this->generateResponse([
|
||||
'success' => true,
|
||||
'isFreeUser'=> isset($form['paymentID']) ? false : true
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->generateResponse($form, 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive the confirmation token from user email provider, login the user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $token
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function confirmAction(Request $request, $token)
|
||||
{
|
||||
/** @var $userManager \FOS\UserBundle\Model\UserManagerInterface */
|
||||
$userManager = $this->get('fos_user.user_manager');
|
||||
|
||||
$user = $userManager->findUserByConfirmationToken($token);
|
||||
|
||||
if (null === $user) {
|
||||
throw new NotFoundHttpException(sprintf('The user with confirmation token "%s" does not exist', $token));
|
||||
}
|
||||
|
||||
/** @var $dispatcher EventDispatcherInterface */
|
||||
$dispatcher = $this->get('event_dispatcher');
|
||||
|
||||
$user->setConfirmationToken(null);
|
||||
$user->setEnabled(true);
|
||||
$user->setVerified(true);
|
||||
|
||||
$event = new GetResponseUserEvent($user, $request);
|
||||
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_CONFIRM, $event);
|
||||
|
||||
$userManager->updateUser($user);
|
||||
|
||||
return $this->generateResponse([
|
||||
'success' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get billing plans
|
||||
*
|
||||
* @Route("/plans", methods={ "GET" })
|
||||
*
|
||||
* @ApiDoc(
|
||||
* resource="Registration",
|
||||
* section="Security",
|
||||
* output={
|
||||
* "class"="Array<UserBundle\Entity\Plan>",
|
||||
* "groups"={ "id", "plan" }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="All available plans."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @return array|\ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function billingPlansAction()
|
||||
{
|
||||
$repository = $this->getManager()->getRepository(Plan::class);
|
||||
$plans = $repository->findAll();
|
||||
if (count($plans) === 0) {
|
||||
return $this->generateResponse("Can't find plans.", 404);
|
||||
}
|
||||
|
||||
return $this->generateResponse($plans, 200, [
|
||||
'id',
|
||||
'plan',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Organization autocomplete
|
||||
*
|
||||
* @Route("/organizationAutocomplete", methods={ "GET" })
|
||||
* @ApiDoc(
|
||||
* resource="Registration",
|
||||
* section="Security",
|
||||
* filters={
|
||||
* {
|
||||
* "name"="organizationName",
|
||||
* "dataType"="string",
|
||||
* "description"="Part of organization name",
|
||||
* "requirements"="[\w\s]+"
|
||||
* }
|
||||
* },
|
||||
* output={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* ""={
|
||||
* "dataType"="Collection of string",
|
||||
* "description"="Matched organization names.",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="All available organization names."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function organizationAutocompleteAction(Request $request)
|
||||
{
|
||||
$repository = $this->getManager()->getRepository(Organization::class);
|
||||
$organizationName = trim($request->query->get('organizationName'));
|
||||
$organizationName = implode(' ', \nspl\a\map(function ($name) {
|
||||
return '%'. trim($name) .'%';
|
||||
}, explode(' ', $organizationName)));
|
||||
|
||||
$organizations = $repository->createQueryBuilder('Organization')
|
||||
->select('Organization.name')
|
||||
->where('Organization.name LIKE :name')
|
||||
->setParameter('name', $organizationName)
|
||||
->getQuery()
|
||||
->setMaxResults(self::DEFAULT_LIMIT)
|
||||
->getResult();
|
||||
|
||||
return $this->generateResponse(\nspl\a\map(\nspl\op\itemGetter('name'), $organizations));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of available gateways.
|
||||
*
|
||||
* @Route("/paymentGateways", methods={ "GET" })
|
||||
* @ApiDoc(
|
||||
* resource="Registration",
|
||||
* section="Security",
|
||||
* output={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* ""={
|
||||
* "dataType"="collection of string",
|
||||
* "description"="Available payment gateways"
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* )
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function gatewaysAction()
|
||||
{
|
||||
return PaymentGatewayEnum::getChoices();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish registration.
|
||||
*
|
||||
* @Route("/finish", methods={ "POST" })
|
||||
* @ApiDoc(
|
||||
* resource="Registration",
|
||||
* section="Security",
|
||||
* input={
|
||||
* "class"="UserBundle\Form\PaymentDataType",
|
||||
* "name"=false
|
||||
* },
|
||||
* output={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* "message"={
|
||||
* "dataType"="string",
|
||||
* "description"="Payment success message"
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* )
|
||||
*
|
||||
* @param Request $request A HTTP Request instance.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function finishAction(Request $request)
|
||||
{
|
||||
$form = $this->createForm(PaymentDataType::class);
|
||||
$form->submit($request->request->all());
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
/** @var PaymentData $data */
|
||||
$data = $form->getData();
|
||||
|
||||
$gatewayName = $data->getGateway();
|
||||
$subscription = $data->getUser()->getBillingSubscription();
|
||||
$creditCard = $data->getCreditCard();
|
||||
|
||||
if ($subscription === null) {
|
||||
return $this->generateResponse([ 'Unknown confirmation token' ], 400);
|
||||
}
|
||||
|
||||
/** @var PaymentGatewayFactoryInterface $gatewayFactory */
|
||||
$gatewayFactory = $this->get(PaymentBundleServices::PAYMENT_GATEWAY_FACTORY);
|
||||
$gateway = $gatewayFactory->getGateway($gatewayName);
|
||||
|
||||
$billingSubscription = new BillingSubscription($subscription, $subscription->getPlan(), $creditCard);
|
||||
$gateway->executeSubscription($billingSubscription);
|
||||
|
||||
$user = $data->getUser();
|
||||
$user->setConfirmationToken(null);
|
||||
|
||||
/** @var EntityManagerInterface $em */
|
||||
$em = $this->get('doctrine.orm.default_entity_manager');
|
||||
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
|
||||
/** @var ConfigurationInterface $configuration */
|
||||
$configuration = $this->get(AppBundleServices::CONFIGURATION);
|
||||
|
||||
return $this->generateResponse([
|
||||
'message' => $configuration->getParameter(ParametersName::REGISTRATION_PAYMENT_AWAITING),
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->generateResponse($form, 400);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\Security;
|
||||
|
||||
use ApiBundle\Controller\AbstractApiController;
|
||||
use FOS\UserBundle\Model\UserManagerInterface;
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Form\ResettingConfirmType;
|
||||
use UserBundle\Form\ResettingRequestType;
|
||||
use UserBundle\Mailer\MailerInterface;
|
||||
use UserBundle\UserBundleServices;
|
||||
|
||||
/**
|
||||
* Class ResettingController
|
||||
* @package UserBundle\Controller\Security
|
||||
*
|
||||
* @Route("/resetting", service="user.controller.resetting")
|
||||
*/
|
||||
class ResettingController extends AbstractApiController
|
||||
{
|
||||
|
||||
/**
|
||||
* Request password resetting.
|
||||
* User will receive email with information about resetting account.
|
||||
*
|
||||
* Example
|
||||
*
|
||||
* Request:
|
||||
* ```json
|
||||
* {
|
||||
* "email": "socialhose@mail.com"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* User will receive email with link "../auth/reset-password/?resetting_token=12dasv...".
|
||||
*
|
||||
* @Route("/request", methods={ "POST" })
|
||||
* @ApiDoc(
|
||||
* resource="Resetting",
|
||||
* section="Security",
|
||||
* input={
|
||||
* "class"="UserBundle\Form\ResettingRequestType",
|
||||
* "name"=false
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function requestAction(Request $request)
|
||||
{
|
||||
$form = $this->createForm(ResettingRequestType::class);
|
||||
|
||||
$form->submit($request->request->all());
|
||||
if ($form->isValid()) {
|
||||
$data = $form->getData();
|
||||
|
||||
/** @var UserManagerInterface $manager */
|
||||
$manager = $this->get('fos_user.user_manager');
|
||||
|
||||
$user = $manager->findUserByEmail($data['email']);
|
||||
if (! $user instanceof User) {
|
||||
$message = "A recovery link has been sent to {$data['email']}, if found in our system.";
|
||||
return $this->generateResponse($message, 400);
|
||||
}
|
||||
|
||||
if (! $user->isEnabled()) {
|
||||
// This user id locked, so we don't send reset email to him.
|
||||
return $this->generateResponse('User is locked.', 400);
|
||||
}
|
||||
|
||||
$ttl = $this->container->getParameter('fos_user.resetting.token_ttl');
|
||||
if ($user->isPasswordRequestNonExpired($ttl)) {
|
||||
// This user already request password changing and reset token is not
|
||||
// expired yet.
|
||||
return $this->generateResponse('Already requested.', 400);
|
||||
}
|
||||
|
||||
// Generate new confirmation token.
|
||||
/** @var TokenGeneratorInterface $tokenGenerator */
|
||||
$tokenGenerator = $this->get('fos_user.util.token_generator');
|
||||
$user->setConfirmationToken($tokenGenerator->generateToken());
|
||||
$user->setPasswordRequestedAt(new \DateTime());
|
||||
$manager->updateUser($user);
|
||||
|
||||
// Send confirmation email to user.
|
||||
/** @var MailerInterface $mailer */
|
||||
$mailer = $this->get(UserBundleServices::MAILER);
|
||||
$mailer->sendPasswordResettingConfirmation($user);
|
||||
|
||||
return $this->generateResponse();
|
||||
}
|
||||
|
||||
return $this->generateResponse($form, 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm password resetting.
|
||||
*
|
||||
* Example
|
||||
*
|
||||
* Request:
|
||||
* ```json
|
||||
* {
|
||||
* "confirmationToken": "12dasv ...",
|
||||
* "password": "newPassword"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @Route("/confirm", methods={ "POST" })
|
||||
* @ApiDoc(
|
||||
* resource="Resetting",
|
||||
* section="Security",
|
||||
* input={
|
||||
* "class"="UserBundle\Form\ResettingConfirmType",
|
||||
* "name"=false
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function confirmAction(Request $request)
|
||||
{
|
||||
$form = $this->createForm(ResettingConfirmType::class);
|
||||
|
||||
$form->submit($request->request->all());
|
||||
if ($form->isValid()) {
|
||||
/** @var UserManagerInterface $userManager */
|
||||
$userManager = $this->get('fos_user.user_manager');
|
||||
|
||||
$data = $form->getData();
|
||||
|
||||
$user = $userManager
|
||||
->findUserByConfirmationToken($data['confirmationToken']);
|
||||
|
||||
if ($user === null) {
|
||||
// Can't find user by provided confirmation token
|
||||
return $this->generateResponse('Invalid token.', 400);
|
||||
}
|
||||
|
||||
if (! $user->isEnabled()) {
|
||||
// This user id locked, so we don't send reset email to him.
|
||||
return $this->generateResponse('User is locked.', 400);
|
||||
}
|
||||
|
||||
$ttl = $this->container->getParameter('fos_user.resetting.token_ttl');
|
||||
if (! $user->isPasswordRequestNonExpired($ttl)) {
|
||||
// This token is expired.
|
||||
return $this->generateResponse('Confirmation token expired.', 400);
|
||||
}
|
||||
|
||||
// All ok.
|
||||
$user
|
||||
->setPlainPassword($data['password'])
|
||||
->setConfirmationToken(null)
|
||||
->setPasswordRequestedAt(null);
|
||||
$userManager->updateUser($user);
|
||||
|
||||
return $this->generateResponse();
|
||||
}
|
||||
|
||||
return $this->generateResponse($form, 400);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\V1;
|
||||
|
||||
use ApiBundle\Controller\AbstractCRUDController;
|
||||
use ApiBundle\Form\ActivatedEntitiesBatchType;
|
||||
use ApiBundle\Form\EntitiesBatchType;
|
||||
use ApiBundle\Form\SubscribeToNotificationsBatchType;
|
||||
use ApiBundle\Security\Inspector\InspectorInterface;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use UserBundle\Manager\Notification\NotificationManagerInterface;
|
||||
use UserBundle\Security\Inspector\NotificationInspector;
|
||||
use UserBundle\UserBundleServices;
|
||||
|
||||
/**
|
||||
* Class AbstractRecipientController
|
||||
*
|
||||
* @package UserBundle\Controller\V1
|
||||
*/
|
||||
abstract class AbstractRecipientController extends AbstractCRUDController
|
||||
{
|
||||
|
||||
/**
|
||||
* Batch remove of recipients.
|
||||
*
|
||||
* @param Request $request A HTTP Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
protected function batchDelete(Request $request)
|
||||
{
|
||||
$processor = function (Collection $recipients) {
|
||||
$em = $this->getManager();
|
||||
|
||||
foreach ($recipients as $recipient) {
|
||||
$em->remove($recipient);
|
||||
}
|
||||
|
||||
$em->flush();
|
||||
};
|
||||
|
||||
return $this->batchProcessing(
|
||||
$request,
|
||||
InspectorInterface::DELETE,
|
||||
EntitiesBatchType::class,
|
||||
$processor
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch activate/deactivate recipients.
|
||||
*
|
||||
* @param Request $request A HTTP Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
protected function batchActiveToggle(Request $request)
|
||||
{
|
||||
$processor = function (Collection $recipients, $active) {
|
||||
$em = $this->getManager();
|
||||
|
||||
foreach ($recipients as $recipient) {
|
||||
$recipient->setActive($active);
|
||||
$em->persist($recipient);
|
||||
}
|
||||
$em->flush();
|
||||
};
|
||||
|
||||
return $this->batchProcessing(
|
||||
$request,
|
||||
InspectorInterface::UPDATE,
|
||||
ActivatedEntitiesBatchType::class,
|
||||
$processor
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch subscribe/unsubscribe specified recipient from notifications.
|
||||
*
|
||||
* @param Request $request A HTTP Request instance.
|
||||
* @param integer $id A recipient entity instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
protected function batchSubscriptionToggle(Request $request, $id)
|
||||
{
|
||||
$recipient = $this->getManager()->getRepository($this->entity)->find($id);
|
||||
|
||||
if ($recipient === null) {
|
||||
$name = \app\c\getShortName($this->entity);
|
||||
// Remove 'Abstract' prefix if it exists.
|
||||
if (strpos($name, 'Abstract') !== false) {
|
||||
$name = substr($name, 8);
|
||||
}
|
||||
|
||||
return $this->generateResponse("Can't find {$name} with id {$id}.", 404);
|
||||
}
|
||||
|
||||
$reasons = $this->checkAccess(NotificationInspector::UPDATE, $recipient);
|
||||
if (count($reasons) > 0) {
|
||||
return $this->generateResponse($reasons, 403);
|
||||
}
|
||||
|
||||
$processor = function (Collection $notifications, $subscribed) use ($recipient) {
|
||||
/** @var NotificationManagerInterface $manager */
|
||||
$manager = $this->get(UserBundleServices::NOTIFICATION_MANAGER);
|
||||
$manager->subscriptionToggle(
|
||||
$recipient,
|
||||
$notifications->toArray(),
|
||||
(bool) $subscribed
|
||||
);
|
||||
};
|
||||
|
||||
return $this->batchProcessing(
|
||||
$request,
|
||||
function (Collection $notifications, $subscribed) {
|
||||
return $subscribed ? NotificationInspector::SUBSCRIBE : NotificationInspector::UNSUBSCRIBE;
|
||||
},
|
||||
SubscribeToNotificationsBatchType::class,
|
||||
$processor
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\V1;
|
||||
|
||||
use ApiBundle\Controller\AbstractApiController;
|
||||
use ApiBundle\Controller\Annotation\Roles;
|
||||
use FOS\UserBundle\Model\UserManagerInterface;
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Enum\UserRoleEnum;
|
||||
use UserBundle\Form\SubscriberType;
|
||||
use UserBundle\Mailer\MailerInterface;
|
||||
use UserBundle\Repository\UserRepository;
|
||||
use UserBundle\UserBundleServices;
|
||||
|
||||
/**
|
||||
* Class CurrentSubscriberController
|
||||
* @package UserBundle\Controller\V1
|
||||
*
|
||||
* @Route(
|
||||
* "/users/current/subscribers",
|
||||
* service="user.controller.current_subscriber"
|
||||
* )
|
||||
*/
|
||||
class CurrentSubscriberController extends AbstractApiController
|
||||
{
|
||||
|
||||
/**
|
||||
* Get list of subscriber for current master.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("", methods={ "GET" })
|
||||
* @ApiDoc(
|
||||
* resource="Current user subscribers",
|
||||
* section="User",
|
||||
* filters={
|
||||
* {
|
||||
* "name"="page",
|
||||
* "dataType"="integer",
|
||||
* "description"="Requested page number, start from 1",
|
||||
* "requirements"="\d+",
|
||||
* "default"="1"
|
||||
* },
|
||||
* {
|
||||
* "name"="limit",
|
||||
* "dataType"="integer",
|
||||
* "description"="Max entities per page, default 100",
|
||||
* "requirements"="\d+",
|
||||
* "default"="100"
|
||||
* }
|
||||
* },
|
||||
* output={
|
||||
* "class"="Pagination<UserBundle\Entity\User>",
|
||||
* "groups"={ "subscriber", "id" }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="Subscribers successfully returned."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function listAction(Request $request)
|
||||
{
|
||||
/** @var UserRepository $repository */
|
||||
$repository = $this->getManager()->getRepository('UserBundle:User');
|
||||
$user = $this->getCurrentUser();
|
||||
|
||||
$pagination = $this->paginate(
|
||||
$request,
|
||||
$repository->getSubscribersQueryBuilder($user->getId())
|
||||
);
|
||||
|
||||
return $this->generateResponse($pagination, 200, [ 'subscriber', 'id' ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about subscriber.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("/{id}", requirements={ "id"="\d+" }, methods={ "GET" })
|
||||
* @ApiDoc(
|
||||
* resource="Current user subscribers",
|
||||
* section="User",
|
||||
* output={
|
||||
* "class"="Pagination<UserBundle\Entity\User>",
|
||||
* "groups"={ "subscriber", "id" }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="Subscriber successfully returned."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param integer $id A subscriber User entity id.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function getAction($id)
|
||||
{
|
||||
/** @var UserManagerInterface $manager */
|
||||
$manager = $this->get('fos_user.user_manager');
|
||||
|
||||
$current = $this->getCurrentUser();
|
||||
$user = $manager->findUserBy([
|
||||
'id' => $id,
|
||||
'masterUser' => $current->getId(),
|
||||
]);
|
||||
|
||||
if ($user === null) {
|
||||
return $this->generateResponse("Can't find subscriber with id {$id}.", 404);
|
||||
}
|
||||
|
||||
return $this->generateResponse($user, 200, [ 'subscriber', 'id' ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new subscriber for current user.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("", methods={ "POST" })
|
||||
* @ApiDoc(
|
||||
* resource="Current user subscribers",
|
||||
* section="User",
|
||||
* input={
|
||||
* "class"="UserBundle\Form\SubscriberType",
|
||||
* "name"=false
|
||||
* },
|
||||
* output={
|
||||
* "class"="Pagination<UserBundle\Entity\User>",
|
||||
* "groups"={ "subscriber", "id" }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="Subscriber successfully created."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return User|\ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function createAction(Request $request)
|
||||
{
|
||||
$current = $this->getCurrentUser();
|
||||
$user = new User();
|
||||
$user
|
||||
->generatePassword()
|
||||
->setMasterUser($current)
|
||||
->setRoles([ UserRoleEnum::SUBSCRIBER ]);
|
||||
|
||||
$form = $this->createForm(SubscriberType::class, $user);
|
||||
|
||||
$form->submit($request->request->all());
|
||||
if ($form->isValid()) {
|
||||
/** @var UserManagerInterface $manager */
|
||||
$manager = $this->get('fos_user.user_manager');
|
||||
|
||||
$password = $user->getPlainPassword();
|
||||
$manager->updateUser($user);
|
||||
|
||||
/** @var MailerInterface $mailer */
|
||||
$mailer = $this->get(UserBundleServices::MAILER);
|
||||
$mailer->sendPassword($user, $password);
|
||||
|
||||
return $this->generateResponse($user, 200, [ 'subscriber', 'id' ]);
|
||||
}
|
||||
|
||||
return $this->generateResponse($form, 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update current user subscriber.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("/{id}", requirements={ "id"="\d+" }, methods={ "PUT" })
|
||||
* @ApiDoc(
|
||||
* resource="Current user subscribers",
|
||||
* section="User",
|
||||
* input={
|
||||
* "class"="UserBundle\Form\SubscriberType",
|
||||
* "name"=false
|
||||
* },
|
||||
* output={
|
||||
* "class"="Pagination<UserBundle\Entity\User>",
|
||||
* "groups"={ "subscriber", "id" }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="Subscriber successfully updated.",
|
||||
* 404="Can't find category by specified id."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
* @param integer $id A subscriber User entity id.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function putAction(Request $request, $id)
|
||||
{
|
||||
/** @var UserManagerInterface $manager */
|
||||
$manager = $this->get('fos_user.user_manager');
|
||||
|
||||
$current = $this->getCurrentUser();
|
||||
$user = $manager->findUserBy([
|
||||
'id' => $id,
|
||||
'masterUser' => $current->getId(),
|
||||
]);
|
||||
|
||||
if ($user === null) {
|
||||
return $this->generateResponse("Can't find subscriber with id {$id}.", 404);
|
||||
}
|
||||
|
||||
$form = $this->createForm(SubscriberType::class, $user, [
|
||||
'method' => 'PUT',
|
||||
]);
|
||||
|
||||
$form->submit($request->request->all());
|
||||
if ($form->isValid()) {
|
||||
$manager->updateUser($user);
|
||||
|
||||
return $this->generateResponse($user, 200, [ 'subscriber', 'id' ]);
|
||||
}
|
||||
|
||||
return $this->generateResponse($form, 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update current user subscriber.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("/{id}", requirements={ "id"="\d+" }, methods={ "DELETE" })
|
||||
* @ApiDoc(
|
||||
* resource="Current user subscribers",
|
||||
* section="User",
|
||||
* statusCodes={
|
||||
* 200="Subscriber successfully deleted.",
|
||||
* 404="Can't find category by specified id."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param integer $id A subscriber User entity id.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
/** @var UserManagerInterface $manager */
|
||||
$manager = $this->get('fos_user.user_manager');
|
||||
|
||||
$current = $this->getCurrentUser();
|
||||
$user = $manager->findUserBy([
|
||||
'id' => $id,
|
||||
'masterUser' => $current->getId(),
|
||||
]);
|
||||
|
||||
if ($user === null) {
|
||||
return $this->generateResponse("Can't find subscriber with id {$id}.", 404);
|
||||
}
|
||||
|
||||
$manager->deleteUser($user);
|
||||
|
||||
return $this->generateResponse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,440 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\V1;
|
||||
|
||||
use ApiBundle\Controller\Annotation\Roles;
|
||||
use ApiBundle\Security\Inspector\InspectorInterface;
|
||||
use AppBundle\Model\SortingOptions;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination;
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use UserBundle\Entity\Recipient\AbstractRecipient;
|
||||
use UserBundle\Entity\Recipient\GroupRecipient;
|
||||
use UserBundle\Entity\Recipient\PersonRecipient;
|
||||
use UserBundle\Enum\StatusFilterEnum;
|
||||
use UserBundle\Repository\GroupRecipientRepository;
|
||||
use UserBundle\Repository\PersonRecipientRepository;
|
||||
use UserBundle\Utils\AdditionalConditions;
|
||||
|
||||
/**
|
||||
* Class GroupRecipientController
|
||||
* @package UserBundle\Controller\V1
|
||||
*
|
||||
* @Route(
|
||||
* "/recipients/groups",
|
||||
* service="user.controller.group_recipient"
|
||||
* )
|
||||
*/
|
||||
class GroupRecipientController extends AbstractRecipientController
|
||||
{
|
||||
|
||||
/**
|
||||
* Get list of available person recipients.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("", methods={ "GET" })
|
||||
* @ApiDoc(
|
||||
* resource="Group",
|
||||
* section="Receivers",
|
||||
* filters={
|
||||
* {
|
||||
* "name"="page",
|
||||
* "dataType"="integer",
|
||||
* "description"="Requested page number, start from 1",
|
||||
* "requirements"="\d+",
|
||||
* "default"="1"
|
||||
* },
|
||||
* {
|
||||
* "name"="limit",
|
||||
* "dataType"="integer",
|
||||
* "description"="Max entities per page, default 100",
|
||||
* "requirements"="\d+",
|
||||
* "default"="100"
|
||||
* },
|
||||
* {
|
||||
* "name"="recipientId",
|
||||
* "dataType"="string",
|
||||
* "description"="If set get recipients for specified recipient group",
|
||||
* "requirements"="\d+",
|
||||
* "required"=false
|
||||
* },
|
||||
* {
|
||||
* "name"="sortField",
|
||||
* "dataType"="string",
|
||||
* "description"="Field name for sorting. Available: name, active, recipientsNumber, creationDate",
|
||||
* "requirements"="\w+",
|
||||
* "default"="name",
|
||||
* "required"=false
|
||||
* },
|
||||
* {
|
||||
* "name"="sortDirection",
|
||||
* "dataType"="string",
|
||||
* "description"="Sort direction. Available: asc, desc",
|
||||
* "requirements"="(asc|desc)",
|
||||
* "default"="asc",
|
||||
* "required"=false
|
||||
* },
|
||||
* {
|
||||
* "name"="filter",
|
||||
* "dataType"="string",
|
||||
* "description"="Keyword for searching groups by names",
|
||||
* "requirements"="\w+"
|
||||
* },
|
||||
* {
|
||||
* "name"="statusFilter",
|
||||
* "dataType"="string",
|
||||
* "description"="Keyword for searching groups by status",
|
||||
* "requirements"="(no|yes|all)"
|
||||
* },
|
||||
* {
|
||||
* "name"="include",
|
||||
* "dataType"="string",
|
||||
* "description"="Comma separated list of recipient group ids."
|
||||
* },
|
||||
* {
|
||||
* "name"="exclude",
|
||||
* "dataType"="string",
|
||||
* "description"="Comma separated list of recipient group ids."
|
||||
* }
|
||||
* },
|
||||
* output={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* "groups"={
|
||||
* "class"="UserBundle\Entity\Recipient\PersonRecipient",
|
||||
* "groups"={ "id", "recipient" }
|
||||
* },
|
||||
* "meta"={
|
||||
* "dataType"="model",
|
||||
* "description"="Response meta information",
|
||||
* "required"=true,
|
||||
* "readonly"=true,
|
||||
* "children"={
|
||||
* "sort"={
|
||||
* "dataType"="model",
|
||||
* "requited"=true,
|
||||
* "readonly"=true,
|
||||
* "children"={
|
||||
* "field"={
|
||||
* "dataType"="string",
|
||||
* "description"="Field name for sorting. Available: name, email, creationDate, active",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* },
|
||||
* "direction"={
|
||||
* "dataType"="string",
|
||||
* "description"="Sort direction. Available: asc, desc",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="Recipients groups successfully funded.",
|
||||
* 403="Don't has requested permissions."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function listAction(Request $request)
|
||||
{
|
||||
/** @var EntityManagerInterface $em */
|
||||
$em = $this->get('doctrine.orm.default_entity_manager');
|
||||
$recipientId = trim($request->query->get('recipientId'));
|
||||
$currentUser = $this->getCurrentUser();
|
||||
|
||||
//
|
||||
// Get sort parameters and filter.
|
||||
//
|
||||
$sortingOptions = SortingOptions::fromRequest($request, 'name');
|
||||
$filter = trim($request->query->get('filter'));
|
||||
|
||||
/** @var GroupRecipientRepository $groupRepository */
|
||||
$groupRepository = $em->getRepository(GroupRecipient::class);
|
||||
|
||||
//
|
||||
// If we got group id we should try to fetch proper recipient group and
|
||||
// check that user can get this group recipient.
|
||||
//
|
||||
if ($recipientId !== '') {
|
||||
/** @var PersonRecipientRepository $personRepository */
|
||||
$personRepository = $em->getRepository(PersonRecipient::class);
|
||||
$person = $personRepository->getForUser($recipientId, $currentUser->getId());
|
||||
|
||||
if (! $person instanceof PersonRecipient) {
|
||||
return $this->generateResponse("Can't find recipient with id {$recipientId}.", 404);
|
||||
}
|
||||
|
||||
//
|
||||
// Check access.
|
||||
//
|
||||
$reasons = $this->checkAccess(InspectorInterface::READ, $person);
|
||||
if (count($reasons) > 0) {
|
||||
return $this->generateResponse($reasons, 403);
|
||||
}
|
||||
|
||||
$statusFilter = trim($request->query->get('statusFilter', StatusFilterEnum::ALL));
|
||||
|
||||
if ($statusFilter !== '') {
|
||||
if (! StatusFilterEnum::isValid($statusFilter)) {
|
||||
return $this->generateResponse("'statusFilter' should be one of ". implode(', ', StatusFilterEnum::getAvailables()));
|
||||
}
|
||||
|
||||
$statusFilter = new StatusFilterEnum($statusFilter);
|
||||
}
|
||||
|
||||
$additionalCond = AdditionalConditions::fromRequest($request);
|
||||
|
||||
$qb = $groupRepository->getQueryBuilderForPerson(
|
||||
$currentUser->getId(),
|
||||
$person->getId(),
|
||||
$statusFilter,
|
||||
$sortingOptions,
|
||||
$filter,
|
||||
$additionalCond
|
||||
);
|
||||
} else {
|
||||
$qb = $groupRepository->getQueryBuilderForUser(
|
||||
$currentUser->getId(),
|
||||
$sortingOptions,
|
||||
$filter
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// We should get all paginated data and put 'subscribed' field value into
|
||||
// Notification entity.
|
||||
//
|
||||
/** @var SlidingPagination $pagination */
|
||||
$pagination = $this->paginate($request, $qb);
|
||||
|
||||
$serializationGroups = [ 'recipient', 'id' ];
|
||||
if ($recipientId !== '') {
|
||||
$data = array_map(function (array $element) {
|
||||
/** @var AbstractRecipient $recipient */
|
||||
$recipient = $element[0];
|
||||
|
||||
$recipient->enrolled = (bool) $element['enrolled'];
|
||||
|
||||
return $recipient;
|
||||
}, iterator_to_array($pagination));
|
||||
|
||||
$serializationGroups[] = 'sublist';
|
||||
$totalCount = $pagination->getTotalItemCount();
|
||||
|
||||
$pagination = $this->paginate($request, $data);
|
||||
$pagination->setTotalItemCount($totalCount);
|
||||
}
|
||||
|
||||
return $this->generateResponse(
|
||||
[
|
||||
'groups' => $pagination,
|
||||
'meta' => [ 'sort' => $sortingOptions ],
|
||||
],
|
||||
200,
|
||||
$serializationGroups
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new recipient group.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("", methods={ "POST" })
|
||||
* @ApiDoc(
|
||||
* resource="Group",
|
||||
* section="Receivers",
|
||||
* input={
|
||||
* "class"="UserBundle\Form\GroupRecipientType",
|
||||
* "name"=false
|
||||
* },
|
||||
* output={
|
||||
* "class"="UserBundle\Entity\Recipient\GroupRecipient",
|
||||
* "groups"={ "id", "recipient" }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 204="New recipient group successfully created.",
|
||||
* 400="Invalid parameters."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Entity\ManageableEntityInterface|\ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function createAction(Request $request)
|
||||
{
|
||||
return parent::createEntity($request, GroupRecipient::create()->setOwner($this->getCurrentUser()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update specified recipient group.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("/{id}", methods={ "PUT" }, requirements={ "id": "\d*" })
|
||||
* @ApiDoc(
|
||||
* resource="Group",
|
||||
* section="Receivers",
|
||||
* input={
|
||||
* "class"="UserBundle\Form\GroupRecipientType",
|
||||
* "name"=false
|
||||
* },
|
||||
* output={
|
||||
* "class"="UserBundle\Entity\Recipient\GroupRecipient",
|
||||
* "groups"={ "id", "recipient" }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 204="Recipient group successfully updated.",
|
||||
* 400="Invalid parameters."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
* @param integer $id A GroupRecipient entity id.
|
||||
*
|
||||
* @return \ApiBundle\Entity\ManageableEntityInterface|\ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function putAction(Request $request, $id)
|
||||
{
|
||||
return parent::putEntity($request, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete recipient groups.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("/delete", methods={ "POST" })
|
||||
* @ApiDoc(
|
||||
* resource="Group",
|
||||
* section="Receivers",
|
||||
* input={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* "ids"={
|
||||
* "dataType"="Array of recipient group ids",
|
||||
* "actualType"="collection",
|
||||
* "subtype"="string",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* output={
|
||||
* "class"="UserBundle\Entity\Recipient\GroupRecipient",
|
||||
* "groups"={ "id", "recipient" }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 204="Recipient groups successfully deleted.",
|
||||
* 400="Invalid parameters."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface|null
|
||||
*/
|
||||
public function deleteAction(Request $request)
|
||||
{
|
||||
return $this->batchDelete($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate/deactivate recipient groups.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("/active", methods={ "PUT" })
|
||||
* @ApiDoc(
|
||||
* resource="Group",
|
||||
* section="Receivers",
|
||||
* input={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* "ids"={
|
||||
* "dataType"="Array of recipient groups ids",
|
||||
* "actualType"="collection",
|
||||
* "subtype"="string",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* },
|
||||
* "active"={
|
||||
* "dataType"="Boolean flag",
|
||||
* "actualType"="boolean",
|
||||
* "subtype"="string",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* },
|
||||
* statusCodes={
|
||||
* 204="Recipient groups successfully activated/deactivated."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function activateAction(Request $request)
|
||||
{
|
||||
return $this->batchActiveToggle($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe/unsubscribe recipient from specified notifications.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("/{id}/subscribe", methods={ "PUT" })
|
||||
* @ApiDoc(
|
||||
* resource="Group",
|
||||
* section="Receivers",
|
||||
* input={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* "ids"={
|
||||
* "dataType"="Array of recipients ids",
|
||||
* "actualType"="collection",
|
||||
* "subtype"="string",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* },
|
||||
* "subscribe"={
|
||||
* "dataType"="Boolean flag",
|
||||
* "actualType"="boolean",
|
||||
* "subtype"="string",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* },
|
||||
* statusCodes={
|
||||
* 204="Recipient group successfully subscribed/unsubscribed."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
* @param integer $id A PersonRecipient entity instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function subscribeAction(Request $request, $id)
|
||||
{
|
||||
return $this->batchSubscriptionToggle($request, $id);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\V1;
|
||||
|
||||
use ApiBundle\Controller\AbstractApiController;
|
||||
use ApiBundle\Controller\Annotation\Roles;
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use UserBundle\Entity\Notification\NotificationTheme;
|
||||
use UserBundle\Repository\NotificationThemeRepository;
|
||||
|
||||
/**
|
||||
* Class NotificationThemeController
|
||||
* @package UserBundle\Controller\V1
|
||||
*
|
||||
* @Route(
|
||||
* "/notifications/themes",
|
||||
* service="user.controller.notification_theme"
|
||||
* )
|
||||
*/
|
||||
class NotificationThemeController extends AbstractApiController
|
||||
{
|
||||
|
||||
/**
|
||||
* Get list of all notification's for current user.
|
||||
*
|
||||
* @Roles("ROLE_SUBSCRIBER")
|
||||
*
|
||||
* @Route("/default", methods={ "GET" })
|
||||
* @ApiDoc(
|
||||
* resource=true,
|
||||
* section="NotificationTheme",
|
||||
* output={
|
||||
* "class"="UserBundle\Entity\Notification\NotificationTheme",
|
||||
* "groups"={ "id", "notification_theme"}
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="Default notification successfully returned.",
|
||||
* 404="Can't find default notification theme."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function defaultAction()
|
||||
{
|
||||
/** @var NotificationThemeRepository $repository */
|
||||
$repository = $this->getManager()->getRepository(NotificationTheme::class);
|
||||
$notification = $repository->getDefault();
|
||||
|
||||
if (! $notification instanceof NotificationTheme) {
|
||||
return $this->generateResponse('Can\'t find default notification theme', 404);
|
||||
}
|
||||
|
||||
return $this->generateResponse($notification, 200, [
|
||||
'id',
|
||||
'notification_theme',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,441 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\V1;
|
||||
|
||||
use ApiBundle\Controller\Annotation\Roles;
|
||||
use ApiBundle\Response\ViewInterface;
|
||||
use ApiBundle\Security\Inspector\InspectorInterface;
|
||||
use AppBundle\Model\SortingOptions;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination;
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use UserBundle\Entity\Recipient\AbstractRecipient;
|
||||
use UserBundle\Entity\Recipient\GroupRecipient;
|
||||
use UserBundle\Entity\Recipient\PersonRecipient;
|
||||
use UserBundle\Enum\StatusFilterEnum;
|
||||
use UserBundle\Repository\GroupRecipientRepository;
|
||||
use UserBundle\Repository\PersonRecipientRepository;
|
||||
use UserBundle\Utils\AdditionalConditions;
|
||||
|
||||
/**
|
||||
* Class PersonRecipientController
|
||||
* @package UserBundle\Controller\V1
|
||||
*
|
||||
* @Route(
|
||||
* "/recipients",
|
||||
* service="user.controller.person_recipient"
|
||||
* )
|
||||
*/
|
||||
class PersonRecipientController extends AbstractRecipientController
|
||||
{
|
||||
|
||||
/**
|
||||
* Get list of available person recipients.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("", methods={ "GET" })
|
||||
* @ApiDoc(
|
||||
* resource="Recipient",
|
||||
* section="Receivers",
|
||||
* filters={
|
||||
* {
|
||||
* "name"="page",
|
||||
* "dataType"="integer",
|
||||
* "description"="Requested page number, start from 1",
|
||||
* "requirements"="\d+",
|
||||
* "default"="1"
|
||||
* },
|
||||
* {
|
||||
* "name"="limit",
|
||||
* "dataType"="integer",
|
||||
* "description"="Max entities per page, default 100",
|
||||
* "requirements"="\d+",
|
||||
* "default"="100"
|
||||
* },
|
||||
* {
|
||||
* "name"="groupId",
|
||||
* "dataType"="string",
|
||||
* "description"="If set get recipients for specified recipient group",
|
||||
* "requirements"="\d+",
|
||||
* "required"=false
|
||||
* },
|
||||
* {
|
||||
* "name"="sortField",
|
||||
* "dataType"="string",
|
||||
* "description"="Field name for sorting. Available: name, email,
|
||||
* creationDate, active",
|
||||
* "requirements"="\w+",
|
||||
* "default"="name",
|
||||
* "required"=false
|
||||
* },
|
||||
* {
|
||||
* "name"="sortDirection",
|
||||
* "dataType"="string",
|
||||
* "description"="Sort direction. Available: asc, desc",
|
||||
* "requirements"="(asc|desc)",
|
||||
* "default"="asc",
|
||||
* "required"=false
|
||||
* },
|
||||
* {
|
||||
* "name"="filter",
|
||||
* "dataType"="string",
|
||||
* "description"="Keyword for searching. Part of name or email",
|
||||
* "requirements"="\w+"
|
||||
* },
|
||||
* {
|
||||
* "name"="statusFilter",
|
||||
* "dataType"="string",
|
||||
* "description"="Keyword for searching groups by status",
|
||||
* "requirements"="(no|yes|all)"
|
||||
* },
|
||||
* {
|
||||
* "name"="include",
|
||||
* "dataType"="string",
|
||||
* "description"="Comma separated list of recipient ids."
|
||||
* },
|
||||
* {
|
||||
* "name"="exclude",
|
||||
* "dataType"="string",
|
||||
* "description"="Comma separated list of recipient ids."
|
||||
* }
|
||||
* },
|
||||
* output={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* "recipients"={
|
||||
* "class"="UserBundle\Entity\Recipient\PersonRecipient",
|
||||
* "groups"={ "id", "recipient" }
|
||||
* },
|
||||
* "meta"={
|
||||
* "dataType"="model",
|
||||
* "description"="Response meta information",
|
||||
* "required"=true,
|
||||
* "readonly"=true,
|
||||
* "children"={
|
||||
* "sort"={
|
||||
* "dataType"="model",
|
||||
* "requited"=true,
|
||||
* "readonly"=true,
|
||||
* "children"={
|
||||
* "field"={
|
||||
* "dataType"="string",
|
||||
* "description"="Field name for sorting. Available:
|
||||
* name, email, creationDate, active",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* },
|
||||
* "direction"={
|
||||
* "dataType"="string",
|
||||
* "description"="Sort direction. Available: asc,
|
||||
* desc",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="Recipients successfully funded.",
|
||||
* 403="Don't has requested permissions."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function listAction(Request $request)
|
||||
{
|
||||
/** @var EntityManagerInterface $em */
|
||||
$em = $this->get('doctrine.orm.default_entity_manager');
|
||||
$groupId = trim($request->query->get('groupId'));
|
||||
|
||||
$currentUser = $this->getCurrentUser();
|
||||
|
||||
//
|
||||
// Get sort parameters and filter.
|
||||
//
|
||||
$sortingOptions = SortingOptions::fromRequest($request, 'name');
|
||||
$filter = $request->query->get('filter', '');
|
||||
|
||||
/** @var PersonRecipientRepository $personRepository */
|
||||
$personRepository = $em->getRepository(PersonRecipient::class);
|
||||
|
||||
//
|
||||
// If we got group id we should try to fetch proper recipient group and
|
||||
// check that user can get this group recipient.
|
||||
//
|
||||
if ($groupId !== '') {
|
||||
/** @var GroupRecipientRepository $groupRepository */
|
||||
$groupRepository = $em->getRepository(GroupRecipient::class);
|
||||
$group = $groupRepository->get($groupId);
|
||||
|
||||
if (! $group instanceof GroupRecipient) {
|
||||
return $this->generateResponse("Can't find group recipient with id {$groupId}.", 404);
|
||||
}
|
||||
|
||||
//
|
||||
// Check access.
|
||||
//
|
||||
$reasons = $this->checkAccess(InspectorInterface::READ, $group);
|
||||
if (count($reasons) > 0) {
|
||||
return $this->generateResponse($reasons, 403);
|
||||
}
|
||||
|
||||
$statusFilter = trim($request->query->get('statusFilter', StatusFilterEnum::ALL));
|
||||
|
||||
if ($statusFilter !== '') {
|
||||
if (! StatusFilterEnum::isValid($statusFilter)) {
|
||||
return $this->generateResponse("'statusFilter' should be one of ". implode(', ', StatusFilterEnum::getAvailables()));
|
||||
}
|
||||
|
||||
$statusFilter = new StatusFilterEnum($statusFilter);
|
||||
}
|
||||
|
||||
$additionalCond = AdditionalConditions::fromRequest($request);
|
||||
|
||||
$qb = $personRepository->getQueryBuilderForGroup(
|
||||
$currentUser->getId(),
|
||||
$group->getId(),
|
||||
$statusFilter,
|
||||
$sortingOptions,
|
||||
$filter,
|
||||
$additionalCond
|
||||
);
|
||||
} else {
|
||||
$qb = $personRepository->getQueryBuilderForUser(
|
||||
$currentUser->getId(),
|
||||
$sortingOptions,
|
||||
$filter
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// We should get all paginated data and put 'subscribed' field value into
|
||||
// Notification entity.
|
||||
//
|
||||
/** @var SlidingPagination $pagination */
|
||||
$pagination = $this->paginate($request, $qb);
|
||||
|
||||
$serializationGroups = [ 'recipient', 'id' ];
|
||||
if ($groupId !== '') {
|
||||
$data = array_map(function (array $element) {
|
||||
/** @var AbstractRecipient $recipient */
|
||||
$recipient = $element[0];
|
||||
|
||||
$recipient->enrolled = (bool) $element['enrolled'];
|
||||
|
||||
return $recipient;
|
||||
}, iterator_to_array($pagination));
|
||||
|
||||
$serializationGroups[] = 'sublist';
|
||||
$totalCount = $pagination->getTotalItemCount();
|
||||
|
||||
$pagination = $this->paginate($request, $data);
|
||||
$pagination->setTotalItemCount($totalCount);
|
||||
}
|
||||
|
||||
return $this->generateResponse(
|
||||
[
|
||||
'recipients' => $pagination,
|
||||
'meta' => [ 'sort' => $sortingOptions ],
|
||||
],
|
||||
200,
|
||||
$serializationGroups
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new recipient.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("", methods={ "POST" })
|
||||
* @ApiDoc(
|
||||
* resource="Recipient",
|
||||
* section="Receivers",
|
||||
* input={
|
||||
* "class"="UserBundle\Form\PersonRecipientType",
|
||||
* "name"=false
|
||||
* },
|
||||
* output={
|
||||
* "class"="UserBundle\Entity\Recipient\PersonRecipient",
|
||||
* "groups"={ "id", "recipient" }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 204="New recipient successfully created.",
|
||||
* 400="Invalid parameters."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function createAction(Request $request)
|
||||
{
|
||||
return parent::createEntity($request, PersonRecipient::create()->setOwner($this->getCurrentUser()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update recipient.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("/{id}", methods={ "PUT" }, requirements={ "id": "\d+" })
|
||||
* @ApiDoc(
|
||||
* resource="Recipient",
|
||||
* section="Receivers",
|
||||
* input={
|
||||
* "class"="UserBundle\Form\PersonRecipientType",
|
||||
* "name"=false
|
||||
* },
|
||||
* output={
|
||||
* "class"="UserBundle\Entity\Recipient\PersonRecipient",
|
||||
* "groups"={ "id", "recipient" }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="Recipient successfully updated.",
|
||||
* 400="Invalid parameters."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
* @param integer $id A PersonRecipient entity id.
|
||||
*
|
||||
* @return \ApiBundle\Entity\ManageableEntityInterface|\ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function putAction(Request $request, $id)
|
||||
{
|
||||
return parent::putEntity($request, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete recipient.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("/delete", methods={ "POST" })
|
||||
* @ApiDoc(
|
||||
* resource="Recipient",
|
||||
* section="Receivers",
|
||||
* input={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* "ids"={
|
||||
* "dataType"="Array of recipients ids",
|
||||
* "actualType"="collection",
|
||||
* "subtype"="string",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 204="Recipients successfully deleted.",
|
||||
* 400="Invalid parameters."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function deleteAction(Request $request)
|
||||
{
|
||||
return $this->batchDelete($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate/deactivate recipients.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("/active", methods={ "PUT" })
|
||||
* @ApiDoc(
|
||||
* resource="Recipient",
|
||||
* section="Receivers",
|
||||
* input={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* "ids"={
|
||||
* "dataType"="Array of recipients ids",
|
||||
* "actualType"="collection",
|
||||
* "subtype"="string",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* },
|
||||
* "active"={
|
||||
* "dataType"="Boolean flag",
|
||||
* "actualType"="boolean",
|
||||
* "subtype"="string",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* },
|
||||
* statusCodes={
|
||||
* 204="Recipient successfully activated/deactivated."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function activateAction(Request $request)
|
||||
{
|
||||
return $this->batchActiveToggle($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe/unsubscribe recipient from specified notifications.
|
||||
*
|
||||
* @Roles("ROLE_MASTER_USER")
|
||||
*
|
||||
* @Route("/{id}/subscribe", methods={ "PUT" })
|
||||
* @ApiDoc(
|
||||
* resource="Recipient",
|
||||
* section="Receivers",
|
||||
* input={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* "ids"={
|
||||
* "dataType"="Array of recipients ids",
|
||||
* "actualType"="collection",
|
||||
* "subtype"="string",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* },
|
||||
* "subscribe"={
|
||||
* "dataType"="Boolean flag",
|
||||
* "actualType"="boolean",
|
||||
* "subtype"="string",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* },
|
||||
* statusCodes={
|
||||
* 204="Recipient successfully subscribed/unsubscribed."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
* @param integer $id A PersonRecipient entity instance.
|
||||
*
|
||||
* @return ViewInterface
|
||||
*/
|
||||
public function subscribeAction(Request $request, $id)
|
||||
{
|
||||
return $this->batchSubscriptionToggle($request, $id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\V1;
|
||||
|
||||
use ApiBundle\Controller\Annotation\Roles;
|
||||
use AppBundle\Controller\Traits\TokenStorageAwareTrait;
|
||||
use AppBundle\Controller\V1\AbstractV1Controller;
|
||||
use AppBundle\Model\SortingOptions;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use UserBundle\Entity\Notification\NotificationSendHistory;
|
||||
use UserBundle\Entity\Recipient\AbstractRecipient;
|
||||
use UserBundle\Enum\NotificationTypeEnum;
|
||||
use UserBundle\Repository\NotificationSendHistoryRepository;
|
||||
use UserBundle\Repository\RecipientRepository;
|
||||
|
||||
/**
|
||||
* Class ReceiverController
|
||||
* @package UserBundle\Controller\V1
|
||||
*
|
||||
* @Route(
|
||||
* "/receivers",
|
||||
* service="user.controller.receiver"
|
||||
* )
|
||||
*/
|
||||
class ReceiverController extends AbstractV1Controller
|
||||
{
|
||||
|
||||
const DEFAULT_LIMIT = 30;
|
||||
|
||||
use TokenStorageAwareTrait;
|
||||
|
||||
/**
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* ReceiverController constructor.
|
||||
*
|
||||
* @param TokenStorageInterface $tokenStorage A TokenStorageInterface
|
||||
* instance.
|
||||
* @param EntityManagerInterface $em A EntityManagerInterface
|
||||
* instance.
|
||||
*/
|
||||
public function __construct(
|
||||
TokenStorageInterface $tokenStorage,
|
||||
EntityManagerInterface $em
|
||||
) {
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of available receivers.
|
||||
*
|
||||
* @Roles("ROLE_SUBSCRIBER")
|
||||
*
|
||||
* @Route("", methods={ "GET" })
|
||||
* @ApiDoc(
|
||||
* resource=true,
|
||||
* section="Receivers",
|
||||
* filters={
|
||||
* {
|
||||
* "name"="filter",
|
||||
* "dataType"="string",
|
||||
* "description"="Receivers name filter",
|
||||
* "requirements"="[\w\s]+"
|
||||
* },
|
||||
* {
|
||||
* "name"="exclude",
|
||||
* "dataType"="string",
|
||||
* "description"="Comma separated list of ids.",
|
||||
* "requirements"="[\w,]+"
|
||||
* }
|
||||
* },
|
||||
* output={
|
||||
* "class"="Pagination<UserBundle\Entity\Recipient\AbstractRecipient>",
|
||||
* "groups"={ "id", "recipient_autocompletion" }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="Receivers successfully funded."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function listAction(Request $request)
|
||||
{
|
||||
$keyword = trim($request->query->get('filter'));
|
||||
$exclude = array_filter(array_map('trim', explode(',', $request->query->get('exclude', ''))));
|
||||
|
||||
/** @var RecipientRepository $repository */
|
||||
$repository = $this->em->getRepository(AbstractRecipient::class);
|
||||
$recipients = $repository->search(
|
||||
$this->getCurrentUser()->getId(),
|
||||
self::DEFAULT_LIMIT,
|
||||
$keyword,
|
||||
$exclude
|
||||
);
|
||||
|
||||
return $this->generateResponse($recipients, 200, [ 'recipient_autocompletion', 'id' ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get email history for specified receiver.
|
||||
*
|
||||
* @Roles("ROLE_SUBSCRIBER")
|
||||
*
|
||||
* @Route("/{id}/emailHistory", methods={ "GET" }, requirements={ "id": "\d+" })
|
||||
* @ApiDoc(
|
||||
* resource=true,
|
||||
* section="Receivers",
|
||||
* filters={
|
||||
* {
|
||||
* "name"="page",
|
||||
* "dataType"="integer",
|
||||
* "description"="Requested page number, start from 1",
|
||||
* "requirements"="\d+",
|
||||
* "default"="1"
|
||||
* },
|
||||
* {
|
||||
* "name"="limit",
|
||||
* "dataType"="integer",
|
||||
* "description"="Max entities per page, default 100",
|
||||
* "requirements"="\d+",
|
||||
* "default"="100"
|
||||
* },
|
||||
* {
|
||||
* "name"="sortField",
|
||||
* "dataType"="string",
|
||||
* "description"="Field name for sorting. Available: name, type, scheduleTime, sentTime",
|
||||
* "requirements"="\w+",
|
||||
* "default"="name",
|
||||
* "required"=false
|
||||
* },
|
||||
* {
|
||||
* "name"="sortDirection",
|
||||
* "dataType"="string",
|
||||
* "description"="Sort direction. Available: asc, desc",
|
||||
* "requirements"="(asc|desc)",
|
||||
* "default"="asc",
|
||||
* "required"=false
|
||||
* },
|
||||
* {
|
||||
* "name"="typeFilter",
|
||||
* "dataType"="string",
|
||||
* "description"="Filter receivers by notification type of specified entity id.",
|
||||
* "requirements"="(alerts|newsletter|all)",
|
||||
* "default"="all",
|
||||
* "required"=false
|
||||
* }
|
||||
* },
|
||||
* output={
|
||||
* "class"="Pagination<UserBundle\Entity\Notification\NotificationSendHistory>",
|
||||
* "groups"={ "id", "history", "schedule" }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="Receivers successfully funded."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Request instance.
|
||||
* @param integer $id A AbstractRecipient entity id.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function historyAction(Request $request, $id)
|
||||
{
|
||||
$recipient = $this->em->find(AbstractRecipient::class, $id);
|
||||
if (! $recipient instanceof AbstractRecipient) {
|
||||
return $this->generateResponse("Can't find receiver with id {$id}.", 404);
|
||||
}
|
||||
|
||||
$sortingOptions = SortingOptions::fromRequest($request, 'sentTime');
|
||||
$typeFilter = $request->query->get('typeFilter', 'all');
|
||||
if (($typeFilter !== 'all') && ! NotificationTypeEnum::isValid($typeFilter)) {
|
||||
return $this->generateResponse("'typeFilter' should be one of all, ". implode(', ', NotificationTypeEnum::getAvailables()));
|
||||
}
|
||||
|
||||
/** @var NotificationSendHistoryRepository $repository */
|
||||
$repository = $this->em->getRepository(NotificationSendHistory::class);
|
||||
$qb = $repository->getListForRecipient($recipient, $sortingOptions, $typeFilter);
|
||||
|
||||
$pagination = $this->paginate(
|
||||
$qb,
|
||||
$request->query->getInt('page', 1),
|
||||
$request->query->getInt('limit', 10)
|
||||
);
|
||||
|
||||
return $this->generateResponse($pagination, 200, [ 'id', 'history', 'schedule' ]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,741 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Controller\V1;
|
||||
|
||||
use ApiBundle\Controller\Annotation\Roles;
|
||||
use AppBundle\Controller\Traits\FormFactoryAwareTrait;
|
||||
use AppBundle\Controller\Traits\TokenStorageAwareTrait;
|
||||
use AppBundle\Controller\V1\AbstractV1Controller;
|
||||
use FOS\UserBundle\Model\UserManagerInterface;
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use UserBundle\Form\ChangePasswordType;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use PaymentBundle\Enum\PaymentGatewayEnum;
|
||||
use UserBundle\Entity\Subscription\OrganizationSubscription;
|
||||
use Stripe\Exception\ApiErrorException;
|
||||
use UserBundle\Entity\Plan;
|
||||
|
||||
/**
|
||||
* Class UserController
|
||||
* @package UserBundle\Controller\V1
|
||||
*
|
||||
* @Route(
|
||||
* "/users",
|
||||
* service="user.controller.user"
|
||||
* )
|
||||
*/
|
||||
class UserController extends AbstractV1Controller
|
||||
{
|
||||
|
||||
use
|
||||
TokenStorageAwareTrait,
|
||||
FormFactoryAwareTrait;
|
||||
|
||||
/**
|
||||
* @var UserManagerInterface
|
||||
*/
|
||||
private $userManager;
|
||||
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* UserController constructor.
|
||||
*
|
||||
* @param TokenStorageInterface $tokenStorage A TokenStorageInterface
|
||||
* instance.
|
||||
* @param FormFactoryInterface $formFactory A FormFactoryInterface instance.
|
||||
* @param UserManagerInterface $userManager A UserManagerInterface instance.
|
||||
*/
|
||||
public function __construct(
|
||||
TokenStorageInterface $tokenStorage,
|
||||
FormFactoryInterface $formFactory,
|
||||
UserManagerInterface $userManager,
|
||||
ContainerInterface $container
|
||||
) {
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->formFactory = $formFactory;
|
||||
$this->userManager = $userManager;
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change password for current user.
|
||||
*
|
||||
* @Roles("ROLE_SUBSCRIBER")
|
||||
*
|
||||
* @Route("/change-password", methods={ "POST" })
|
||||
* @ApiDoc(
|
||||
* resource="Security",
|
||||
* section="User",
|
||||
* input={
|
||||
* "class"="UserBundle\Form\ChangePasswordType",
|
||||
* "name"=false
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @param Request $request A Http Request instance.
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function changePasswordAction(Request $request)
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
$form = $this
|
||||
->createForm(ChangePasswordType::class, $user)
|
||||
->submit($request->request->all());
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->userManager->updateUser($user);
|
||||
|
||||
return $this->generateResponse();
|
||||
}
|
||||
|
||||
return $this->generateResponse($form, 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of subscriber for current master.
|
||||
*
|
||||
* @Roles("ROLE_SUBSCRIBER")
|
||||
*
|
||||
* @Route("/current/restrictions", methods={ "GET" })
|
||||
* @ApiDoc(
|
||||
* resource="Current",
|
||||
* section="User",
|
||||
* output={
|
||||
* "class"="",
|
||||
* "data"={
|
||||
* "limits"={
|
||||
* "dataType"="object",
|
||||
* "required"=true,
|
||||
* "readonly"=true,
|
||||
* "children"={
|
||||
* "searchesPerDay"={
|
||||
* "dataType"="object",
|
||||
* "description"="Searches per day limits",
|
||||
* "required"=true,
|
||||
* "readonly"=true,
|
||||
* "children"={
|
||||
* "limit"={
|
||||
* "dataType"="integer",
|
||||
* "description"="Allowed searches count",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* },
|
||||
* "current"={
|
||||
* "dataType"="integer",
|
||||
* "description"="Used searches count",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* "savedFeeds"={
|
||||
* "dataType"="object",
|
||||
* "description"="Feeds limits",
|
||||
* "required"=true,
|
||||
* "readonly"=true,
|
||||
* "children"={
|
||||
* "limit"={
|
||||
* "dataType"="integer",
|
||||
* "description"="Allowed feeds count",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* },
|
||||
* "current"={
|
||||
* "dataType"="integer",
|
||||
* "description"="Used feeds count",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* "masterAccounts"={
|
||||
* "dataType"="object",
|
||||
* "description"="Master accounts limits",
|
||||
* "required"=true,
|
||||
* "readonly"=true,
|
||||
* "children"={
|
||||
* "limit"={
|
||||
* "dataType"="integer",
|
||||
* "description"="Allowed master accounts count",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* },
|
||||
* "current"={
|
||||
* "dataType"="integer",
|
||||
* "description"="Used master accounts count",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* "subscriberAccounts"={
|
||||
* "dataType"="object",
|
||||
* "description"="Subscriber accounts limits",
|
||||
* "required"=true,
|
||||
* "readonly"=true,
|
||||
* "children"={
|
||||
* "limit"={
|
||||
* "dataType"="integer",
|
||||
* "description"="Allowed subscriber accounts count",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* },
|
||||
* "current"={
|
||||
* "dataType"="integer",
|
||||
* "description"="Used subscriber accounts count",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* "alerts"={
|
||||
* "dataType"="object",
|
||||
* "description"="Alerts limits",
|
||||
* "required"=true,
|
||||
* "readonly"=true,
|
||||
* "children"={
|
||||
* "limit"={
|
||||
* "dataType"="integer",
|
||||
* "description"="Allowed alerts count",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* },
|
||||
* "current"={
|
||||
* "dataType"="integer",
|
||||
* "description"="Used alerts count",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* "newsletters"={
|
||||
* "dataType"="object",
|
||||
* "description"="Newsletters limits",
|
||||
* "required"=true,
|
||||
* "readonly"=true,
|
||||
* "children"={
|
||||
* "limit"={
|
||||
* "dataType"="integer",
|
||||
* "description"="Allowed newsletters count",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* },
|
||||
* "current"={
|
||||
* "dataType"="integer",
|
||||
* "description"="Used newsletters count",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* }
|
||||
* },
|
||||
* "permissions"={
|
||||
* "dataType"="object",
|
||||
* "required"=true,
|
||||
* "readonly"=true,
|
||||
* "children"={
|
||||
* "analytics"={
|
||||
* "dataType"="boolean",
|
||||
* "description"="Can user use analytics or not",
|
||||
* "required"=true,
|
||||
* "readonly"=true
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* statusCodes={
|
||||
* 200="List of restrictions successfully returned."
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @return \ApiBundle\Response\ViewInterface
|
||||
*/
|
||||
public function restrictionsAction()
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
if ($user === null) {
|
||||
return $this->generateResponse([], 403);
|
||||
}
|
||||
|
||||
return $this->generateResponse($user->getRestrictions());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @Route("/update/plan", methods={ "POST" })
|
||||
*
|
||||
* @param Request $request A Http Request instance.
|
||||
*/
|
||||
public function updatePlanAction(Request $request)
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
$data = $request->request->all();
|
||||
$gateway = PaymentGatewayEnum::paypal();
|
||||
$em = $this->container->get('doctrine.orm.default_entity_manager');
|
||||
if (isset(
|
||||
$data['news'],
|
||||
$data['blog'],
|
||||
$data['reddit'],
|
||||
$data['instagram'],
|
||||
$data['twitter'],
|
||||
$data['analytics'],
|
||||
$data['searchesPerDay'],
|
||||
$data['savedFeeds'],
|
||||
$data['masterAccounts'],
|
||||
$data['subscriberAccounts'],
|
||||
$data['webFeeds'],
|
||||
$data['alerts']
|
||||
) &&
|
||||
($data['searchesPerDay'] >= 0) &&
|
||||
($data['savedFeeds'] >= 0) &&
|
||||
($data['masterAccounts'] >= 0) &&
|
||||
($data['subscriberAccounts'] >= 0) &&
|
||||
($data['webFeeds'] >= 0) &&
|
||||
($data['alerts'] >= 0)
|
||||
) {
|
||||
//Call cost calculation plan
|
||||
$costCalculation = $this->container->get('cost.calculation');
|
||||
$response = $costCalculation->costCalculationAction($request, true);
|
||||
$oldPrice = $user->getBillingSubscription()->getPlan()->getPrice();
|
||||
|
||||
//Stripe process
|
||||
$stripe = $this->container->get('stripe.service');
|
||||
$stripe->setApiKey();
|
||||
if (empty($user->getStripeUserId())) {
|
||||
$customer = $stripe->createCustomer(
|
||||
[
|
||||
'email' => $user->getEmail(),
|
||||
'name' => $user->getFirstName().' '.$user->getLastName(),
|
||||
'metadata' => ['paymentMethod' => $data['paymentID']]
|
||||
]
|
||||
);
|
||||
$customerArray = [];
|
||||
if ($customer instanceof ApiErrorException) {
|
||||
$customerArray = ['paymentError' => 1,'data'=>$customer,'message'=>'Customer failed'];
|
||||
return $this->generateResponse($customerArray, 400);
|
||||
}
|
||||
|
||||
if (isset($customer['id'])) {
|
||||
$user->setStripeUserId($customer['id']);
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
//Add card atatch to customer
|
||||
if (isset($data['paymentID']) && !empty($data['paymentID'])) {
|
||||
$cardAttach = $stripe->paymentMethodAttachToCustomer($data['paymentID'],
|
||||
['customer' => $customer['id']]
|
||||
);
|
||||
|
||||
if ($cardAttach instanceof ApiErrorException) {
|
||||
$cardAttachArray = ['paymentError' => 1,'data'=>$cardAttach,'message'=>'Card attached to customer failed'];
|
||||
return $this->generateResponse($cardAttachArray, 500);
|
||||
}
|
||||
}
|
||||
//Add product
|
||||
$product = $stripe->addProduct(
|
||||
[
|
||||
'name' => $user->getCompanyName(),
|
||||
'metadata' => (array)$customer['id']
|
||||
]
|
||||
);
|
||||
if ($product instanceof ApiErrorException) {
|
||||
$productArray = ['paymentError' => 1,'data'=>$product,'message'=>'Product failed'];
|
||||
return $this->generateResponse($productArray, 400);
|
||||
}
|
||||
|
||||
if (isset($product['id'])) {
|
||||
//Call cost calculation plan
|
||||
$costCalculation = $this->container->get('cost.calculation');
|
||||
$response = $costCalculation->costCalculationAction($request, true);
|
||||
|
||||
$price = $stripe->addPrice(
|
||||
[
|
||||
'unit_amount' => isset($response['price']) ? $response['price'] * 100 : 0,
|
||||
'currency' => 'usd',
|
||||
'recurring' => ['interval' => 'month'],
|
||||
'product' => $product['id']
|
||||
]
|
||||
);
|
||||
if ($price instanceof ApiErrorException) {
|
||||
$priceArray = ['paymentError' => 1,'data'=>$price,'message'=>'Price add failed'];
|
||||
return $this->generateResponse($priceArray, 400);
|
||||
}
|
||||
|
||||
//Plan subscription code
|
||||
if (isset($price['id'])) {
|
||||
//Add plan
|
||||
$subscription = $stripe->createSubscription(
|
||||
[
|
||||
'customer' => $customer['id'],
|
||||
'items' => [['price' => $price['id']]],
|
||||
'default_payment_method' => $data['paymentID']
|
||||
]
|
||||
);
|
||||
if ($subscription instanceof ApiErrorException) {
|
||||
$subscriptionArray = ['paymentError' => 1,'data'=>$subscription,'message'=>'Subscribtion failed'];
|
||||
return $this->generateResponse($subscriptionArray, 400);
|
||||
}
|
||||
//update customer metadata
|
||||
$customer = $stripe->updateCustomer($customer['id'],
|
||||
[
|
||||
'metadata' => [
|
||||
'paymentMethod' => $data['paymentID'],
|
||||
'productId' => $product['id'],
|
||||
'priceId' => $price['id'],
|
||||
'subscriptionId' => $subscription['id'],
|
||||
'subStartDate' => $subscription['current_period_start'],
|
||||
'subEndDate' => $subscription['current_period_end'],
|
||||
]
|
||||
]
|
||||
);
|
||||
$customerArray = [];
|
||||
if ($customer instanceof ApiErrorException) {
|
||||
$customerArray = ['paymentError' => 1,'data'=>$customer,'message'=>'Customer add meta data failed'];
|
||||
return $this->generateResponse($customerArray, 400);
|
||||
}
|
||||
|
||||
$plan = $user->getBillingSubscription()->getPlan();
|
||||
$plan->setTitle($user->getCompanyName())
|
||||
->setInnerName('Starter')
|
||||
->setPrice(isset($response['price']) ? $response['price'] : 0)
|
||||
->setNews($data['news'])
|
||||
->setBlog($data['blog'])
|
||||
->setReddit($data['reddit'])
|
||||
->setInstagram($data['instagram'])
|
||||
->setTwitter($data['twitter'])
|
||||
->setAnalytics($data['analytics'])
|
||||
->setSearchesPerDay($data['searchesPerDay'])
|
||||
->setSavedFeeds($data['savedFeeds'])
|
||||
->setMasterAccounts($data['masterAccounts'])
|
||||
->setSubscriberAccounts($data['subscriberAccounts'])
|
||||
->setWebFeeds($data['webFeeds'])
|
||||
->setUser($user)
|
||||
->setAlerts($data['alerts']);
|
||||
$em->persist($plan);
|
||||
$em->flush();
|
||||
|
||||
|
||||
$subscriptionObj = $user->getBillingSubscription();
|
||||
$subscriptionObj->setGateway($gateway);
|
||||
$subscriptionObj->setStartDate(new \DateTime('@' . $subscription['current_period_start']));
|
||||
$subscriptionObj->setEndDate(new \DateTime('@' . $subscription['current_period_end']));
|
||||
$em->persist($subscriptionObj);
|
||||
$em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if ($response['price'] < $oldPrice) {
|
||||
$planNew = new Plan();
|
||||
$planNew->setTitle($user->getCompanyName());
|
||||
$planNew->setInnerName('Starter');
|
||||
$planNew->setPrice(isset($response['price']) ? $response['price'] : 0);
|
||||
$planNew->setNews($data['news']);
|
||||
$planNew->setBlog($data['blog']);
|
||||
$planNew->setReddit($data['reddit']);
|
||||
$planNew->setInstagram($data['instagram']);
|
||||
$planNew->setTwitter($data['twitter']);
|
||||
$planNew->setAnalytics($data['analytics']);
|
||||
$planNew->setSearchesPerDay($data['searchesPerDay']);
|
||||
$planNew->setSavedFeeds($data['savedFeeds']);
|
||||
$planNew->setMasterAccounts($data['masterAccounts']);
|
||||
$planNew->setSubscriberAccounts($data['subscriberAccounts']);
|
||||
$planNew->setWebFeeds($data['webFeeds']);
|
||||
$planNew->setAlerts($data['alerts']);
|
||||
$planNew->setUser($user);
|
||||
$planNew->setIsPlanDowngrade(true);
|
||||
$em->persist($planNew);
|
||||
$em->flush();
|
||||
|
||||
$subscription = $user->getBillingSubscription();
|
||||
$subscription->setIsPlanDowngrade(true);
|
||||
$em->persist($subscription);
|
||||
$em->flush();
|
||||
|
||||
$customer = $stripe->getCustomer(
|
||||
$user->getStripeUserId()
|
||||
);
|
||||
$customerArray = [];
|
||||
if ($customer instanceof ApiErrorException) {
|
||||
$customerArray = ['paymentError' => 1,'data'=>$customer,'message'=>'Customer not found'];
|
||||
return $this->generateResponse($customerArray, 400);
|
||||
}
|
||||
if (isset($customer['id']) && isset($data['paymentID']) && !empty($data['paymentID'])) {
|
||||
//Add card atatch to customer
|
||||
$cardAttach = $stripe->paymentMethodAttachToCustomer($data['paymentID'],
|
||||
['customer' => $customer['id']]
|
||||
);
|
||||
|
||||
if ($cardAttach instanceof ApiErrorException) {
|
||||
$cardAttachArray = ['paymentError' => 1,'data'=>$cardAttach,'message'=>'Card update attached to customer failed'];
|
||||
return $this->generateResponse($cardAttachArray, 500);
|
||||
}
|
||||
//Card detach to customer
|
||||
$cardDetachPaymentMethod = $stripe->paymentMethodDetachToCustomer($customer['metadata']['paymentMethod']
|
||||
);
|
||||
if ($cardDetachPaymentMethod instanceof ApiErrorException) {
|
||||
$cardDetachArray = ['paymentError' => 1,'data'=>$cardDetachPaymentMethod,'message'=>'Card detach to customer failed'];
|
||||
return $this->generateResponse($cardDetachArray, 500);
|
||||
}
|
||||
//update customer metadata
|
||||
$customer = $stripe->updateCustomer($customer['id'],
|
||||
[
|
||||
'metadata' => [
|
||||
'paymentMethod' => isset($data['paymentID']) ? $data['paymentID'] : $customer['metadata']['paymentMethod'],
|
||||
]
|
||||
]
|
||||
);
|
||||
$customerArray = [];
|
||||
if ($customer instanceof ApiErrorException) {
|
||||
$customerArray = ['paymentError' => 1,'data'=>$customer,'message'=>'Customer update meta data failed'];
|
||||
return $this->generateResponse($customerArray, 400);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
$customer = $stripe->getCustomer(
|
||||
$user->getStripeUserId()
|
||||
);
|
||||
$customerArray = [];
|
||||
if ($customer instanceof ApiErrorException) {
|
||||
$customerArray = ['paymentError' => 1,'data'=>$customer,'message'=>'Customer not found'];
|
||||
return $this->generateResponse($customerArray, 400);
|
||||
}
|
||||
if (isset($customer['id'])) {
|
||||
//Add card atatch to customer
|
||||
if (isset($data['paymentID']) && !empty($data['paymentID'])) {
|
||||
$cardAttach = $stripe->paymentMethodAttachToCustomer($data['paymentID'],
|
||||
['customer' => $customer['id']]
|
||||
);
|
||||
|
||||
if ($cardAttach instanceof ApiErrorException) {
|
||||
$cardAttachArray = ['paymentError' => 1,'data'=>$cardAttach,'message'=>'Card update attached to customer failed'];
|
||||
return $this->generateResponse($cardAttachArray, 500);
|
||||
}
|
||||
//Card detach to customer
|
||||
$cardDetachPaymentMethod = $stripe->paymentMethodDetachToCustomer($customer['metadata']['paymentMethod']
|
||||
);
|
||||
if ($cardDetachPaymentMethod instanceof ApiErrorException) {
|
||||
$cardDetachArray = ['paymentError' => 1,'data'=>$cardDetachPaymentMethod,'message'=>'Card detach to customer failed'];
|
||||
return $this->generateResponse($cardDetachArray, 500);
|
||||
}
|
||||
}
|
||||
if (isset($customer['metadata']['productId'])) {
|
||||
|
||||
$price = $stripe->addPrice(
|
||||
[
|
||||
'unit_amount' => isset($response['price']) ? $response['price'] * 100 : 0,
|
||||
'currency' => 'usd',
|
||||
'recurring' => ['interval' => 'month'],
|
||||
'product' => $customer['metadata']['productId']
|
||||
]
|
||||
);
|
||||
if ($price instanceof ApiErrorException) {
|
||||
$priceArray = ['paymentError' => 1,'data'=>$price,'message'=>'Price not found'];
|
||||
return $this->generateResponse($priceArray, 400);
|
||||
}
|
||||
|
||||
//Plan subscription code
|
||||
if (isset($price['id'])) {
|
||||
//Add subscription
|
||||
$subscription = $stripe->getSubscription(
|
||||
$customer['metadata']['subscriptionId']
|
||||
);
|
||||
|
||||
if ($subscription instanceof ApiErrorException) {
|
||||
$subscriptionArray = ['paymentError' => 1,'data'=>$subscription,'message'=>'Subscribtion get failed'];
|
||||
return $this->generateResponse($subscriptionArray, 400);
|
||||
}
|
||||
|
||||
if (isset($subscription['id'])) {
|
||||
//Add subscription item
|
||||
$subscriptionItem = $stripe->updateSubscriptionItem($subscription['items']['data'][0]['id'],
|
||||
[
|
||||
'price' => $price['id'],
|
||||
]
|
||||
);
|
||||
if ($subscriptionItem instanceof ApiErrorException) {
|
||||
$subscriptionItemArray = ['paymentError' => 1,'data'=>$subscriptionItem,'message'=>'Subscribtion Item failed'];
|
||||
return $this->generateResponse($subscriptionItemArray, 400);
|
||||
}
|
||||
}
|
||||
|
||||
//update customer metadata
|
||||
$customer = $stripe->updateCustomer($customer['id'],
|
||||
[
|
||||
'metadata' => [
|
||||
'paymentMethod' => isset($data['paymentID']) ? $data['paymentID'] : $customer['metadata']['paymentMethod'],
|
||||
'priceId' => $price['id'],
|
||||
'subscriptionId' => $subscription['id'],
|
||||
'subStartDate' => $subscription['current_period_start'],
|
||||
'subEndDate' => $subscription['current_period_end'],
|
||||
]
|
||||
]
|
||||
);
|
||||
$customerArray = [];
|
||||
if ($customer instanceof ApiErrorException) {
|
||||
$customerArray = ['paymentError' => 1,'data'=>$customer,'message'=>'Customer update meta data failed'];
|
||||
return $this->generateResponse($customerArray, 400);
|
||||
}
|
||||
$plan = $user->getBillingSubscription()->getPlan();
|
||||
$plan->setTitle($user->getCompanyName())
|
||||
->setInnerName('Starter')
|
||||
->setPrice(isset($response['price']) ? $response['price'] : 0)
|
||||
->setNews($data['news'])
|
||||
->setBlog($data['blog'])
|
||||
->setReddit($data['reddit'])
|
||||
->setInstagram($data['instagram'])
|
||||
->setTwitter($data['twitter'])
|
||||
->setAnalytics($data['analytics'])
|
||||
->setSearchesPerDay($data['searchesPerDay'])
|
||||
->setSavedFeeds($data['savedFeeds'])
|
||||
->setMasterAccounts($data['masterAccounts'])
|
||||
->setSubscriberAccounts($data['subscriberAccounts'])
|
||||
->setWebFeeds($data['webFeeds'])
|
||||
->setUser($user)
|
||||
->setAlerts($data['alerts']);
|
||||
$em->persist($plan);
|
||||
$em->flush();
|
||||
|
||||
$user->getBillingSubscription()->setStartDate(new \DateTime('@' . $subscription['current_period_start']));
|
||||
$user->getBillingSubscription()->setEndDate(new \DateTime('@' . $subscription['current_period_end']));
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $this->generateResponse([
|
||||
'success' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @Route("/cancel/plan", methods={ "POST" })
|
||||
*
|
||||
* @param Request $request A Http Request instance.
|
||||
*/
|
||||
public function cancelSubscriptionAction(Request $request)
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
//Stripe process
|
||||
$stripe = $this->container->get('stripe.service');
|
||||
$stripe->setApiKey();
|
||||
$em = $this->container->get('doctrine.orm.default_entity_manager');
|
||||
|
||||
$customer = $stripe->getCustomer(
|
||||
$user->getStripeUserId()
|
||||
);
|
||||
$customerArray = [];
|
||||
if ($customer instanceof ApiErrorException) {
|
||||
$customerArray = ['paymentError' => 1,'data'=>$customer,'message'=>'Customer not found'];
|
||||
return $this->generateResponse($customerArray, 400);
|
||||
}
|
||||
if (isset($customer['id'])) {
|
||||
$updateSubscription = $stripe->updateSubscription($customer['metadata']['subscriptionId'],
|
||||
[
|
||||
'cancel_at_period_end' => true,
|
||||
]
|
||||
);
|
||||
if ($updateSubscription instanceof ApiErrorException) {
|
||||
$updateSubscriptionArray = ['paymentError' => 1,'data'=>$updateSubscription,'message'=>'Cancel subscription'];
|
||||
return $this->generateResponse($updateSubscriptionArray, 500);
|
||||
}
|
||||
$user->getBillingSubscription()->setIsSubscriptionCancelled(true);
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
return $this->generateResponse([
|
||||
'success' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @Route("/card/change", methods={ "POST" })
|
||||
*
|
||||
* @param Request $request A Http Request instance.
|
||||
*/
|
||||
public function changeCardAction(Request $request)
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
if (!empty($user->getStripeUserId())) {
|
||||
$customerStripeId = $user->getStripeUserId();
|
||||
$stripe = $this->container->get('stripe.service');
|
||||
$stripe->setApiKey();
|
||||
$customer = $stripe->getCustomer(
|
||||
$user->getStripeUserId()
|
||||
);
|
||||
//Card detach to customer
|
||||
$cardDetachPaymentMethod = $stripe->paymentMethodDetachToCustomer($customer['metadata']['paymentMethod']
|
||||
);
|
||||
if ($cardDetachPaymentMethod instanceof ApiErrorException) {
|
||||
$cardDetachArray = ['paymentError' => 1,'data'=>$cardDetachPaymentMethod,'message'=>'Card detach to customer failed'];
|
||||
return $this->generateResponse($cardDetachArray, 500);
|
||||
}
|
||||
//Card attach to customer
|
||||
$cardAttachPaymentMethod = $stripe->paymentMethodAttachToCustomer($request->request->get('paymentID'),
|
||||
['customer' => $customerStripeId]
|
||||
);
|
||||
if ($cardAttachPaymentMethod instanceof ApiErrorException) {
|
||||
$cardAttachArray = ['paymentError' => 1,'data'=>$cardAttachPaymentMethod,'message'=>'Updated card attached to customer failed'];
|
||||
return $this->generateResponse($cardAttachArray, 500);
|
||||
}
|
||||
//update customer metadata
|
||||
$customer = $stripe->updateCustomer($customerStripeId,
|
||||
[
|
||||
'metadata' => ['paymentMethod' => $request->request->get('paymentID')]
|
||||
]
|
||||
);
|
||||
if ($customer instanceof ApiErrorException) {
|
||||
$customerArray = ['paymentError' => 1,'data'=>$customer,'message'=>'Customer update meta data failed'];
|
||||
return $this->generateResponse($customerArray, 400);
|
||||
}
|
||||
$data = ['success' => 1,'message'=>'Card updated successfully to this customer..'];
|
||||
return $this->generateResponse($data,200);
|
||||
}
|
||||
$data = ['error' => 1,'message'=>'Customer not registered in Stripe'];
|
||||
return $this->generateResponse($data, 400);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @Route("/invoices", methods={ "GET" })
|
||||
*
|
||||
* @param Request $request A Http Request instance.
|
||||
*/
|
||||
public function getInvoiceAction(Request $request)
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
$invoices = [];
|
||||
if (!empty($user->getStripeUserId())) {
|
||||
$stripe = $this->container->get('stripe.service');
|
||||
$stripe->setApiKey();
|
||||
$invoices = $stripe->getAllInvoice(['customer' => $user->getStripeUserId()]);
|
||||
if ($invoices instanceof ApiErrorException) {
|
||||
$invoicesArray = ['paymentError' => 1,'data'=>$invoices,'message'=>'List all invoice of customer faild'];
|
||||
return $this->generateResponse($invoicesArray, 400);
|
||||
}
|
||||
}
|
||||
$data = ['success' => 1,'data' => $invoices];
|
||||
return $this->generateResponse($data, 200);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
|
||||
/**
|
||||
* Class RemoveLastLoginListenerPass
|
||||
*
|
||||
* Remove standard LastLoginListener.
|
||||
* We use stateless authentication so last login will be update on each request
|
||||
* to api and this is not right.
|
||||
*
|
||||
* @package UserBundle\DependencyInjection\Compiler
|
||||
*/
|
||||
class RemoveLastLoginListenerPass implements CompilerPassInterface
|
||||
{
|
||||
|
||||
const ID = 'fos_user.security.interactive_login_listener';
|
||||
|
||||
/**
|
||||
* You can modify the container here before it is dumped to PHP code.
|
||||
*
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if ($container->hasDefinition(self::ID)) {
|
||||
$container->removeDefinition(self::ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Doctrine\DBAL\Types;
|
||||
|
||||
use AppBundle\Doctrine\DBAL\Types\AbstractEnumType;
|
||||
use UserBundle\Enum\NotificationTypeEnum;
|
||||
|
||||
/**
|
||||
* Class NotificationTypeEnumType
|
||||
* @package UserBundle\Doctrine\DBAL\Types
|
||||
*/
|
||||
class NotificationTypeEnumType extends AbstractEnumType
|
||||
{
|
||||
|
||||
/**
|
||||
* Return concrete enum class
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getClass()
|
||||
{
|
||||
return NotificationTypeEnum::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'notification_type';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Doctrine\DBAL\Types;
|
||||
|
||||
use AppBundle\Doctrine\DBAL\Types\AbstractEnumType;
|
||||
use UserBundle\Enum\ThemeTypeEnum;
|
||||
|
||||
/**
|
||||
* Class ThemeTypeEnumType
|
||||
* @package UserBundle\Doctrine\DBAL\Types
|
||||
*/
|
||||
class ThemeTypeEnumType extends AbstractEnumType
|
||||
{
|
||||
|
||||
/**
|
||||
* Return concrete enum class
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getClass()
|
||||
{
|
||||
return ThemeTypeEnum::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'theme_type';
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification;
|
||||
|
||||
use ApiBundle\Entity\NormalizableEntityInterface;
|
||||
use ApiBundle\Serializer\Metadata\Metadata;
|
||||
use ApiBundle\Serializer\Metadata\PropertyMetadata;
|
||||
use AppBundle\Entity\BaseEntityTrait;
|
||||
use AppBundle\Entity\EntityInterface;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use UserBundle\Entity\Notification\Schedule\AbstractNotificationSchedule;
|
||||
|
||||
/**
|
||||
* Class NotificationSendHistory
|
||||
*
|
||||
* @ORM\Table(name="notifications_history")
|
||||
* @ORM\Entity(repositoryClass="UserBundle\Repository\NotificationSendHistoryRepository")
|
||||
*/
|
||||
class NotificationSendHistory implements EntityInterface, NormalizableEntityInterface
|
||||
{
|
||||
|
||||
use BaseEntityTrait;
|
||||
|
||||
/**
|
||||
* @var Notification
|
||||
*
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="UserBundle\Entity\Notification\Notification",
|
||||
* inversedBy="history"
|
||||
* )
|
||||
*/
|
||||
private $notification;
|
||||
|
||||
/**
|
||||
* Schedules which trigger notification sending.
|
||||
*
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity="UserBundle\Entity\Notification\Schedule\AbstractNotificationSchedule",
|
||||
* mappedBy="history",
|
||||
* cascade={ "persist", "remove" }
|
||||
* )
|
||||
*/
|
||||
private $schedules;
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*
|
||||
* @ORM\Column(type="datetime")
|
||||
*/
|
||||
private $date;
|
||||
|
||||
/**
|
||||
* NotificationSendHistory constructor.
|
||||
*
|
||||
* @param Notification $notification A Notification entity
|
||||
* instance.
|
||||
* @param AbstractNotificationSchedule[]|array $schedule Array of schedules which
|
||||
* trigger notification
|
||||
* sending.
|
||||
*/
|
||||
public function __construct(Notification $notification, array $schedule)
|
||||
{
|
||||
$this->notification = $notification;
|
||||
|
||||
foreach ($schedule as $item) {
|
||||
$this->addSchedule($item);
|
||||
}
|
||||
$this->date = $notification->getLastSentAt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set notification
|
||||
*
|
||||
* @param Notification $notification A Notification entity instance.
|
||||
*
|
||||
* @return NotificationSendHistory
|
||||
*/
|
||||
public function setNotification(Notification $notification = null)
|
||||
{
|
||||
$this->notification = $notification;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notification
|
||||
*
|
||||
* @return Notification
|
||||
*/
|
||||
public function getNotification()
|
||||
{
|
||||
return $this->notification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add schedule
|
||||
*
|
||||
* @param AbstractNotificationSchedule $schedule A AbstractNotificationSchedule
|
||||
* instance.
|
||||
*
|
||||
* @return NotificationSendHistory
|
||||
*/
|
||||
public function addSchedule(AbstractNotificationSchedule $schedule)
|
||||
{
|
||||
$this->schedules[] = $schedule;
|
||||
$schedule->setHistory($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove schedule
|
||||
*
|
||||
* @param AbstractNotificationSchedule $schedule A AbstractNotificationSchedule
|
||||
* instance.
|
||||
*
|
||||
* @return NotificationSendHistory
|
||||
*/
|
||||
public function removeSchedule(AbstractNotificationSchedule $schedule)
|
||||
{
|
||||
$this->schedules->removeElement($schedule);
|
||||
$schedule->setHistory(null);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get schedules
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getSchedules()
|
||||
{
|
||||
return $this->schedules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set date
|
||||
*
|
||||
* @param \DateTime $date Sent date.
|
||||
*
|
||||
* @return NotificationSendHistory
|
||||
*/
|
||||
public function setDate(\DateTime $date)
|
||||
{
|
||||
$this->date = $date;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get date
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getDate()
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return metadata for current entity.
|
||||
*
|
||||
* @return \ApiBundle\Serializer\Metadata\Metadata
|
||||
*/
|
||||
public function getMetadata()
|
||||
{
|
||||
return new Metadata(static::class, [
|
||||
PropertyMetadata::createInteger('notification', [ 'history' ])
|
||||
->setField(function () {
|
||||
return $this->notification->getId();
|
||||
}),
|
||||
PropertyMetadata::createString('name', [ 'history' ])
|
||||
->setField(function () {
|
||||
return $this->notification->getName();
|
||||
}),
|
||||
PropertyMetadata::createString('type', [ 'history' ])
|
||||
->setField(function () {
|
||||
return $this->notification->getNotificationType()->getValue();
|
||||
}),
|
||||
PropertyMetadata::createCollection('schedule', AbstractNotificationSchedule::class, [ 'history' ])
|
||||
->setField('schedules'),
|
||||
PropertyMetadata::createDate('date', [ 'history' ]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default normalization groups.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function defaultGroups()
|
||||
{
|
||||
return [ 'id', 'history' ];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification;
|
||||
|
||||
use ApiBundle\Entity\NormalizableEntityInterface;
|
||||
use ApiBundle\Serializer\Metadata\Metadata;
|
||||
use ApiBundle\Serializer\Metadata\PropertyMetadata;
|
||||
use AppBundle\Entity\BaseEntityTrait;
|
||||
use AppBundle\Entity\EntityInterface;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* NotificationTheme
|
||||
*
|
||||
* @ORM\Table(name="notification_themes")
|
||||
* @ORM\Entity(repositoryClass="UserBundle\Repository\NotificationThemeRepository")
|
||||
*/
|
||||
class NotificationTheme implements EntityInterface, NormalizableEntityInterface
|
||||
{
|
||||
|
||||
use BaseEntityTrait;
|
||||
|
||||
/**
|
||||
* Theme name.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var NotificationThemeOptions
|
||||
*
|
||||
* @ORM\Embedded(
|
||||
* class="UserBundle\Entity\Notification\NotificationThemeOptions",
|
||||
* columnPrefix="enhanced_"
|
||||
* )
|
||||
*/
|
||||
private $enhanced;
|
||||
|
||||
/**
|
||||
* @var NotificationThemeOptions
|
||||
*
|
||||
* @ORM\Embedded(
|
||||
* class="UserBundle\Entity\Notification\NotificationThemeOptions",
|
||||
* columnPrefix="plain_"
|
||||
* )
|
||||
*/
|
||||
private $plain;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $published = false;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean", name="`default`")
|
||||
*/
|
||||
private $default = false;
|
||||
|
||||
/**
|
||||
* Set name
|
||||
*
|
||||
* @param string $name Theme name.
|
||||
*
|
||||
* @return NotificationTheme
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set enhanced
|
||||
*
|
||||
* @param NotificationThemeOptions $enhanced A NotificationThemeOptions instance.
|
||||
*
|
||||
* @return NotificationTheme
|
||||
*/
|
||||
public function setEnhanced(NotificationThemeOptions $enhanced)
|
||||
{
|
||||
$this->enhanced = $enhanced;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get enhanced
|
||||
*
|
||||
* @return NotificationThemeOptions
|
||||
*/
|
||||
public function getEnhanced()
|
||||
{
|
||||
return $this->enhanced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set plain
|
||||
*
|
||||
* @param NotificationThemeOptions $plain A NotificationThemeOptions instance.
|
||||
*
|
||||
* @return NotificationTheme
|
||||
*/
|
||||
public function setPlain(NotificationThemeOptions $plain)
|
||||
{
|
||||
$this->plain = $plain;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plainOptions
|
||||
*
|
||||
* @return NotificationThemeOptions
|
||||
*/
|
||||
public function getPlain()
|
||||
{
|
||||
return $this->plain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $published Should this notification be published or not.
|
||||
*
|
||||
* @return NotificationTheme
|
||||
*/
|
||||
public function setPublished($published = true)
|
||||
{
|
||||
$this->published = $published;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isPublished()
|
||||
{
|
||||
return $this->published;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default
|
||||
*
|
||||
* @param boolean $default Set theme as default.
|
||||
*
|
||||
* @return NotificationTheme
|
||||
*/
|
||||
public function setDefault($default = true)
|
||||
{
|
||||
$this->default = $default;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isDefault()
|
||||
{
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return metadata for current entity.
|
||||
*
|
||||
* @return \ApiBundle\Serializer\Metadata\Metadata
|
||||
*/
|
||||
public function getMetadata()
|
||||
{
|
||||
return new Metadata(static::class, [
|
||||
PropertyMetadata::createInteger('id', [ 'id' ]),
|
||||
PropertyMetadata::createString('name', [ 'notification_theme', 'notification_theme_list' ]),
|
||||
PropertyMetadata::createBoolean('published', [ 'notification_theme' ]),
|
||||
PropertyMetadata::createObject('enhanced', [ 'notification_theme' ])
|
||||
->setField('enhanced')
|
||||
->setActualType(NotificationThemeOptions::class),
|
||||
PropertyMetadata::createObject('plain', [ 'notification_theme' ])
|
||||
->setField('plain')
|
||||
->setActualType(NotificationThemeOptions::class),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default normalization groups.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function defaultGroups()
|
||||
{
|
||||
return [ 'id', 'notification_theme' ];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use UserBundle\Entity\Notification\ThemeOption\ThemeOptionColors;
|
||||
use UserBundle\Entity\Notification\ThemeOption\ThemeOptionColorsBackground;
|
||||
use UserBundle\Entity\Notification\ThemeOption\ThemeOptionColorsText;
|
||||
use UserBundle\Entity\Notification\ThemeOption\ThemeOptionContent;
|
||||
use UserBundle\Entity\Notification\ThemeOption\ThemeOptionFont;
|
||||
use UserBundle\Entity\Notification\ThemeOption\ThemeOptionFonts;
|
||||
use UserBundle\Entity\Notification\ThemeOption\ThemeOptionHeader;
|
||||
use UserBundle\Entity\Notification\ThemeOption\ThemeOptionHighlightKeywords;
|
||||
use UserBundle\Entity\Notification\ThemeOption\ThemeOptionShowInfo;
|
||||
use UserBundle\Enum\FontFamilyEnum;
|
||||
use UserBundle\Enum\ThemeOptionExtractEnum;
|
||||
use UserBundle\Enum\ThemeOptionsTableOfContentsEnum;
|
||||
use UserBundle\Enum\ThemeOptionsUserCommentsEnum;
|
||||
|
||||
/**
|
||||
* NotificationThemeOptions
|
||||
*
|
||||
* @ORM\Embeddable
|
||||
*/
|
||||
class NotificationThemeOptions
|
||||
{
|
||||
|
||||
const DEFAULT_HEADER_SIZE = 18;
|
||||
const DEFAULT_TABLE_OF_CONTENTS_SIZE = 12;
|
||||
const DEFAULT_FEED_TITLE_SIZE = 12;
|
||||
const DEFAULT_ARTICLE_HEADLINE_SIZE = 16;
|
||||
const DEFAULT_SOURCE_SIZE = 12;
|
||||
const DEFAULT_AUTHOR_SIZE = 12;
|
||||
const DEFAULT_DATE_SIZE = 12;
|
||||
const DEFAULT_ARTICLE_CONTENT_SIZE = 12;
|
||||
|
||||
/**
|
||||
* Text which locate just after header but before content.
|
||||
* Contains HTML.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="text")
|
||||
*/
|
||||
private $summary;
|
||||
|
||||
/**
|
||||
* Text which locate before footer just after content.
|
||||
* Contains HTML.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="text")
|
||||
*/
|
||||
private $conclusion;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionHeader
|
||||
*
|
||||
* @ORM\Column(type="object")
|
||||
*/
|
||||
private $header;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionFonts
|
||||
*
|
||||
* @ORM\Column(type="object")
|
||||
*/
|
||||
private $fonts;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionContent
|
||||
*
|
||||
* @ORM\Column(type="object")
|
||||
*/
|
||||
private $content;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionColors
|
||||
*
|
||||
* @ORM\Column(type="object")
|
||||
*/
|
||||
private $colors;
|
||||
|
||||
/**
|
||||
* NotificationThemeOptions constructor.
|
||||
*
|
||||
* @param string $summary Summary text.
|
||||
* @param string $conclusion Conclusion text.
|
||||
* @param ThemeOptionHeader $header A ThemeOptionHeader instance.
|
||||
* @param ThemeOptionFonts $fonts A ThemeOptionFonts instance.
|
||||
* @param ThemeOptionContent $content A ThemeOptionContent instance.
|
||||
* @param ThemeOptionColors $colors A ThemeOptionColors instance.
|
||||
*/
|
||||
public function __construct(
|
||||
$summary,
|
||||
$conclusion,
|
||||
ThemeOptionHeader $header,
|
||||
ThemeOptionFonts $fonts,
|
||||
ThemeOptionContent $content,
|
||||
ThemeOptionColors $colors
|
||||
) {
|
||||
$this->summary = trim($summary);
|
||||
$this->conclusion = trim($conclusion);
|
||||
$this->header = $header;
|
||||
$this->fonts = $fonts;
|
||||
$this->content = $content;
|
||||
$this->colors = $colors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return static
|
||||
*/
|
||||
public static function createDefault()
|
||||
{
|
||||
return new static(
|
||||
'',
|
||||
'',
|
||||
new ThemeOptionHeader(
|
||||
ThemeOptionHeader::DEFAULT_IMAGE,
|
||||
'',
|
||||
'Newsletter'
|
||||
),
|
||||
new ThemeOptionFonts(
|
||||
new ThemeOptionFont(FontFamilyEnum::arial(), self::DEFAULT_HEADER_SIZE),
|
||||
new ThemeOptionFont(FontFamilyEnum::arial(), self::DEFAULT_TABLE_OF_CONTENTS_SIZE),
|
||||
new ThemeOptionFont(FontFamilyEnum::arial(), self::DEFAULT_FEED_TITLE_SIZE),
|
||||
new ThemeOptionFont(FontFamilyEnum::arial(), self::DEFAULT_ARTICLE_HEADLINE_SIZE),
|
||||
new ThemeOptionFont(FontFamilyEnum::arial(), self::DEFAULT_SOURCE_SIZE),
|
||||
new ThemeOptionFont(FontFamilyEnum::arial(), self::DEFAULT_AUTHOR_SIZE),
|
||||
new ThemeOptionFont(FontFamilyEnum::arial(), self::DEFAULT_DATE_SIZE),
|
||||
new ThemeOptionFont(FontFamilyEnum::arial(), self::DEFAULT_ARTICLE_CONTENT_SIZE)
|
||||
),
|
||||
new ThemeOptionContent(
|
||||
new ThemeOptionHighlightKeywords(),
|
||||
new ThemeOptionShowInfo(
|
||||
ThemeOptionsUserCommentsEnum::no(),
|
||||
ThemeOptionsTableOfContentsEnum::simple()
|
||||
),
|
||||
'en',
|
||||
ThemeOptionExtractEnum::context()
|
||||
),
|
||||
new ThemeOptionColors(
|
||||
new ThemeOptionColorsBackground(),
|
||||
new ThemeOptionColorsText()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSummary()
|
||||
{
|
||||
return $this->summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasSummary()
|
||||
{
|
||||
return $this->summary !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $summary Summary text.
|
||||
*
|
||||
* @return NotificationThemeOptions
|
||||
*/
|
||||
public function setSummary($summary)
|
||||
{
|
||||
$this->summary = $summary;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getConclusion()
|
||||
{
|
||||
return $this->conclusion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasConclusion()
|
||||
{
|
||||
return $this->conclusion !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $conclusion Conclusion text.
|
||||
*
|
||||
* @return NotificationThemeOptions
|
||||
*/
|
||||
public function setConclusion($conclusion)
|
||||
{
|
||||
$this->conclusion = $conclusion;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionHeader
|
||||
*/
|
||||
public function getHeader()
|
||||
{
|
||||
return $this->header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionHeader $header A ThemeOptionHeader instance.
|
||||
*
|
||||
* @return NotificationThemeOptions
|
||||
*/
|
||||
public function setHeader(ThemeOptionHeader $header)
|
||||
{
|
||||
$this->header = $header;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionFonts
|
||||
*/
|
||||
public function getFonts()
|
||||
{
|
||||
return $this->fonts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionFonts $fonts A ThemeOptionFonts instance.
|
||||
*
|
||||
* @return NotificationThemeOptions
|
||||
*/
|
||||
public function setFonts(ThemeOptionFonts $fonts)
|
||||
{
|
||||
$this->fonts = $fonts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionContent
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionContent $content A ThemeOptionContent instance.
|
||||
*
|
||||
* @return NotificationThemeOptions
|
||||
*/
|
||||
public function setContent(ThemeOptionContent $content)
|
||||
{
|
||||
$this->content = $content;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionColors
|
||||
*/
|
||||
public function getColors()
|
||||
{
|
||||
return $this->colors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionColors $colors A ThemeOptionColors instace.
|
||||
*
|
||||
* @return NotificationThemeOptions
|
||||
*/
|
||||
public function setColors(ThemeOptionColors $colors)
|
||||
{
|
||||
$this->colors = $colors;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'summary' => $this->summary,
|
||||
'conclusion' => $this->conclusion,
|
||||
'header' => $this->header->toArray(),
|
||||
'fonts' => $this->fonts->toArray(),
|
||||
'content' => $this->content->toArray(),
|
||||
'colors' => $this->colors->toArray(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\Schedule;
|
||||
|
||||
use ApiBundle\Entity\NormalizableEntityInterface;
|
||||
use AppBundle\Entity\BaseEntityTrait;
|
||||
use AppBundle\Entity\EntityInterface;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\Notification\NotificationSendHistory;
|
||||
|
||||
/**
|
||||
* Class AbstractNotificationSchedule
|
||||
*
|
||||
* @ORM\Table(name="notification_schedule")
|
||||
* @ORM\Entity
|
||||
* @ORM\InheritanceType("SINGLE_TABLE")
|
||||
* @ORM\DiscriminatorColumn(name="type", type="string")
|
||||
* @ORM\DiscriminatorMap({
|
||||
* "daily"="DailyNotificationSchedule",
|
||||
* "weekly"="WeeklyNotificationSchedule",
|
||||
* "monthly"="MonthlyNotificationSchedule"
|
||||
* })
|
||||
*/
|
||||
abstract class AbstractNotificationSchedule implements
|
||||
EntityInterface,
|
||||
NormalizableEntityInterface
|
||||
{
|
||||
|
||||
use BaseEntityTrait;
|
||||
|
||||
/**
|
||||
* @var Notification
|
||||
*
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="UserBundle\Entity\Notification\Notification",
|
||||
* inversedBy="schedules"
|
||||
* )
|
||||
*/
|
||||
private $notification;
|
||||
|
||||
/**
|
||||
* @var NotificationSendHistory
|
||||
*
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="UserBundle\Entity\Notification\NotificationSendHistory",
|
||||
* inversedBy="schedules"
|
||||
* )
|
||||
*/
|
||||
private $history;
|
||||
|
||||
/**
|
||||
* Set notification
|
||||
*
|
||||
* @param Notification $notification A Notification instance.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setNotification(Notification $notification = null)
|
||||
{
|
||||
$this->notification = $notification;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notification
|
||||
*
|
||||
* @return Notification
|
||||
*/
|
||||
public function getNotification()
|
||||
{
|
||||
return $this->notification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set history
|
||||
*
|
||||
* @param NotificationSendHistory $history A NotificationSendHistory instance.
|
||||
*
|
||||
* @return AbstractNotificationSchedule
|
||||
*/
|
||||
public function setHistory(NotificationSendHistory $history = null)
|
||||
{
|
||||
$this->history = $history;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get history
|
||||
*
|
||||
* @return NotificationSendHistory
|
||||
*/
|
||||
public function getHistory()
|
||||
{
|
||||
return $this->history;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute all date's for this schedule in specified period.
|
||||
*
|
||||
* @param \DateTime $start Start of computing period.
|
||||
* @param \DateTime $end End of computing period.
|
||||
*
|
||||
* @return \DateTime[]
|
||||
*/
|
||||
public function computeDates(\DateTime $start, \DateTime $end)
|
||||
{
|
||||
$modifiedStart = clone $start;
|
||||
$modifiedEnd = clone $end;
|
||||
|
||||
$modifiedStart
|
||||
->setTime($modifiedStart->format('H'), $modifiedStart->format('i'), 0);
|
||||
|
||||
// Add 1 seconds in order to catch end date if it should exists in result's.
|
||||
$modifiedEnd
|
||||
->setTime($modifiedEnd->format('H'), $modifiedEnd->format('i'), 1);
|
||||
|
||||
return $this->doComputeDates($modifiedStart, $modifiedEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return key identifier for current schedule.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getKey();
|
||||
|
||||
/**
|
||||
* Compute all date's for this schedule in specified period.
|
||||
*
|
||||
* @param \DateTime $start Start of computing period.
|
||||
* @param \DateTime $end End of computing period.
|
||||
*
|
||||
* @return \DateTime[]
|
||||
*/
|
||||
abstract protected function doComputeDates(\DateTime $start, \DateTime $end);
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\Schedule;
|
||||
|
||||
use ApiBundle\Serializer\Metadata\Metadata;
|
||||
use ApiBundle\Serializer\Metadata\PropertyMetadata;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* Class DailyNotificationSchedule
|
||||
*
|
||||
* @ORM\Entity
|
||||
*/
|
||||
class DailyNotificationSchedule extends AbstractNotificationSchedule
|
||||
{
|
||||
|
||||
const TIME_15_M = '15m';
|
||||
const TIME_30_M = '30m';
|
||||
const TIME_1_H = '1h';
|
||||
const TIME_2_H = '2h';
|
||||
const TIME_3_H = '3h';
|
||||
const TIME_4_H = '4h';
|
||||
const TIME_6_H = '6h';
|
||||
const TIME_12_H = '12h';
|
||||
const TIME_ONCE = 'once';
|
||||
|
||||
const DAYS_ALL = 'all';
|
||||
const DAYS_WEEKDAYS = 'weekdays';
|
||||
const DAYS_WEEKENDS = 'weekends';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(length=5)
|
||||
* @Assert\Choice(callback="getAvailableTime")
|
||||
*/
|
||||
private $time;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(length=9)
|
||||
* @Assert\Choice(callback="getAvailableDays")
|
||||
*/
|
||||
private $days;
|
||||
|
||||
/**
|
||||
* Map between available time values and crontab schedule string.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private static $timeMap = [
|
||||
self::TIME_15_M => 'T15M',
|
||||
self::TIME_30_M => 'T30M',
|
||||
self::TIME_1_H => 'T1H',
|
||||
self::TIME_2_H => 'T2H',
|
||||
self::TIME_3_H => 'T3H',
|
||||
self::TIME_4_H => 'T4H',
|
||||
self::TIME_6_H => 'T6H',
|
||||
self::TIME_12_H => 'T12H',
|
||||
self::TIME_ONCE => '1D',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Get available time values.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getAvailableTime()
|
||||
{
|
||||
return [
|
||||
self::TIME_15_M,
|
||||
self::TIME_30_M,
|
||||
self::TIME_1_H,
|
||||
self::TIME_2_H,
|
||||
self::TIME_3_H,
|
||||
self::TIME_4_H,
|
||||
self::TIME_6_H,
|
||||
self::TIME_12_H,
|
||||
self::TIME_ONCE,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available days values.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getAvailableDays()
|
||||
{
|
||||
return [
|
||||
self::DAYS_ALL,
|
||||
self::DAYS_WEEKDAYS,
|
||||
self::DAYS_WEEKENDS,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set time
|
||||
*
|
||||
* @param string $time One of TIME_ constant's.
|
||||
*
|
||||
* @return DailyNotificationSchedule
|
||||
*/
|
||||
public function setTime($time)
|
||||
{
|
||||
$this->time = $time;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get time
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTime()
|
||||
{
|
||||
return $this->time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set days
|
||||
*
|
||||
* @param string $days One of DAYS_ constant's.
|
||||
*
|
||||
* @return DailyNotificationSchedule
|
||||
*/
|
||||
public function setDays($days)
|
||||
{
|
||||
$this->days = $days;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get days
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDays()
|
||||
{
|
||||
return $this->days;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get entity type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEntityType()
|
||||
{
|
||||
return 'daily';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return metadata for current entity.
|
||||
*
|
||||
* @return \ApiBundle\Serializer\Metadata\Metadata
|
||||
*/
|
||||
public function getMetadata()
|
||||
{
|
||||
return new Metadata(static::class, [
|
||||
PropertyMetadata::createString('time', [ 'schedule' ]),
|
||||
PropertyMetadata::createString('days', [ 'schedule' ]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default normalization groups.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function defaultGroups()
|
||||
{
|
||||
return [ 'schedule' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data Normalized DailyNotificationSchedule.
|
||||
*
|
||||
* @return DailyNotificationSchedule
|
||||
*/
|
||||
public static function denormalize(array $data)
|
||||
{
|
||||
if (! isset($data['time'], $data['days'])) {
|
||||
throw new \LogicException('Normalized DailyNotificationSchedule data must have \'time\' and \'days\' fields.');
|
||||
}
|
||||
|
||||
return DailyNotificationSchedule::create()
|
||||
->setTime($data['time'])
|
||||
->setDays($data['days']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return key identifier for current schedule.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKey()
|
||||
{
|
||||
return sprintf('daily_%s_%s', $this->time, $this->days);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute all date's for this schedule in specified period.
|
||||
*
|
||||
* @param \DateTime $start Start of computing period.
|
||||
* @param \DateTime $end End of computing period.
|
||||
*
|
||||
* @return \DateTime[]
|
||||
*/
|
||||
protected function doComputeDates(\DateTime $start, \DateTime $end)
|
||||
{
|
||||
$period = new \DatePeriod(
|
||||
$start,
|
||||
new \DateInterval('P'. self::$timeMap[$this->time]),
|
||||
$end,
|
||||
\DatePeriod::EXCLUDE_START_DATE
|
||||
);
|
||||
|
||||
$results = [];
|
||||
switch ($this->days) {
|
||||
case self::DAYS_ALL:
|
||||
$results = iterator_to_array($period);
|
||||
break;
|
||||
|
||||
case self::DAYS_WEEKDAYS:
|
||||
/** @var \DateTime $date */
|
||||
foreach ($period as $date) {
|
||||
if ($date->format('N') <= 5) {
|
||||
$results[] = $date;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case self::DAYS_WEEKENDS:
|
||||
/** @var \DateTime $date */
|
||||
foreach ($period as $date) {
|
||||
if ($date->format('N') > 5) {
|
||||
$results[] = $date;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\Schedule;
|
||||
|
||||
use ApiBundle\Serializer\Metadata\Metadata;
|
||||
use ApiBundle\Serializer\Metadata\PropertyMetadata;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* Class MonthlyNotificationSchedule
|
||||
*
|
||||
* @ORM\Entity
|
||||
*/
|
||||
class MonthlyNotificationSchedule extends AbstractNotificationSchedule
|
||||
{
|
||||
|
||||
const DAY_LAST = 'last';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(length=10)
|
||||
* @Assert\Choice(callback="getAvailableDay")
|
||||
*/
|
||||
private $day;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
private $hour;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
private $minute;
|
||||
|
||||
/**
|
||||
* Get available day's.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getAvailableDay()
|
||||
{
|
||||
$days = range(1, 31);
|
||||
$days[] = self::DAY_LAST;
|
||||
|
||||
return $days;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set day
|
||||
*
|
||||
* @param string $day One of DAY_ const's.
|
||||
*
|
||||
* @return MonthlyNotificationSchedule
|
||||
*/
|
||||
public function setDay($day)
|
||||
{
|
||||
$this->day = $day;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get day
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDay()
|
||||
{
|
||||
return $this->day;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set hour
|
||||
*
|
||||
* @param integer $hour Schedule hours.
|
||||
*
|
||||
* @return MonthlyNotificationSchedule
|
||||
*/
|
||||
public function setHour($hour)
|
||||
{
|
||||
$this->hour = $hour;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hour
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getHour()
|
||||
{
|
||||
return $this->hour;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set minutes
|
||||
*
|
||||
* @param integer $minute Schedule minutes.
|
||||
*
|
||||
* @return MonthlyNotificationSchedule
|
||||
*/
|
||||
public function setMinute($minute)
|
||||
{
|
||||
$this->minute = $minute;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get minute
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getMinute()
|
||||
{
|
||||
return $this->minute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get entity type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEntityType()
|
||||
{
|
||||
return 'monthly';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return metadata for current entity.
|
||||
*
|
||||
* @return \ApiBundle\Serializer\Metadata\Metadata
|
||||
*/
|
||||
public function getMetadata()
|
||||
{
|
||||
return new Metadata(static::class, [
|
||||
PropertyMetadata::createString('day', [ 'schedule' ]),
|
||||
PropertyMetadata::createString('hour', [ 'schedule' ]),
|
||||
PropertyMetadata::createString('minute', [ 'schedule' ]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default normalization groups.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function defaultGroups()
|
||||
{
|
||||
return [ 'schedule' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data Normalized MonthlyNotificationSchedule.
|
||||
*
|
||||
* @return MonthlyNotificationSchedule
|
||||
*/
|
||||
public static function denormalize(array $data)
|
||||
{
|
||||
if (! isset($data['day'], $data['hour'], $data['minute'])) {
|
||||
throw new \LogicException('Normalized MonthlyNotificationSchedule data must have \'day\', \'hour\' and \'minute\' fields.');
|
||||
}
|
||||
|
||||
return MonthlyNotificationSchedule::create()
|
||||
->setDay($data['day'])
|
||||
->setHour($data['hour'])
|
||||
->setMinute($data['minute']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return key identifier for current schedule.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKey()
|
||||
{
|
||||
return sprintf(
|
||||
'monthly_%s_%s_%s',
|
||||
$this->day,
|
||||
$this->hour,
|
||||
$this->minute
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute all date's for this schedule in specified period.
|
||||
*
|
||||
* @param \DateTime $start Start of computing period.
|
||||
* @param \DateTime $end End of computing period.
|
||||
*
|
||||
* @return \DateTime[]
|
||||
*/
|
||||
protected function doComputeDates(\DateTime $start, \DateTime $end)
|
||||
{
|
||||
$dates = [];
|
||||
$date = clone $start;
|
||||
|
||||
if ($this->day === self::DAY_LAST) {
|
||||
$date->modify('last day of this month');
|
||||
while ($date <= $end) {
|
||||
$tmp = clone $date;
|
||||
$dates[] = $tmp->setTime($this->hour, $this->minute);
|
||||
$date->modify('last day of next month');
|
||||
}
|
||||
} else {
|
||||
$currentNum = $date->format('j');
|
||||
|
||||
if ($currentNum > $this->day) {
|
||||
$date
|
||||
->modify('first day of next month')
|
||||
->modify(sprintf('%d day', $this->day - 1));
|
||||
} elseif ($currentNum < $this->day) {
|
||||
$date->modify(sprintf('%d day', $this->day - $currentNum));
|
||||
}
|
||||
|
||||
while ($date <= $end) {
|
||||
$tmp = clone $date;
|
||||
$dates[] = $tmp->setTime($this->hour, $this->minute);
|
||||
$date
|
||||
->modify('first day of next month')
|
||||
->modify(sprintf('%d day', $this->day - 1));
|
||||
}
|
||||
}
|
||||
|
||||
return $dates;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\Schedule;
|
||||
|
||||
use ApiBundle\Serializer\Metadata\Metadata;
|
||||
use ApiBundle\Serializer\Metadata\PropertyMetadata;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* Class WeeklyNotificationSchedule
|
||||
*
|
||||
* @ORM\Entity
|
||||
*/
|
||||
class WeeklyNotificationSchedule extends AbstractNotificationSchedule
|
||||
{
|
||||
|
||||
const PERIOD_EVERY = 'every';
|
||||
const PERIOD_FIRST = 'first';
|
||||
const PERIOD_SECOND = 'second';
|
||||
const PERIOD_THIRD = 'third';
|
||||
const PERIOD_FOURTH = 'fourth';
|
||||
const PERIOD_LAST = 'last';
|
||||
|
||||
const DAY_MONDAY = 'monday';
|
||||
const DAY_TUESDAY = 'tuesday';
|
||||
const DAY_WEDNESDAY = 'wednesday';
|
||||
const DAY_THURSDAY = 'thursday';
|
||||
const DAY_FRIDAY = 'friday';
|
||||
const DAY_SATURDAY = 'saturday';
|
||||
const DAY_SUNDAY = 'sunday';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(length=7)
|
||||
* @Assert\Choice(callback="getAvailablePeriod")
|
||||
*/
|
||||
private $period;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(length=10)
|
||||
* @Assert\Choice(callback="getAvailableDay")
|
||||
*/
|
||||
private $day;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
private $hour;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
private $minute;
|
||||
|
||||
/**
|
||||
* Map between day and corntab schedule. Make sense only for PERIOD_EVERY.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
private static $dayMap = [
|
||||
self::DAY_MONDAY => 1,
|
||||
self::DAY_TUESDAY => 2,
|
||||
self::DAY_WEDNESDAY => 3,
|
||||
self::DAY_TUESDAY => 4,
|
||||
self::DAY_FRIDAY => 5,
|
||||
self::DAY_SATURDAY => 6,
|
||||
self::DAY_SUNDAY => 7,
|
||||
];
|
||||
|
||||
/**
|
||||
* Get available period's.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getAvailablePeriod()
|
||||
{
|
||||
return [
|
||||
self::PERIOD_EVERY,
|
||||
self::PERIOD_FIRST,
|
||||
self::PERIOD_SECOND,
|
||||
self::PERIOD_THIRD,
|
||||
self::PERIOD_FOURTH,
|
||||
self::PERIOD_LAST,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available day's.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getAvailableDay()
|
||||
{
|
||||
return [
|
||||
self::DAY_MONDAY,
|
||||
self::DAY_TUESDAY,
|
||||
self::DAY_WEDNESDAY,
|
||||
self::DAY_TUESDAY,
|
||||
self::DAY_FRIDAY,
|
||||
self::DAY_SATURDAY,
|
||||
self::DAY_SUNDAY,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set period
|
||||
*
|
||||
* @param string $period One of PERIOD_ const's.
|
||||
*
|
||||
* @return WeeklyNotificationSchedule
|
||||
*/
|
||||
public function setPeriod($period)
|
||||
{
|
||||
$this->period = $period;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get period
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPeriod()
|
||||
{
|
||||
return $this->period;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set day
|
||||
*
|
||||
* @param string $day One of DAY_ const's.
|
||||
*
|
||||
* @return WeeklyNotificationSchedule
|
||||
*/
|
||||
public function setDay($day)
|
||||
{
|
||||
$this->day = $day;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get day
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDay()
|
||||
{
|
||||
return $this->day;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set hour
|
||||
*
|
||||
* @param integer $hour Schedule hours.
|
||||
*
|
||||
* @return WeeklyNotificationSchedule
|
||||
*/
|
||||
public function setHour($hour)
|
||||
{
|
||||
$this->hour = $hour;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hour
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getHour()
|
||||
{
|
||||
return $this->hour;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set minute
|
||||
*
|
||||
* @param integer $minute Schedule minute.
|
||||
*
|
||||
* @return WeeklyNotificationSchedule
|
||||
*/
|
||||
public function setMinute($minute)
|
||||
{
|
||||
$this->minute = $minute;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get minute
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getMinute()
|
||||
{
|
||||
return $this->minute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get entity type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEntityType()
|
||||
{
|
||||
return 'weekly';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return metadata for current entity.
|
||||
*
|
||||
* @return \ApiBundle\Serializer\Metadata\Metadata
|
||||
*/
|
||||
public function getMetadata()
|
||||
{
|
||||
return new Metadata(static::class, [
|
||||
PropertyMetadata::createString('period', [ 'schedule' ]),
|
||||
PropertyMetadata::createString('day', [ 'schedule' ]),
|
||||
PropertyMetadata::createString('hour', [ 'schedule' ]),
|
||||
PropertyMetadata::createString('minute', [ 'schedule' ]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default normalization groups.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function defaultGroups()
|
||||
{
|
||||
return [ 'schedule' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data Normalized WeeklyNotificationSchedule.
|
||||
*
|
||||
* @return WeeklyNotificationSchedule
|
||||
*/
|
||||
public static function denormalize(array $data)
|
||||
{
|
||||
if (! isset($data['period'], $data['day'], $data['hour'], $data['minute'])) {
|
||||
throw new \LogicException('Normalized WeeklyNotificationSchedule data must have \'period\', \'day\', \'hour\' and \'minute\' fields.');
|
||||
}
|
||||
|
||||
return WeeklyNotificationSchedule::create()
|
||||
->setPeriod($data['period'])
|
||||
->setDay($data['day'])
|
||||
->setHour($data['hour'])
|
||||
->setMinute($data['minute']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return key identifier for current schedule.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKey()
|
||||
{
|
||||
return sprintf(
|
||||
'weekly_%s_%s_%s_%s',
|
||||
$this->period,
|
||||
$this->day,
|
||||
$this->hour,
|
||||
$this->minute
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute all date's for this schedule in specified period.
|
||||
*
|
||||
* @param \DateTime $start Start of computing period.
|
||||
* @param \DateTime $end End of computing period.
|
||||
*
|
||||
* @return \DateTime[]
|
||||
*/
|
||||
protected function doComputeDates(\DateTime $start, \DateTime $end)
|
||||
{
|
||||
$dates = [];
|
||||
$date = clone $start;
|
||||
|
||||
if ($this->period === self::PERIOD_EVERY) {
|
||||
//
|
||||
// Process every weekdays days.
|
||||
//
|
||||
|
||||
if ($date->format('N') !== self::$dayMap[$this->day]) {
|
||||
//
|
||||
// If start date is not required weekday we should proceed to next
|
||||
// required weekday.
|
||||
//
|
||||
$date->modify('next '. $this->day);
|
||||
}
|
||||
while ($date <= $end) {
|
||||
$tmp = clone $date;
|
||||
$dates[] = $tmp->setTime($this->hour, $this->minute);
|
||||
$date->modify('next '. $this->day);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Process specified weekday like second monday, third friday and etc.
|
||||
//
|
||||
|
||||
$date->modify(sprintf(
|
||||
'%s %s of this month',
|
||||
$this->period,
|
||||
$this->day
|
||||
));
|
||||
while ($date <= $end) {
|
||||
$tmp = clone $date;
|
||||
$dates[] = $tmp->setTime($this->hour, $this->minute);
|
||||
$date->modify(sprintf(
|
||||
'%s %s of next month',
|
||||
$this->period,
|
||||
$this->day
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return $dates;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\ThemeOption;
|
||||
|
||||
/**
|
||||
* Class ThemeOptionColors
|
||||
* @package UserBundle\Entity\Notification\ThemeOption
|
||||
*/
|
||||
class ThemeOptionColors implements \Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ThemeOptionColorsBackground
|
||||
*/
|
||||
private $background;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionColorsText
|
||||
*/
|
||||
private $text;
|
||||
|
||||
/**
|
||||
* ThemeOptionColors constructor.
|
||||
*
|
||||
* @param ThemeOptionColorsBackground $background A ThemeOptionColorsBackground
|
||||
* instance.
|
||||
* @param ThemeOptionColorsText $text A ThemeOptionColorsText
|
||||
* instance.
|
||||
*/
|
||||
public function __construct(
|
||||
ThemeOptionColorsBackground $background,
|
||||
ThemeOptionColorsText $text
|
||||
) {
|
||||
$this->background = $background;
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionColorsBackground
|
||||
*/
|
||||
public function getBackground()
|
||||
{
|
||||
return $this->background;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionColorsBackground $background A ThemeOptionColorsBackground
|
||||
* instance.
|
||||
*
|
||||
* @return ThemeOptionColors
|
||||
*/
|
||||
public function setBackground(ThemeOptionColorsBackground $background)
|
||||
{
|
||||
$this->background = $background;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionColorsText
|
||||
*/
|
||||
public function getText()
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionColorsText $text A ThemeOptionColorsText instance.
|
||||
*
|
||||
* @return ThemeOptionColors
|
||||
*/
|
||||
public function setText(ThemeOptionColorsText $text)
|
||||
{
|
||||
$this->text = $text;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of object.
|
||||
*
|
||||
* @return string the string representation of the object or null.
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize([
|
||||
$this->background,
|
||||
$this->text,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the object
|
||||
*
|
||||
* @param string $serialized The string representation of the object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$data = unserialize($serialized);
|
||||
|
||||
$this->background = $data[0];
|
||||
$this->text = $data[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'background' => $this->background->toArray(),
|
||||
'text' => $this->text->toArray(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\ThemeOption;
|
||||
|
||||
/**
|
||||
* Class ThemeOptionColorsBackground
|
||||
* @package UserBundle\Entity\Notification\ThemeOption
|
||||
*/
|
||||
class ThemeOptionColorsBackground implements \Serializable
|
||||
{
|
||||
|
||||
const DEFAULT_HEADER = 'rgba(36, 37, 37, 1)';
|
||||
const DEFAULT_EMAIL_BODY = 'rgba(244, 244, 245, 1)';
|
||||
const DEFAULT_ACCENT = 'rgba(109, 110, 113, 1)';
|
||||
|
||||
/**
|
||||
* CSS RGBA.
|
||||
*
|
||||
* ```
|
||||
* rgba(125, 125, 125, 0.5);
|
||||
* ```
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $header;
|
||||
|
||||
/**
|
||||
* CSS RGBA.
|
||||
*
|
||||
* ```
|
||||
* rgba(125, 125, 125, 0.5);
|
||||
* ```
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $emailBody;
|
||||
|
||||
/**
|
||||
* CSS RGBA.
|
||||
*
|
||||
* ```
|
||||
* rgba(125, 125, 125, 0.5);
|
||||
* ```
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $accent;
|
||||
|
||||
/**
|
||||
* ThemeOptionColorsBackground constructor.
|
||||
*
|
||||
* @param string $header Header background color.
|
||||
* @param string $emailBody Email body color.
|
||||
* @param string $accent Accent color.
|
||||
*/
|
||||
public function __construct(
|
||||
$header = self::DEFAULT_HEADER,
|
||||
$emailBody = self::DEFAULT_EMAIL_BODY,
|
||||
$accent = self::DEFAULT_ACCENT
|
||||
) {
|
||||
$this->header = trim($header);
|
||||
$this->emailBody = trim($emailBody);
|
||||
$this->accent = trim($accent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getHeader()
|
||||
{
|
||||
return $this->header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $header Header background color.
|
||||
*
|
||||
* @return ThemeOptionColorsBackground
|
||||
*/
|
||||
public function setHeader($header)
|
||||
{
|
||||
$this->header = $header;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getEmailBody()
|
||||
{
|
||||
return $this->emailBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $emailBody Email body color.
|
||||
*
|
||||
* @return ThemeOptionColorsBackground
|
||||
*/
|
||||
public function setEmailBody($emailBody)
|
||||
{
|
||||
$this->emailBody = $emailBody;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAccent()
|
||||
{
|
||||
return $this->accent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accent Accent background color.
|
||||
*
|
||||
* @return ThemeOptionColorsBackground
|
||||
*/
|
||||
public function setAccent($accent)
|
||||
{
|
||||
$this->accent = $accent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of object.
|
||||
*
|
||||
* @return string the string representation of the object or null.
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize([
|
||||
$this->header,
|
||||
$this->emailBody,
|
||||
$this->accent,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the object
|
||||
*
|
||||
* @param string $serialized The string representation of the object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$data = unserialize($serialized);
|
||||
|
||||
$this->header = $data[0];
|
||||
$this->emailBody = $data[1];
|
||||
$this->accent = $data[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'header' => $this->header,
|
||||
'emailBody' => $this->emailBody,
|
||||
'accent' => $this->accent,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\ThemeOption;
|
||||
|
||||
/**
|
||||
* Class ThemeOptionColorsText
|
||||
* @package UserBundle\Entity\Notification\ThemeOption
|
||||
*/
|
||||
class ThemeOptionColorsText implements \Serializable
|
||||
{
|
||||
|
||||
const DEFAULT_HEADER = 'rgba(255, 255, 255, 1)';
|
||||
const DEFAULT_ARTICLE_HEADLINE = 'rgba(0, 147, 176, 1)';
|
||||
const DEFAULT_ARTICLE_CONTENT = 'rgba(102, 102, 102, 1)';
|
||||
const DEFAULT_AUTHOR = 'rgba(143, 43, 140, 1)';
|
||||
const DEFAULT_PUBLISH_DATE = 'rgba(109, 110, 113, 1)';
|
||||
const DEFAULT_SOURCE = 'rgba(82, 83, 85, 1)';
|
||||
|
||||
/**
|
||||
* CSS RGBA.
|
||||
*
|
||||
* ```
|
||||
* rgba(125, 125, 125, 0.5);
|
||||
* ```
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $header;
|
||||
|
||||
/**
|
||||
* CSS RGBA.
|
||||
*
|
||||
* ```
|
||||
* rgba(125, 125, 125, 0.5);
|
||||
* ```
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $articleHeadline;
|
||||
|
||||
/**
|
||||
* CSS RGBA.
|
||||
*
|
||||
* ```
|
||||
* rgba(125, 125, 125, 0.5);
|
||||
* ```
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $articleContent;
|
||||
|
||||
/**
|
||||
* CSS RGBA.
|
||||
*
|
||||
* ```
|
||||
* rgba(125, 125, 125, 0.5);
|
||||
* ```
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $author;
|
||||
|
||||
/**
|
||||
* CSS RGBA.
|
||||
*
|
||||
* ```
|
||||
* rgba(125, 125, 125, 0.5);
|
||||
* ```
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $publishDate;
|
||||
|
||||
/**
|
||||
* CSS RGBA.
|
||||
*
|
||||
* ```
|
||||
* rgba(125, 125, 125, 0.5);
|
||||
* ```
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $source;
|
||||
|
||||
/**
|
||||
* ThemeOptionColorsText constructor.
|
||||
*
|
||||
* @param string $header Header text color.
|
||||
* @param string $articleHeadline Article headline text color.
|
||||
* @param string $articleContent Article content text color.
|
||||
* @param string $author Author text color.
|
||||
* @param string $publishDate Publish date text color.
|
||||
* @param string $source Source text color.
|
||||
*/
|
||||
public function __construct(
|
||||
$header = self::DEFAULT_HEADER,
|
||||
$articleHeadline = self::DEFAULT_ARTICLE_HEADLINE,
|
||||
$articleContent = self::DEFAULT_ARTICLE_CONTENT,
|
||||
$author = self::DEFAULT_AUTHOR,
|
||||
$publishDate = self::DEFAULT_PUBLISH_DATE,
|
||||
$source = self::DEFAULT_SOURCE
|
||||
) {
|
||||
$this->header = trim($header);
|
||||
$this->articleHeadline = trim($articleHeadline);
|
||||
$this->articleContent = trim($articleContent);
|
||||
$this->author = trim($author);
|
||||
$this->publishDate = trim($publishDate);
|
||||
$this->source = trim($source);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getHeader()
|
||||
{
|
||||
return $this->header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $header Header text color.
|
||||
*
|
||||
* @return ThemeOptionColorsText
|
||||
*/
|
||||
public function setHeader($header)
|
||||
{
|
||||
$this->header = $header;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getArticleHeadline()
|
||||
{
|
||||
return $this->articleHeadline;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $articleHeadline Article headline text color.
|
||||
*
|
||||
* @return ThemeOptionColorsText
|
||||
*/
|
||||
public function setArticleHeadline($articleHeadline)
|
||||
{
|
||||
$this->articleHeadline = $articleHeadline;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getArticleContent()
|
||||
{
|
||||
return $this->articleContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $articleContent Article content text color.
|
||||
*
|
||||
* @return ThemeOptionColorsText
|
||||
*/
|
||||
public function setArticleContent($articleContent)
|
||||
{
|
||||
$this->articleContent = $articleContent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthor()
|
||||
{
|
||||
return $this->author;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $author Author text color.
|
||||
*
|
||||
* @return ThemeOptionColorsText
|
||||
*/
|
||||
public function setAuthor($author)
|
||||
{
|
||||
$this->author = $author;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPublishDate()
|
||||
{
|
||||
return $this->publishDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $publishDate Publish date text color.
|
||||
*
|
||||
* @return ThemeOptionColorsText
|
||||
*/
|
||||
public function setPublishDate($publishDate)
|
||||
{
|
||||
$this->publishDate = $publishDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSource()
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $source Source text color.
|
||||
*
|
||||
* @return ThemeOptionColorsText
|
||||
*/
|
||||
public function setSource($source)
|
||||
{
|
||||
$this->source = $source;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of object.
|
||||
*
|
||||
* @return string the string representation of the object or null.
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize([
|
||||
$this->header,
|
||||
$this->articleHeadline,
|
||||
$this->articleContent,
|
||||
$this->author,
|
||||
$this->publishDate,
|
||||
$this->source,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the object
|
||||
*
|
||||
* @param string $serialized The string representation of the object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$data = unserialize($serialized);
|
||||
|
||||
$this->header = $data[0];
|
||||
$this->articleHeadline = $data[1];
|
||||
$this->articleContent = $data[2];
|
||||
$this->author = $data[3];
|
||||
$this->publishDate = $data[4];
|
||||
$this->source = $data[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'header' => $this->header,
|
||||
'articleHeadline' => $this->articleHeadline,
|
||||
'articleContent' => $this->articleContent,
|
||||
'author' => $this->author,
|
||||
'publishDate' => $this->publishDate,
|
||||
'source' => $this->source,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\ThemeOption;
|
||||
|
||||
use UserBundle\Enum\ThemeOptionExtractEnum;
|
||||
|
||||
/**
|
||||
* Class ThemeOptionContent
|
||||
* @package UserBundle\Entity\Notification\ThemeOption
|
||||
*/
|
||||
class ThemeOptionContent implements \Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ThemeOptionHighlightKeywords
|
||||
*/
|
||||
private $highlightKeywords;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionShowInfo
|
||||
*/
|
||||
private $showInfo;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $language;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionExtractEnum
|
||||
*/
|
||||
private $extract;
|
||||
|
||||
/**
|
||||
* ThemeOptionContent constructor.
|
||||
*
|
||||
* @param ThemeOptionHighlightKeywords $highlightKeywords A ThemeOptionHighlightKeywords
|
||||
* instance.
|
||||
* @param ThemeOptionShowInfo $showInfo A ThemeOptionShowInfo
|
||||
* instance.
|
||||
* @param string $language Selected notification
|
||||
* language.
|
||||
* @param ThemeOptionExtractEnum $extract A ThemeOptionExtractEnum
|
||||
* instance.
|
||||
*/
|
||||
public function __construct(
|
||||
ThemeOptionHighlightKeywords $highlightKeywords,
|
||||
ThemeOptionShowInfo $showInfo,
|
||||
$language,
|
||||
ThemeOptionExtractEnum $extract
|
||||
) {
|
||||
$this->highlightKeywords = $highlightKeywords;
|
||||
$this->showInfo = $showInfo;
|
||||
$this->language = trim($language);
|
||||
$this->extract = $extract;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionHighlightKeywords
|
||||
*/
|
||||
public function getHighlightKeywords()
|
||||
{
|
||||
return $this->highlightKeywords;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionHighlightKeywords $highlightKeywords A ThemeOptionHighlightKeywords
|
||||
* instance.
|
||||
*
|
||||
* @return ThemeOptionContent
|
||||
*/
|
||||
public function setHighlightKeywords(ThemeOptionHighlightKeywords $highlightKeywords)
|
||||
{
|
||||
$this->highlightKeywords = $highlightKeywords;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionShowInfo
|
||||
*/
|
||||
public function getShowInfo()
|
||||
{
|
||||
return $this->showInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionShowInfo $showInfo A ThemeOptionShowInfo instance.
|
||||
*
|
||||
* @return ThemeOptionContent
|
||||
*/
|
||||
public function setShowInfo(ThemeOptionShowInfo $showInfo)
|
||||
{
|
||||
$this->showInfo = $showInfo;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLanguage()
|
||||
{
|
||||
return $this->language;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $language Selected theme language.
|
||||
*
|
||||
* @return ThemeOptionContent
|
||||
*/
|
||||
public function setLanguage($language)
|
||||
{
|
||||
$this->language = $language;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionExtractEnum
|
||||
*/
|
||||
public function getExtract()
|
||||
{
|
||||
return $this->extract;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionExtractEnum $extract A ThemeOptionExtractEnum
|
||||
* instance.
|
||||
*
|
||||
* @return ThemeOptionContent
|
||||
*/
|
||||
public function setExtract(ThemeOptionExtractEnum $extract)
|
||||
{
|
||||
$this->extract = $extract;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of object.
|
||||
*
|
||||
* @return string the string representation of the object or null.
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize([
|
||||
$this->highlightKeywords,
|
||||
$this->showInfo,
|
||||
$this->language,
|
||||
$this->extract,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the object
|
||||
*
|
||||
* @param string $serialized The string representation of the object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$data = unserialize($serialized);
|
||||
|
||||
$this->highlightKeywords = $data[0];
|
||||
$this->showInfo = $data[1];
|
||||
$this->language = $data[2];
|
||||
$this->extract = $data[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'highlightKeywords' => $this->highlightKeywords->toArray(),
|
||||
'showInfo' => $this->showInfo->toArray(),
|
||||
'language' => $this->language,
|
||||
'extract' => $this->extract->getValue(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\ThemeOption;
|
||||
|
||||
use UserBundle\Enum\FontFamilyEnum;
|
||||
|
||||
/**
|
||||
* Class ThemeOptionFont
|
||||
* @package UserBundle\Entity\Notification\ThemeOption
|
||||
*/
|
||||
class ThemeOptionFont implements \Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
* @var FontFamilyEnum
|
||||
*/
|
||||
private $family;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*/
|
||||
private $size;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionFontStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* ThemeOptionFont constructor.
|
||||
*
|
||||
* @param FontFamilyEnum $family Font family name.
|
||||
* @param integer $size Font size.
|
||||
* @param ThemeOptionFontStyle $style A ThemeOptionFontStyle instance.
|
||||
*/
|
||||
public function __construct(FontFamilyEnum $family, $size, ThemeOptionFontStyle $style = null)
|
||||
{
|
||||
$this->family = $family;
|
||||
$this->size = (int) trim($size);
|
||||
$this->style = $style === null ? new ThemeOptionFontStyle() : $style;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FontFamilyEnum
|
||||
*/
|
||||
public function getFamily()
|
||||
{
|
||||
return $this->family;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FontFamilyEnum $family Font family name.
|
||||
*
|
||||
* @return ThemeOptionFont
|
||||
*/
|
||||
public function setFamily(FontFamilyEnum $family)
|
||||
{
|
||||
$this->family = $family;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $size Font size.
|
||||
*
|
||||
* @return ThemeOptionFont
|
||||
*/
|
||||
public function setSize($size)
|
||||
{
|
||||
$this->size = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionFontStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionFontStyle $style A ThemeOptionFontStyle instance.
|
||||
*
|
||||
* @return ThemeOptionFont
|
||||
*/
|
||||
public function setStyle(ThemeOptionFontStyle $style)
|
||||
{
|
||||
$this->style = $style;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of object.
|
||||
*
|
||||
* @return string the string representation of the object or null.
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize([
|
||||
$this->family,
|
||||
$this->size,
|
||||
$this->style,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the object
|
||||
*
|
||||
* @param string $serialized The string representation of the object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$data = unserialize($serialized);
|
||||
|
||||
$this->family = $data[0];
|
||||
$this->size = $data[1];
|
||||
$this->style = $data[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'family' => $this->family->getCss(),
|
||||
'size' => $this->size,
|
||||
'style' => $this->style->toArray(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\ThemeOption;
|
||||
|
||||
/**
|
||||
* Class ThemeOptionFontStyle
|
||||
* @package UserBundle\Entity\Notification\ThemeOption
|
||||
*/
|
||||
class ThemeOptionFontStyle implements \Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $bold;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $italic;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $underline;
|
||||
|
||||
/**
|
||||
* ThemeOptionFontStyle constructor.
|
||||
*
|
||||
* @param boolean $bold Should be text bold or not.
|
||||
* @param boolean $italic Should be text italic or not.
|
||||
* @param boolean $underline Should be text underlined or not.
|
||||
*/
|
||||
public function __construct($bold = false, $italic = false, $underline = false)
|
||||
{
|
||||
$this->bold = (bool) $bold;
|
||||
$this->italic = (bool) $italic;
|
||||
$this->underline = (bool) $underline;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isBold()
|
||||
{
|
||||
return $this->bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $bold Should be text bold or not.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setBold($bold = true)
|
||||
{
|
||||
$this->bold = $bold;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isItalic()
|
||||
{
|
||||
return $this->italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $italic Should be text italic or not.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setItalic($italic = true)
|
||||
{
|
||||
$this->italic = $italic;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isUnderline()
|
||||
{
|
||||
return $this->underline;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $underline Should be text underlined or not.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setUnderline($underline = true)
|
||||
{
|
||||
$this->underline = $underline;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of object.
|
||||
*
|
||||
* @return string the string representation of the object or null.
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize([
|
||||
$this->bold,
|
||||
$this->italic,
|
||||
$this->underline,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the object
|
||||
*
|
||||
* @param string $serialized The string representation of the object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$data = unserialize($serialized);
|
||||
|
||||
$this->bold = $data[0];
|
||||
$this->italic = $data[1];
|
||||
$this->underline = $data[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'bold' => $this->bold,
|
||||
'italic' => $this->italic,
|
||||
'underline' => $this->underline,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\ThemeOption;
|
||||
|
||||
/**
|
||||
* Class ThemeOptionFonts
|
||||
* @package UserBundle\Entity\Notification\ThemeOption
|
||||
*/
|
||||
class ThemeOptionFonts implements \Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ThemeOptionFont
|
||||
*/
|
||||
private $header;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionFont
|
||||
*/
|
||||
private $tableOfContents;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionFont
|
||||
*/
|
||||
private $feedTitle;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionFont
|
||||
*/
|
||||
private $articleHeadline;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionFont
|
||||
*/
|
||||
private $source;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionFont
|
||||
*/
|
||||
private $author;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionFont
|
||||
*/
|
||||
private $date;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionFont
|
||||
*/
|
||||
private $articleContent;
|
||||
|
||||
/**
|
||||
* ThemeOptionFonts constructor.
|
||||
*
|
||||
* @param ThemeOptionFont $header A ThemeOptionFont instance.
|
||||
* @param ThemeOptionFont $tableOfContents A ThemeOptionFont instance.
|
||||
* @param ThemeOptionFont $feedTitle A ThemeOptionFont instance.
|
||||
* @param ThemeOptionFont $articleHeadline A ThemeOptionFont instance.
|
||||
* @param ThemeOptionFont $source A ThemeOptionFont instance.
|
||||
* @param ThemeOptionFont $author A ThemeOptionFont instance.
|
||||
* @param ThemeOptionFont $date A ThemeOptionFont instance.
|
||||
* @param ThemeOptionFont $articleContent A ThemeOptionFont instance.
|
||||
*/
|
||||
public function __construct(
|
||||
ThemeOptionFont $header,
|
||||
ThemeOptionFont $tableOfContents,
|
||||
ThemeOptionFont $feedTitle,
|
||||
ThemeOptionFont $articleHeadline,
|
||||
ThemeOptionFont $source,
|
||||
ThemeOptionFont $author,
|
||||
ThemeOptionFont $date,
|
||||
ThemeOptionFont $articleContent
|
||||
) {
|
||||
$this->header = $header;
|
||||
$this->tableOfContents = $tableOfContents;
|
||||
$this->feedTitle = $feedTitle;
|
||||
$this->articleHeadline = $articleHeadline;
|
||||
$this->source = $source;
|
||||
$this->author = $author;
|
||||
$this->date = $date;
|
||||
$this->articleContent = $articleContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionFont
|
||||
*/
|
||||
public function getHeader()
|
||||
{
|
||||
return $this->header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionFont $header A ThemeOptionFont instance.
|
||||
*
|
||||
* @return ThemeOptionFonts
|
||||
*/
|
||||
public function setHeader(ThemeOptionFont $header)
|
||||
{
|
||||
$this->header = $header;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionFont
|
||||
*/
|
||||
public function getTableOfContents()
|
||||
{
|
||||
return $this->tableOfContents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionFont $tableOfContents A ThemeOptionFont instance.
|
||||
*
|
||||
* @return ThemeOptionFonts
|
||||
*/
|
||||
public function setTableOfContents(ThemeOptionFont $tableOfContents)
|
||||
{
|
||||
$this->tableOfContents = $tableOfContents;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionFont
|
||||
*/
|
||||
public function getFeedTitle()
|
||||
{
|
||||
return $this->feedTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionFont $feedTitle A ThemeOptionFont instance.
|
||||
*
|
||||
* @return ThemeOptionFonts
|
||||
*/
|
||||
public function setFeedTitle(ThemeOptionFont $feedTitle)
|
||||
{
|
||||
$this->feedTitle = $feedTitle;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionFont
|
||||
*/
|
||||
public function getArticleHeadline()
|
||||
{
|
||||
return $this->articleHeadline;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionFont $articleHeadline A ThemeOptionFont instance.
|
||||
*
|
||||
* @return ThemeOptionFonts
|
||||
*/
|
||||
public function setArticleHeadline(ThemeOptionFont $articleHeadline)
|
||||
{
|
||||
$this->articleHeadline = $articleHeadline;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionFont A ThemeOptionFont instance.
|
||||
*/
|
||||
public function getSource()
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionFont $source A ThemeOptionFont instance.
|
||||
*
|
||||
* @return ThemeOptionFonts
|
||||
*/
|
||||
public function setSource(ThemeOptionFont $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionFont
|
||||
*/
|
||||
public function getAuthor()
|
||||
{
|
||||
return $this->author;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionFont $author A ThemeOptionFont instance.
|
||||
*
|
||||
* @return ThemeOptionFonts
|
||||
*/
|
||||
public function setAuthor(ThemeOptionFont $author)
|
||||
{
|
||||
$this->author = $author;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionFont
|
||||
*/
|
||||
public function getDate()
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionFont $date A ThemeOptionFont instance.
|
||||
*
|
||||
* @return ThemeOptionFonts
|
||||
*/
|
||||
public function setDate(ThemeOptionFont $date)
|
||||
{
|
||||
$this->date = $date;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionFont
|
||||
*/
|
||||
public function getArticleContent()
|
||||
{
|
||||
return $this->articleContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionFont $articleContent A ThemeOptionFont instance.
|
||||
*
|
||||
* @return ThemeOptionFonts
|
||||
*/
|
||||
public function setArticleContent(ThemeOptionFont $articleContent)
|
||||
{
|
||||
$this->articleContent = $articleContent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of object.
|
||||
*
|
||||
* @return string the string representation of the object or null.
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize([
|
||||
$this->header,
|
||||
$this->tableOfContents,
|
||||
$this->feedTitle,
|
||||
$this->articleHeadline,
|
||||
$this->source,
|
||||
$this->author,
|
||||
$this->date,
|
||||
$this->articleContent,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the object
|
||||
*
|
||||
* @param string $serialized The string representation of the object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$data = unserialize($serialized);
|
||||
|
||||
$this->header = $data[0];
|
||||
$this->tableOfContents = $data[1];
|
||||
$this->feedTitle = $data[2];
|
||||
$this->articleHeadline = $data[3];
|
||||
$this->source = $data[4];
|
||||
$this->author = $data[5];
|
||||
$this->date = $data[6];
|
||||
$this->articleContent = $data[7];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'header' => $this->header->toArray(),
|
||||
'tableOfContents' => $this->tableOfContents->toArray(),
|
||||
'feedTitle' => $this->feedTitle->toArray(),
|
||||
'articleHeadline' => $this->articleHeadline->toArray(),
|
||||
'source' => $this->source->toArray(),
|
||||
'author' => $this->author->toArray(),
|
||||
'date' => $this->date->toArray(),
|
||||
'articleContent' => $this->articleContent->toArray(),
|
||||
];
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\ThemeOption;
|
||||
|
||||
/**
|
||||
* Class ThemeOptionHighlightKeywords
|
||||
* @package UserBundle\Entity\Notification\ThemeOption
|
||||
*/
|
||||
class ThemeOptionHighlightKeywords implements \Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $highlight;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $bold;
|
||||
|
||||
/**
|
||||
* CSS RGBA.
|
||||
*
|
||||
* ```
|
||||
* rgba(125, 125, 125, 0.5);
|
||||
* ```
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $color;
|
||||
|
||||
/**
|
||||
* ThemeOptionHighlightKeywords constructor.
|
||||
*
|
||||
* @param boolean $highlight Should system highlight keywords or not.
|
||||
* @param boolean $bold Should highlight keyword be bold or not.
|
||||
* @param string $color Highlight color.
|
||||
*/
|
||||
public function __construct($highlight = true, $bold = true, $color = 'rgba(255, 255, 0, 1)')
|
||||
{
|
||||
$this->highlight = (bool) $highlight;
|
||||
$this->bold = (bool) $bold;
|
||||
$this->color = trim($color);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isHighlight()
|
||||
{
|
||||
return $this->highlight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $highlight Should system highlight keywords or not.
|
||||
*
|
||||
* @return ThemeOptionHighlightKeywords
|
||||
*/
|
||||
public function setHighlight($highlight = true)
|
||||
{
|
||||
$this->highlight = $highlight;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isBold()
|
||||
{
|
||||
return $this->bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $bold Should highlight keyword be bold or not.
|
||||
*
|
||||
* @return ThemeOptionHighlightKeywords
|
||||
*/
|
||||
public function setBold($bold = true)
|
||||
{
|
||||
$this->bold = $bold;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getColor()
|
||||
{
|
||||
return $this->color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $color Highlight color.
|
||||
*
|
||||
* @return ThemeOptionHighlightKeywords
|
||||
*/
|
||||
public function setColor($color)
|
||||
{
|
||||
$this->color = $color;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of object.
|
||||
*
|
||||
* @return string the string representation of the object or null.
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize([
|
||||
$this->highlight,
|
||||
$this->bold,
|
||||
$this->color,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the object
|
||||
*
|
||||
* @param string $serialized The string representation of the object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$data = unserialize($serialized);
|
||||
|
||||
$this->highlight = $data[0];
|
||||
$this->bold = $data[1];
|
||||
$this->color = $data[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'highlight' => $this->highlight,
|
||||
'bold' => $this->bold,
|
||||
'color' => $this->color,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Notification\ThemeOption;
|
||||
|
||||
use UserBundle\Enum\ThemeOptionsTableOfContentsEnum;
|
||||
use UserBundle\Enum\ThemeOptionsUserCommentsEnum;
|
||||
|
||||
/**
|
||||
* Class ThemeOptionShowInfo
|
||||
* @package UserBundle\Entity\Notification\ThemeOption
|
||||
*/
|
||||
class ThemeOptionShowInfo implements \Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $sourceCountry;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $articleSentiment;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $articleCount;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $images;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $sharingOptions;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $sectionDivider;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionsUserCommentsEnum
|
||||
*/
|
||||
private $userComments;
|
||||
|
||||
/**
|
||||
* @var ThemeOptionsTableOfContentsEnum
|
||||
*/
|
||||
private $tableOfContents;
|
||||
|
||||
/**
|
||||
* ThemeOptionShowInfo constructor.
|
||||
*
|
||||
* @param ThemeOptionsUserCommentsEnum|string $userComments A ThemeOptionsUserCommentsEnum
|
||||
* instance.
|
||||
* @param ThemeOptionsTableOfContentsEnum|string $tableOfContents A ThemeOptionsTableOfContentsEnum
|
||||
* instance.
|
||||
* @param boolean $sourceCountry Show or not source country.
|
||||
* @param boolean $articleSentiment Show or not article sentiment.
|
||||
* @param boolean $articleCount Show or not article count.
|
||||
* @param boolean $images Show or not article images.
|
||||
* @param boolean $sharingOptions Show or not sharing options.
|
||||
* @param boolean $sectionDivider Show or not section divider.
|
||||
*/
|
||||
public function __construct(
|
||||
$userComments,
|
||||
$tableOfContents,
|
||||
$sourceCountry = false,
|
||||
$articleSentiment = true,
|
||||
$articleCount = true,
|
||||
$images = true,
|
||||
$sharingOptions = true,
|
||||
$sectionDivider = false
|
||||
) {
|
||||
$this->sourceCountry = (bool) $sourceCountry;
|
||||
$this->articleSentiment = (bool) $articleSentiment;
|
||||
$this->articleCount = (bool) $articleCount;
|
||||
$this->images = (bool) $images;
|
||||
$this->sharingOptions = (bool) $sharingOptions;
|
||||
$this->sectionDivider = (bool) $sectionDivider;
|
||||
$this->setUserComments($userComments);
|
||||
$this->setTableOfContents($tableOfContents);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isSourceCountry()
|
||||
{
|
||||
return $this->sourceCountry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $sourceCountry Show source country.
|
||||
*
|
||||
* @return ThemeOptionShowInfo
|
||||
*/
|
||||
public function setSourceCountry($sourceCountry = true)
|
||||
{
|
||||
$this->sourceCountry = $sourceCountry;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isArticleSentiment()
|
||||
{
|
||||
return $this->articleSentiment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $articleSentiment Show article sentiment.
|
||||
*
|
||||
* @return ThemeOptionShowInfo
|
||||
*/
|
||||
public function setArticleSentiment($articleSentiment = true)
|
||||
{
|
||||
$this->articleSentiment = $articleSentiment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isArticleCount()
|
||||
{
|
||||
return $this->articleCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $articleCount Show article count.
|
||||
*
|
||||
* @return ThemeOptionShowInfo
|
||||
*/
|
||||
public function setArticleCount($articleCount = true)
|
||||
{
|
||||
$this->articleCount = $articleCount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isImages()
|
||||
{
|
||||
return $this->images;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $images Show or not articles images.
|
||||
*
|
||||
* @return ThemeOptionShowInfo
|
||||
*/
|
||||
public function setImages($images = true)
|
||||
{
|
||||
$this->images = $images;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isSharingOptions()
|
||||
{
|
||||
return $this->sharingOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $sharingOptions Show or not sharing options.
|
||||
*
|
||||
* @return ThemeOptionShowInfo
|
||||
*/
|
||||
public function setSharingOptions($sharingOptions = true)
|
||||
{
|
||||
$this->sharingOptions = $sharingOptions;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isSectionDivider()
|
||||
{
|
||||
return $this->sectionDivider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $sectionDivider Show section divider or not.
|
||||
*
|
||||
* @return ThemeOptionShowInfo
|
||||
*/
|
||||
public function setSectionDivider($sectionDivider = true)
|
||||
{
|
||||
$this->sectionDivider = $sectionDivider;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionsUserCommentsEnum
|
||||
*/
|
||||
public function getUserComments()
|
||||
{
|
||||
return $this->userComments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionsUserCommentsEnum|string $userComments A ThemeOptionsUserCommentsEnum
|
||||
* instance.
|
||||
*
|
||||
* @return ThemeOptionShowInfo
|
||||
*/
|
||||
public function setUserComments($userComments)
|
||||
{
|
||||
if (is_string($userComments)) {
|
||||
$userComments = new ThemeOptionsUserCommentsEnum($userComments);
|
||||
}
|
||||
$this->userComments = $userComments;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ThemeOptionsTableOfContentsEnum
|
||||
*/
|
||||
public function getTableOfContents()
|
||||
{
|
||||
return $this->tableOfContents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ThemeOptionsTableOfContentsEnum|string $tableOfContents A ThemeOptionsTableOfContentsEnum
|
||||
* instance.
|
||||
*
|
||||
* @return ThemeOptionShowInfo
|
||||
*/
|
||||
public function setTableOfContents($tableOfContents)
|
||||
{
|
||||
if (is_string($tableOfContents)) {
|
||||
$tableOfContents = new ThemeOptionsTableOfContentsEnum($tableOfContents);
|
||||
}
|
||||
$this->tableOfContents = $tableOfContents;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of object.
|
||||
*
|
||||
* @return string the string representation of the object or null.
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize([
|
||||
$this->sourceCountry,
|
||||
$this->articleSentiment,
|
||||
$this->articleCount,
|
||||
$this->images,
|
||||
$this->sharingOptions,
|
||||
$this->sectionDivider,
|
||||
$this->userComments,
|
||||
$this->tableOfContents,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the object
|
||||
*
|
||||
* @param string $serialized The string representation of the object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$data = unserialize($serialized);
|
||||
|
||||
$this->sourceCountry = $data[0];
|
||||
$this->articleSentiment = $data[1];
|
||||
$this->articleCount = $data[2];
|
||||
$this->images = $data[3];
|
||||
$this->sharingOptions = $data[4];
|
||||
$this->sectionDivider = $data[5];
|
||||
$this->userComments = $data[6];
|
||||
$this->tableOfContents = $data[7];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'sourceCountry' => $this->sourceCountry,
|
||||
'articleSentiment' => $this->articleSentiment,
|
||||
'articleCount' => $this->articleCount,
|
||||
'images' => $this->images,
|
||||
'sharingOptions' => $this->sharingOptions,
|
||||
'sectionDivider' => $this->sectionDivider,
|
||||
'userComments' => $this->userComments->getValue(),
|
||||
'tableOfContents' => $this->tableOfContents->getValue(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity;
|
||||
|
||||
use AppBundle\Entity\BaseEntityTrait;
|
||||
use AppBundle\Entity\EntityInterface;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use UserBundle\Entity\Subscription\OrganizationSubscription;
|
||||
|
||||
/**
|
||||
* Organization
|
||||
*
|
||||
* @ORM\Table(name="organizations")
|
||||
* @ORM\Entity(repositoryClass="UserBundle\Repository\OrganizationRepository")
|
||||
*
|
||||
* @UniqueEntity(fields={"name"})
|
||||
*/
|
||||
class Organization implements EntityInterface
|
||||
{
|
||||
|
||||
use BaseEntityTrait;
|
||||
|
||||
/**
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity="UserBundle\Entity\Subscription\OrganizationSubscription",
|
||||
* mappedBy="organization",
|
||||
* cascade={ "persist", "remove" }
|
||||
* )
|
||||
*/
|
||||
private $subscriptions;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column
|
||||
*
|
||||
* @Assert\NotBlank
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name A Organization name.
|
||||
*
|
||||
* @return Organization
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string) $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->subscriptions = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subscription
|
||||
*
|
||||
* @param OrganizationSubscription $subscription A new OrganizationSubscription
|
||||
* entity instance.
|
||||
*
|
||||
* @return Organization
|
||||
*/
|
||||
public function addSubscription(OrganizationSubscription $subscription)
|
||||
{
|
||||
$this->subscriptions[] = $subscription;
|
||||
$subscription->setOrganization($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove subscription
|
||||
*
|
||||
* @param OrganizationSubscription $subscription A removed OrganizationSubscription
|
||||
* entity instance.
|
||||
*
|
||||
* @return Organization
|
||||
*/
|
||||
public function removeSubscription(OrganizationSubscription $subscription)
|
||||
{
|
||||
$this->subscriptions->removeElement($subscription);
|
||||
$subscription->setOrganization(null);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subscriptions
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getSubscriptions()
|
||||
{
|
||||
return $this->subscriptions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,532 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity;
|
||||
|
||||
use ApiBundle\Serializer\Metadata\Metadata;
|
||||
use ApiBundle\Serializer\Metadata\PropertyMetadata;
|
||||
use AppBundle\Entity\BaseEntityTrait;
|
||||
use ApiBundle\Entity\NormalizableEntityInterface;
|
||||
use AppBundle\Entity\EntityInterface;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use UserBundle\Entity\Subscription\AbstractSubscription;
|
||||
use UserBundle\Entity\Traits\LimitAwareTrait;
|
||||
use UserBundle\Enum\AppPermissionEnum;
|
||||
|
||||
/**
|
||||
* Plan
|
||||
*
|
||||
* @ORM\Table(name="plan")
|
||||
* @ORM\Entity(repositoryClass="UserBundle\Repository\PlanRepository")
|
||||
*/
|
||||
class Plan implements EntityInterface, NormalizableEntityInterface
|
||||
{
|
||||
|
||||
use
|
||||
BaseEntityTrait,
|
||||
LimitAwareTrait;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column
|
||||
*
|
||||
* @Assert\NotBlank
|
||||
*/
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column
|
||||
*
|
||||
* @Assert\NotBlank
|
||||
*/
|
||||
private $innerName;
|
||||
|
||||
/**
|
||||
* One Plan has Many Subscriptions.
|
||||
*
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity="UserBundle\Entity\Subscription\AbstractSubscription",
|
||||
* mappedBy="plan"
|
||||
* )
|
||||
*/
|
||||
private $subscriptions;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*
|
||||
* @ORM\Column(name="price", type="float")
|
||||
*
|
||||
* @Assert\NotBlank
|
||||
* @Assert\GreaterThanOrEqual(value=0.0)
|
||||
*/
|
||||
private $price;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $analytics = false;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $is_default = false;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $news = false;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $blog = false;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $reddit = false;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $instagram = false;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $twitter = false;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $isPlanDowngrade = false;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="UserBundle\Entity\User", inversedBy="plan")
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
*/
|
||||
private $user;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->subscriptions = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name
|
||||
*
|
||||
* @param string $title A Human readable plan name.
|
||||
*
|
||||
* @return Plan
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getInnerName()
|
||||
{
|
||||
return $this->innerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $innerName A plan inner name used for binding with plans on
|
||||
* payment gateways.
|
||||
*
|
||||
* @return Plan
|
||||
*/
|
||||
public function setInnerName($innerName)
|
||||
{
|
||||
$this->innerName = $innerName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set price
|
||||
*
|
||||
* @param float $price Monthly plan price.
|
||||
*
|
||||
* @return Plan
|
||||
*/
|
||||
public function setPrice($price)
|
||||
{
|
||||
$this->price = $price;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get price
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getPrice()
|
||||
{
|
||||
return $this->price;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that current plan is free.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isFree()
|
||||
{
|
||||
return $this->price <= 0.000001;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isAnalytics()
|
||||
{
|
||||
return $this->analytics;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isDefault()
|
||||
{
|
||||
return $this->is_default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $analytics Allow to use analytics or not.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setAnalytics($analytics)
|
||||
{
|
||||
$this->analytics = $analytics;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param boolean $is_default Allow to use default or not.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setIsDefault(bool $is_default)
|
||||
{
|
||||
$this->is_default = $is_default;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get specified permission.
|
||||
*
|
||||
* @param AppPermissionEnum $appPermission A requested permission name.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getPermission(AppPermissionEnum $appPermission)
|
||||
{
|
||||
return $this->{$appPermission->getValue()};
|
||||
}
|
||||
|
||||
/**
|
||||
* Change specified permission.
|
||||
*
|
||||
* @param AppPermissionEnum $appPermission A changed permission name.
|
||||
* @param boolean $permission New permission value.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPermission(AppPermissionEnum $appPermission, $permission)
|
||||
{
|
||||
$this->{$appPermission->getValue()} = $permission;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subscription
|
||||
*
|
||||
* @param AbstractSubscription $subscription A new subscription entity instance.
|
||||
*
|
||||
* @return Plan
|
||||
*/
|
||||
public function addSubscription(AbstractSubscription $subscription)
|
||||
{
|
||||
$this->subscriptions[] = $subscription;
|
||||
$subscription->setPlan($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove subscription
|
||||
*
|
||||
* @param AbstractSubscription $subscription A removed subscription entity
|
||||
* instance.
|
||||
*
|
||||
* @return Plan
|
||||
*/
|
||||
public function removeSubscription(AbstractSubscription $subscription)
|
||||
{
|
||||
$this->subscriptions->removeElement($subscription);
|
||||
$subscription->setPlan(null);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subscriptions
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getSubscriptions()
|
||||
{
|
||||
return $this->subscriptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default normalization groups.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function defaultGroups()
|
||||
{
|
||||
return [ 'plan', 'id', 'name' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get entity type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEntityType()
|
||||
{
|
||||
return 'plan';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return metadata for current entity.
|
||||
*
|
||||
* @return Metadata
|
||||
*/
|
||||
public function getMetadata()
|
||||
{
|
||||
return new Metadata(static::class, [
|
||||
PropertyMetadata::createInteger('id', [ 'id' ]),
|
||||
PropertyMetadata::createString('name', [ 'plan' ])
|
||||
->setField('title'),
|
||||
PropertyMetadata::createInteger('searchesPerDay', [ 'plan' ]),
|
||||
PropertyMetadata::createInteger('savedFeeds', [ 'plan' ]),
|
||||
PropertyMetadata::createInteger('masterAccounts', [ 'plan' ]),
|
||||
PropertyMetadata::createInteger('subscriberAccounts', [ 'plan' ]),
|
||||
PropertyMetadata::createInteger('alerts', [ 'plan' ]),
|
||||
PropertyMetadata::createInteger('newsletters', [ 'plan' ]),
|
||||
PropertyMetadata::createBoolean('analytics', [ 'plan' ]),
|
||||
PropertyMetadata::createDouble('price', [ 'plan' ]),
|
||||
PropertyMetadata::createBoolean('free', [ 'plan' ])
|
||||
->setField(function () {
|
||||
return $this->isFree();
|
||||
}),
|
||||
PropertyMetadata::createBoolean('is_default', [ 'plan' ]),
|
||||
PropertyMetadata::createBoolean('news', [ 'plan' ]),
|
||||
PropertyMetadata::createBoolean('blog', [ 'plan' ]),
|
||||
PropertyMetadata::createBoolean('reddit', [ 'plan' ]),
|
||||
PropertyMetadata::createBoolean('instagram', [ 'plan' ]),
|
||||
PropertyMetadata::createBoolean('twitter', [ 'plan' ]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set news
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setNews($news)
|
||||
{
|
||||
$this->news = $news;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isNews()
|
||||
{
|
||||
return $this->news;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set blog
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setBlog($blog)
|
||||
{
|
||||
$this->blog = $blog;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isBlog()
|
||||
{
|
||||
return $this->blog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set reddit
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setReddit($reddit)
|
||||
{
|
||||
$this->reddit = $reddit;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isReddit()
|
||||
{
|
||||
return $this->reddit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set instagram
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setInstagram($instagram)
|
||||
{
|
||||
$this->instagram = $instagram;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isInstagram()
|
||||
{
|
||||
return $this->instagram;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set twitter
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTwitter($twitter)
|
||||
{
|
||||
$this->twitter = $twitter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isTwitter()
|
||||
{
|
||||
return $this->twitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isPlanDowngrade(): bool
|
||||
{
|
||||
return $this->isPlanDowngrade;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isPlanDowngrade
|
||||
*/
|
||||
public function setIsPlanDowngrade(bool $isPlanDowngrade): void
|
||||
{
|
||||
$this->isPlanDowngrade = $isPlanDowngrade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
public function setUser(User $user = null)
|
||||
{
|
||||
$this->user = $user;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity;
|
||||
|
||||
use AppBundle\Entity\BaseEntityTrait;
|
||||
use AppBundle\Entity\EntityInterface;
|
||||
use CacheBundle\Entity\Feed\AbstractFeed;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* RecentlyUsedFeed
|
||||
*
|
||||
* @ORM\Table(name="recently_used_feeds")
|
||||
* @ORM\Entity(repositoryClass="UserBundle\Repository\RecentlyUsedFeedRepository")
|
||||
*/
|
||||
class RecentlyUsedFeed implements EntityInterface
|
||||
{
|
||||
|
||||
const POOL_SIZE = 10;
|
||||
|
||||
use BaseEntityTrait;
|
||||
|
||||
/**
|
||||
* @var AbstractFeed
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="CacheBundle\Entity\Feed\AbstractFeed")
|
||||
*/
|
||||
private $feed;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="UserBundle\Entity\User")
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*
|
||||
* @ORM\Column(type="datetime")
|
||||
*/
|
||||
private $usedAt;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->usedAt = new \DateTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set feed
|
||||
*
|
||||
* @param AbstractFeed $feed A AbstractFeed entity instance.
|
||||
*
|
||||
* @return RecentlyUsedFeed
|
||||
*/
|
||||
public function setFeed(AbstractFeed $feed = null)
|
||||
{
|
||||
$this->feed = $feed;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get feed
|
||||
*
|
||||
* @return AbstractFeed
|
||||
*/
|
||||
public function getFeed()
|
||||
{
|
||||
return $this->feed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
*
|
||||
* @return RecentlyUsedFeed
|
||||
*/
|
||||
public function setUser(User $user = null)
|
||||
{
|
||||
$this->user = $user;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set usedAt
|
||||
*
|
||||
* @param \DateTime $usedAt A DateTime instance.
|
||||
*
|
||||
* @return RecentlyUsedFeed
|
||||
*/
|
||||
public function setUsedAt(\DateTime $usedAt = null)
|
||||
{
|
||||
$this->usedAt = $usedAt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get usedAt
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getUsedAt()
|
||||
{
|
||||
return $this->usedAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Recipient;
|
||||
|
||||
use ApiBundle\Entity\ManageableEntityInterface;
|
||||
use ApiBundle\Entity\NormalizableEntityInterface;
|
||||
use AppBundle\Entity\ActivateAwareEntityTrait;
|
||||
use AppBundle\Entity\BaseEntityTrait;
|
||||
use AppBundle\Entity\EntityInterface;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Enum\NotificationTypeEnum;
|
||||
|
||||
/**
|
||||
* Class AbstractRecipient
|
||||
*
|
||||
* @package UserBundle\Entity\Recipient
|
||||
*
|
||||
* @ORM\Table(name="recipients")
|
||||
* @ORM\Entity(repositoryClass="UserBundle\Repository\RecipientRepository")
|
||||
* @ORM\InheritanceType("SINGLE_TABLE")
|
||||
* @ORM\DiscriminatorColumn(name="type", type="string")
|
||||
* @ORM\DiscriminatorMap({
|
||||
* "person"="PersonRecipient",
|
||||
* "group"="GroupRecipient",
|
||||
* })
|
||||
*/
|
||||
abstract class AbstractRecipient implements
|
||||
EntityInterface,
|
||||
NormalizableEntityInterface,
|
||||
ManageableEntityInterface
|
||||
{
|
||||
|
||||
use
|
||||
BaseEntityTrait,
|
||||
ActivateAwareEntityTrait;
|
||||
|
||||
/**
|
||||
* The user who created this notification.
|
||||
*
|
||||
* @var User
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="UserBundle\Entity\User", inversedBy="recipients")
|
||||
* @ORM\JoinColumn(name="owner_id", referencedColumnName="id", onDelete="SET NULL")
|
||||
*/
|
||||
protected $owner;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column
|
||||
* @Assert\NotBlank
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Array of subscriber notification count by types.
|
||||
*
|
||||
* @var integer[]
|
||||
*
|
||||
* @ORM\Column(type="array")
|
||||
*/
|
||||
protected $subscribedCount = [];
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*
|
||||
* @ORM\Column(type="datetime")
|
||||
*/
|
||||
protected $createdAt;
|
||||
|
||||
/**
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\ManyToMany(
|
||||
* targetEntity="UserBundle\Entity\Notification\Notification",
|
||||
* inversedBy="recipients"
|
||||
* )
|
||||
* @ORM\JoinTable(name="cross_recipient_notifications")
|
||||
*/
|
||||
protected $notifications;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
public $enrolled;
|
||||
|
||||
/**
|
||||
* AbstractRecipient constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->createdAt = new \DateTime();
|
||||
$this->notifications = new ArrayCollection();
|
||||
|
||||
foreach (NotificationTypeEnum::getAvailables() as $available) {
|
||||
$this->subscribedCount[$available] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set owner
|
||||
*
|
||||
* @param User $owner The owner of this notification.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setOwner(User $owner = null)
|
||||
{
|
||||
$this->owner = $owner;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get owner
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
public function getOwner()
|
||||
{
|
||||
return $this->owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that this entity is owned by specified user.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isOwnedBy(User $user)
|
||||
{
|
||||
return $this->owner->getId() === $user->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name
|
||||
*
|
||||
* @param string $name Group name.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set createdAt
|
||||
*
|
||||
* @param \DateTime $createdAt When this recipient is created.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setCreatedAt(\DateTime $createdAt = null)
|
||||
{
|
||||
$this->createdAt = $createdAt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get createdAt
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getCreatedAt()
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set subscribedCount
|
||||
*
|
||||
* @param array $subscribedCount Array of subscribed notification counts by
|
||||
* type.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setSubscribedCount(array $subscribedCount)
|
||||
{
|
||||
$this->subscribedCount = $subscribedCount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subscribedCount
|
||||
*
|
||||
* @return integer[]
|
||||
*/
|
||||
public function getSubscribedCount()
|
||||
{
|
||||
return $this->subscribedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NotificationTypeEnum $type A NotificationTypeEnum instance.
|
||||
* @param integer $count New subscription count.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setSubscribedCountByType(NotificationTypeEnum $type, $count)
|
||||
{
|
||||
$this->subscribedCount[(string) $type] = $count;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NotificationTypeEnum $type A NotificationTypeEnum instance.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getSubscribedCountByType(NotificationTypeEnum $type)
|
||||
{
|
||||
return $this->subscribedCount[(string) $type];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NotificationTypeEnum $type A NotificationTypeEnum instance.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function incSubscribedCountByType(NotificationTypeEnum $type)
|
||||
{
|
||||
$this->subscribedCount[(string) $type]++;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NotificationTypeEnum $type A NotificationTypeEnum instance.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function decSubscribedCountByType(NotificationTypeEnum $type)
|
||||
{
|
||||
$this->subscribedCount[(string) $type]--;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add notification
|
||||
*
|
||||
* @param Notification $notification A Notification entity instance.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function addNotification(Notification $notification)
|
||||
{
|
||||
$this->notifications[] = $notification;
|
||||
$this->incSubscribedCountByType($notification->getNotificationType());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove notification
|
||||
*
|
||||
* @param Notification $notification A Notification entity instance.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function removeNotification(Notification $notification)
|
||||
{
|
||||
$this->notifications->removeElement($notification);
|
||||
$this->decSubscribedCountByType($notification->getNotificationType());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notifications
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getNotifications()
|
||||
{
|
||||
return $this->notifications;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default normalization groups.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function defaultGroups()
|
||||
{
|
||||
return [ 'id', 'recipient' ];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Recipient;
|
||||
|
||||
use ApiBundle\Serializer\Metadata\Metadata;
|
||||
use ApiBundle\Serializer\Metadata\PropertyMetadata;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Enum\NotificationTypeEnum;
|
||||
use UserBundle\Enum\RecipientTypeEnum;
|
||||
use UserBundle\Form\GroupRecipientType;
|
||||
|
||||
/**
|
||||
* Class GroupRecipient
|
||||
*
|
||||
* @package UserBundle\Entity\Recipient
|
||||
*
|
||||
* @ORM\Entity(repositoryClass="UserBundle\Repository\GroupRecipientRepository")
|
||||
*/
|
||||
class GroupRecipient extends AbstractRecipient
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="text")
|
||||
*/
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
protected $recipientsNumber = 0;
|
||||
|
||||
/**
|
||||
* @var Collection
|
||||
*
|
||||
* We use 'EXTRA_LAZY' in order to avoid fetching all recipients when we need
|
||||
* only compute numbers of recipient.
|
||||
*
|
||||
* @ORM\ManyToMany(
|
||||
* targetEntity="UserBundle\Entity\Recipient\PersonRecipient",
|
||||
* inversedBy="groups",
|
||||
* fetch="EXTRA_LAZY"
|
||||
* )
|
||||
* @ORM\JoinTable(name="cross_groups_persons")
|
||||
*/
|
||||
protected $recipients;
|
||||
|
||||
/**
|
||||
* AbstractRecipient constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->recipients = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set description
|
||||
*
|
||||
* @param string $description Group description.
|
||||
*
|
||||
* @return GroupRecipient
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set personsCount
|
||||
*
|
||||
* @param integer $recipientsNumber Count of person in group.
|
||||
*
|
||||
* @return GroupRecipient
|
||||
*/
|
||||
public function setRecipientsNumber($recipientsNumber)
|
||||
{
|
||||
$this->recipientsNumber = $recipientsNumber;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get personsCount
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getRecipientsNumber()
|
||||
{
|
||||
return $this->recipientsNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add person
|
||||
*
|
||||
* @param PersonRecipient $person A PersonRecipient entity instance.
|
||||
*
|
||||
* @return GroupRecipient
|
||||
*/
|
||||
public function addRecipient(PersonRecipient $person)
|
||||
{
|
||||
$this->recipients[] = $person;
|
||||
$this->recipientsNumber++;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove person
|
||||
*
|
||||
* @param PersonRecipient $person A PersonRecipient entity instance.
|
||||
*
|
||||
* @return GroupRecipient
|
||||
*/
|
||||
public function removeRecipient(PersonRecipient $person)
|
||||
{
|
||||
$this->recipients->removeElement($person);
|
||||
$this->recipientsNumber--;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get persons
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getRecipients()
|
||||
{
|
||||
return $this->recipients;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return metadata for current entity.
|
||||
*
|
||||
* @return \ApiBundle\Serializer\Metadata\Metadata
|
||||
*/
|
||||
public function getMetadata()
|
||||
{
|
||||
$subscriptions = array_map(function ($type) {
|
||||
return PropertyMetadata::createInteger($type, [ 'recipient' ])
|
||||
->setField(function () use ($type) {
|
||||
return $this->subscribedCount[$type];
|
||||
});
|
||||
}, NotificationTypeEnum::getAvailables());
|
||||
$subscriptions[] = PropertyMetadata::createArray('ids', [ 'recipient' ])
|
||||
->setField(function () {
|
||||
return $this->getNotifications()->map(function (Notification $notification) {
|
||||
return $notification->getId();
|
||||
})->toArray();
|
||||
});
|
||||
|
||||
return new Metadata(static::class, [
|
||||
PropertyMetadata::createInteger('id', [ 'id' ]),
|
||||
PropertyMetadata::createString('name', [ 'recipient', 'notification', 'notification_list', 'recipient_autocompletion' ]),
|
||||
PropertyMetadata::createString('email', [ 'notification', 'notification_list', 'recipient_autocompletion' ])
|
||||
->setField(function () {
|
||||
return '';
|
||||
}),
|
||||
PropertyMetadata::createString('description', [ 'recipient' ]),
|
||||
PropertyMetadata::groupProperties('subscriptions', $subscriptions, [ 'recipient' ]),
|
||||
PropertyMetadata::createArray('recipients', [ 'recipient' ])
|
||||
->setField(function () {
|
||||
return $this->getRecipients()->map(function (PersonRecipient $recipient) {
|
||||
return $recipient->getId();
|
||||
})->toArray();
|
||||
}),
|
||||
PropertyMetadata::createBoolean('active', [ 'recipient' ]),
|
||||
PropertyMetadata::createBoolean('enrolled', [ 'sublist' ]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get entity type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEntityType()
|
||||
{
|
||||
return RecipientTypeEnum::GROUP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return fqcn of form used for creating this entity.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCreateFormClass()
|
||||
{
|
||||
return GroupRecipientType::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return fqcn of form used for updating this entity.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUpdateFormClass()
|
||||
{
|
||||
return GroupRecipientType::class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,370 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Recipient;
|
||||
|
||||
use ApiBundle\Serializer\Metadata\Metadata;
|
||||
use ApiBundle\Serializer\Metadata\PropertyMetadata;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Enum\NotificationTypeEnum;
|
||||
use UserBundle\Enum\RecipientTypeEnum;
|
||||
use UserBundle\Form\PersonRecipientType;
|
||||
|
||||
/**
|
||||
* Class PersonRecipient
|
||||
*
|
||||
* @package UserBundle\Entity\Recipient
|
||||
*
|
||||
* @ORM\Entity(repositoryClass="UserBundle\Repository\PersonRecipientRepository")
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*/
|
||||
class PersonRecipient extends AbstractRecipient
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column
|
||||
* @Assert\NotBlank
|
||||
*/
|
||||
protected $firstName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column
|
||||
* @Assert\NotBlank
|
||||
*/
|
||||
protected $lastName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column
|
||||
* @Assert\NotBlank
|
||||
* @Assert\Email
|
||||
*/
|
||||
protected $email;
|
||||
|
||||
/**
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\ManyToMany(
|
||||
* targetEntity="UserBundle\Entity\Recipient\GroupRecipient",
|
||||
* mappedBy="recipients"
|
||||
* )
|
||||
*/
|
||||
protected $groups;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*
|
||||
* @ORM\OneToOne(
|
||||
* targetEntity="UserBundle\Entity\User",
|
||||
* mappedBy="recipient",
|
||||
* cascade={ "ALL" }
|
||||
* )
|
||||
*/
|
||||
protected $associatedUser;
|
||||
|
||||
/**
|
||||
* AbstractRecipient constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->groups = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->firstName .' '. $this->lastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create recipient from user.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
*
|
||||
* @return PersonRecipient
|
||||
*/
|
||||
public static function createFromUser(User $user)
|
||||
{
|
||||
return static::create()
|
||||
->setFirstName($user->getFirstName())
|
||||
->setLastName($user->getLastName())
|
||||
->setEmail($user->getEmail());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set firstName
|
||||
*
|
||||
* @param string $firstName Person first name.
|
||||
*
|
||||
* @return PersonRecipient
|
||||
*/
|
||||
public function setFirstName($firstName)
|
||||
{
|
||||
$this->firstName = trim($firstName);
|
||||
$this->name = $this->firstName .' '. $this->lastName;
|
||||
|
||||
if (($this->associatedUser !== null) && ($this->associatedUser->getFirstName() !== $firstName)) {
|
||||
$this->associatedUser->setFirstName($firstName);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get firstName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFirstName()
|
||||
{
|
||||
return $this->firstName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set lastName
|
||||
*
|
||||
* @param string $lastName Person last name.
|
||||
*
|
||||
* @return PersonRecipient
|
||||
*/
|
||||
public function setLastName($lastName)
|
||||
{
|
||||
$this->lastName = trim($lastName);
|
||||
$this->name = $this->firstName .' '. $this->lastName;
|
||||
|
||||
if (($this->associatedUser !== null) && ($this->associatedUser->getLastName() !== $lastName)) {
|
||||
$this->associatedUser->setLastName($lastName);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name
|
||||
*
|
||||
* @param string $name Group name.
|
||||
*
|
||||
* @return AbstractRecipient
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
list($firstName, $lastName) = explode(' ', $name, 2);
|
||||
|
||||
$this->firstName = trim($firstName);
|
||||
$this->lastName = trim($lastName);
|
||||
|
||||
$this->name = $this->firstName .' '. $this->lastName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get lastName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLastName()
|
||||
{
|
||||
return $this->lastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set email
|
||||
*
|
||||
* @param string $email Person email.
|
||||
*
|
||||
* @return PersonRecipient
|
||||
*/
|
||||
public function setEmail($email)
|
||||
{
|
||||
$this->email = $email;
|
||||
|
||||
if (($this->associatedUser !== null) && ($this->associatedUser->getEmail() !== $email)) {
|
||||
$this->associatedUser->setEmail($email);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get email
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEmail()
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getActive()
|
||||
{
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add group
|
||||
*
|
||||
* @param GroupRecipient $group A GroupRecipient entity instance.
|
||||
*
|
||||
* @return PersonRecipient
|
||||
*/
|
||||
public function addGroup(GroupRecipient $group)
|
||||
{
|
||||
$this->groups[] = $group;
|
||||
$group->addRecipient($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove group
|
||||
*
|
||||
* @param GroupRecipient $group A GroupRecipient entity instance.
|
||||
*
|
||||
* @return PersonRecipient
|
||||
*/
|
||||
public function removeGroup(GroupRecipient $group)
|
||||
{
|
||||
$this->groups->removeElement($group);
|
||||
$group->removeRecipient($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get groups
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getGroups()
|
||||
{
|
||||
return $this->groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User $associatedUser
|
||||
*/
|
||||
public function getAssociatedUser()
|
||||
{
|
||||
return $this->associatedUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $associatedUser Associated user.
|
||||
*
|
||||
* @return PersonRecipient
|
||||
*/
|
||||
public function setAssociatedUser(User $associatedUser = null)
|
||||
{
|
||||
if ($associatedUser === null) {
|
||||
$this->associatedUser->setRecipient(null);
|
||||
} else {
|
||||
$associatedUser->setRecipient($this);
|
||||
}
|
||||
|
||||
$this->associatedUser = $associatedUser;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return metadata for current entity.
|
||||
*
|
||||
* @return \ApiBundle\Serializer\Metadata\Metadata
|
||||
*/
|
||||
public function getMetadata()
|
||||
{
|
||||
$subscriptions = array_map(function ($type) {
|
||||
return PropertyMetadata::createInteger($type, [ 'recipient' ])
|
||||
->setField(function () use ($type) {
|
||||
return $this->subscribedCount[$type];
|
||||
});
|
||||
}, NotificationTypeEnum::getAvailables());
|
||||
$subscriptions[] = PropertyMetadata::createArray('ids', [ 'recipient' ])
|
||||
->setField(function () {
|
||||
return $this->getNotifications()->map(function (Notification $notification) {
|
||||
return $notification->getId();
|
||||
})->toArray();
|
||||
});
|
||||
|
||||
return new Metadata(static::class, [
|
||||
PropertyMetadata::createInteger('id', [ 'id' ]),
|
||||
PropertyMetadata::createString('firstName', [ 'recipient' ]),
|
||||
PropertyMetadata::createString('lastName', [ 'recipient' ]),
|
||||
PropertyMetadata::createString('name', [ 'notification', 'notification_list', 'recipient_autocompletion' ]),
|
||||
PropertyMetadata::createString('email', [ 'recipient', 'notification', 'notification_list', 'recipient_autocompletion' ]),
|
||||
PropertyMetadata::createDate('creationDate', [ 'recipient' ])
|
||||
->setField('createdAt'),
|
||||
PropertyMetadata::groupProperties('subscriptions', $subscriptions, [ 'recipient' ]),
|
||||
PropertyMetadata::createCollection('groups', GroupRecipient::class, [ 'recipient' ]),
|
||||
PropertyMetadata::createBoolean('active', [ 'recipient' ]),
|
||||
PropertyMetadata::createBoolean('enrolled', [ 'sublist' ]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get entity type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEntityType()
|
||||
{
|
||||
return RecipientTypeEnum::PERSON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return fqcn of form used for creating this entity.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCreateFormClass()
|
||||
{
|
||||
return PersonRecipientType::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return fqcn of form used for updating this entity.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUpdateFormClass()
|
||||
{
|
||||
return PersonRecipientType::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\PreRemove
|
||||
*
|
||||
* @param LifecycleEventArgs $event A LifecycleEventArgs instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function preRemove(LifecycleEventArgs $event)
|
||||
{
|
||||
$em = $event->getObjectManager();
|
||||
|
||||
foreach ($this->groups as $group) {
|
||||
$group->removeRecipient($this);
|
||||
$em->persist($group);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Subscription;
|
||||
|
||||
use AppBundle\Entity\BaseEntityTrait;
|
||||
use AppBundle\Entity\EntityInterface;
|
||||
use AppBundle\Entity\OwnerAwareEntityTrait;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use PaymentBundle\Entity\Payment;
|
||||
use PaymentBundle\Enum\PaymentGatewayEnum;
|
||||
use PaymentBundle\Gateway\Factory\PaymentGatewayFactoryInterface;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\Plan;
|
||||
use UserBundle\Entity\Traits\LimitAwareTrait;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Enum\BillingSubscriptionTypeEnum;
|
||||
|
||||
/**
|
||||
* AbstractSubscription
|
||||
*
|
||||
* @ORM\Table(name="subscriptions")
|
||||
* @ORM\Entity(repositoryClass="UserBundle\Repository\SubscriptionRepository")
|
||||
*
|
||||
* @ORM\InheritanceType("SINGLE_TABLE")
|
||||
* @ORM\DiscriminatorColumn(name="type", type="string")
|
||||
* @ORM\DiscriminatorMap({
|
||||
* "organization"="OrganizationSubscription",
|
||||
* "personal"="PersonalSubscription",
|
||||
* })
|
||||
*/
|
||||
abstract class AbstractSubscription implements EntityInterface
|
||||
{
|
||||
|
||||
use
|
||||
OwnerAwareEntityTrait,
|
||||
BaseEntityTrait,
|
||||
LimitAwareTrait;
|
||||
|
||||
/**
|
||||
* @var Plan
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="UserBundle\Entity\Plan", inversedBy="subscriptions")
|
||||
*/
|
||||
private $plan;
|
||||
|
||||
/**
|
||||
* @var PaymentGatewayEnum
|
||||
*
|
||||
* @ORM\Column(type="payment_gateway")
|
||||
*/
|
||||
private $gateway;
|
||||
|
||||
/**
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity="UserBundle\Entity\User",
|
||||
* mappedBy="billingSubscription",
|
||||
* cascade={ "persist", "remove" }
|
||||
* )
|
||||
*/
|
||||
private $users;
|
||||
|
||||
/**
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity="UserBundle\Entity\Notification\Notification",
|
||||
* mappedBy="billingSubscription",
|
||||
* cascade={ "persist", "remove" }
|
||||
* )
|
||||
*/
|
||||
private $notifications;
|
||||
|
||||
/**
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity="PaymentBundle\Entity\Payment",
|
||||
* mappedBy="subscription",
|
||||
* cascade={ "persist", "remove" }
|
||||
* )
|
||||
*/
|
||||
private $payments;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $payed = false;
|
||||
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $isSubscriptionCancelled = false;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $isPlanDowngrade = false;
|
||||
|
||||
/**
|
||||
* @var datetime
|
||||
*
|
||||
* @ORM\Column(type="datetime",nullable=true)
|
||||
*/
|
||||
private $startDate;
|
||||
|
||||
/**
|
||||
* @var datetime
|
||||
*
|
||||
* @ORM\Column(type="datetime",nullable=true)
|
||||
*/
|
||||
private $endDate;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->notifications = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Plan
|
||||
*/
|
||||
public function getPlan()
|
||||
{
|
||||
return $this->plan;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Plan $plan A Plan entity instance.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPlan(Plan $plan = null)
|
||||
{
|
||||
$this->plan = $plan;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PaymentGatewayEnum
|
||||
*/
|
||||
public function getGateway()
|
||||
{
|
||||
return $this->gateway;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PaymentGatewayEnum $gateway A used payment gateway.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setGateway(PaymentGatewayEnum $gateway)
|
||||
{
|
||||
$this->gateway = $gateway;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add notification
|
||||
*
|
||||
* @param Notification $notification A new Notification entity instance.
|
||||
*
|
||||
* @return AbstractSubscription
|
||||
*/
|
||||
public function addNotification(Notification $notification)
|
||||
{
|
||||
$this->notifications[] = $notification;
|
||||
$notification->setBillingSubscription($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove notification
|
||||
*
|
||||
* @param Notification $notification A removed Notification entity instance.
|
||||
*
|
||||
* @return AbstractSubscription
|
||||
*/
|
||||
public function removeNotification(Notification $notification)
|
||||
{
|
||||
$this->notifications->removeElement($notification);
|
||||
$notification->setBillingSubscription(null);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notifications
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getNotifications()
|
||||
{
|
||||
return $this->notifications;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add payment
|
||||
*
|
||||
* @param Payment $payment A new Payment entity instance.
|
||||
*
|
||||
* @return AbstractSubscription
|
||||
*/
|
||||
public function addPayment(Payment $payment)
|
||||
{
|
||||
$this->payments[] = $payment;
|
||||
$payment->setSubscription($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove payment
|
||||
*
|
||||
* @param Payment $payment A removed Payment entity instance.
|
||||
*
|
||||
* @return AbstractSubscription
|
||||
*/
|
||||
public function removePayment(Payment $payment)
|
||||
{
|
||||
$this->payments->removeElement($payment);
|
||||
$payment->setSubscription(null);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get payments
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getPayments()
|
||||
{
|
||||
return $this->payments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add user
|
||||
*
|
||||
* @param User $user A new User entity instance.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function addUser(User $user)
|
||||
{
|
||||
$this->users[] = $user;
|
||||
$user->setBillingSubscription($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove user
|
||||
*
|
||||
* @param User $user A removed User entity instance.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function removeUser(User $user)
|
||||
{
|
||||
$this->users->removeElement($user);
|
||||
$user->setBillingSubscription(null);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get users
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getUsers()
|
||||
{
|
||||
return $this->users;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isPayed()
|
||||
{
|
||||
return $this->payed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $payed Has owner paid for this subscription or not.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPayed($payed)
|
||||
{
|
||||
$this->payed = $payed;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PaymentGatewayFactoryInterface $factory A PaymentGatewayFactoryInterface
|
||||
* instance.
|
||||
* @param string $note Cancel note.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(PaymentGatewayFactoryInterface $factory, $note)
|
||||
{
|
||||
$factory->getGateway($this->getGateway())->cancelSubscription($this, $note);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSubscriptionCancelled(): bool
|
||||
{
|
||||
return $this->isSubscriptionCancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isSubscriptionCancelled
|
||||
*/
|
||||
public function setIsSubscriptionCancelled(bool $isSubscriptionCancelled): void
|
||||
{
|
||||
$this->isSubscriptionCancelled = $isSubscriptionCancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isPlanDowngrade(): bool
|
||||
{
|
||||
return $this->isPlanDowngrade;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isPlanDowngrade
|
||||
*/
|
||||
public function setIsPlanDowngrade(bool $isPlanDowngrade): void
|
||||
{
|
||||
$this->isPlanDowngrade = $isPlanDowngrade;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return startDate
|
||||
*/
|
||||
public function getStartDate(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startDate
|
||||
*
|
||||
* @return startDate
|
||||
*/
|
||||
public function setStartDate(\DateTimeInterface $startDate)
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return endDate
|
||||
*/
|
||||
public function getEndDate(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param endDate
|
||||
*
|
||||
* @return endDate
|
||||
*/
|
||||
public function setEndDate(\DateTimeInterface $endDate)
|
||||
{
|
||||
$this->endDate = $endDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BillingSubscriptionTypeEnum
|
||||
*/
|
||||
abstract public function getSubscriptionType();
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Subscription;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use UserBundle\Entity\Organization;
|
||||
use UserBundle\Enum\BillingSubscriptionTypeEnum;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="UserBundle\Repository\SubscriptionRepository")
|
||||
*/
|
||||
class OrganizationSubscription extends AbstractSubscription
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Organization
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="UserBundle\Entity\Organization", inversedBy="subscriptions")
|
||||
*/
|
||||
private $organization;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column
|
||||
* @Assert\NotBlank
|
||||
*/
|
||||
protected $organizationAddress;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column
|
||||
* @Assert\NotBlank
|
||||
*/
|
||||
protected $organizationEmail;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column
|
||||
* @Assert\NotBlank
|
||||
*/
|
||||
protected $organizationPhone;
|
||||
|
||||
/**
|
||||
* @return Organization
|
||||
*/
|
||||
public function getOrganization()
|
||||
{
|
||||
return $this->organization;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Organization $organization A Organization entity instance.
|
||||
*
|
||||
* @return OrganizationSubscription
|
||||
*/
|
||||
public function setOrganization(Organization $organization)
|
||||
{
|
||||
$this->organization = $organization;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOrganizationAddress()
|
||||
{
|
||||
return $this->organizationAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $organizationAddress Organization department address.
|
||||
*
|
||||
* @return OrganizationSubscription
|
||||
*/
|
||||
public function setOrganizationAddress($organizationAddress)
|
||||
{
|
||||
$this->organizationAddress = $organizationAddress;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOrganizationEmail()
|
||||
{
|
||||
return $this->organizationEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $organizationEmail Organization department email.
|
||||
*
|
||||
* @return OrganizationSubscription
|
||||
*/
|
||||
public function setOrganizationEmail($organizationEmail)
|
||||
{
|
||||
$this->organizationEmail = $organizationEmail;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOrganizationPhone()
|
||||
{
|
||||
return $this->organizationPhone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $organizationPhone Organization department phone.
|
||||
*
|
||||
* @return OrganizationSubscription
|
||||
*/
|
||||
public function setOrganizationPhone($organizationPhone)
|
||||
{
|
||||
$this->organizationPhone = $organizationPhone;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BillingSubscriptionTypeEnum
|
||||
*/
|
||||
public function getSubscriptionType()
|
||||
{
|
||||
return BillingSubscriptionTypeEnum::organization();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Subscription;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use UserBundle\Enum\BillingSubscriptionTypeEnum;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
*/
|
||||
class PersonalSubscription extends AbstractSubscription
|
||||
{
|
||||
|
||||
/**
|
||||
* @return BillingSubscriptionTypeEnum
|
||||
*/
|
||||
public function getSubscriptionType()
|
||||
{
|
||||
return BillingSubscriptionTypeEnum::personal();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Entity\Traits;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use UserBundle\Enum\AppLimitEnum;
|
||||
|
||||
/**
|
||||
* Trait LimitAwareTrait
|
||||
*
|
||||
* Contains mapping for some application limits and setter and getter for it.
|
||||
*
|
||||
* @package UserBundle\Entity\Traits
|
||||
*/
|
||||
trait LimitAwareTrait
|
||||
{
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(type="integer")
|
||||
*
|
||||
* @Assert\NotBlank
|
||||
* @Assert\GreaterThanOrEqual(value=0)
|
||||
*/
|
||||
private $searchesPerDay = 0;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(type="integer")
|
||||
*
|
||||
* @Assert\NotBlank
|
||||
* @Assert\GreaterThanOrEqual(value=0)
|
||||
*/
|
||||
private $savedFeeds = 0;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(type="integer")
|
||||
*
|
||||
* @Assert\NotBlank
|
||||
* @Assert\GreaterThanOrEqual(value=0)
|
||||
*/
|
||||
private $masterAccounts = 0;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(type="integer")
|
||||
*
|
||||
* @Assert\NotBlank
|
||||
* @Assert\GreaterThanOrEqual(value=0)
|
||||
*/
|
||||
private $subscriberAccounts = 0;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(type="integer")
|
||||
*
|
||||
* @Assert\NotBlank
|
||||
* @Assert\GreaterThanOrEqual(value=0)
|
||||
*/
|
||||
private $alerts = 0;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(type="integer")
|
||||
*
|
||||
* @Assert\NotBlank
|
||||
* @Assert\GreaterThanOrEqual(value=0)
|
||||
*/
|
||||
private $newsletters = 0;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(type="integer")
|
||||
*
|
||||
* @Assert\NotBlank
|
||||
* @Assert\GreaterThanOrEqual(value=0)
|
||||
*/
|
||||
private $webFeeds = 0;
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getSearchesPerDay()
|
||||
{
|
||||
return $this->searchesPerDay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set searchesPerDay
|
||||
*
|
||||
* @param integer $searchesPerDay Search per day limit.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setSearchesPerDay($searchesPerDay)
|
||||
{
|
||||
$this->searchesPerDay = $searchesPerDay;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSavedFeeds()
|
||||
{
|
||||
return $this->savedFeeds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set savedFeeds
|
||||
*
|
||||
* @param integer $savedFeeds Saved feed limit.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setSavedFeeds($savedFeeds)
|
||||
{
|
||||
$this->savedFeeds = $savedFeeds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getWebFeeds()
|
||||
{
|
||||
return $this->webFeeds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set webFeeds
|
||||
*
|
||||
* @param integer $webFeeds Saved feed limit.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setWebFeeds($webFeeds)
|
||||
{
|
||||
$this->webFeeds = $webFeeds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getMasterAccounts()
|
||||
{
|
||||
return $this->masterAccounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $masterAccounts Master accounts limit.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setMasterAccounts($masterAccounts)
|
||||
{
|
||||
$this->masterAccounts = $masterAccounts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getSubscriberAccounts()
|
||||
{
|
||||
return $this->subscriberAccounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $subscriberAccounts Subscriber account limit.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setSubscriberAccounts($subscriberAccounts)
|
||||
{
|
||||
$this->subscriberAccounts = $subscriberAccounts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getAlerts()
|
||||
{
|
||||
return $this->alerts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $alerts Alerts count.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setAlerts($alerts)
|
||||
{
|
||||
$this->alerts = $alerts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getNewsletters()
|
||||
{
|
||||
return $this->newsletters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $newsletters Newsletters count.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setNewsletters($newsletters)
|
||||
{
|
||||
$this->newsletters = $newsletters;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get limit value for specified limit name.
|
||||
*
|
||||
* @param AppLimitEnum $appLimit Requested limit name.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getLimitValue(AppLimitEnum $appLimit)
|
||||
{
|
||||
return $this->{'get'. ucfirst($appLimit->getValue())}();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set limit value for specified limit name.
|
||||
*
|
||||
* @param AppLimitEnum $appLimit Changed limit name.
|
||||
* @param integer $newValue New value for limit.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setLimitValue(AppLimitEnum $appLimit, $newValue)
|
||||
{
|
||||
$this->{'set'. ucfirst($appLimit->getValue())}($newValue);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Enum;
|
||||
|
||||
use AppBundle\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Class AppLimitEnum
|
||||
* @package UserBundle\Enum
|
||||
*
|
||||
* @method static AppLimitEnum searches()
|
||||
* @method static AppLimitEnum feeds()
|
||||
* @method static AppLimitEnum masterAccounts()
|
||||
* @method static AppLimitEnum subscriberAccounts()
|
||||
* @method static AppLimitEnum alerts()
|
||||
* @method static AppLimitEnum newsletters()
|
||||
* @method static AppLimitEnum webfeeds()
|
||||
*/
|
||||
class AppLimitEnum extends AbstractEnum
|
||||
{
|
||||
|
||||
const SEARCHES = 'searchesPerDay';
|
||||
const FEEDS = 'savedFeeds';
|
||||
const MASTER_ACCOUNTS = 'masterAccounts';
|
||||
const SUBSCRIBER_ACCOUNTS = 'subscriberAccounts';
|
||||
const ALERTS = 'alerts';
|
||||
const NEWSLETTERS = 'newsletters';
|
||||
const WEBFEEDS = 'webFeeds';
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Enum;
|
||||
|
||||
use AppBundle\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Class AppPermissionEnum
|
||||
* @package UserBundle\Enum
|
||||
*
|
||||
* @method static AppPermissionEnum analytics()
|
||||
*/
|
||||
class AppPermissionEnum extends AbstractEnum
|
||||
{
|
||||
|
||||
const ANALYTICS = 'analytics';
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Enum;
|
||||
|
||||
use AppBundle\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Class BillingSubscriptionTypeEnum
|
||||
* @package UserBundle\Enum
|
||||
*
|
||||
* @method static BillingSubscriptionTypeEnum organization()
|
||||
* @method static BillingSubscriptionTypeEnum personal()
|
||||
*/
|
||||
class BillingSubscriptionTypeEnum extends AbstractEnum
|
||||
{
|
||||
|
||||
const ORGANIZATION = 'organization';
|
||||
const PERSONAL = 'personal';
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Enum;
|
||||
|
||||
use AppBundle\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Class ThemeTypeEnum
|
||||
* @package UserBundle\Enum
|
||||
*
|
||||
* @method static FontFamilyEnum arial()
|
||||
* @method static FontFamilyEnum calibri()
|
||||
* @method static FontFamilyEnum centuryGothic()
|
||||
* @method static FontFamilyEnum courierNew()
|
||||
* @method static FontFamilyEnum georgia()
|
||||
* @method static FontFamilyEnum lucidaSansUnicode()
|
||||
* @method static FontFamilyEnum myriadProRegular()
|
||||
* @method static FontFamilyEnum tahoma()
|
||||
* @method static FontFamilyEnum timesNewRoman()
|
||||
* @method static FontFamilyEnum trebuchet()
|
||||
* @method static FontFamilyEnum verdana()
|
||||
*/
|
||||
class FontFamilyEnum extends AbstractEnum
|
||||
{
|
||||
|
||||
const ARIAL = 'Arial';
|
||||
const CALIBRI = 'Calibri';
|
||||
const CENTURY_GOTHIC = 'Century Gothic';
|
||||
const COURIER_NEW = 'Courier New';
|
||||
const GEORGIA = 'Georgia';
|
||||
const LUCIDA_SANS_UNICODE = 'Lucida Sans Unicode';
|
||||
const MYRIAD_PRO_REGULAR = 'Myriad Pro Regular';
|
||||
const TAHOMA = 'Tahoma';
|
||||
const TIMES_NEW_ROMAN = 'Times New Roman';
|
||||
const TREBUCHET = 'Trebuchet';
|
||||
const VERDANA = 'Verdana';
|
||||
|
||||
private static $nameToFamilyMap = [
|
||||
FontFamilyEnum::ARIAL => 'Arial,helvetica,sans-serif',
|
||||
FontFamilyEnum::CALIBRI => 'Calibri,Helvetica,sans-serif',
|
||||
FontFamilyEnum::CENTURY_GOTHIC => '\'Century Gothic\',CenturyGothic,AppleGothic,sans-serif',
|
||||
FontFamilyEnum::COURIER_NEW => '\'Courier new\',courier,monospace',
|
||||
FontFamilyEnum::GEORGIA => 'Georgia,serif',
|
||||
FontFamilyEnum::LUCIDA_SANS_UNICODE => '\'Lucida Sans Unicode\',sans-serif',
|
||||
FontFamilyEnum::MYRIAD_PRO_REGULAR => 'MyriadPro-Regular,\'Lucida Sans Unicode\',\'Lucida Grande\',sans-serif',
|
||||
FontFamilyEnum::TAHOMA => '\'Tahoma Verdana\',Segoe,sans-serif',
|
||||
FontFamilyEnum::TIMES_NEW_ROMAN => 'TimesNewRoman,serif',
|
||||
FontFamilyEnum::TREBUCHET => 'Trebuchet,Trebuchet MS,sans-serif',
|
||||
FontFamilyEnum::VERDANA => 'Verdana,geneva,sans-serif',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get css font family option.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCss()
|
||||
{
|
||||
return self::$nameToFamilyMap[$this->value];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Enum;
|
||||
|
||||
use AppBundle\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Class NotificationTypeEnum
|
||||
* @package UserBundle\Enum
|
||||
*
|
||||
* @method static NotificationTypeEnum alert()
|
||||
* @method static NotificationTypeEnum newsletter()
|
||||
*/
|
||||
class NotificationTypeEnum extends AbstractEnum
|
||||
{
|
||||
|
||||
const ALERT = 'alert';
|
||||
const NEWSLETTER = 'newsletter';
|
||||
|
||||
/**
|
||||
* @return AppLimitEnum
|
||||
*/
|
||||
public function toAppLimit()
|
||||
{
|
||||
if ($this->value === self::ALERT) {
|
||||
return AppLimitEnum::alerts();
|
||||
}
|
||||
|
||||
return AppLimitEnum::newsletters();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Enum;
|
||||
|
||||
use AppBundle\Enum\AbstractEnum;
|
||||
use UserBundle\Entity\Recipient\GroupRecipient;
|
||||
use UserBundle\Entity\Recipient\PersonRecipient;
|
||||
|
||||
/**
|
||||
* Class RecipientTypeEnum
|
||||
* @package UserBundle\Enum
|
||||
*
|
||||
* @method static RecipientTypeEnum person()
|
||||
* @method static RecipientTypeEnum group()
|
||||
*/
|
||||
class RecipientTypeEnum extends AbstractEnum
|
||||
{
|
||||
|
||||
const PERSON = 'recipient';
|
||||
const GROUP = 'group';
|
||||
|
||||
private static $map = [
|
||||
self::PERSON => PersonRecipient::class,
|
||||
self::GROUP => GroupRecipient::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Get entity class for this type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEntityClass()
|
||||
{
|
||||
return self::$map[$this->value];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Enum;
|
||||
|
||||
use AppBundle\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Class ThemeTypeEnum
|
||||
* @package UserBundle\Enum
|
||||
*
|
||||
* @method static StatusFilterEnum no()
|
||||
* @method static StatusFilterEnum yes()
|
||||
* @method static StatusFilterEnum all()
|
||||
*/
|
||||
class StatusFilterEnum extends AbstractEnum
|
||||
{
|
||||
|
||||
const NO = 'no';
|
||||
const YES = 'yes';
|
||||
const ALL = 'all';
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Enum;
|
||||
|
||||
use AppBundle\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Class ThemeOptionExtractEnum
|
||||
* @package UserBundle\Enum
|
||||
*
|
||||
* @method static ThemeOptionExtractEnum no()
|
||||
* @method static ThemeOptionExtractEnum start()
|
||||
* @method static ThemeOptionExtractEnum context()
|
||||
*/
|
||||
class ThemeOptionExtractEnum extends AbstractEnum
|
||||
{
|
||||
|
||||
const NO = 'no';
|
||||
const START = 'start';
|
||||
const CONTEXT = 'context';
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Enum;
|
||||
|
||||
use AppBundle\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Class ThemeOptionsTableOfContentsEnum
|
||||
* @package UserBundle\Enum
|
||||
*
|
||||
* @method static ThemeOptionsTableOfContentsEnum no()
|
||||
* @method static ThemeOptionsTableOfContentsEnum simple()
|
||||
* @method static ThemeOptionsTableOfContentsEnum headline()
|
||||
* @method static ThemeOptionsTableOfContentsEnum headlineSourceDate()
|
||||
* @method static ThemeOptionsTableOfContentsEnum sourceHeadlineDate()
|
||||
*/
|
||||
class ThemeOptionsTableOfContentsEnum extends AbstractEnum
|
||||
{
|
||||
|
||||
const NO = 'no';
|
||||
const SIMPLE = 'simple';
|
||||
const HEADLINE = 'headline';
|
||||
const HEADLINE_SOURCE_DATE = 'headline_source_date';
|
||||
const SOURCE_HEADLINE_DATE = 'source_headline_date';
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Enum;
|
||||
|
||||
use AppBundle\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Class ThemeOptionsUserCommentsEnum
|
||||
* @package UserBundle\Enum
|
||||
*
|
||||
* @method static ThemeOptionsUserCommentsEnum no()
|
||||
* @method static ThemeOptionsUserCommentsEnum withAuthorDate()
|
||||
* @method static ThemeOptionsUserCommentsEnum withoutAuthorDate()
|
||||
*/
|
||||
class ThemeOptionsUserCommentsEnum extends AbstractEnum
|
||||
{
|
||||
|
||||
const NO = 'no';
|
||||
const WITH_AUTHOR_DATE = 'with_author_date';
|
||||
const WITHOUT_AUTHOR_DATE = 'without_author_date';
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Enum;
|
||||
|
||||
use AppBundle\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Class ThemeTypeEnum
|
||||
* @package UserBundle\Enum
|
||||
*
|
||||
* @method static ThemeTypeEnum enhanced()
|
||||
* @method static ThemeTypeEnum plain()
|
||||
*/
|
||||
class ThemeTypeEnum extends AbstractEnum
|
||||
{
|
||||
|
||||
const ENHANCED = 'enhanced';
|
||||
const PLAIN = 'plain';
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Enum;
|
||||
|
||||
use AppBundle\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Class UserRoleEnum
|
||||
* @package UserBundle\Enum
|
||||
*
|
||||
* @method static UserRoleEnum subscriber()
|
||||
* @method static UserRoleEnum masterUser()
|
||||
* @method static UserRoleEnum admin()
|
||||
* @method static UserRoleEnum superAdmin()
|
||||
*/
|
||||
class UserRoleEnum extends AbstractEnum
|
||||
{
|
||||
|
||||
const SUBSCRIBER = 'ROLE_SUBSCRIBER';
|
||||
const MASTER_USER = 'ROLE_MASTER_USER';
|
||||
const ADMIN = 'ROLE_ADMIN';
|
||||
const SUPER_ADMIN = 'ROLE_SUPER_ADMIN';
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
|
||||
use Symfony\Component\Validator\Constraints\Callback;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use UserBundle\Entity\User;
|
||||
|
||||
/**
|
||||
* Class ChangePasswordType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class ChangePasswordType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserPasswordEncoderInterface
|
||||
*/
|
||||
private $userPasswordEncoder;
|
||||
|
||||
/**
|
||||
* ChangePasswordType constructor.
|
||||
*
|
||||
* @param UserPasswordEncoderInterface $userPasswordEncoder A UserPasswordEncoderInterface
|
||||
* instance.
|
||||
*/
|
||||
public function __construct(UserPasswordEncoderInterface $userPasswordEncoder)
|
||||
{
|
||||
$this->userPasswordEncoder = $userPasswordEncoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('password', PasswordType::class, [
|
||||
'trim' => true,
|
||||
'property_path' => 'plainPassword',
|
||||
'constraints' => new NotBlank(),
|
||||
])
|
||||
->add('oldPassword', PasswordType::class, [
|
||||
'trim' => true,
|
||||
'mapped' => false,
|
||||
'constraints' => [
|
||||
new NotBlank(),
|
||||
new Callback([ $this, 'checkPassword' ]),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => User::class,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $value Old user password.
|
||||
* @param ExecutionContextInterface $context A ExecutionContextInterface
|
||||
* instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function checkPassword($value, ExecutionContextInterface $context)
|
||||
{
|
||||
if ($value === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var FormInterface $form */
|
||||
$form = $context->getRoot();
|
||||
/** @var User $user */
|
||||
$user = $form->getData();
|
||||
|
||||
if (! $this->userPasswordEncoder->isPasswordValid($user, $value)) {
|
||||
$context->buildViolation('Old password don\'t match to current password')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form\Extension\Core\DataMapper;
|
||||
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
|
||||
/**
|
||||
* Class NotificationDataMapper
|
||||
* @package UserBundle\Form\Extension\Core\DataMapper
|
||||
*/
|
||||
class NotificationDataMapper extends PropertyPathMapper
|
||||
{
|
||||
|
||||
/**
|
||||
* List of required form fields.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private static $requiredFields = [
|
||||
'sources',
|
||||
'automatic',
|
||||
'plainDiff',
|
||||
'enhancedDiff',
|
||||
];
|
||||
|
||||
/**
|
||||
* Maps properties of some data to a list of forms.
|
||||
*
|
||||
* @param mixed $data Structured data.
|
||||
* @param FormInterface[]|array $forms A list of {@link FormInterface} instances.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function mapDataToForms($data, $forms)
|
||||
{
|
||||
// Do nothing because it's not necessary.
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the data of a list of forms into the properties of some data.
|
||||
*
|
||||
* @param FormInterface[]|\Traversable $forms A list of {@link FormInterface}
|
||||
* instances.
|
||||
* @param mixed $data Structured data.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws UnexpectedTypeException If the type of the data parameter is not
|
||||
* supported.
|
||||
*/
|
||||
public function mapFormsToData($forms, &$data)
|
||||
{
|
||||
$forms = iterator_to_array($forms);
|
||||
if (! $data instanceof Notification) {
|
||||
throw new UnexpectedTypeException($data, Notification::class);
|
||||
}
|
||||
|
||||
//
|
||||
// Check that all required fields is set.
|
||||
//
|
||||
// if (\Functional\some(self::$requiredFields, function ($name) use ($forms) {
|
||||
// return ! isset($forms[$name]);
|
||||
// })) {
|
||||
if (\nspl\a\any(self::$requiredFields, function ($name) use ($forms) {
|
||||
return ! isset($forms[$name]);
|
||||
})) {
|
||||
throw new UnexpectedTypeException(current($forms)->getParent(), Notification::class);
|
||||
}
|
||||
|
||||
//
|
||||
// Map sources.
|
||||
//
|
||||
$sources = $forms['sources']->getData();
|
||||
|
||||
// todo uncomment and refactor when analytics is added
|
||||
// if (($sources['feeds'] !== null) && ($sources['charts'] !== null)) {
|
||||
if (isset($sources['feeds'])) {
|
||||
// Do not map data if we have null.
|
||||
$data
|
||||
->setFeeds($sources['feeds']);
|
||||
}
|
||||
|
||||
//
|
||||
// Map schedules.
|
||||
//
|
||||
$data->setSchedules($forms['automatic']->getData());
|
||||
|
||||
//
|
||||
// Map diffs.
|
||||
//
|
||||
$data->setPlainThemeOptionsDiff($forms['plainDiff']->getData());
|
||||
$data->setEnhancedThemeOptionsDiff($forms['enhancedDiff']->getData());
|
||||
|
||||
//
|
||||
// Remove all processed fields.
|
||||
//
|
||||
// \Functional\each(self::$requiredFields, function ($name) use (&$forms) {
|
||||
// unset($forms[$name]);
|
||||
// });
|
||||
foreach (self::$requiredFields as $name) {
|
||||
unset($forms[$name]);
|
||||
}
|
||||
|
||||
//
|
||||
// Map other fields.
|
||||
//
|
||||
parent::mapFormsToData($forms, $data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\Recipient\GroupRecipient;
|
||||
use UserBundle\Entity\Recipient\PersonRecipient;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Repository\NotificationRepository;
|
||||
use UserBundle\Repository\PersonRecipientRepository;
|
||||
|
||||
/**
|
||||
* Class GroupRecipientType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class GroupRecipientType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* @var TokenStorageInterface
|
||||
*/
|
||||
private $storage;
|
||||
|
||||
/**
|
||||
* PersonRecipientType constructor.
|
||||
*
|
||||
* @param TokenStorageInterface $storage A TokenStorageInterface instance.
|
||||
*/
|
||||
public function __construct(TokenStorageInterface $storage)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$user = \app\op\invokeIf($this->storage->getToken(), 'getUser');
|
||||
|
||||
$builder
|
||||
->add('name')
|
||||
->add('description')
|
||||
->add('active', CheckboxType::class)
|
||||
->add('recipients', EntityType::class, [
|
||||
'class' => PersonRecipient::class,
|
||||
'multiple' => true,
|
||||
'by_reference' => false,
|
||||
'query_builder' => function (PersonRecipientRepository $repository) use ($user) {
|
||||
if ($user instanceof User) {
|
||||
return $repository->getAvailableForUser($user);
|
||||
}
|
||||
|
||||
return $repository->createQueryBuilder('Person');
|
||||
},
|
||||
])
|
||||
->add('notifications', EntityType::class, [
|
||||
'class' => Notification::class,
|
||||
'multiple' => true,
|
||||
'by_reference' => false,
|
||||
'query_builder' => function (NotificationRepository $repository) use ($user) {
|
||||
if ($user instanceof User) {
|
||||
return $repository->getQueryBuilderForForm($user);
|
||||
}
|
||||
|
||||
return $repository->createQueryBuilder('Notification');
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => GroupRecipient::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use PaymentBundle\Enum\PaymentGatewayEnum;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataMapperInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\Length;
|
||||
use Symfony\Component\Validator\Constraints\Regex;
|
||||
use UserBundle\Entity\Organization;
|
||||
use UserBundle\Entity\Plan;
|
||||
use UserBundle\Entity\Subscription\OrganizationSubscription;
|
||||
use UserBundle\Entity\Subscription\PersonalSubscription;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Enum\UserRoleEnum;
|
||||
use UserBundle\Repository\OrganizationRepository;
|
||||
|
||||
/**
|
||||
* Class HubSpotRegistrationType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class HubSpotRegistrationType extends AbstractType implements DataMapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* RegistrationType constructor.
|
||||
*
|
||||
* @param EntityManagerInterface $em A EntityManagerInterface instance.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('email', EmailType::class, [
|
||||
'constraints' => [
|
||||
new Regex([
|
||||
'pattern' => '/^[a-zA-Z0-9!#$%&\'*+\/=?^_` {|}~;."-]+@[a-zA-Z0-9!#$%&\'*+\/=?^_` {|}~;."-]+\.[a-zA-Z0-9]+$/',
|
||||
'message' => 'This value is not a valid email address',
|
||||
]),
|
||||
new Length([
|
||||
'max' => 160,
|
||||
'maxMessage' => 'Email address is too long. It should have {{ limit }} character or less',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('firstName')
|
||||
->add('lastName')
|
||||
->add('companyName')
|
||||
->add('jobFunction')
|
||||
->add('numberOfEmployee')
|
||||
->add('industry')
|
||||
->add('websiteUrl')
|
||||
// ->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
|
||||
// $data = $event->getData();
|
||||
// $form = $event->getForm();
|
||||
// })
|
||||
->setDataMapper($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => User::class,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps properties of some data to a list of forms.
|
||||
*
|
||||
* @param User|null $data Structured data.
|
||||
* @param FormInterface[]|\RecursiveIteratorIterator $forms A list of
|
||||
* {@link FormInterface}
|
||||
* instances.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function mapDataToForms($data, $forms)
|
||||
{
|
||||
// Do nothing because it's not necessary method.
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the data of a list of forms into the properties of some data.
|
||||
*
|
||||
* @param FormInterface[]|\RecursiveIteratorIterator $forms A list of
|
||||
* {@link FormInterface}
|
||||
* instances.
|
||||
* @param User|null $data Structured data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function mapFormsToData($forms, &$data)
|
||||
{
|
||||
$forms = iterator_to_array($forms);
|
||||
|
||||
$data->setEmail($forms['email']->getData());
|
||||
$data->setFirstName($forms['firstName']->getData());
|
||||
$data->setLastName($forms['lastName']->getData());
|
||||
$data->setJobFunction($forms['jobFunction']->getData());
|
||||
$data->setCompanyName($forms['companyName']->getData());
|
||||
$data->setNumberOfEmployee($forms['numberOfEmployee']->getData());
|
||||
$data->setIndustry($forms['industry']->getData());
|
||||
$data->setWebsiteUrl($forms['websiteUrl']->getData());
|
||||
$data->setPhoneNumber(' ');
|
||||
$data->setHubSpot(true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use AppBundle\Form\Type\EnumType;
|
||||
use CacheBundle\Form\Type\CurrentUserOwnedEntityType;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type as FormType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\Notification\NotificationTheme;
|
||||
use UserBundle\Entity\Recipient\AbstractRecipient;
|
||||
use UserBundle\Enum\NotificationTypeEnum;
|
||||
use UserBundle\Enum\ThemeTypeEnum;
|
||||
use UserBundle\Form\Extension\Core\DataMapper\NotificationDataMapper;
|
||||
use UserBundle\Form\Type\NotificationDiffType;
|
||||
use UserBundle\Form\Type\ScheduleType;
|
||||
use UserBundle\Form\Type\SimpleTimeZoneType;
|
||||
use UserBundle\Form\Type\SourcesType;
|
||||
|
||||
/**
|
||||
* Class NotificationType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class NotificationType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('name')
|
||||
->add('notificationType', EnumType::class, [
|
||||
'enum_class' => NotificationTypeEnum::class,
|
||||
])
|
||||
->add('recipients', CurrentUserOwnedEntityType::class, [
|
||||
'class' => AbstractRecipient::class,
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
'by_reference' => 'false',
|
||||
'user_property' => 'owner',
|
||||
])
|
||||
->add('themeType', EnumType::class, [
|
||||
'enum_class' => ThemeTypeEnum::class,
|
||||
])
|
||||
->add('theme', EntityType::class, [
|
||||
'class' => NotificationTheme::class,
|
||||
])
|
||||
->add('subject', null, [ 'required' => false ])
|
||||
->add('automatedSubject', FormType\CheckboxType::class)
|
||||
->add('published', FormType\CheckboxType::class)
|
||||
->add('allowUnsubscribe', FormType\CheckboxType::class)
|
||||
->add('unsubscribeNotification', FormType\CheckboxType::class)
|
||||
->add('sources', SourcesType::class)
|
||||
->add('sendWhenEmpty', FormType\CheckboxType::class)
|
||||
->add('timezone', SimpleTimeZoneType::class)
|
||||
->add('automatic', FormType\CollectionType::class, [
|
||||
'entry_type' => ScheduleType::class,
|
||||
'description' => 'Array of daily, weekly or monthly scheduling objects.',
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
'empty_data' => [],
|
||||
])
|
||||
->add('sendUntil', FormType\DateType::class, [ 'widget' => 'single_text' ])
|
||||
->add('plainDiff', NotificationDiffType::class)
|
||||
->add('enhancedDiff', NotificationDiffType::class)
|
||||
->setDataMapper(new NotificationDataMapper())
|
||||
->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
|
||||
$data = $event->getData();
|
||||
$form = $event->getForm();
|
||||
|
||||
if (isset($data['automatedSubject']) && ($data['automatedSubject'] === false)) {
|
||||
$options = $form->get('subject')->getConfig()->getOptions();
|
||||
$options['constraints'] = new NotBlank([ 'message' => 'Subject should not be blank' ]);
|
||||
|
||||
$form
|
||||
->remove('subject')
|
||||
->add('subject', null, $options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefault('data_class', Notification::class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use UserBundle\Entity\Organization;
|
||||
use UserBundle\Entity\Plan;
|
||||
use UserBundle\Entity\Subscription\OrganizationSubscription;
|
||||
|
||||
/**
|
||||
* Class OrganizationType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class OrganizationType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('organizationAddress')
|
||||
->add('organizationEmail')
|
||||
->add('organizationPhone')
|
||||
->add('organizationPhone')
|
||||
->add('organization', EntityType::class, array('class' => Organization::class))
|
||||
->add('billingPlanId', EntityType::class, array('class' => Plan::class, 'property_path' => 'plan'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => OrganizationSubscription::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use PaymentBundle\Enum\PaymentGatewayEnum;
|
||||
use PaymentBundle\Model\PaymentData;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataMapperInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints as Constraint;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Form\Type\CreditCardType;
|
||||
|
||||
/**
|
||||
* Class PaymentDataType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class PaymentDataType extends AbstractType implements DataMapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var User[]
|
||||
*/
|
||||
private $userCache = [];
|
||||
|
||||
/**
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* PaymentDataType constructor.
|
||||
*
|
||||
* @param EntityManagerInterface $em A EntityManagerInterface instance.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('paymentGateway', ChoiceType::class, [
|
||||
'choices' => PaymentGatewayEnum::getAvailables(),
|
||||
'empty_data' => PaymentGatewayEnum::PAYPAL,
|
||||
])
|
||||
->add('code', null, [
|
||||
'constraints' => [
|
||||
new Constraint\NotBlank(),
|
||||
new Constraint\Callback([ $this, 'validateCode' ]),
|
||||
],
|
||||
])
|
||||
->add('card', CreditCardType::class)
|
||||
->setDataMapper($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => PaymentData::class,
|
||||
'empty_data' => new PaymentData(PaymentGatewayEnum::paypal()),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps properties of some data to a list of forms.
|
||||
*
|
||||
* @param PaymentData|null $data Structured data.
|
||||
* @param FormInterface[]|\Iterator $forms A list of {@link FormInterface}
|
||||
* instances.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function mapDataToForms($data, $forms)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the data of a list of forms into the properties of some data.
|
||||
*
|
||||
* @param FormInterface[]|\Iterator $forms A list of {@link FormInterface}
|
||||
* instances.
|
||||
* @param PaymentData|null $data Structured data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function mapFormsToData($forms, &$data)
|
||||
{
|
||||
$forms = iterator_to_array($forms);
|
||||
$user = $this->getUserByCode($forms['code']->getData());
|
||||
|
||||
try {
|
||||
$data = new PaymentData(
|
||||
new PaymentGatewayEnum($forms['paymentGateway']->getData()),
|
||||
$user,
|
||||
$forms['card']->getData()
|
||||
);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
//
|
||||
// This may occurred 'cause form don't validate values before mapping
|
||||
// it data to source object.
|
||||
//
|
||||
throw new \RuntimeException('Can\'t create payment data', 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $code Validated code.
|
||||
* @param ExecutionContextInterface $context A ExecutionContextInterface
|
||||
* instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function validateCode($code, ExecutionContextInterface $context)
|
||||
{
|
||||
$user = $this->getUserByCode($code);
|
||||
|
||||
if ($user === null) {
|
||||
$context->buildViolation('Invalid code. Can\'t find user with specified code')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $code User confirmation code.
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
private function getUserByCode($code)
|
||||
{
|
||||
if (! array_key_exists($code, $this->userCache)) {
|
||||
$this->userCache[$code] = $this->em->getRepository(User::class)
|
||||
->findOneBy(['confirmationToken' => $code]);
|
||||
}
|
||||
|
||||
return $this->userCache[$code];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\Recipient\GroupRecipient;
|
||||
use UserBundle\Entity\Recipient\PersonRecipient;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Repository\GroupRecipientRepository;
|
||||
use UserBundle\Repository\NotificationRepository;
|
||||
|
||||
/**
|
||||
* Class PersonRecipientType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class PersonRecipientType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* @var TokenStorageInterface
|
||||
*/
|
||||
private $storage;
|
||||
|
||||
/**
|
||||
* PersonRecipientType constructor.
|
||||
*
|
||||
* @param TokenStorageInterface $storage A TokenStorageInterface instance.
|
||||
*/
|
||||
public function __construct(TokenStorageInterface $storage)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$user = \app\op\invokeIf($this->storage->getToken(), 'getUser');
|
||||
|
||||
$builder
|
||||
->add('firstName')
|
||||
->add('lastName')
|
||||
->add('email', EmailType::class)
|
||||
->add('active', CheckboxType::class)
|
||||
->add('groups', EntityType::class, [
|
||||
'class' => GroupRecipient::class,
|
||||
'multiple' => true,
|
||||
'by_reference' => false,
|
||||
'query_builder' => function (GroupRecipientRepository $repository) use ($user) {
|
||||
if ($user instanceof User) {
|
||||
return $repository->getAvailableForUser($user);
|
||||
}
|
||||
|
||||
return $repository->createQueryBuilder('Grp');
|
||||
},
|
||||
])
|
||||
->add('notifications', EntityType::class, [
|
||||
'class' => Notification::class,
|
||||
'multiple' => true,
|
||||
'by_reference' => false,
|
||||
'query_builder' => function (NotificationRepository $repository) use ($user) {
|
||||
if ($user instanceof User) {
|
||||
return $repository->getQueryBuilderForForm($user);
|
||||
}
|
||||
|
||||
return $repository->createQueryBuilder('Notification');
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => PersonRecipient::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use UserBundle\Entity\Plan;
|
||||
|
||||
/**
|
||||
* Class PlanType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class PlanType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('title', null, [
|
||||
'constraints' => new NotBlank(),
|
||||
])
|
||||
->add('price', MoneyType::class, [
|
||||
'currency' => 'USD',
|
||||
])
|
||||
->add('searchesPerDay', IntegerType::class, [ 'attr' => [ 'min' => 0 ] ])
|
||||
->add('savedFeeds', IntegerType::class, [ 'attr' => [ 'min' => 0 ] ])
|
||||
->add('masterAccounts', IntegerType::class, [ 'attr' => [ 'min' => 0 ] ])
|
||||
->add('subscriberAccounts', IntegerType::class, [ 'attr' => [ 'min' => 0 ] ])
|
||||
->add('alerts', IntegerType::class, [ 'attr' => [ 'min' => 0 ] ])
|
||||
->add('newsletters', IntegerType::class, [ 'attr' => [ 'min' => 0 ] ])
|
||||
->add('analytics', CheckboxType::class, [ 'required' => false ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Plan::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,392 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use PaymentBundle\Enum\PaymentGatewayEnum;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataMapperInterfacePasswordType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\Length;
|
||||
use Symfony\Component\Validator\Constraints\Regex;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use UserBundle\Entity\Organization;
|
||||
use UserBundle\Entity\Plan;
|
||||
use UserBundle\Entity\Subscription\OrganizationSubscription;
|
||||
use UserBundle\Entity\Subscription\PersonalSubscription;
|
||||
use UserBundle\Entity\User;
|
||||
use CacheBundle\Entity\Category;
|
||||
use UserBundle\Enum\UserRoleEnum;
|
||||
use UserBundle\Repository\OrganizationRepository;
|
||||
use Symfony\Component\Form\DataMapperInterface;
|
||||
/**
|
||||
* Class RegistrationType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class RegistrationType extends AbstractType implements DataMapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* RegistrationType constructor.
|
||||
*
|
||||
* @param EntityManagerInterface $em A EntityManagerInterface instance.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('email', EmailType::class, [
|
||||
'constraints' => [
|
||||
new Regex([
|
||||
'pattern' => '/^[a-zA-Z0-9!#$%&\'*+\/=?^_` {|}~;."-]+@[a-zA-Z0-9!#$%&\'*+\/=?^_` {|}~;."-]+\.[a-zA-Z0-9]+$/',
|
||||
'message' => 'This value is not a valid email address',
|
||||
]),
|
||||
new Length([
|
||||
'max' => 160,
|
||||
'maxMessage' => 'Email address is too long. It should have {{ limit }} character or less',
|
||||
]),
|
||||
new NotBlank([
|
||||
'message' => 'Email address should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('firstName')
|
||||
->add('lastName')
|
||||
->add('companyName')
|
||||
->add('jobFunction')
|
||||
->add('industry')
|
||||
->add('websiteUrl')
|
||||
->add('password',PasswordType::class)
|
||||
->add('numberOfEmployee');
|
||||
|
||||
if (!empty($options['paymentID'])) {
|
||||
//->add('phoneNumber')
|
||||
$builder->add('searchesPerDay', TextType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank([
|
||||
'message' => 'Searches Per Day should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('savedFeeds', TextType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank([
|
||||
'message' => 'Saved Feeds should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('masterAccounts', TextType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank([
|
||||
'message' => 'Master Accounts should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('subscriberAccounts', TextType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank([
|
||||
'message' => 'Subscriber Accounts should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('webFeeds', TextType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank([
|
||||
'message' => 'Web Feeds should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('alerts', TextType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank([
|
||||
'message' => 'Alerts should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('news', TextType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank([
|
||||
'message' => 'News should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('blog', TextType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank([
|
||||
'message' => 'Blog should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('reddit', TextType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank([
|
||||
'message' => 'Reddit should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('instagram', TextType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank([
|
||||
'message' => 'Instagram should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('twitter', TextType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank([
|
||||
'message' => 'Twitter should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('analytics', TextType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank([
|
||||
'message' => 'Analytics should not be blank',
|
||||
]),
|
||||
],
|
||||
])
|
||||
->add('paymentID');
|
||||
//->add('billingPlanId', EntityType::class, [ 'class' => Plan::class ])
|
||||
// ->add('privatePerson', CheckboxType::class, [ 'mapped' => false ])
|
||||
// ->add('organizationName', null, [ 'description' => 'Used only for organization subscription.' ])
|
||||
// ->add('organizationAddress', null, [ 'description' => 'Used only for organization subscription.' ])
|
||||
// ->add('organizationEmail', null, [ 'description' => 'Used only for organization subscription.' ])
|
||||
// ->add('organizationPhone', null, [ 'description' => 'Used only for organization subscription.' ])
|
||||
// ->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
|
||||
// $data = $event->getData();
|
||||
// $form = $event->getForm();
|
||||
// if (isset($data['privatePerson']) && $data['privatePerson']) {
|
||||
// $form
|
||||
// ->remove('organizationName')
|
||||
// ->remove('organizationAddress')
|
||||
// ->remove('organizationEmail')
|
||||
// ->remove('organizationPhone');
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
$builder->setDataMapper($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => User::class,
|
||||
'paymentID' => null
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps properties of some data to a list of forms.
|
||||
*
|
||||
* @param User|null $data Structured data.
|
||||
* @param FormInterface[]|\RecursiveIteratorIterator $forms A list of
|
||||
* {@link FormInterface}
|
||||
* instances.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function mapDataToForms($data, $forms)
|
||||
{
|
||||
// Do nothing because it's not necessary method.
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the data of a list of forms into the properties of some data.
|
||||
*
|
||||
* @param FormInterface[]|\RecursiveIteratorIterator $forms A list of
|
||||
* {@link FormInterface}
|
||||
* instances.
|
||||
* @param User|null $data Structured data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function mapFormsToData($forms, &$data)
|
||||
{
|
||||
$forms = iterator_to_array($forms);
|
||||
// TODO for now it's ok, but used gateway should be selected by users.
|
||||
$gateway = PaymentGatewayEnum::paypal();
|
||||
//Add plan
|
||||
if (isset(
|
||||
$forms['news'],
|
||||
$forms['blog'],
|
||||
$forms['reddit'],
|
||||
$forms['instagram'],
|
||||
$forms['twitter'],
|
||||
$forms['analytics'],
|
||||
$forms['searchesPerDay'],
|
||||
$forms['savedFeeds'],
|
||||
$forms['masterAccounts'],
|
||||
$forms['subscriberAccounts'],
|
||||
$forms['webFeeds'],
|
||||
$forms['alerts'],
|
||||
$forms['paymentID']
|
||||
) &&
|
||||
($forms['searchesPerDay']->getData() >= 0) &&
|
||||
($forms['savedFeeds']->getData() >= 0) &&
|
||||
($forms['masterAccounts']->getData() >= 0) &&
|
||||
($forms['subscriberAccounts']->getData() >= 0) &&
|
||||
($forms['webFeeds']->getData() >= 0) &&
|
||||
($forms['alerts']->getData() >= 0)
|
||||
) {
|
||||
$plan = Plan::create()
|
||||
->setTitle($forms['companyName']->getData())
|
||||
->setInnerName('Starter')
|
||||
->setPrice(0)
|
||||
->setNews($forms['news']->getData())
|
||||
->setBlog($forms['blog']->getData())
|
||||
->setReddit($forms['reddit']->getData())
|
||||
->setInstagram($forms['instagram']->getData())
|
||||
->setTwitter($forms['twitter']->getData())
|
||||
->setAnalytics($forms['analytics']->getData())
|
||||
->setSearchesPerDay($forms['searchesPerDay']->getData())
|
||||
->setSavedFeeds($forms['savedFeeds']->getData())
|
||||
->setMasterAccounts($forms['masterAccounts']->getData())
|
||||
->setSubscriberAccounts($forms['subscriberAccounts']->getData())
|
||||
->setWebFeeds($forms['webFeeds']->getData())
|
||||
->setAlerts($forms['alerts']->getData());
|
||||
$this->em->persist($plan);
|
||||
|
||||
$subscription = OrganizationSubscription::create()
|
||||
->setPlan($plan)
|
||||
->setGateway($gateway)
|
||||
->addUser($data)
|
||||
->setOwner($data);
|
||||
|
||||
//Category add default
|
||||
$category = new Category($data, 'My Hose');
|
||||
$category->setType(Category::TYPE_MY_CONTENT);
|
||||
$category = new Category($data, 'Shared Hose');
|
||||
$category->setType(Category::TYPE_SHARED_CONTENT);
|
||||
$category = new Category($data, 'Deleted Hose');
|
||||
$category->setType(Category::TYPE_DELETED_CONTENT);
|
||||
} else if (!isset($forms['paymentID'])) {
|
||||
$gateway = PaymentGatewayEnum::free();
|
||||
//Get a free plan
|
||||
$repository = $this->em->getRepository(Plan::class);
|
||||
$planObj = $repository->findOneBy([ 'title' => 'Free' ]);
|
||||
$plan = Plan::create()
|
||||
->setTitle($forms['companyName']->getData())
|
||||
->setInnerName('Starter')
|
||||
->setPrice(0)
|
||||
->setNews($planObj->isNews())
|
||||
->setBlog($planObj->isBlog())
|
||||
->setReddit($planObj->isReddit())
|
||||
->setInstagram($planObj->isInstagram())
|
||||
->setTwitter($planObj->isTwitter())
|
||||
->setAnalytics($planObj->isAnalytics())
|
||||
->setSearchesPerDay($planObj->getSearchesPerDay())
|
||||
->setSavedFeeds($planObj->getSavedFeeds())
|
||||
->setMasterAccounts($planObj->getMasterAccounts())
|
||||
->setSubscriberAccounts($planObj->getSubscriberAccounts())
|
||||
->setAlerts($planObj->getAlerts())
|
||||
->setNewsLetters($planObj->getNewsLetters())
|
||||
->setWebFeeds($planObj->getWebFeeds())
|
||||
->setAlerts($planObj->getAlerts());
|
||||
$this->em->persist($plan);
|
||||
|
||||
$subscription = OrganizationSubscription::create()
|
||||
->setPlan($plan)
|
||||
->setGateway($gateway)
|
||||
->addUser($data)
|
||||
->setOwner($data);
|
||||
|
||||
//Category add default
|
||||
$category = new Category($data, 'My Hose');
|
||||
$category->setType(Category::TYPE_MY_CONTENT);
|
||||
$category = new Category($data, 'Shared Hose');
|
||||
$category->setType(Category::TYPE_SHARED_CONTENT);
|
||||
$category = new Category($data, 'Deleted Hose');
|
||||
$category->setType(Category::TYPE_DELETED_CONTENT);
|
||||
|
||||
}
|
||||
// if (isset(
|
||||
// $forms['organizationName'],
|
||||
// $forms['organizationAddress'],
|
||||
// $forms['organizationEmail'],
|
||||
// $forms['organizationPhone']
|
||||
// )) {
|
||||
// //
|
||||
// // Try to find already exists organization.
|
||||
// //
|
||||
// $orgName = $forms['organizationName']->getData();
|
||||
|
||||
// /** @var OrganizationRepository $repository */
|
||||
// $repository = $this->em->getRepository(Organization::class);
|
||||
// $organization = $repository->findOneBy([ 'name' => $orgName ]);
|
||||
|
||||
// if (! $organization instanceof Organization) {
|
||||
// $organization = Organization::create()->setName($orgName);
|
||||
// $data->setRoles([ UserRoleEnum::MASTER_USER ]);
|
||||
// $this->em->persist($organization);
|
||||
// } else {
|
||||
// $data->setRoles([ UserRoleEnum::SUBSCRIBER ]);
|
||||
// }
|
||||
|
||||
// $subscription = OrganizationSubscription::create()
|
||||
// ->setOrganization($organization)
|
||||
// ->setOrganizationAddress($forms['organizationAddress']->getData())
|
||||
// ->setOrganizationEmail($forms['organizationEmail']->getData())
|
||||
// ->setOrganizationPhone($forms['organizationPhone']->getData());
|
||||
// }
|
||||
// else {
|
||||
// $subscription = PersonalSubscription::create();
|
||||
// $data->setRoles([ UserRoleEnum::MASTER_USER ]);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
$data->setRoles([ UserRoleEnum::MASTER_USER ]);
|
||||
$data->setEmail($forms['email']->getData());
|
||||
$data->setFirstName($forms['firstName']->getData());
|
||||
$data->setIndustry($forms['industry']->getData());
|
||||
$data->setLastName($forms['lastName']->getData());
|
||||
$data->setCompanyName($forms['companyName']->getData());
|
||||
$data->setJobFunction($forms['jobFunction']->getData());
|
||||
$data->setWebsiteUrl($forms['websiteUrl']->getData());
|
||||
$data->setNumberOfEmployee($forms['numberOfEmployee']->getData());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Constraints\Email;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
|
||||
/**
|
||||
* Class ResetPasswordType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class ResetPasswordType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('email', EmailType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank(),
|
||||
new Email(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use UserBundle\Entity\User;
|
||||
|
||||
/**
|
||||
* Class ResettingConfirmType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class ResettingConfirmType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('confirmationToken', null, [ 'constraints' => new NotBlank() ])
|
||||
->add('password', null, [ 'constraints' => new NotBlank() ]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Constraints\Email;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
|
||||
/**
|
||||
* Class ResettingRequestType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class ResettingRequestType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add('email', EmailType::class, [
|
||||
'constraints' => [
|
||||
new NotBlank(),
|
||||
new Email(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use UserBundle\Entity\User;
|
||||
|
||||
/**
|
||||
* Class SubscriberType
|
||||
* @package UserBundle\Form
|
||||
*/
|
||||
class SubscriberType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('email', EmailType::class)
|
||||
->add('firstName')
|
||||
->add('lastName')
|
||||
->add('position')
|
||||
->add('phoneNumber')
|
||||
->add('allowToCreateSavedFeeds');
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => User::class,
|
||||
'validation_groups' => [ 'subscribers_creation' ],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\Callback;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
/**
|
||||
* Class ColorType
|
||||
*
|
||||
* @package UserBundle\Form\Type
|
||||
*/
|
||||
class ColorType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefault('constraints', new Callback([ $this, 'validate' ]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the parent type.
|
||||
*
|
||||
* @return string|null The name of the parent type if any, null otherwise.
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return TextType::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate sources.
|
||||
*
|
||||
* @param mixed $color Color.
|
||||
* @param ExecutionContextInterface $context A ExecutionContextInterface
|
||||
* instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function validate($color, ExecutionContextInterface $context)
|
||||
{
|
||||
if ($color === null) {
|
||||
// Do not validate null values.
|
||||
return;
|
||||
}
|
||||
|
||||
$matches = [];
|
||||
|
||||
if (is_string($color) && preg_match('/rgba\(([0-9%.,\s]+)\)/', $color, $matches)) {
|
||||
$arguments = array_map('trim', explode(',', $matches[1]));
|
||||
|
||||
if (count($arguments) === 4) {
|
||||
$alpha = array_pop($arguments);
|
||||
|
||||
//
|
||||
// Validate color components.
|
||||
//
|
||||
if (is_numeric($alpha) && $this->containsColorDigits($arguments)) {
|
||||
//
|
||||
// Validate alpha component.
|
||||
//
|
||||
|
||||
$alpha = (float) $alpha;
|
||||
|
||||
if (($alpha >= 0.0) && ($alpha <= 1.0)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It's not valid 'rgba' color.
|
||||
$context
|
||||
->buildViolation('Color should be valid css color definition string')
|
||||
->addViolation();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array Checked array.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function containsColorDigits(array $array)
|
||||
{
|
||||
// return \Functional\every($array, function ($item) {
|
||||
return \nspl\a\all($array, function ($item) {
|
||||
if (! is_numeric($item)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$item = (int) $item;
|
||||
|
||||
return ($item >= 0) && ($item <= 255);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form\Type;
|
||||
|
||||
use PaymentBundle\Model\CreditCardAddress;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataMapperInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CountryType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
|
||||
/**
|
||||
* Class CreditCardAddressType
|
||||
*
|
||||
* @package UserBundle\Form\Type
|
||||
*/
|
||||
class CreditCardAddressType extends AbstractType implements DataMapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('country', CountryType::class, [
|
||||
'constraints' => new NotBlank(),
|
||||
])
|
||||
->add('city', null, [ 'constraints' => new NotBlank() ])
|
||||
->add('street', null, [ 'constraints' => new NotBlank() ])
|
||||
->add('postalCode', null, [ 'constraints' => new NotBlank() ])
|
||||
->setDataMapper($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps properties of some data to a list of forms.
|
||||
*
|
||||
* @param CreditCardAddress|null $data Structured data.
|
||||
* @param FormInterface[]|\Iterator $forms A list of {@link FormInterface}
|
||||
* instances.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function mapDataToForms($data, $forms)
|
||||
{
|
||||
if ($data !== null) {
|
||||
$forms = iterator_to_array($forms);
|
||||
$forms['country']->setData($data->getCountry());
|
||||
$forms['city']->setData($data->getCity());
|
||||
$forms['street']->setData($data->getStreet());
|
||||
$forms['postalCode']->setData($data->getPostalCode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the data of a list of forms into the properties of some data.
|
||||
*
|
||||
* @param FormInterface[]|\Iterator $forms A list of {@link FormInterface}
|
||||
* instances.
|
||||
* @param CreditCardAddress|null $data Structured data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function mapFormsToData($forms, &$data)
|
||||
{
|
||||
$forms = iterator_to_array($forms);
|
||||
|
||||
$data = new CreditCardAddress(
|
||||
$forms['country']->getData(),
|
||||
$forms['city']->getData(),
|
||||
$forms['street']->getData(),
|
||||
$forms['postalCode']->getData()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form\Type;
|
||||
|
||||
use PaymentBundle\Model\CreditCard;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataMapperInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints as Constraint;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
/**
|
||||
* Class CreditCardType
|
||||
*
|
||||
* @package UserBundle\Form\Type
|
||||
*/
|
||||
class CreditCardType extends AbstractType implements DataMapperInterface
|
||||
{
|
||||
|
||||
private static $availableMonth = [
|
||||
'01',
|
||||
'02',
|
||||
'03',
|
||||
'04',
|
||||
'05',
|
||||
'06',
|
||||
'07',
|
||||
'08',
|
||||
'09',
|
||||
'10',
|
||||
'11',
|
||||
'12',
|
||||
];
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$currentYear = (int) date('Y');
|
||||
|
||||
$builder
|
||||
->add('creditCardNumber', null, [
|
||||
'constraints' => [
|
||||
new Constraint\Luhn(),
|
||||
new Constraint\CardScheme([ 'schemes' => [ 'VISA', 'MASTERCARD', 'AMEX' ] ]),
|
||||
],
|
||||
])
|
||||
->add('CVV', null, [
|
||||
'constraints' => [
|
||||
new Constraint\Length([
|
||||
'min' => 3,
|
||||
'max' => 4,
|
||||
'minMessage' => 'Card Verification Code is too short. It should have 3 or 4 characters.',
|
||||
'maxMessage' => 'Card Verification Code is too long. It should have 3 or 4 characters.',
|
||||
]),
|
||||
new Constraint\Type([ 'type' => 'numeric' ]),
|
||||
],
|
||||
])
|
||||
->add('expireMonth', ChoiceType::class, [
|
||||
'choices' => self::$availableMonth,
|
||||
'constraints' => new Constraint\NotBlank(),
|
||||
])
|
||||
->add('expireYear', ChoiceType::class, [
|
||||
'choices' => range($currentYear, $currentYear + 10),
|
||||
'constraints' => new Constraint\NotBlank(),
|
||||
])
|
||||
->add('address', CreditCardAddressType::class)
|
||||
->setDataMapper($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'constraints' => new Constraint\Callback([ $this, 'validate' ]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps properties of some data to a list of forms.
|
||||
*
|
||||
* @param CreditCard|null $data Structured data.
|
||||
* @param FormInterface[]|\Iterator $forms A list of {@link FormInterface}
|
||||
* instances.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function mapDataToForms($data, $forms)
|
||||
{
|
||||
if ($data !== null) {
|
||||
$forms = iterator_to_array($forms);
|
||||
$forms['creditCardNumber']->setData($data->getNumber());
|
||||
$forms['CVV']->setData($data->getCvv());
|
||||
$forms['expireMonth']->setData($data->getExpiresAt()->format('m'));
|
||||
$forms['expireYear']->setData($data->getExpiresAt()->format('Y'));
|
||||
$forms['address']->setData($data->getAddress());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the data of a list of forms into the properties of some data.
|
||||
*
|
||||
* @param FormInterface[]|\Iterator $forms A list of {@link FormInterface}
|
||||
* instances.
|
||||
* @param CreditCard|null $data Structured data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function mapFormsToData($forms, &$data)
|
||||
{
|
||||
$forms = iterator_to_array($forms);
|
||||
|
||||
$expiresAt = \DateTime::createFromFormat(
|
||||
'Y-m-d',
|
||||
$forms['expireYear']->getData(). '-'. $forms['expireMonth']->getData() .'-01'
|
||||
)->setTime(0, 0);
|
||||
|
||||
$data = new CreditCard(
|
||||
'First',
|
||||
'Second',
|
||||
$forms['creditCardNumber']->getData(),
|
||||
$forms['CVV']->getData(),
|
||||
$expiresAt,
|
||||
$forms['address']->getData()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CreditCard|mixed $data Validated payment data.
|
||||
* @param ExecutionContextInterface $context A ExecutionContextInterface
|
||||
* instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function validate($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if (($data instanceof CreditCard)
|
||||
&& ($data->getExpiresAt() < date_create('first day of this month 00:00:00'))) {
|
||||
$context->buildViolation('Card has already expired')
|
||||
->atPath('expireMonth')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,490 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form\Type;
|
||||
|
||||
use AppBundle\Form\Type\EnumType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use UserBundle\Enum\FontFamilyEnum;
|
||||
use UserBundle\Enum\ThemeOptionExtractEnum;
|
||||
use UserBundle\Enum\ThemeOptionsTableOfContentsEnum;
|
||||
use UserBundle\Enum\ThemeOptionsUserCommentsEnum;
|
||||
|
||||
/**
|
||||
* Class ScheduleType
|
||||
* @package UserBundle\Form\Type
|
||||
*/
|
||||
class NotificationDiffType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $typesMap = [
|
||||
'summary' => [
|
||||
'class' => TextType::class,
|
||||
'options' => [
|
||||
'description' => 'Summary text at top of notification.',
|
||||
],
|
||||
],
|
||||
'conclusion' => [
|
||||
'class' => TextType::class,
|
||||
'options' => [
|
||||
'description' => 'Notification conclusion text.',
|
||||
],
|
||||
],
|
||||
|
||||
'header:imageUrl' => [
|
||||
'class' => TextType::class,
|
||||
'options' => [
|
||||
'description' => 'Path to notification logo image.',
|
||||
],
|
||||
],
|
||||
'header:logoLink' => [
|
||||
'class' => TextType::class,
|
||||
'options' => [
|
||||
'description' => 'Logo href.',
|
||||
],
|
||||
],
|
||||
'header:title' => [
|
||||
'class' => TextType::class,
|
||||
'options' => [
|
||||
'description' => 'Notification title. Enhanced only',
|
||||
],
|
||||
],
|
||||
|
||||
'fonts:header:size' => [
|
||||
'class' => NumberType::class,
|
||||
'options' => [
|
||||
'description' => 'Header font size.',
|
||||
],
|
||||
],
|
||||
'fonts:header:family' => [
|
||||
'class' => EnumType::class,
|
||||
'options' => [
|
||||
'enum_class' => FontFamilyEnum::class,
|
||||
'description' => 'Header font family.',
|
||||
],
|
||||
],
|
||||
'fonts:header:style:bold' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should header text bold or not.',
|
||||
],
|
||||
],
|
||||
'fonts:header:style:italic' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should header text italic or not.',
|
||||
],
|
||||
],
|
||||
'fonts:header:style:underline' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should header text underlined or not.',
|
||||
],
|
||||
],
|
||||
'fonts:tableOfContents:size' => [
|
||||
'class' => NumberType::class,
|
||||
'options' => [
|
||||
'description' => 'Table of contents font size.',
|
||||
],
|
||||
],
|
||||
'fonts:tableOfContents:family' => [
|
||||
'class' => EnumType::class,
|
||||
'options' => [
|
||||
'enum_class' => FontFamilyEnum::class,
|
||||
'description' => 'Table of contents font family.',
|
||||
],
|
||||
],
|
||||
'fonts:tableOfContents:style:bold' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should table of contents text bold or not.',
|
||||
],
|
||||
],
|
||||
'fonts:tableOfContents:style:italic' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should table of contents text italic or not.',
|
||||
],
|
||||
],
|
||||
'fonts:tableOfContents:style:underline' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should table of contents text underlined or not.',
|
||||
],
|
||||
],
|
||||
'fonts:feedTitle:size' => [
|
||||
'class' => NumberType::class,
|
||||
'options' => [
|
||||
'description' => 'Feed title font size.',
|
||||
],
|
||||
],
|
||||
'fonts:feedTitle:family' => [
|
||||
'class' => EnumType::class,
|
||||
'options' => [
|
||||
'enum_class' => FontFamilyEnum::class,
|
||||
'description' => 'Feed title font family.',
|
||||
],
|
||||
],
|
||||
'fonts:feedTitle:style:bold' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should feed title text bold or not.',
|
||||
],
|
||||
],
|
||||
'fonts:feedTitle:style:italic' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should feed text text italic or not.',
|
||||
],
|
||||
],
|
||||
'fonts:feedTitle:style:underline' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should feed title text underlined or not.',
|
||||
],
|
||||
],
|
||||
'fonts:articleHeadline:size' => [
|
||||
'class' => NumberType::class,
|
||||
'options' => [
|
||||
'description' => 'Article headline font size.',
|
||||
],
|
||||
],
|
||||
'fonts:articleHeadline:family' => [
|
||||
'class' => EnumType::class,
|
||||
'options' => [
|
||||
'enum_class' => FontFamilyEnum::class,
|
||||
'description' => 'Article headline font family.',
|
||||
],
|
||||
],
|
||||
'fonts:articleHeadline:style:bold' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should article headline text bold or not.',
|
||||
],
|
||||
],
|
||||
'fonts:articleHeadline:style:italic' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should article headline text italic or not.',
|
||||
],
|
||||
],
|
||||
'fonts:articleHeadline:style:underline' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should article headline text underlined or not.',
|
||||
],
|
||||
],
|
||||
'fonts:source:size' => [
|
||||
'class' => NumberType::class,
|
||||
'options' => [
|
||||
'description' => 'Source font size.',
|
||||
],
|
||||
],
|
||||
'fonts:source:family' => [
|
||||
'class' => EnumType::class,
|
||||
'options' => [
|
||||
'enum_class' => FontFamilyEnum::class,
|
||||
'description' => 'Source font family.',
|
||||
],
|
||||
],
|
||||
'fonts:source:style:bold' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should source text bold or not.',
|
||||
],
|
||||
],
|
||||
'fonts:source:style:italic' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should source text italic or not.',
|
||||
],
|
||||
],
|
||||
'fonts:source:style:underline' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should source text underlined or not.',
|
||||
],
|
||||
],
|
||||
'fonts:author:size' => [
|
||||
'class' => NumberType::class,
|
||||
'options' => [
|
||||
'description' => 'Author font size.',
|
||||
],
|
||||
],
|
||||
'fonts:author:family' => [
|
||||
'class' => EnumType::class,
|
||||
'options' => [
|
||||
'enum_class' => FontFamilyEnum::class,
|
||||
'description' => 'Author font family.',
|
||||
],
|
||||
],
|
||||
'fonts:author:style:bold' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should author text bold or not.',
|
||||
],
|
||||
],
|
||||
'fonts:author:style:italic' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should author text italic or not.',
|
||||
],
|
||||
],
|
||||
'fonts:author:style:underline' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should author text underlined or not.',
|
||||
],
|
||||
],
|
||||
'fonts:date:size' => [
|
||||
'class' => NumberType::class,
|
||||
'options' => [
|
||||
'description' => 'Date font size.',
|
||||
],
|
||||
],
|
||||
'fonts:date:family' => [
|
||||
'class' => EnumType::class,
|
||||
'options' => [
|
||||
'enum_class' => FontFamilyEnum::class,
|
||||
'description' => 'Date font family.',
|
||||
],
|
||||
],
|
||||
'fonts:date:style:bold' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should date text bold or not.',
|
||||
],
|
||||
],
|
||||
'fonts:date:style:italic' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should date text italic or not.',
|
||||
],
|
||||
],
|
||||
'fonts:date:style:underline' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should date text underlined or not.',
|
||||
],
|
||||
],
|
||||
'fonts:articleContent:size' => [
|
||||
'class' => NumberType::class,
|
||||
'options' => [
|
||||
'description' => 'Article content font size.',
|
||||
],
|
||||
],
|
||||
'fonts:articleContent:family' => [
|
||||
'class' => EnumType::class,
|
||||
'options' => [
|
||||
'enum_class' => FontFamilyEnum::class,
|
||||
'description' => 'Article content font family.',
|
||||
],
|
||||
],
|
||||
'fonts:articleContent:style:bold' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should article content text bold or not.',
|
||||
],
|
||||
],
|
||||
'fonts:articleContent:style:italic' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should article content text italic or not.',
|
||||
],
|
||||
],
|
||||
'fonts:articleContent:style:underline' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should article content text underlined or not.',
|
||||
],
|
||||
],
|
||||
|
||||
'content:highlightKeywords:highlight' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should highlights search keywords or not',
|
||||
],
|
||||
],
|
||||
'content:highlightKeywords:bold' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Should highlighted search keywords bold or not.',
|
||||
],
|
||||
],
|
||||
'content:highlightKeywords:color' => [
|
||||
'class' => ColorType::class,
|
||||
'options' => [
|
||||
'description' => 'Highlight color.',
|
||||
],
|
||||
],
|
||||
'content:showInfo:userComments' => [
|
||||
'class' => EnumType::class,
|
||||
'options' => [
|
||||
'enum_class' => ThemeOptionsUserCommentsEnum::class,
|
||||
'description' => 'How user comments should shown.',
|
||||
],
|
||||
],
|
||||
'content:showInfo:tableOfContents' => [
|
||||
'class' => EnumType::class,
|
||||
'options' => [
|
||||
'enum_class' => ThemeOptionsTableOfContentsEnum::class,
|
||||
'description' => 'How table of contents should shown.',
|
||||
],
|
||||
],
|
||||
'content:showInfo:sourceCountry' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Show source country or not.',
|
||||
],
|
||||
],
|
||||
'content:showInfo:articleSentiment' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Show article sentiment or not.',
|
||||
],
|
||||
],
|
||||
'content:showInfo:articleCount' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Show article count or not.',
|
||||
],
|
||||
],
|
||||
'content:showInfo:images' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Show images or not.',
|
||||
],
|
||||
],
|
||||
'content:showInfo:sharingOptions' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Show section divider or not.',
|
||||
],
|
||||
],
|
||||
'content:showInfo:sectionDivider' => [
|
||||
'class' => CheckboxType::class,
|
||||
'options' => [
|
||||
'description' => 'Show section divider or not.',
|
||||
],
|
||||
],
|
||||
'content:language' => [
|
||||
'class' => TextType::class,
|
||||
'options' => [
|
||||
'description' => 'Notification language.',
|
||||
],
|
||||
],
|
||||
'content:extract' => [
|
||||
'class' => EnumType::class,
|
||||
'options' => [
|
||||
'enum_class' => ThemeOptionExtractEnum::class,
|
||||
'description' => 'How article content should be extracted',
|
||||
],
|
||||
],
|
||||
|
||||
'colors:background:header' => [
|
||||
'class' => ColorType::class,
|
||||
'options' => [
|
||||
'description' => 'Header background color.',
|
||||
],
|
||||
],
|
||||
'colors:background:emailBody' => [
|
||||
'class' => ColorType::class,
|
||||
'options' => [
|
||||
'description' => 'Email body background color.',
|
||||
],
|
||||
],
|
||||
'colors:background:accent' => [
|
||||
'class' => ColorType::class,
|
||||
'options' => [
|
||||
'description' => 'Accent background color.',
|
||||
],
|
||||
],
|
||||
|
||||
'colors:text:header' => [
|
||||
'class' => ColorType::class,
|
||||
'options' => [
|
||||
'description' => 'Header text color.',
|
||||
],
|
||||
],
|
||||
'colors:text:articleHeadline' => [
|
||||
'class' => ColorType::class,
|
||||
'options' => [
|
||||
'description' => 'Article headline text color.',
|
||||
],
|
||||
],
|
||||
'colors:text:articleContent' => [
|
||||
'class' => ColorType::class,
|
||||
'options' => [
|
||||
'description' => 'Article content text color.',
|
||||
],
|
||||
],
|
||||
'colors:text:author' => [
|
||||
'class' => ColorType::class,
|
||||
'options' => [
|
||||
'description' => 'Author text color.',
|
||||
],
|
||||
],
|
||||
'colors:text:publishDate' => [
|
||||
'class' => ColorType::class,
|
||||
'options' => [
|
||||
'description' => 'Publish date text color.',
|
||||
],
|
||||
],
|
||||
'colors:text:source' => [
|
||||
'class' => ColorType::class,
|
||||
'options' => [
|
||||
'description' => 'Source text color.',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
foreach (self::$typesMap as $name => $config) {
|
||||
$class = $config['class'];
|
||||
$typeOptions = array_merge($config['options'], [ 'required' => false ]);
|
||||
|
||||
$builder->add($name, $class, $typeOptions);
|
||||
}
|
||||
|
||||
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
|
||||
//
|
||||
// Remove not form field which don't submit.
|
||||
//
|
||||
$data = $event->getData();
|
||||
$form = $event->getForm();
|
||||
|
||||
$availableDiffs = array_keys(self::$typesMap);
|
||||
$submittedDiffs = array_keys(($data === null) ? [] : $data);
|
||||
|
||||
$notProvidedDiffs = array_diff($availableDiffs, $submittedDiffs);
|
||||
|
||||
foreach ($notProvidedDiffs as $name) {
|
||||
$form->remove($name);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form\Type;
|
||||
|
||||
use AppBundle\Form\Transformer\OnlyReverseTransformerTrait;
|
||||
use CacheBundle\Entity\Feed\AbstractFeed;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Constraints\GreaterThan;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
|
||||
/**
|
||||
* Class NotificationSourceType
|
||||
* @package UserBundle\Form\Type
|
||||
*/
|
||||
class NotificationSourceType extends AbstractType implements DataTransformerInterface
|
||||
{
|
||||
|
||||
use OnlyReverseTransformerTrait;
|
||||
|
||||
/**
|
||||
* Map between available type and actual entity class.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $types = [
|
||||
'feed' => AbstractFeed::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('type', ChoiceType::class, [
|
||||
'choices' => array_keys(self::$types),
|
||||
'constraints' => new NotBlank(),
|
||||
])
|
||||
->add('id', null, [
|
||||
'constraints' => [
|
||||
new NotBlank(),
|
||||
new GreaterThan([ 'value' => 0 ]),
|
||||
],
|
||||
])
|
||||
->addModelTransformer($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a value from the transformed representation to its original
|
||||
* representation.
|
||||
*
|
||||
* This method is called when {@link Form::submit()} is called to transform
|
||||
* the requests tainted data into an acceptable format for your data
|
||||
* processing/model layer.
|
||||
*
|
||||
* This method must be able to deal with empty values. Usually this will
|
||||
* be an empty string, but depending on your implementation other empty
|
||||
* values are possible as well (such as NULL). The reasoning behind
|
||||
* this is that value transformers must be chainable. If the
|
||||
* reverseTransform() method of the first value transformer outputs an
|
||||
* empty string, the second value transformer must be able to process that
|
||||
* value.
|
||||
*
|
||||
* By convention, reverseTransform() should return NULL if an empty string
|
||||
* is passed.
|
||||
*
|
||||
* @param mixed $data The value in the transformed representation.
|
||||
*
|
||||
* @return mixed The value in the original representation
|
||||
*
|
||||
* @throws TransformationFailedException When the transformation fails.
|
||||
*/
|
||||
public function reverseTransform($data)
|
||||
{
|
||||
//
|
||||
// Unfortunately we can't use here 'getPartialReference' or
|
||||
// 'getReference' methods for creating partial entity or proxy.
|
||||
//
|
||||
// * getPartialReference method is trying to instantiate specified
|
||||
// entity but for feeds we use base abstract class.
|
||||
//
|
||||
// getReference perform query to database for AbstractFeed entity.
|
||||
// https://github.com/doctrine/doctrine2/blob/v2.5.6/lib/Doctrine/ORM/EntityManager.php#L493
|
||||
//
|
||||
// So we just replace 'type' by entity class.
|
||||
//
|
||||
if (! isset($data['type'], self::$types[$data['type']])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data['type'] = self::$types[$data['type']];
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataMapperInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use UserBundle\Entity\Notification\Schedule\AbstractNotificationSchedule;
|
||||
use UserBundle\Entity\Notification\Schedule\DailyNotificationSchedule;
|
||||
use UserBundle\Entity\Notification\Schedule\MonthlyNotificationSchedule;
|
||||
use UserBundle\Entity\Notification\Schedule\WeeklyNotificationSchedule;
|
||||
|
||||
/**
|
||||
* Class ScheduleType
|
||||
* @package UserBundle\Form\Type
|
||||
*/
|
||||
class ScheduleType extends AbstractType implements DataMapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('type', ChoiceType::class, [
|
||||
'choices' => [
|
||||
'daily',
|
||||
'weekly',
|
||||
'monthly',
|
||||
],
|
||||
'description' => 'Notification schedule type.',
|
||||
])
|
||||
|
||||
// DailyNotificationSchedule
|
||||
->add('time', ChoiceType::class, [
|
||||
'choices' => DailyNotificationSchedule::getAvailableTime(),
|
||||
'description' => 'Daily schedule time.',
|
||||
])
|
||||
->add('days', ChoiceType::class, [
|
||||
'choices' => DailyNotificationSchedule::getAvailableDays(),
|
||||
'description' => 'Daily schedule days.',
|
||||
])
|
||||
|
||||
// WeeklyNotificationSchedule
|
||||
->add('period', ChoiceType::class, [
|
||||
'choices' => WeeklyNotificationSchedule::getAvailablePeriod(),
|
||||
'description' => 'Weekly schedule period.',
|
||||
])
|
||||
|
||||
// Common for WeeklyNotificationSchedule and MonthlyNotificationSchedule
|
||||
->add('day', ChoiceType::class, [
|
||||
'choices' => [], // Filled on submitting, when we known schedule
|
||||
// type.
|
||||
'description' => 'Weekly and monthly schedule day. For weekly: day name. For monthly: numbers from 1 to 31 and word last.',
|
||||
])
|
||||
->add('hour', ChoiceType::class, [
|
||||
'choices' => range(0, 23),
|
||||
'description' => 'Weekly and monthly schedule hour.',
|
||||
])
|
||||
->add('minute', ChoiceType::class, [
|
||||
'choices' => range(0, 55, 5),
|
||||
'description' => 'Weekly and monthly schedule minute.',
|
||||
])
|
||||
->setDataMapper($this)
|
||||
->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
|
||||
$data = $event->getData();
|
||||
$form = $event->getForm();
|
||||
|
||||
if (isset($data['type'])) {
|
||||
//
|
||||
// We should update form only if we got valid type.
|
||||
//
|
||||
switch ($data['type']) {
|
||||
case 'daily':
|
||||
$form
|
||||
->remove('period')
|
||||
->remove('day')
|
||||
->remove('hour')
|
||||
->remove('minute');
|
||||
break;
|
||||
|
||||
case 'weekly':
|
||||
$options = $form->get('day')->getConfig()->getOptions();
|
||||
|
||||
$form
|
||||
->remove('time')
|
||||
->remove('days')
|
||||
->remove('day');
|
||||
|
||||
$options['choices'] = array_combine(
|
||||
WeeklyNotificationSchedule::getAvailableDay(),
|
||||
WeeklyNotificationSchedule::getAvailableDay()
|
||||
);
|
||||
$form->add('day', ChoiceType::class, $options);
|
||||
break;
|
||||
|
||||
case 'monthly':
|
||||
$options = $form->get('day')->getConfig()->getOptions();
|
||||
|
||||
$form
|
||||
->remove('time')
|
||||
->remove('days')
|
||||
->remove('period')
|
||||
->remove('day');
|
||||
|
||||
$options['choices'] = array_combine(
|
||||
MonthlyNotificationSchedule::getAvailableDay(),
|
||||
MonthlyNotificationSchedule::getAvailableDay()
|
||||
);
|
||||
$form->add('day', ChoiceType::class, $options);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps properties of some data to a list of forms.
|
||||
*
|
||||
* @param AbstractNotificationSchedule|null $data Structured data.
|
||||
* @param FormInterface[]|\RecursiveIteratorIterator $forms A list of
|
||||
* {@link FormInterface}
|
||||
* instances.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function mapDataToForms($data, $forms)
|
||||
{
|
||||
$forms = iterator_to_array($forms);
|
||||
|
||||
switch (true) {
|
||||
case ($data instanceof DailyNotificationSchedule):
|
||||
$forms['time']->setData($data->getTime());
|
||||
$forms['days']->setData($data->getDays());
|
||||
break;
|
||||
|
||||
case ($data instanceof WeeklyNotificationSchedule):
|
||||
$forms['period']->setData($data->getPeriod());
|
||||
$forms['day']->setData($data->getDay());
|
||||
$forms['hour']->setData($data->getHour());
|
||||
$forms['minute']->setData($data->getMinute());
|
||||
break;
|
||||
|
||||
case ($data instanceof MonthlyNotificationSchedule):
|
||||
$forms['day']->setData($data->getDay());
|
||||
$forms['hour']->setData($data->getHour());
|
||||
$forms['minute']->setData($data->getMinute());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the data of a list of forms into the properties of some data.
|
||||
*
|
||||
* @param FormInterface[]|\RecursiveIteratorIterator $forms A list of
|
||||
* {@link FormInterface}
|
||||
* instances.
|
||||
* @param AbstractNotificationSchedule|null $data Structured data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function mapFormsToData($forms, &$data)
|
||||
{
|
||||
$forms = iterator_to_array($forms);
|
||||
|
||||
switch ($forms['type']->getData()) {
|
||||
case 'daily':
|
||||
$data = DailyNotificationSchedule::create()
|
||||
->setTime($forms['time']->getData())
|
||||
->setDays($forms['days']->getData());
|
||||
break;
|
||||
|
||||
case 'weekly':
|
||||
$data = WeeklyNotificationSchedule::create()
|
||||
->setPeriod($forms['period']->getData())
|
||||
->setDay($forms['day']->getData())
|
||||
->setHour($forms['hour']->getData())
|
||||
->setMinute($forms['minute']->getData());
|
||||
break;
|
||||
|
||||
case 'monthly':
|
||||
$data = MonthlyNotificationSchedule::create()
|
||||
->setDay($forms['day']->getData())
|
||||
->setHour($forms['hour']->getData())
|
||||
->setMinute($forms['minute']->getData());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form\Type;
|
||||
|
||||
use AppBundle\Form\Transformer\OnlyReverseTransformerTrait;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* Class SimpleTimeZoneType
|
||||
* @package UserBundle\Form\Type
|
||||
*/
|
||||
class SimpleTimeZoneType extends AbstractType implements DataTransformerInterface
|
||||
{
|
||||
|
||||
use OnlyReverseTransformerTrait;
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->addModelTransformer($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefault('choices', \DateTimeZone::listIdentifiers(\DateTimeZone::ALL_WITH_BC));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the parent type.
|
||||
*
|
||||
* @return string|null The name of the parent type if any, null otherwise
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return ChoiceType::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a value from the transformed representation to its original
|
||||
* representation.
|
||||
*
|
||||
* This method is called when {@link Form::submit()} is called to transform
|
||||
* the requests tainted data into an acceptable format for your data
|
||||
* processing/model layer.
|
||||
*
|
||||
* This method must be able to deal with empty values. Usually this will
|
||||
* be an empty string, but depending on your implementation other empty
|
||||
* values are possible as well (such as NULL). The reasoning behind
|
||||
* this is that value transformers must be chainable. If the
|
||||
* reverseTransform() method of the first value transformer outputs an
|
||||
* empty string, the second value transformer must be able to process that
|
||||
* value.
|
||||
*
|
||||
* By convention, reverseTransform() should return NULL if an empty string
|
||||
* is passed.
|
||||
*
|
||||
* @param mixed $timezone The value in the transformed representation.
|
||||
*
|
||||
* @return mixed The value in the original representation
|
||||
*
|
||||
* @throws TransformationFailedException When the transformation fails.
|
||||
*/
|
||||
public function reverseTransform($timezone)
|
||||
{
|
||||
return ($timezone !== null) ? new \DateTimeZone($timezone) : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Form\Type;
|
||||
|
||||
use AppBundle\Form\Transformer\OnlyReverseTransformerTrait;
|
||||
use CacheBundle\Entity\Feed\AbstractFeed;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Validator\Constraints\Callback;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use UserBundle\Entity\User;
|
||||
|
||||
/**
|
||||
* Class SourcesType
|
||||
* @package UserBundle\Form\Type
|
||||
*/
|
||||
class SourcesType extends AbstractType implements DataTransformerInterface
|
||||
{
|
||||
|
||||
use OnlyReverseTransformerTrait;
|
||||
|
||||
/**
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* @var TokenStorageInterface
|
||||
*/
|
||||
private $storage;
|
||||
|
||||
/**
|
||||
* NotificationSourceType constructor.
|
||||
*
|
||||
* @param EntityManagerInterface $em A EntityManagerInterface instance.
|
||||
* @param TokenStorageInterface $storage A TokenStorageInterface instance.
|
||||
*/
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
TokenStorageInterface $storage
|
||||
) {
|
||||
$this->em = $em;
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the form.
|
||||
*
|
||||
* This method is called for each type in the hierarchy starting from the
|
||||
* top most type. Type extensions can further modify the form.
|
||||
*
|
||||
* @see FormTypeExtensionInterface::buildForm()
|
||||
*
|
||||
* @param FormBuilderInterface $builder The form builder.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->addModelTransformer($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options for this type.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'entry_type' => NotificationSourceType::class,
|
||||
'allow_add' => true,
|
||||
'by_reference' => true,
|
||||
'constraints' => new Callback([ $this, 'validate' ]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate sources.
|
||||
*
|
||||
* @param array $sources Array of transformed sources.
|
||||
* @param ExecutionContextInterface $context A ExecutionContextInterface
|
||||
* instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function validate(array $sources, ExecutionContextInterface $context)
|
||||
{
|
||||
// todo uncomment and rewrite when analytic is added
|
||||
// if (($sources['feeds'] === null) || ($sources['charts'] === null)) {
|
||||
if ($sources['feeds'] === null) {
|
||||
$context
|
||||
->buildViolation('Some of sources has invalid id.')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the parent type.
|
||||
*
|
||||
* @return string|null The name of the parent type if any, null otherwise.
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return CollectionType::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a value from the transformed representation to its original
|
||||
* representation.
|
||||
*
|
||||
* This method is called when {@link Form::submit()} is called to transform
|
||||
* the requests tainted data into an acceptable format for your data
|
||||
* processing/model layer.
|
||||
*
|
||||
* This method must be able to deal with empty values. Usually this will
|
||||
* be an empty string, but depending on your implementation other empty
|
||||
* values are possible as well (such as NULL). The reasoning behind
|
||||
* this is that value transformers must be chainable. If the
|
||||
* reverseTransform() method of the first value transformer outputs an
|
||||
* empty string, the second value transformer must be able to process that
|
||||
* value.
|
||||
*
|
||||
* By convention, reverseTransform() should return NULL if an empty string
|
||||
* is passed.
|
||||
*
|
||||
* @param mixed $data The value in the transformed representation.
|
||||
*
|
||||
* @return mixed The value in the original representation
|
||||
*
|
||||
* @throws TransformationFailedException When the transformation fails.
|
||||
*/
|
||||
public function reverseTransform($data)
|
||||
{
|
||||
//
|
||||
// Split feeds and charts.
|
||||
// todo uncomment when analytic is added
|
||||
//
|
||||
// list($feedsIds, $chartsIds) = \nspl\a\partition(function (array $row) {
|
||||
// return $row['type'] === AbstractFeed::class;
|
||||
// }, $data);
|
||||
|
||||
//
|
||||
// Fetch proper entities from database.
|
||||
//
|
||||
$feedsIds = \nspl\a\map(\nspl\op\itemGetter('id'), $data);
|
||||
$feeds = $this->getEntities(AbstractFeed::class, $feedsIds);
|
||||
|
||||
//
|
||||
// We return hash here to simplify further processing.
|
||||
//
|
||||
return [
|
||||
'feeds' => (count($feeds) === count($feedsIds)) ? $feeds : null,
|
||||
'charts' => null,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that all specified id is exists.
|
||||
*
|
||||
* @param string $class Entity fqcn.
|
||||
* @param array $ids Array of entities ids.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getEntities($class, array $ids)
|
||||
{
|
||||
/** @var EntityRepository $repository */
|
||||
$repository = $this->em->getRepository($class);
|
||||
$expr = $this->em->getExpressionBuilder();
|
||||
|
||||
$condition = $expr->andX($expr->in('Source.id', ':ids'));
|
||||
$parameters = [ 'ids' => $ids ];
|
||||
|
||||
//
|
||||
// Filter by user only if we have it.
|
||||
//
|
||||
$user = \app\op\invokeIf($this->storage->getToken(), 'getUser');
|
||||
if ($user instanceof User) {
|
||||
$condition->add($expr->eq('Source.user', ':user'));
|
||||
$parameters['user'] = $user->getId();
|
||||
}
|
||||
|
||||
//
|
||||
// We should get only ids and names of sources 'cause it will be used
|
||||
// for generating response to client.
|
||||
//
|
||||
return $repository->createQueryBuilder('Source')
|
||||
->select('partial Source.{id, name}')
|
||||
->where($condition)
|
||||
->setParameters($parameters)
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Mailer;
|
||||
|
||||
use AppBundle\Entity\EmailedDocument;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\User;
|
||||
|
||||
/**
|
||||
* Class LoggableMailer
|
||||
*
|
||||
* @package UserBundle\Mailer
|
||||
*/
|
||||
class LoggableMailer implements MailerInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var MailerInterface
|
||||
*/
|
||||
private $mailer;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* LoggableMailer constructor.
|
||||
*
|
||||
* @param MailerInterface $mailer A MailerInterface instance.
|
||||
* @param LoggerInterface $logger A LoggerInterface instance.
|
||||
*/
|
||||
public function __construct(
|
||||
MailerInterface $mailer,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->mailer = $mailer;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send generated password to user.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
* @param string $password Generated password.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendPassword(User $user, $password)
|
||||
{
|
||||
$this->logger->info('Send password to '. $user->getId());
|
||||
|
||||
return $this->mailer->sendPassword($user, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send password resetting confirmation email.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendPasswordResettingConfirmation(User $user)
|
||||
{
|
||||
$this->logger->info('Send password resetting confirmation to '. $user->getId());
|
||||
|
||||
return $this->mailer->sendPasswordResettingConfirmation($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send notification email to specified addresses.
|
||||
*
|
||||
* @param array $addresses Array of recipient emails.
|
||||
* @param string $subject Notification subject.
|
||||
* @param string $body Notification body.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendNotificationEmail(array $addresses, $subject, $body)
|
||||
{
|
||||
$this->logger->info(
|
||||
'Send notification to '. implode(', ', $addresses) .' recipients'
|
||||
);
|
||||
|
||||
return $this->mailer->sendNotificationEmail($addresses, $subject, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send emailed document to recipients.
|
||||
*
|
||||
* @param EmailedDocument $emailedDocument A EmailedDocument instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendEmailedDocument(EmailedDocument $emailedDocument)
|
||||
{
|
||||
$this->logger->info('Send emailed document to '. implode(', ', $emailedDocument->getEmailTo()));
|
||||
|
||||
return $this->mailer->sendEmailedDocument($emailedDocument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send generated password and confirm url to user.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
* @param string $confirmUrl Generated confirm url.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendVerificationSuccess(User $user, $confirmUrl)
|
||||
{
|
||||
$this->logger->info('Send verification success email to '. $user->getId());
|
||||
|
||||
return $this->mailer->sendVerificationSuccess($user, $confirmUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send email about failed verification.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendVerificationRejected(User $user)
|
||||
{
|
||||
$this->logger->info('Send verification success email to '. $user->getId());
|
||||
|
||||
return $this->mailer->sendVerificationRejected($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send unsubscribe notification.
|
||||
*
|
||||
* @param Notification $notification A Notification entity.
|
||||
* @param User $user A User entity who unsubscribe from
|
||||
* specified notification.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendUnsubscribe(Notification $notification, User $user)
|
||||
{
|
||||
$this->logger->info('Send unsubscribe notification to '. $notification->getOwner()->getFullName());
|
||||
|
||||
return $this->mailer->sendUnsubscribe($notification, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send mail messages.
|
||||
*
|
||||
* Should be called only in command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function flushQueue()
|
||||
{
|
||||
$this->logger->info('Spool messages');
|
||||
|
||||
$this->mailer->flushQueue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,337 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Mailer;
|
||||
|
||||
use AppBundle\Configuration\ConfigurationInterface;
|
||||
use AppBundle\Configuration\ParametersName;
|
||||
use AppBundle\Entity\EmailedDocument;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\User;
|
||||
use FOS\UserBundle\Model\UserInterface;
|
||||
|
||||
/**
|
||||
* Class Mailer
|
||||
* Default implementation of MailerInterface.
|
||||
*
|
||||
* @package UserBundle\Mailer
|
||||
*/
|
||||
class Mailer implements MailerInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \Swift_Mailer
|
||||
*/
|
||||
private $mailer;
|
||||
|
||||
/**
|
||||
* @var \Swift_Transport
|
||||
*/
|
||||
private $transport;
|
||||
|
||||
/**
|
||||
* @var \Twig_Environment
|
||||
*/
|
||||
private $twig;
|
||||
|
||||
/**
|
||||
* @var ConfigurationInterface
|
||||
*/
|
||||
private $configuration;
|
||||
|
||||
/**
|
||||
* @var UrlGeneratorInterface
|
||||
*/
|
||||
private $urlGenerator;
|
||||
|
||||
/**
|
||||
* @param \Swift_Mailer $mailer A Swift_Mailer instance.
|
||||
* @param \Swift_Transport $transport A Swift_Transport instance.
|
||||
* @param \Twig_Environment $twig A \Twig_Environment instance.
|
||||
* @param ConfigurationInterface $configuration A ConfigurationInterface
|
||||
* instance.
|
||||
* @param UrlGeneratorInterface $urlGenerator A UrlGeneratorInterface
|
||||
* instance.
|
||||
*/
|
||||
public function __construct(
|
||||
\Swift_Mailer $mailer,
|
||||
\Swift_Transport $transport,
|
||||
\Twig_Environment $twig,
|
||||
ConfigurationInterface $configuration,
|
||||
UrlGeneratorInterface $urlGenerator
|
||||
) {
|
||||
$this->mailer = $mailer;
|
||||
$this->transport = $transport;
|
||||
$this->twig = $twig;
|
||||
$this->configuration = $configuration;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send generated password to user.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
* @param string $password Generated password.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendPassword(User $user, $password)
|
||||
{
|
||||
return $this->sendEmail(
|
||||
$user->getEmail(),
|
||||
'Password is changed',
|
||||
ParametersName::MAIL_PASSWORD,
|
||||
[
|
||||
'user' => $user,
|
||||
'password' => $password,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send generated password and confirm url to user.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
* @param string $password A user plain password.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendVerificationSuccess(User $user, $password)
|
||||
{
|
||||
return $this->sendEmail(
|
||||
$user->getEmail(),
|
||||
'Verification status',
|
||||
ParametersName::MAIL_VERIFICATION_SUCCESS,
|
||||
[
|
||||
'user' => $user,
|
||||
'password' => $password,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send email about failed verification.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendVerificationRejected(User $user)
|
||||
{
|
||||
return $this->sendEmail(
|
||||
$user->getEmail(),
|
||||
'Verification status',
|
||||
ParametersName::MAIL_VERIFICATION_REJECT,
|
||||
[
|
||||
'user' => $user,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send password resetting confirmation email.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendPasswordResettingConfirmation(User $user)
|
||||
{
|
||||
return $this->sendEmail(
|
||||
$user->getEmail(),
|
||||
'Password resetting',
|
||||
ParametersName::MAIL_RESETTING_CONFIRMATION,
|
||||
[
|
||||
'user' => $user,
|
||||
'confirmationUrl' => $this->urlGenerator->generate('app_index_index', [
|
||||
'part' => 'auth/reset-password',
|
||||
'resetting_token' => $user->getConfirmationToken(),
|
||||
], UrlGeneratorInterface::ABSOLUTE_URL),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send notification email to specified addresses.
|
||||
*
|
||||
* @param array $addresses Array of recipient emails.
|
||||
* @param string $subject Notification subject.
|
||||
* @param string $body Notification body.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendNotificationEmail(array $addresses, $subject, $body)
|
||||
{
|
||||
$from = $this->configuration->getParameter(ParametersName::MAILER_ADDRESS);
|
||||
$fromName = $this->configuration->getParameter(ParametersName::MAILER_SENDER_NAME);
|
||||
|
||||
$message = \Swift_Message::newInstance()
|
||||
->setTo($addresses)
|
||||
->setFrom($from, $fromName)
|
||||
->setSubject($subject)
|
||||
->setBody($body, 'text/html');
|
||||
|
||||
return $this->send($message) > 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string $renderedTemplate
|
||||
* @param array|string $fromEmail
|
||||
* @param array|string $toEmail
|
||||
*/
|
||||
public function sendEmailMessage(UserInterface $user, $baseurl)
|
||||
{
|
||||
// Render the email, use the first line as the subject, and the rest as the body
|
||||
$parameters = array(
|
||||
'user' => $user,
|
||||
'confirmationUrl' => $baseurl.'/auth/confirm-account/'.$user->getConfirmationToken(),
|
||||
);
|
||||
$toEmail = (string) $user->getEmail();
|
||||
$template = $this->twig->load('@FOSUser/Registration/email.txt.twig');
|
||||
|
||||
$message = (new \Swift_Message())
|
||||
->setSubject('Verify your email address')
|
||||
->setFrom("support@socialhose.io","SOCIALHOSE.IO")
|
||||
->setTo($toEmail)
|
||||
->setBody($template->render(
|
||||
$parameters
|
||||
));
|
||||
|
||||
$this->send($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send emailed document to recipients.
|
||||
*
|
||||
* @param EmailedDocument $emailedDocument A EmailedDocument instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendEmailedDocument(EmailedDocument $emailedDocument)
|
||||
{
|
||||
$subject = $emailedDocument->getSubject() === ''
|
||||
? 'Emailed document content'
|
||||
: $emailedDocument->getSubject();
|
||||
|
||||
$from = $this->configuration->getParameter(ParametersName::MAILER_ADDRESS);
|
||||
$fromName = $this->configuration->getParameter(ParametersName::MAILER_SENDER_NAME);
|
||||
|
||||
$message = \Swift_Message::newInstance()
|
||||
->setTo($emailedDocument->getEmailTo())
|
||||
->setFrom($from, $fromName)
|
||||
->setReplyTo($emailedDocument->getEmailReplyTo())
|
||||
->setSubject($subject)
|
||||
->setBody($emailedDocument->getContent(), 'text/html');
|
||||
|
||||
return $this->send($message) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send unsubscribe notification.
|
||||
*
|
||||
* @param Notification $notification A Notification entity.
|
||||
* @param User $user A User entity who unsubscribe from
|
||||
* specified notification.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendUnsubscribe(Notification $notification, User $user)
|
||||
{
|
||||
return $this->sendEmail(
|
||||
$user->getEmail(),
|
||||
sprintf(
|
||||
'User %s unsubscribed from %s',
|
||||
$user->getFullName(),
|
||||
$notification->getName()
|
||||
),
|
||||
ParametersName::MAIL_UNSUBSCRIBE,
|
||||
[
|
||||
'user' => $user,
|
||||
'notification' => $notification,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send mail messages.
|
||||
*
|
||||
* Should be called only in command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function flushQueue()
|
||||
{
|
||||
$transport = $this->mailer->getTransport();
|
||||
if ($transport instanceof \Swift_Transport_SpoolTransport) {
|
||||
$spool = $transport->getSpool();
|
||||
if ($spool instanceof \Swift_MemorySpool) {
|
||||
$spool->flushQueue($this->transport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $recipient Recipient email address.
|
||||
* @param string $subject Email subject.
|
||||
* @param string $bodyParameterName Name of configuration parameter which is
|
||||
* holds body text.
|
||||
* @param array $parameters Template parameters.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function sendEmail($recipient, $subject, $bodyParameterName, array $parameters = [])
|
||||
{
|
||||
$from = $this->configuration->getParameter(ParametersName::MAILER_ADDRESS);
|
||||
$fromName = $this->configuration->getParameter(ParametersName::MAILER_SENDER_NAME);
|
||||
|
||||
$message = \Swift_Message::newInstance($subject, $this->twig->render(
|
||||
'UserBundle::email_layout.html.twig',
|
||||
[
|
||||
'body' => $this->twig->createTemplate(
|
||||
$this->configuration->getParameter($bodyParameterName)
|
||||
)->render($parameters),
|
||||
]
|
||||
), 'text/html')
|
||||
->setTo($recipient)
|
||||
->setFrom($from, $fromName);
|
||||
|
||||
return $this->send($message) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Swift_Message $message
|
||||
* @return int
|
||||
*/
|
||||
private function send($message)
|
||||
{
|
||||
$this->resetTransport();
|
||||
|
||||
return $this->mailer->send($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset SMTP connection for each send so that connections
|
||||
* are not dropped during long-running processes.
|
||||
*
|
||||
* See https://github.com/swiftmailer/swiftmailer/issues/490#issuecomment-72492442
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function resetTransport()
|
||||
{
|
||||
try {
|
||||
if ($this->transport instanceof \Swift_Transport_AbstractSmtpTransport) {
|
||||
$this->transport->reset();
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
try {
|
||||
$this->transport->stop();
|
||||
} catch (\Exception $e) {
|
||||
// pass
|
||||
}
|
||||
// $this->transport->start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Mailer;
|
||||
|
||||
use AppBundle\Entity\EmailedDocument;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\User;
|
||||
|
||||
/**
|
||||
* Interface MailerInterface
|
||||
* Send emails to user.
|
||||
*
|
||||
* @package UserBundle\Mailer
|
||||
*/
|
||||
interface MailerInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Send generated password to user.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
* @param string $password Generated password.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendPassword(User $user, $password);
|
||||
|
||||
/**
|
||||
* Send email about success verification.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
* @param string $confirmUrl Generated confirm url.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendVerificationSuccess(User $user, $confirmUrl);
|
||||
|
||||
/**
|
||||
* Send email about failed verification.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendVerificationRejected(User $user);
|
||||
|
||||
/**
|
||||
* Send password resetting confirmation email.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendPasswordResettingConfirmation(User $user);
|
||||
|
||||
/**
|
||||
* Send notification email to specified addresses.
|
||||
*
|
||||
* @param array $addresses Array of recipient emails.
|
||||
* @param string $subject Notification subject.
|
||||
* @param string $body Notification body.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendNotificationEmail(array $addresses, $subject, $body);
|
||||
|
||||
/**
|
||||
* Send emailed document to recipients.
|
||||
*
|
||||
* @param EmailedDocument $emailedDocument A EmailedDocument instance.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendEmailedDocument(EmailedDocument $emailedDocument);
|
||||
|
||||
/**
|
||||
* Send unsubscribe notification.
|
||||
*
|
||||
* @param Notification $notification A Notification entity.
|
||||
* @param User $user A User entity who unsubscribe from
|
||||
* specified notification.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendUnsubscribe(Notification $notification, User $user);
|
||||
|
||||
/**
|
||||
* Send mail messages.
|
||||
*
|
||||
* Should be called only in command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function flushQueue();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Manager\Notification\Computer;
|
||||
|
||||
use UserBundle\Entity\Notification\Schedule\AbstractNotificationSchedule;
|
||||
|
||||
/**
|
||||
* Class NotificationScheduleComputer
|
||||
*
|
||||
* Compute notification schedule date's.
|
||||
*
|
||||
* @package UserBundle\Manager\Notification\Computer
|
||||
*/
|
||||
class NotificationScheduleComputer implements NotificationScheduleComputerInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Compute all notification send date's from current date to specified.
|
||||
*
|
||||
* All date's is unique even if notification have some interacting scheduling.
|
||||
*
|
||||
* @param AbstractNotificationSchedule[]|array $schedules An array of
|
||||
* AbstractNotificationSchedule
|
||||
* instance's.
|
||||
* @param \DateTime|string $to Computing bound. If parameter
|
||||
* is string expects format
|
||||
* accepted by 'modify' method
|
||||
* of DateTime class.
|
||||
* @param \DateTimeZone $timeZone Timezone used for each
|
||||
* date.
|
||||
*
|
||||
* @return array[]
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ShortVariable)
|
||||
*/
|
||||
public function compute(array $schedules, $to, \DateTimeZone $timeZone)
|
||||
{
|
||||
$start = new \DateTime('now', $timeZone);
|
||||
$to = is_string($to) ? new \DateTime($to) : $to;
|
||||
|
||||
if (! $to instanceof \DateTime) {
|
||||
throw new \InvalidArgumentException('Expects date or valid \DateTime constructor parameter.');
|
||||
}
|
||||
|
||||
$dates = [];
|
||||
foreach ($schedules as $schedule) {
|
||||
$tmp = $schedule->computeDates($start, $to);
|
||||
foreach ($tmp as $date) {
|
||||
$key = $date->format('Y-m-d H:i');
|
||||
|
||||
if (! isset($dates[$key])) {
|
||||
$dates[$key] = [
|
||||
'date' => $date,
|
||||
'ids' => [],
|
||||
];
|
||||
}
|
||||
|
||||
$dates[$key]['ids'][] = $schedule->getId();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Now we should convert date's back to current timezone in order to
|
||||
// simplify further processing.
|
||||
//
|
||||
$defaultTZ = new \DateTimeZone(date_default_timezone_get());
|
||||
return array_map(function (array $row) use ($defaultTZ) {
|
||||
$row['date']->setTimezone($defaultTZ);
|
||||
|
||||
return $row;
|
||||
}, $dates);
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Manager\Notification\Computer;
|
||||
|
||||
use UserBundle\Entity\Notification\Schedule\AbstractNotificationSchedule;
|
||||
|
||||
/**
|
||||
* Interface NotificationScheduleComputerInterface
|
||||
*
|
||||
* Compute notification schedule date's.
|
||||
*
|
||||
* @package UserBundle\Manager\Notification\Computer
|
||||
*/
|
||||
interface NotificationScheduleComputerInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Compute all notification send date's from current date to specified.
|
||||
*
|
||||
* All date's is unique even if notification have some interacting scheduling.
|
||||
*
|
||||
* @param AbstractNotificationSchedule[]|array $schedules An array of
|
||||
* AbstractNotificationSchedule
|
||||
* instance's.
|
||||
* @param \DateTime|string $to Computing bound. If parameter
|
||||
* is string expects format
|
||||
* accepted by 'modify' method
|
||||
* of DateTime class.
|
||||
* @param \DateTimeZone $timeZone Timezone used for each
|
||||
* date.
|
||||
*
|
||||
* @return \DateTime[]
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ShortVariable)
|
||||
*/
|
||||
public function compute(array $schedules, $to, \DateTimeZone $timeZone);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Manager\Notification\Model;
|
||||
|
||||
use CacheBundle\Entity\Document;
|
||||
use Doctrine\Common\Proxy\Exception\UnexpectedValueException;
|
||||
use IndexBundle\Model\ArticleDocumentInterface;
|
||||
|
||||
/**
|
||||
* Class FeedData
|
||||
*
|
||||
* Holds all necessary data for render feed in notifications.
|
||||
*
|
||||
* @package UserBundle\Manager\Notification\Model
|
||||
*/
|
||||
class FeedData implements \Countable, \IteratorAggregate
|
||||
{
|
||||
|
||||
/**
|
||||
* Feed name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* Array of fetched documents.
|
||||
*
|
||||
* @var Document[]
|
||||
*/
|
||||
private $documents;
|
||||
|
||||
/**
|
||||
* Count of documents.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $documentsCount;
|
||||
|
||||
/**
|
||||
* FeedData constructor.
|
||||
*
|
||||
* @param string $name Feed name.
|
||||
* @param ArticleDocumentInterface[] $documents Array of documents.
|
||||
*/
|
||||
public function __construct($name, array $documents)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
if (! \nspl\a\all($documents, \nspl\f\rpartial(\app\op\isInstanceOf, ArticleDocumentInterface::class))) {
|
||||
throw new UnexpectedValueException(sprintf(
|
||||
'All documents should be instances of %s',
|
||||
ArticleDocumentInterface::class
|
||||
));
|
||||
}
|
||||
|
||||
$this->documents = \nspl\a\map(\nspl\op\methodCaller('normalize'), $documents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fet documents.
|
||||
*
|
||||
* @return ArticleDocumentInterface[]
|
||||
*/
|
||||
public function getDocuments()
|
||||
{
|
||||
return $this->documents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get documents count.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getDocumentsCount()
|
||||
{
|
||||
if ($this->documentsCount === null) {
|
||||
$this->documentsCount = count($this->documents);
|
||||
}
|
||||
|
||||
return $this->documentsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count elements of an object
|
||||
*
|
||||
* @return integer The custom count as an integer.
|
||||
*
|
||||
* The return value is cast to an integer.
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return $this->getDocumentsCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an external iterator.
|
||||
*
|
||||
* @return \Traversable An instance of an object implementing Iterator or Traversable.
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->documents);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'name' => $this->name,
|
||||
'documents' => $this->documents,
|
||||
'documentsCount' => $this->documentsCount,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,524 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Manager\Notification;
|
||||
|
||||
use AppBundle\Configuration\ConfigurationImmutableInterface;
|
||||
use CacheBundle\Document\Extractor\DocumentContentExtractorInterface;
|
||||
use CacheBundle\Entity\Comment;
|
||||
use CacheBundle\Entity\Document;
|
||||
use CacheBundle\Entity\Feed\AbstractFeed;
|
||||
use CacheBundle\Entity\Feed\QueryFeed;
|
||||
use CacheBundle\Feed\Fetcher\Factory\FeedFetcherFactoryInterface;
|
||||
use CacheBundle\Repository\CommentRepository;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use IndexBundle\Model\ArticleDocumentInterface;
|
||||
use IndexBundle\SearchRequest\SearchRequestBuilderInterface;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\Notification\NotificationThemeOptions;
|
||||
use UserBundle\Entity\Recipient\AbstractRecipient;
|
||||
use UserBundle\Enum\ThemeOptionsUserCommentsEnum;
|
||||
use UserBundle\Manager\Notification\Computer\NotificationScheduleComputer;
|
||||
use UserBundle\Manager\Notification\Computer\NotificationScheduleComputerInterface;
|
||||
use UserBundle\Manager\Notification\Model\FeedData;
|
||||
|
||||
/**
|
||||
* Class NotificationManager
|
||||
* @package UserBundle\Manager\Notification
|
||||
*/
|
||||
class NotificationManager implements NotificationManagerInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Max row's in single insert.
|
||||
*/
|
||||
const BUCKET_SIZE = 100;
|
||||
|
||||
/**
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* @var NotificationScheduleComputerInterface
|
||||
*/
|
||||
private $computer;
|
||||
|
||||
/**
|
||||
* @var FeedFetcherFactoryInterface
|
||||
*/
|
||||
private $feedFetcherFactory;
|
||||
|
||||
/**
|
||||
* @var ConfigurationImmutableInterface
|
||||
*/
|
||||
private $configuration;
|
||||
|
||||
/**
|
||||
* @var DocumentContentExtractorInterface
|
||||
*/
|
||||
private $extractor;
|
||||
|
||||
/**
|
||||
* NotificationManager constructor.
|
||||
*
|
||||
* @param EntityManagerInterface $em A EntityManagerInterface
|
||||
* instance.
|
||||
* @param FeedFetcherFactoryInterface $feedFetcherFactory A CacheInterface
|
||||
* instance.
|
||||
* @param ConfigurationImmutableInterface $configuration A ConfigurationImmutableInterface
|
||||
* instance.
|
||||
* @param DocumentContentExtractorInterface $extractor A DocumentContentExtractorInterface
|
||||
* instance.
|
||||
*/
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
FeedFetcherFactoryInterface $feedFetcherFactory,
|
||||
ConfigurationImmutableInterface $configuration,
|
||||
DocumentContentExtractorInterface $extractor
|
||||
) {
|
||||
$this->em = $em;
|
||||
$this->feedFetcherFactory = $feedFetcherFactory;
|
||||
$this->configuration = $configuration;
|
||||
$this->extractor = $extractor;
|
||||
|
||||
$this->computer = new NotificationScheduleComputer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new notification or update exists.
|
||||
*
|
||||
* @param Notification $notification A Notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function persists(Notification $notification)
|
||||
{
|
||||
/**
|
||||
* @param array|\Traversable $collection Filtered collection.
|
||||
* @param string $keyMethod Method used for getting unique
|
||||
* key.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
$unique = static function ($collection, $keyMethod) {
|
||||
$unique = [];
|
||||
foreach ($collection as $item) {
|
||||
$unique[$item->$keyMethod()] = $item;
|
||||
}
|
||||
|
||||
return array_values($unique);
|
||||
};
|
||||
|
||||
//
|
||||
// We should check all schedule's record's and remove duplicates.
|
||||
// Same for feeds.
|
||||
//
|
||||
|
||||
$schedules = $unique($notification->getSchedules(), 'getKey');
|
||||
$feeds = $unique($notification->getFeeds(), 'getId');
|
||||
$notification
|
||||
->setSchedules($schedules)
|
||||
->setFeeds($feeds);
|
||||
|
||||
//
|
||||
// Persist schedule.
|
||||
//
|
||||
$this->em->persist($notification);
|
||||
$this->em->flush();
|
||||
|
||||
//
|
||||
// Get notification id for further processing.
|
||||
//
|
||||
$id = $notification->getId();
|
||||
|
||||
//
|
||||
// We should remove previously computed values.
|
||||
//
|
||||
$this->removeComputedScheduling($notification->getId());
|
||||
|
||||
if ($notification->isCanBeSent(date_create())) {
|
||||
//
|
||||
// We should'nt compute render date's if specified notification is can't
|
||||
// be sent.
|
||||
//
|
||||
$timezone = $notification->getTimezone();
|
||||
$bound = new \DateTime('+ 1 month');
|
||||
$sendUntil = $notification->getSendUntil();
|
||||
$bound = (($sendUntil === null) || ($bound <= $sendUntil))
|
||||
? $bound
|
||||
: $notification->getSendUntil();
|
||||
|
||||
$dates = $this->computer->compute(
|
||||
$schedules,
|
||||
$bound->setTimezone($timezone),
|
||||
$timezone
|
||||
);
|
||||
|
||||
$this->em->getConnection()->transactional(function (Connection $con) use ($id, $dates) {
|
||||
$bucket = [];
|
||||
$count = 0;
|
||||
foreach ($dates as $date) {
|
||||
$bucket[] = sprintf(
|
||||
"('%s', %d, '%s')",
|
||||
$date['date']->format('Y-m-d H:i:s'),
|
||||
$id,
|
||||
implode(',', $date['ids'])
|
||||
);
|
||||
if (++$count === self::BUCKET_SIZE) {
|
||||
$con->executeQuery(
|
||||
'INSERT INTO internal_notification_scheduling (date, notification_id, schedules) VALUES ' .
|
||||
implode(',', $bucket)
|
||||
);
|
||||
$count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ($count > 0) {
|
||||
$con->executeQuery(
|
||||
'INSERT INTO internal_notification_scheduling (date, notification_id, schedules) VALUES ' .
|
||||
implode(',', $bucket)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate specified notifications.
|
||||
*
|
||||
* @param Notification|Notification[] $notifications A activated Notification
|
||||
* entity instance or array
|
||||
* of instances.
|
||||
* @param boolean $active Activate or deactivate
|
||||
* specified notifications.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function activatedToggle($notifications, $active = true)
|
||||
{
|
||||
$notifications = $this->normalizeNotifications($notifications);
|
||||
|
||||
foreach ($notifications as $notification) {
|
||||
$notification->setActive($active);
|
||||
$this->em->persist($notification);
|
||||
}
|
||||
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish specified notifications.
|
||||
*
|
||||
* @param Notification|Notification[] $notifications A activated Notification
|
||||
* entity instance or array
|
||||
* of instances.
|
||||
* @param boolean $publish Publish or make private
|
||||
* specified notifications.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function publishedToggle($notifications, $publish = true)
|
||||
{
|
||||
$notifications = $this->normalizeNotifications($notifications);
|
||||
|
||||
foreach ($notifications as $notification) {
|
||||
$notification->setPublished($publish);
|
||||
$this->em->persist($notification);
|
||||
}
|
||||
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish specified notifications.
|
||||
*
|
||||
* @param AbstractRecipient $recipient Who try to subscribe or
|
||||
* unsubscribe from specified
|
||||
* notifications.
|
||||
* @param Notification|Notification[] $notifications A Notification entity
|
||||
* instance or array of
|
||||
* instances.
|
||||
* @param boolean $subscribe Subscribe or unsubscribe
|
||||
* from specified notifications.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function subscriptionToggle(AbstractRecipient $recipient, $notifications, $subscribe = true)
|
||||
{
|
||||
$notifications = $this->normalizeNotifications($notifications);
|
||||
|
||||
if ($subscribe) {
|
||||
//
|
||||
// User should not be subscribed to notification twice so we remove
|
||||
// all notification on which he already subscribed.
|
||||
//
|
||||
$checker = \nspl\f\compose(\nspl\f\rpartial('\nspl\a\all', function (AbstractRecipient $checked) use ($recipient) {
|
||||
return $checked->getId() !== $recipient->getId();
|
||||
}), \nspl\op\methodCaller('getRecipients'));
|
||||
|
||||
$notifications = \nspl\a\filter($checker, $notifications);
|
||||
|
||||
$method = \nspl\op\methodCaller('addRecipient', [ $recipient ]);
|
||||
} else {
|
||||
$method = \nspl\op\methodCaller('removeRecipient', [ $recipient ]);
|
||||
}
|
||||
|
||||
foreach ($notifications as $notification) {
|
||||
$method($notification);
|
||||
$this->em->persist($notification);
|
||||
}
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove specified notifications.
|
||||
*
|
||||
* @param Notification|Notification[] $notifications A removed Notification entity instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function remove($notifications)
|
||||
{
|
||||
$notifications = $this->normalizeNotifications($notifications);
|
||||
|
||||
foreach ($notifications as $notification) {
|
||||
$this->em->remove($notification);
|
||||
}
|
||||
|
||||
$this->removeComputedScheduling(\nspl\a\map(\nspl\op\methodCaller('getId'), $notifications));
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare specified notification for sending.
|
||||
*
|
||||
* @param Notification $notification A Notification instance.
|
||||
*
|
||||
* @return SendableNotification
|
||||
*/
|
||||
public function prepareToSend(Notification $notification)
|
||||
{
|
||||
//
|
||||
// We should sync parameters.
|
||||
//
|
||||
$this->configuration->syncParameters();
|
||||
$config = SendableNotificationConfig::fromConfiguration($this->configuration);
|
||||
|
||||
//
|
||||
// We should not render notification if it shouldn't be rendered.
|
||||
//
|
||||
if (! $notification->isCanBeSent(new \DateTime())) {
|
||||
return new SendableNotification($config, $notification, [], false);
|
||||
}
|
||||
|
||||
//
|
||||
// Get used notification theme with applied diff.
|
||||
//
|
||||
$themeOptions = $notification->getActualThemeOptions();
|
||||
|
||||
/**
|
||||
* @param Document $document A Document entity instance.
|
||||
*
|
||||
* @return ArticleDocumentInterface
|
||||
*/
|
||||
$commentsFetcherFn = $this->createCommentsFetcherFn($themeOptions, $config);
|
||||
|
||||
//
|
||||
// Now we should get requested number of documents for every notification
|
||||
// feed.
|
||||
//
|
||||
$feeds = [];
|
||||
/** @var AbstractFeed $feed */
|
||||
foreach ($notification->getFeeds() as $feed) {
|
||||
//
|
||||
// Get all documents ids.
|
||||
//
|
||||
$builder = $this->feedFetcherFactory->get($feed)
|
||||
->createRequestBuilder($feed);
|
||||
|
||||
if (! $builder instanceof SearchRequestBuilderInterface) {
|
||||
return new SendableNotification($config, $notification, [], false);
|
||||
}
|
||||
|
||||
$filterFactory = $builder->getIndex()->getFilterFactory();
|
||||
$lastSentUTC = clone $notification->getLastSentAt();
|
||||
$lastSentUTC->setTimezone(new \DateTimeZone('UTC'));
|
||||
|
||||
$documents = $builder
|
||||
//
|
||||
// We should get documents which were added after last notification
|
||||
// sending.
|
||||
//
|
||||
->addFilter($filterFactory->gte('date_found', $lastSentUTC->format('c')))
|
||||
//
|
||||
// Set document limit.
|
||||
// This limit is configured by super admin.
|
||||
//
|
||||
->setLimit($config->documentsPerFeed)
|
||||
->build()
|
||||
->execute()
|
||||
->getDocuments();
|
||||
|
||||
//
|
||||
// Obviously, we should not try to fetch information from database if
|
||||
// we don't get any documents.
|
||||
//
|
||||
if (count($documents) > 0) {
|
||||
//
|
||||
// Get documents with necessary fields by ids which we fetch from
|
||||
// index.
|
||||
//
|
||||
// Also we should fetch comments, extract content and convert to
|
||||
// article instances.
|
||||
//
|
||||
$extract = $themeOptions->getContent()->getExtract();
|
||||
|
||||
$documents = \nspl\a\map(function (ArticleDocumentInterface $document) use ($commentsFetcherFn, $feed, $extract) {
|
||||
$id = $document->getId();
|
||||
|
||||
return $document
|
||||
->mapRawData(function (array $data) use ($commentsFetcherFn, $id) {
|
||||
$data['__comments'] = $commentsFetcherFn($id);
|
||||
$data['__commentsCount'] = count($data['__comments']);
|
||||
|
||||
return $data;
|
||||
})
|
||||
->mapNormalizedData(function (array $data) use ($feed, $extract) {
|
||||
$query = '';
|
||||
if ($feed instanceof QueryFeed) {
|
||||
$query = $feed->getQuery()->getRaw();
|
||||
}
|
||||
|
||||
$result =$this->extractor->extract(
|
||||
$data['content'],
|
||||
$query,
|
||||
$extract,
|
||||
true
|
||||
);
|
||||
|
||||
$data['content'] = $result->getText() . (
|
||||
mb_strlen($data['content']) < $result->getLength()
|
||||
? '...'
|
||||
: ''
|
||||
);
|
||||
|
||||
return $data;
|
||||
});
|
||||
}, $documents);
|
||||
|
||||
$feeds[] = new FeedData(
|
||||
$feed->getName(),
|
||||
$documents
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Clear entity manager to avoid memory consuming grow and possible
|
||||
// side-effects on flush.
|
||||
//
|
||||
$this->em->clear();
|
||||
|
||||
return new SendableNotification($config, $notification, $feeds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer|integer[] $notification A Notification id or array of ids.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function removeComputedScheduling($notification)
|
||||
{
|
||||
$filteredNotifications = array_filter((array) $notification);
|
||||
|
||||
if (count($filteredNotifications) > 0) {
|
||||
$this->em->getConnection()->executeQuery(sprintf('
|
||||
DELETE FROM internal_notification_scheduling
|
||||
WHERE notification_id in (%s)
|
||||
', implode(',', $filteredNotifications)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize 'notifications' parameter.
|
||||
*
|
||||
* @param array|object $notifications Passed parameters.
|
||||
*
|
||||
* @return Notification[]
|
||||
*/
|
||||
private function normalizeNotifications($notifications)
|
||||
{
|
||||
if ($notifications instanceof Notification) {
|
||||
$notifications = [ $notifications ];
|
||||
}
|
||||
|
||||
$checkerFn = function ($object) {
|
||||
return ! $object instanceof Notification;
|
||||
};
|
||||
|
||||
if (! is_array($notifications) || \nspl\a\any($notifications, $checkerFn)) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'Expects single %s or array of instances',
|
||||
Notification::class
|
||||
));
|
||||
}
|
||||
|
||||
return $notifications;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create proper comment fetcher for current notification.
|
||||
*
|
||||
* @param NotificationThemeOptions $options A NotificationThemeOptions
|
||||
* instance.
|
||||
* @param SendableNotificationConfig $config A SendableNotificationConfig
|
||||
* instance.
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
private function createCommentsFetcherFn(
|
||||
NotificationThemeOptions $options,
|
||||
SendableNotificationConfig $config
|
||||
) {
|
||||
$userComments = $options->getContent()->getShowInfo()->getUserComments();
|
||||
|
||||
//
|
||||
// We should not fetch comments if notification don't require they.
|
||||
//
|
||||
if (! $userComments->is(ThemeOptionsUserCommentsEnum::no())) {
|
||||
return function (Document $document) {
|
||||
return $document;
|
||||
};
|
||||
}
|
||||
|
||||
/** @var CommentRepository $repository */
|
||||
$repository = $this->em->getRepository(Comment::class);
|
||||
|
||||
//
|
||||
// Find out which fields do we need for processing current notification.
|
||||
//
|
||||
$commentFields = [
|
||||
'title',
|
||||
'content',
|
||||
];
|
||||
if ($userComments->is(ThemeOptionsUserCommentsEnum::WITH_AUTHOR_DATE)) {
|
||||
$commentFields[] = 'createdAt';
|
||||
$commentFields['author'] = [
|
||||
'firstName',
|
||||
'lastName',
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
// Create proper fetcher.
|
||||
//
|
||||
return function ($id) use ($repository, $commentFields, $config) {
|
||||
return $repository->getListForDocument(
|
||||
$id,
|
||||
$commentFields,
|
||||
$config->commentsPerDocument
|
||||
)->getQuery()->getResult();
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Manager\Notification;
|
||||
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\Recipient\AbstractRecipient;
|
||||
|
||||
/**
|
||||
* Interface NotificationManagerInterface
|
||||
* @package UserBundle\Manager\Notification
|
||||
*/
|
||||
interface NotificationManagerInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Add new notification or update exists.
|
||||
*
|
||||
* @param Notification $notification A Notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function persists(Notification $notification);
|
||||
|
||||
/**
|
||||
* Activate specified notifications.
|
||||
*
|
||||
* @param Notification|Notification[] $notifications A Notification entity
|
||||
* instance or array of
|
||||
* instances.
|
||||
* @param boolean $active Activate or deactivate
|
||||
* specified notifications.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function activatedToggle($notifications, $active = true);
|
||||
|
||||
/**
|
||||
* Publish specified notifications.
|
||||
*
|
||||
* @param Notification|Notification[] $notifications A Notification entity
|
||||
* instance or array of
|
||||
* instances.
|
||||
* @param boolean $publish Publish or make private
|
||||
* specified notifications.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function publishedToggle($notifications, $publish = true);
|
||||
|
||||
/**
|
||||
* Publish specified notifications.
|
||||
*
|
||||
* @param AbstractRecipient $recipient Who try to subscribe or
|
||||
* unsubscribe from specified
|
||||
* notifications.
|
||||
* @param Notification|Notification[] $notifications A Notification entity
|
||||
* instance or array of
|
||||
* instances.
|
||||
* @param boolean $subscribe Subscribe or unsubscribe
|
||||
* from specified notifications.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function subscriptionToggle(AbstractRecipient $recipient, $notifications, $subscribe = true);
|
||||
|
||||
/**
|
||||
* Remove specified notifications.
|
||||
*
|
||||
* @param Notification|Notification[] $notifications A removed Notification
|
||||
* entity instance or array
|
||||
* of instances.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function remove($notifications);
|
||||
|
||||
/**
|
||||
* Prepare specified notification for sending.
|
||||
*
|
||||
* @param Notification $notification A Notification instance.
|
||||
*
|
||||
* @return SendableNotification
|
||||
*/
|
||||
public function prepareToSend(Notification $notification);
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Manager\Notification;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\Notification\NotificationSendHistory;
|
||||
use UserBundle\Entity\Notification\Schedule\AbstractNotificationSchedule;
|
||||
use UserBundle\Entity\Notification\ThemeOption\ThemeOptionHeader;
|
||||
use UserBundle\Entity\Recipient\AbstractRecipient;
|
||||
use UserBundle\Entity\Recipient\GroupRecipient;
|
||||
use UserBundle\Entity\Recipient\PersonRecipient;
|
||||
use UserBundle\Enum\ThemeTypeEnum;
|
||||
use UserBundle\Mailer\MailerInterface;
|
||||
use UserBundle\Manager\Notification\Model\FeedData;
|
||||
use UserBundle\Repository\PersonRecipientRepository;
|
||||
|
||||
/**
|
||||
* Class SendableNotification
|
||||
* @package UserBundle\Manager\Notification
|
||||
*/
|
||||
class SendableNotification
|
||||
{
|
||||
|
||||
const TEMPLATE = 'UserBundle:Notification:index.html.twig';
|
||||
|
||||
/**
|
||||
* @var SendableNotificationConfig
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @var Notification
|
||||
*/
|
||||
private $notification;
|
||||
|
||||
/**
|
||||
* Sent data.
|
||||
*
|
||||
* @var FeedData[]
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $success;
|
||||
|
||||
/**
|
||||
* SendableNotification constructor.
|
||||
*
|
||||
* @param SendableNotificationConfig $config A SendableNotificationConfig
|
||||
* instance.
|
||||
* @param Notification $notification A Notification instance.
|
||||
* @param FeedData[]|array $data Sent data.
|
||||
* @param boolean $success Flag, true if we successfully
|
||||
* get data.
|
||||
*/
|
||||
public function __construct(
|
||||
SendableNotificationConfig $config,
|
||||
Notification $notification,
|
||||
array $data,
|
||||
$success = true
|
||||
) {
|
||||
$this->config = $config;
|
||||
$this->notification = $notification;
|
||||
$this->data = $data;
|
||||
$this->success = $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send notification.
|
||||
*
|
||||
* @param MailerInterface $mailer A MailerInterface instance.
|
||||
* @param EngineInterface $templating A templating EngineInterface
|
||||
* instance.
|
||||
* @param EntityManagerInterface $em A EntityManagerInterface
|
||||
* instance.
|
||||
* @param integer[]|array $schedules Array of schedules entity ids.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function send(
|
||||
MailerInterface $mailer,
|
||||
EngineInterface $templating,
|
||||
EntityManagerInterface $em,
|
||||
array $schedules
|
||||
) {
|
||||
// if (! $this->success) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
$body = $this->render($templating);
|
||||
if ($body === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Get recipient's emails.
|
||||
//
|
||||
$recipients = $this->notification->getRecipients()->map(function (AbstractRecipient $recipient) use ($em) {
|
||||
$emails = null;
|
||||
if ($recipient instanceof GroupRecipient) {
|
||||
/** @var PersonRecipientRepository $repository */
|
||||
$repository = $em->getRepository(PersonRecipient::class);
|
||||
|
||||
$emails = $repository->getEmailsByGroup($recipient->getId());
|
||||
} elseif ($recipient instanceof PersonRecipient) {
|
||||
$emails = $recipient->getEmail();
|
||||
}
|
||||
|
||||
return $emails;
|
||||
})->toArray();
|
||||
|
||||
// $recipients = array_filter(\Functional\flatten($recipients));
|
||||
$recipients = array_filter(\nspl\a\flatten($recipients));
|
||||
|
||||
//
|
||||
// Send notification and flush queue.
|
||||
//
|
||||
$sent = $mailer->sendNotificationEmail(
|
||||
$recipients,
|
||||
$this->notification->getSubject(),
|
||||
$body
|
||||
);
|
||||
$mailer->flushQueue();
|
||||
|
||||
if ($sent) {
|
||||
//
|
||||
// We should change date of last notification sending and store it to
|
||||
// history.
|
||||
//
|
||||
/** @var Notification $notificationReference */
|
||||
$notificationReference = $em->getReference(Notification::class, $this->notification->getId());
|
||||
$schedules = $em->getRepository(AbstractNotificationSchedule::class)
|
||||
->findBy([ 'id' => $schedules ]);
|
||||
$schedules = array_map(function (AbstractNotificationSchedule $schedule) {
|
||||
$historySchedule = clone $schedule;
|
||||
$historySchedule->setNotification(null);
|
||||
|
||||
return $historySchedule;
|
||||
}, $schedules);
|
||||
|
||||
$notificationReference->setLastSentAt(new \DateTime());
|
||||
$history = new NotificationSendHistory(
|
||||
$notificationReference,
|
||||
$schedules
|
||||
);
|
||||
|
||||
$em->persist($notificationReference);
|
||||
$em->persist($history);
|
||||
$em->flush();
|
||||
|
||||
//
|
||||
// Remove old history.
|
||||
//
|
||||
$em->createQueryBuilder()
|
||||
->delete()
|
||||
->from(NotificationSendHistory::class, 'History')
|
||||
->where('History.date <= :date')
|
||||
->setParameter('date', date_create()->modify($this->config->historyStorePeriod))
|
||||
->getQuery()
|
||||
->execute();
|
||||
}
|
||||
|
||||
return $sent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render notification template.
|
||||
*
|
||||
* @param EngineInterface $templating A templating EngineInterface instance.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function render(EngineInterface $templating)
|
||||
{
|
||||
// if (! $this->success) {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
$body = null;
|
||||
if (count($this->data) > 0) {
|
||||
//
|
||||
// Render proper notification template.
|
||||
//
|
||||
$isEnhanced = $this->notification->getThemeType()->is(ThemeTypeEnum::ENHANCED);
|
||||
|
||||
$themeOptions = $this->notification->getActualThemeOptions();
|
||||
|
||||
//
|
||||
// Set default logo image for enhanced layout.
|
||||
//
|
||||
$header = $themeOptions->getHeader();
|
||||
|
||||
if ($isEnhanced && ($header->getImageUrl() === '')) {
|
||||
$header->setImageUrl(ThemeOptionHeader::DEFAULT_IMAGE);
|
||||
} elseif (! $isEnhanced && ($header->getImageUrl() === ThemeOptionHeader::DEFAULT_IMAGE)) {
|
||||
$header->setImageUrl('');
|
||||
}
|
||||
|
||||
$body = $templating->render(self::TEMPLATE, [
|
||||
'feeds' => $this->data,
|
||||
'theme' => [
|
||||
'options' => $themeOptions->toArray(),
|
||||
'type' => $this->notification->getThemeType()->getValue(),
|
||||
],
|
||||
]);
|
||||
} elseif ($this->notification->isSendWhenEmpty()) {
|
||||
//
|
||||
// Render empty notification template if notification allow empty sending.
|
||||
//
|
||||
$body = $this->config->emptyMessage;
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Manager\Notification;
|
||||
|
||||
use AppBundle\Configuration\ConfigurationImmutableInterface;
|
||||
use AppBundle\Configuration\ParametersName;
|
||||
|
||||
/**
|
||||
* Class SendableNotification
|
||||
* @package UserBundle\Manager\Notification
|
||||
*
|
||||
* @property integer documentsPerFeed()
|
||||
* @property integer commentsPerDocument()
|
||||
* @property integer extractContextualCharacter()
|
||||
* @property integer extractFromStartCharacter()
|
||||
* @property string emptyMessage()
|
||||
* @property integer historyStorePeriod()
|
||||
*/
|
||||
class SendableNotificationConfig
|
||||
{
|
||||
|
||||
/**
|
||||
* @var integer[]
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* SendableNotificationConfig constructor.
|
||||
*
|
||||
* @param integer $documentsPerFeed Max number of documents showing
|
||||
* in each feed.
|
||||
* @param integer $commentsPerDocument Max number of comments showing
|
||||
* in each document.
|
||||
* @param integer $extractContextualCharacter Number of character before and
|
||||
* after extracted document content.
|
||||
* Used when notification field
|
||||
* `articleExtracts` has value
|
||||
* 'contextual'.
|
||||
* @param integer $extractFromStartCharacter Number of character from beginning
|
||||
* of document content. Used when
|
||||
* notification field `articleExtracts`
|
||||
* has value 'start'.
|
||||
* @param string $emptyMessage Empty notification message.
|
||||
* Used when notification field
|
||||
* `sendWhenEmpty` set to true.
|
||||
* @param integer $historyStorePeriod How long we should store render
|
||||
* history.
|
||||
*/
|
||||
public function __construct(
|
||||
$documentsPerFeed,
|
||||
$commentsPerDocument,
|
||||
$extractContextualCharacter,
|
||||
$extractFromStartCharacter,
|
||||
$emptyMessage,
|
||||
$historyStorePeriod
|
||||
) {
|
||||
$this->config = [
|
||||
'documentsPerFeed' => $documentsPerFeed,
|
||||
'commentsPerDocument' => $commentsPerDocument,
|
||||
'extractContextualCharacter' => $extractContextualCharacter,
|
||||
'extractFromStartCharacter' => $extractFromStartCharacter,
|
||||
'emptyMessage' => $emptyMessage,
|
||||
'historyStorePeriod' => $historyStorePeriod,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConfigurationImmutableInterface $configuration A ConfigurationImmutableInterface
|
||||
* instance.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function fromConfiguration(ConfigurationImmutableInterface $configuration)
|
||||
{
|
||||
return new static(
|
||||
$configuration->getParameter(ParametersName::NOTIFICATION_DOCUMENT_PER_FEED),
|
||||
$configuration->getParameter(ParametersName::NOTIFICATION_COMMENTS_PER_DOCUMENT),
|
||||
0, // TODO add proper parameter.
|
||||
$configuration->getParameter(ParametersName::NOTIFICATION_START_EXTRACT_LENGTH),
|
||||
$configuration->getParameter(ParametersName::NOTIFICATION_EMPTY_MESSAGE),
|
||||
$configuration->getParameter(ParametersName::NOTIFICATION_SEND_HISTORY_MODIFY)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name Parameter name.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if (isset($this->{$name})) {
|
||||
return $this->config[$name];
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Unknown parameter name '. $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name Parameter name.
|
||||
* @param mixed $value Parameter value.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
throw new \LogicException('SendableNotificationConfig is immutable.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name Parameter name.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
return isset($this->config[$name]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Manager\User;
|
||||
|
||||
use CacheBundle\Entity\Category;
|
||||
use FOS\UserBundle\Doctrine\UserManager as BaseManager;
|
||||
use FOS\UserBundle\Model\UserInterface;
|
||||
use UserBundle\Entity\Recipient\PersonRecipient;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Enum\UserRoleEnum;
|
||||
|
||||
/**
|
||||
* Class UserManager
|
||||
*
|
||||
* @package UserBundle\Manager\User
|
||||
*/
|
||||
class UserManager extends BaseManager implements UserManagerInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Deletes a user.
|
||||
*
|
||||
* @param UserInterface $user A UserInterface entity instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteUser(UserInterface $user)
|
||||
{
|
||||
if (! $user instanceof User) {
|
||||
throw new \InvalidArgumentException('Expects instance of ' . User::class);
|
||||
}
|
||||
|
||||
$this->objectManager->remove($user->getRecipient());
|
||||
$user->setRecipient(null);
|
||||
|
||||
$billingSubscriptions = $user->getBillingSubscription();
|
||||
$billingSubscriptions->removeUser($user);
|
||||
$user->setBillingSubscription(null);
|
||||
|
||||
if ($billingSubscriptions->isOwnedBy($user)) {
|
||||
$this->objectManager->remove($billingSubscriptions);
|
||||
}
|
||||
|
||||
parent::deleteUser($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a user.
|
||||
*
|
||||
* @param UserInterface $user A UserInterface entity instance.
|
||||
* @param boolean $andFlush Flush data to storage.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function updateUser(UserInterface $user, $andFlush = true)
|
||||
{
|
||||
if (! $user instanceof User) {
|
||||
throw new \InvalidArgumentException('Expects instance of ' . User::class);
|
||||
}
|
||||
|
||||
if (($user->getId() === null)
|
||||
&& ($user->hasRole(UserRoleEnum::SUBSCRIBER)
|
||||
|| $user->hasRole(UserRoleEnum::MASTER_USER))
|
||||
) {
|
||||
//
|
||||
// For all new users we create recipient with their emails.
|
||||
//
|
||||
$recipient = PersonRecipient::createFromUser($user)
|
||||
->setAssociatedUser($user)
|
||||
->setOwner($user);
|
||||
$this->objectManager->persist($recipient);
|
||||
}
|
||||
|
||||
parent::updateUser($user, $andFlush);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user A Confirmed user instance.
|
||||
*
|
||||
* @return string New password.
|
||||
*/
|
||||
public function confirmUser(User $user)
|
||||
{
|
||||
|
||||
Category::createMainCategory($user);
|
||||
Category::createSharedCategory($user);
|
||||
Category::createTrashCategory($user);
|
||||
|
||||
$user
|
||||
->setVerified()
|
||||
->setEnabled(true)
|
||||
->generatePassword();
|
||||
|
||||
$password = $user->getPlainPassword();
|
||||
$this->updateUser($user);
|
||||
|
||||
return $password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Manager\User;
|
||||
|
||||
use FOS\UserBundle\Model\UserManagerInterface as BaseManagerInterface;
|
||||
use UserBundle\Entity\User;
|
||||
|
||||
/**
|
||||
* Class UserManager
|
||||
*
|
||||
* @package UserBundle\Manager\User
|
||||
*/
|
||||
interface UserManagerInterface extends BaseManagerInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param User $user A Confirmed user instance.
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
public function confirmUser(User $user);
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Repository;
|
||||
|
||||
use AppBundle\Model\SortingOptions;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query\Parameter;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use UserBundle\Entity\Recipient\GroupRecipient;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Enum\StatusFilterEnum;
|
||||
use UserBundle\Utils\AdditionalConditions;
|
||||
|
||||
/**
|
||||
* GroupRecipientRepository
|
||||
*
|
||||
* This class was generated by the Doctrine ORM. Add your own custom
|
||||
* repository methods below.
|
||||
*/
|
||||
class GroupRecipientRepository extends EntityRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* Get available for specified user.
|
||||
*
|
||||
* @param User $user A User entity instance.
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function getAvailableForUser(User $user)
|
||||
{
|
||||
return $this->createQueryBuilder('Grp')
|
||||
->where('Grp.owner = :user')
|
||||
->setParameter('user', $user->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $user A User entity id.
|
||||
* @param SortingOptions $sortingOptions A SortingOptions instance.
|
||||
* @param string $nameFilter Filter recipient groups by name.
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function getQueryBuilderForUser(
|
||||
$user,
|
||||
SortingOptions $sortingOptions,
|
||||
$nameFilter = ''
|
||||
) {
|
||||
$sortField = $this->resolveSortField($sortingOptions);
|
||||
$expr = $this->_em->getExpressionBuilder();
|
||||
|
||||
$condition = $expr->andX($expr->eq('Grp.owner', ':user'));
|
||||
$parameters = new ArrayCollection([ new Parameter('user', $user) ]);
|
||||
|
||||
if ($nameFilter !== '') {
|
||||
$condition->add($expr->like('Grp.name', ':filter'));
|
||||
$parameters[] = new Parameter('filter', '%'. $nameFilter .'%');
|
||||
}
|
||||
|
||||
return $this->createQueryBuilder('Grp')
|
||||
->where($condition)
|
||||
->setParameters($parameters)
|
||||
->orderBy($sortField, $sortingOptions->getSortDirection());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $user A User entity id.
|
||||
* @param integer $person A PersonRecipient entity
|
||||
* id.
|
||||
* @param StatusFilterEnum $statusFilter A StatusFilterEnum instance.
|
||||
* @param SortingOptions $sortingOptions A SortingOptions instance.
|
||||
* @param string $filter Filter recipient groups
|
||||
* by name.
|
||||
* @param AdditionalConditions $additionalConditions A AdditionalConditions
|
||||
* instance.
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function getQueryBuilderForPerson(
|
||||
$user,
|
||||
$person,
|
||||
StatusFilterEnum $statusFilter,
|
||||
SortingOptions $sortingOptions,
|
||||
$filter,
|
||||
AdditionalConditions $additionalConditions
|
||||
) {
|
||||
$sortField = $this->resolveSortField($sortingOptions);
|
||||
$expr = $this->_em->getExpressionBuilder();
|
||||
|
||||
$condition = $expr->andX($expr->eq('Grp.owner', ':user'));
|
||||
$parameters = new ArrayCollection([
|
||||
new Parameter('user', $user),
|
||||
new Parameter('person', $person),
|
||||
]);
|
||||
$parameters = $additionalConditions->addToParameters($parameters);
|
||||
|
||||
if ($filter !== '') {
|
||||
$condition->add($expr->like('Grp.name', ':filter'));
|
||||
$parameters[] = new Parameter('filter', '%'. $filter .'%');
|
||||
}
|
||||
|
||||
$qb = $this->createQueryBuilder('Grp');
|
||||
|
||||
switch ($statusFilter->getValue()) {
|
||||
//
|
||||
// Show only not enrolled groups.
|
||||
//
|
||||
case StatusFilterEnum::NO:
|
||||
//
|
||||
// Select groups ids which has association with specified recipient
|
||||
// and remove them from results.
|
||||
//
|
||||
$subCondition = $expr->andX(
|
||||
$expr->eq('_Person.id', ':person'),
|
||||
$expr->eq('_Grp.owner', ':user')
|
||||
);
|
||||
$subCondition = $additionalConditions->addToConditions($subCondition, '_Grp');
|
||||
|
||||
$subDql = $this->createQueryBuilder('_Grp')
|
||||
->select('_Grp.id')
|
||||
->leftJoin('_Grp.recipients', '_Person')
|
||||
->where($subCondition)
|
||||
->getDQL();
|
||||
|
||||
$condition->add($expr->notIn('Grp', $subDql));
|
||||
$qb->addSelect('0 AS enrolled');
|
||||
break;
|
||||
|
||||
//
|
||||
// Fetch only enrolled groups.
|
||||
//
|
||||
case StatusFilterEnum::YES:
|
||||
$condition->add($expr->eq('Person.id', ':person'));
|
||||
$condition = $additionalConditions->addToConditions($condition, 'Grp');
|
||||
|
||||
|
||||
$qb
|
||||
->join('Grp.recipients', 'Person')
|
||||
->addSelect('1 AS enrolled');
|
||||
break;
|
||||
|
||||
//
|
||||
// If we not apply filters we should check in which groups specified
|
||||
// recipient is enrolled.
|
||||
//
|
||||
case StatusFilterEnum::ALL:
|
||||
$countCondition = $expr->andX(
|
||||
$expr->eq('_Person.id', ':person'),
|
||||
$expr->eq('_Grp.id', 'Grp.id')
|
||||
);
|
||||
|
||||
$countCondition = $additionalConditions->addToConditions($countCondition, 'Grp');
|
||||
|
||||
$countDQL = $this->createQueryBuilder('_Grp')
|
||||
->select('COUNT(_Grp.id)')
|
||||
->join('_Grp.recipients', '_Person')
|
||||
->where($countCondition)
|
||||
->getDQL();
|
||||
|
||||
$qb->addSelect("(CASE WHEN ({$countDQL}) > 0 THEN 1 ELSE 0 END) AS enrolled");
|
||||
break;
|
||||
}
|
||||
|
||||
return $qb
|
||||
->where($condition)
|
||||
->setParameters($parameters)
|
||||
->orderBy($sortField, $sortingOptions->getSortDirection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get group recipient by id.
|
||||
*
|
||||
* @param integer $id A GroupRecipient entity id.
|
||||
*
|
||||
* @return GroupRecipient|null
|
||||
*/
|
||||
public function get($id)
|
||||
{
|
||||
return $this->createQueryBuilder('Grp')
|
||||
->where('Grp.id = :id')
|
||||
->setParameter('id', $id)
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SortingOptions $sortingOptions A SortingOptions instance.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function resolveSortField(SortingOptions $sortingOptions)
|
||||
{
|
||||
$sortField = $sortingOptions->getFieldName();
|
||||
switch ($sortField) {
|
||||
case 'active':
|
||||
case 'name':
|
||||
case 'recipientsNumber':
|
||||
$sortField = "Grp.{$sortField}";
|
||||
break;
|
||||
|
||||
case 'creationDate':
|
||||
$sortField = 'Grp.createdAt';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("Unknown field name '{$sortField}'.");
|
||||
}
|
||||
|
||||
return $sortField;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,439 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Repository;
|
||||
|
||||
use AppBundle\Model\SortingOptions;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\Query\Parameter;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use UserBundle\Entity\Notification\Notification;
|
||||
use UserBundle\Entity\Recipient\AbstractRecipient;
|
||||
use UserBundle\Entity\Subscription\AbstractSubscription;
|
||||
use UserBundle\Entity\User;
|
||||
use UserBundle\Enum\NotificationTypeEnum;
|
||||
use UserBundle\Enum\StatusFilterEnum;
|
||||
|
||||
/**
|
||||
* NotificationRepository
|
||||
*
|
||||
* This class was generated by the Doctrine ORM. Add your own custom
|
||||
* repository methods below.
|
||||
*/
|
||||
class NotificationRepository extends EntityRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* @param integer $id A Notification entity instance.
|
||||
* @param NotificationTypeEnum $type A NotificationTypeEnum instance.
|
||||
*
|
||||
* @return Notification|null
|
||||
*/
|
||||
public function get($id, NotificationTypeEnum $type = null)
|
||||
{
|
||||
$expr = $this->_em->getExpressionBuilder();
|
||||
|
||||
$condition = $expr->andX(
|
||||
$expr->eq('Notification.id', ':id')
|
||||
);
|
||||
|
||||
$parameters = new ArrayCollection([
|
||||
new Parameter('id', $id),
|
||||
]);
|
||||
|
||||
if ($type !== null) {
|
||||
$condition->add($expr->eq(
|
||||
'Notification.notificationType',
|
||||
':type'
|
||||
));
|
||||
$parameters[] = new Parameter('type', (string) $type);
|
||||
}
|
||||
|
||||
return $this->createQueryBuilder('Notification')
|
||||
// ->addSelect('Feed, Chart, Owner, Recipient')
|
||||
->addSelect('Feed, Owner, Recipient')
|
||||
->leftJoin('Notification.feeds', 'Feed')
|
||||
// ->leftJoin('Notification.charts', 'Chart')
|
||||
->leftJoin('Notification.owner', 'Owner')
|
||||
->leftJoin('Notification.recipients', 'Recipient')
|
||||
->where($condition)
|
||||
->setParameters($parameters)
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notification instance for sending.
|
||||
*
|
||||
* @param integer $id A Notification entity id.
|
||||
*
|
||||
* @return Notification|null
|
||||
*/
|
||||
public function getForSending($id)
|
||||
{
|
||||
return $this->createQueryBuilder('Notification')
|
||||
->addSelect(
|
||||
'partial Feed.{id, name}, Owner, Recipient',
|
||||
'partial Schedule.{id}'
|
||||
)
|
||||
->leftJoin('Notification.feeds', 'Feed')
|
||||
->leftJoin('Notification.owner', 'Owner')
|
||||
->leftJoin('Notification.recipients', 'Recipient')
|
||||
->leftJoin('Notification.schedules', 'Schedule')
|
||||
->where('Notification.id = :id')
|
||||
->setParameter('id', $id)
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function getQueryBuilderForSubscription()
|
||||
{
|
||||
return $this->createQueryBuilder('Notification')
|
||||
->addSelect('partial Owner.{id, email}')
|
||||
->join('Notification.owner', 'Owner');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get query builder for fetching available notifications for forms.
|
||||
*
|
||||
* @param User $user A User entity instance, who ask.
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function getQueryBuilderForForm(User $user)
|
||||
{
|
||||
$expr = $this->_em->getExpressionBuilder();
|
||||
|
||||
return $this->createQueryBuilder('Notification')
|
||||
->where($expr->orX(
|
||||
$expr->eq('Notification.owner', ':user'),
|
||||
$expr->andX(
|
||||
$expr->eq('Notification.published', 1),
|
||||
$expr->eq('Notification.billingSubscription', ':subscription')
|
||||
)
|
||||
))
|
||||
->setParameter('user', $user->getId())
|
||||
->setParameter('subscription', $user->getBillingSubscription()->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AbstractRecipient $recipient Requested AbstractRecipient
|
||||
* entity instance.
|
||||
* @param User $owner A User entity id.
|
||||
* @param SortingOptions $sortingOptions A SortingOptions instance.
|
||||
* @param StatusFilterEnum $statusFilter A StatusFilterEnum instance.
|
||||
* @param string $nameFilter Part of Notification entity name
|
||||
* for filtering.
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function getQueryBuilderForRecipient(
|
||||
AbstractRecipient $recipient,
|
||||
User $owner,
|
||||
SortingOptions $sortingOptions,
|
||||
StatusFilterEnum $statusFilter,
|
||||
$nameFilter
|
||||
) {
|
||||
$expr = $this->_em->getExpressionBuilder();
|
||||
|
||||
$sortField = $sortingOptions->getFieldName();
|
||||
|
||||
$qb = $this->getQueryBuilderForForm($owner)
|
||||
->addSelect(
|
||||
'RecipientList',
|
||||
'Schedule',
|
||||
'Owner'
|
||||
)
|
||||
->join('Notification.owner', 'Owner')
|
||||
->leftJoin('Notification.recipients', 'RecipientList')
|
||||
->leftJoin('Notification.schedules', 'Schedule')
|
||||
->orderBy($sortField, $sortingOptions->getSortDirection())
|
||||
->setParameter('recipient', $recipient->getId());
|
||||
|
||||
if ($nameFilter !== '') {
|
||||
$qb
|
||||
->andWhere($expr->like('Notification.name', ':name'))
|
||||
->setParameter('name', '%'. $nameFilter .'%');
|
||||
}
|
||||
|
||||
switch ($statusFilter->getValue()) {
|
||||
//
|
||||
// Select notification ids which has association with specified recipient
|
||||
// and remove them from results.
|
||||
//
|
||||
case StatusFilterEnum::NO:
|
||||
$subDql = $this->createQueryBuilder('_Notification')
|
||||
->select('_Notification.id')
|
||||
->join('_Notification.recipients', '_Recipient', Join::WITH, '_Recipient.id = :recipient')
|
||||
->getDQL();
|
||||
|
||||
$qb
|
||||
->addSelect('0 AS subscribed')
|
||||
->andWhere($expr->notIn('Notification.id', $subDql));
|
||||
break;
|
||||
|
||||
//
|
||||
// Fetch only subscribed notifications.
|
||||
//
|
||||
case StatusFilterEnum::YES:
|
||||
$qb
|
||||
->addSelect('1 AS subscribed')
|
||||
->join('Notification.recipients', 'Recipient', Join::WITH, 'Recipient.id = :recipient');
|
||||
break;
|
||||
|
||||
case StatusFilterEnum::ALL:
|
||||
$countDQL = $this->createQueryBuilder('_Notification')
|
||||
->select('COUNT(_Notification.id)')
|
||||
->join('_Notification.recipients', '_Recipient', Join::WITH, '_Recipient.id = :recipient')
|
||||
->where('_Notification.id = Notification.id')
|
||||
->getDQL();
|
||||
|
||||
$qb
|
||||
->addSelect("({$countDQL}) AS subscribed")
|
||||
->join('Notification.recipients', 'Recipient');
|
||||
break;
|
||||
}
|
||||
|
||||
$qb = $this->resolveSortingOptions($qb, $sortingOptions);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get query builder for notifications.
|
||||
*
|
||||
* @param SortingOptions $sortingOptions A SortingOptions instance.
|
||||
* @param User $owner A User entity instance or null.
|
||||
* @param boolean $onlyPublished Fetch only published notifications.
|
||||
* @param string $nameFilter Filter notification by name.
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function getQueryBuilder(
|
||||
SortingOptions $sortingOptions,
|
||||
User $owner,
|
||||
$onlyPublished = false,
|
||||
$nameFilter = null
|
||||
) {
|
||||
$expr = $this->_em->getExpressionBuilder();
|
||||
$condition = $expr->andX(
|
||||
$expr->eq('Notification.billingSubscription', ':subscription'),
|
||||
$expr->eq('Notification.owner', ':owner')
|
||||
);
|
||||
$parameters = new ArrayCollection([
|
||||
new Parameter('subscription', $owner->getBillingSubscription()->getId()),
|
||||
new Parameter('recipient', $owner->getRecipient()->getId()),
|
||||
new Parameter('owner', $owner->getId()),
|
||||
]);
|
||||
|
||||
if ($onlyPublished) {
|
||||
$condition->add($expr->eq('Notification.published', 1));
|
||||
}
|
||||
|
||||
$qb = $this->createQueryBuilder('Notification')
|
||||
->addSelect(
|
||||
'Recipient',
|
||||
'Schedule',
|
||||
'Owner',
|
||||
'(CASE WHEN Recipient.id = :recipient THEN 1 ELSE 0 END) AS subscribed'
|
||||
)
|
||||
->join('Notification.owner', 'Owner')
|
||||
->leftJoin('Notification.recipients', 'Recipient')
|
||||
->leftJoin('Notification.schedules', 'Schedule')
|
||||
->where($condition)
|
||||
->setParameters($parameters);
|
||||
|
||||
if ($nameFilter !== null) {
|
||||
$qb
|
||||
->andWhere($expr->like('Notification.name', ':name'))
|
||||
->setParameter('name', '%'. $nameFilter .'%');
|
||||
}
|
||||
return $this->resolveSortingOptions(
|
||||
$qb,
|
||||
$sortingOptions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param QueryBuilder $qb A QueryBuilder instance.
|
||||
* @param SortingOptions $sortingOptions A SortingOptions instance.
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
private function resolveSortingOptions(QueryBuilder $qb, SortingOptions $sortingOptions)
|
||||
{
|
||||
$sortField = $sortingOptions->getFieldName();
|
||||
switch ($sortField) {
|
||||
case 'published':
|
||||
case 'active':
|
||||
case 'sourcesCount':
|
||||
case 'owner':
|
||||
case 'name':
|
||||
$sortField = "Notification.{$sortField}";
|
||||
break;
|
||||
|
||||
case 'type':
|
||||
$sortField = 'Notification.notificationType';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("Unknown field name '{$sortField}'.");
|
||||
}
|
||||
|
||||
return $qb
|
||||
->orderBy($sortField, $sortingOptions->getSortDirection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count notifications for user.
|
||||
*
|
||||
* @param SortingOptions $sortingOptions A SortingOptions instance.
|
||||
*
|
||||
* @return \Doctrine\ORM\QueryBuilder
|
||||
*/
|
||||
public function computeUserNotificationsCount(SortingOptions $sortingOptions)
|
||||
{
|
||||
$sortField = $sortingOptions->getFieldName();
|
||||
|
||||
return $this->createQueryBuilder('Notification')
|
||||
->select(
|
||||
'COUNT(Notification.id) as notifications',
|
||||
'IDENTITY(Notification.owner) as id',
|
||||
'Owner.email as name',
|
||||
'\'owner\' as type'
|
||||
)
|
||||
->join('Notification.owner', 'Owner')
|
||||
->orderBy($sortField, $sortingOptions->getSortDirection())
|
||||
->groupBy('Notification.owner')
|
||||
->getQuery()
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count notifications for recipient.
|
||||
*
|
||||
* @param SortingOptions $sortingOptions A SortingOptions instance.
|
||||
*
|
||||
* @return \Doctrine\ORM\QueryBuilder
|
||||
*/
|
||||
public function computeRecipientNotificationsCount(SortingOptions $sortingOptions)
|
||||
{
|
||||
$sortField = $sortingOptions->getFieldName();
|
||||
return $this->createQueryBuilder('Notification')
|
||||
->select(
|
||||
'COUNT(Notification.id) as notifications',
|
||||
'Recipient.id as id',
|
||||
'Recipient.name as name',
|
||||
'\'recipient\' as type'
|
||||
)
|
||||
->leftJoin('Notification.recipients', 'Recipient')
|
||||
->orderBy($sortField, $sortingOptions->getSortDirection())
|
||||
->groupBy('Recipient.id')
|
||||
->getQuery()
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count notifications for feed.
|
||||
*
|
||||
* @param SortingOptions $sortingOptions A SortingOptions instance.
|
||||
*
|
||||
* @return \Doctrine\ORM\QueryBuilder
|
||||
*/
|
||||
public function getCountFeedNotifications(SortingOptions $sortingOptions)
|
||||
{
|
||||
$sortField = $sortingOptions->getFieldName();
|
||||
return $this->createQueryBuilder('Notification')
|
||||
->select(
|
||||
'COUNT(Notification.id) as notifications',
|
||||
'Feed.id as id',
|
||||
'Feed.name as name',
|
||||
'\'feed\' as type'
|
||||
)
|
||||
->leftJoin('Notification.feeds', 'Feed')
|
||||
->orderBy($sortField, $sortingOptions->getSortDirection())
|
||||
->groupBy('Feed.id')
|
||||
->getQuery()
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get query builder for all notifications.
|
||||
*
|
||||
* @param SortingOptions $sortingOptions A SortingOptions instance.
|
||||
* @param AbstractSubscription $subscription A AbstractSubscription instance.
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function getNotificationsAllQueryBuilder(
|
||||
SortingOptions $sortingOptions,
|
||||
AbstractSubscription $subscription
|
||||
) {
|
||||
return $this->resolveSortingOptions(
|
||||
$this->createQueryBuilder('Notification')
|
||||
->addSelect(
|
||||
'Recipient',
|
||||
'Schedule',
|
||||
'Owner'
|
||||
)
|
||||
->join('Notification.owner', 'Owner')
|
||||
->leftJoin('Notification.recipients', 'Recipient')
|
||||
->leftJoin('Notification.schedules', 'Schedule')
|
||||
->where('Notification.billingSubscription = :subscription')
|
||||
->setParameter('subscription', $subscription->getId())
|
||||
->groupBy('Notification.id'),
|
||||
$sortingOptions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SortingOptions $sortingOptions A SortingOptions instance.
|
||||
* @param string $typeFilter One of available filter.
|
||||
* @param string $filterId Filter id.
|
||||
* @param User $user Filter owner.
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function getQueryBuilderForFilter(
|
||||
SortingOptions $sortingOptions,
|
||||
$typeFilter,
|
||||
$filterId,
|
||||
User $user
|
||||
) {
|
||||
|
||||
$sortField = $sortingOptions->getFieldName();
|
||||
$qb = $this->createQueryBuilder('Notification')
|
||||
->addSelect(
|
||||
'RecipientList',
|
||||
'Schedule',
|
||||
'Owner'
|
||||
)
|
||||
->leftJoin('Notification.owner', 'Owner')
|
||||
->leftJoin('Notification.recipients', 'RecipientList')
|
||||
->leftJoin('Notification.schedules', 'Schedule')
|
||||
->leftJoin('Notification.billingSubscription', 'Subscription', Join::WITH, 'Subscription.masterAccounts =:masterUser')
|
||||
->setParameter('masterUser', $user->getId())
|
||||
->orderBy($sortField, $sortingOptions->getSortDirection());
|
||||
|
||||
switch ($typeFilter) {
|
||||
case 'owner':
|
||||
$qb->andWhere('Notification.owner =:owner')
|
||||
->setParameter(':owner', $filterId);
|
||||
break;
|
||||
case 'recipient':
|
||||
$qb->join('Notification.recipients', 'Recipient', Join::WITH, 'Recipient.id = :recipient')
|
||||
->setParameter('recipient', $filterId);
|
||||
break;
|
||||
case 'feed':
|
||||
$qb->join('Notification.feeds', 'Feed', Join::WITH, 'Feed.id = :feed')
|
||||
->setParameter('feed', $filterId);
|
||||
break;
|
||||
}
|
||||
$qb = $this->resolveSortingOptions($qb, $sortingOptions);
|
||||
return $qb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Repository;
|
||||
|
||||
use AppBundle\Model\SortingOptions;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use UserBundle\Entity\Notification\Schedule\AbstractNotificationSchedule;
|
||||
use UserBundle\Entity\Recipient\AbstractRecipient;
|
||||
use UserBundle\Enum\NotificationTypeEnum;
|
||||
|
||||
/**
|
||||
* NotificationRepository
|
||||
*
|
||||
* This class was generated by the Doctrine ORM. Add your own custom
|
||||
* repository methods below.
|
||||
*/
|
||||
class NotificationSendHistoryRepository extends EntityRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* @param integer $notification A Notification entity id.
|
||||
*
|
||||
* @return \Doctrine\ORM\QueryBuilder
|
||||
*/
|
||||
public function getListForNotification($notification)
|
||||
{
|
||||
return $this->createQueryBuilder('History')
|
||||
->select('History.date')
|
||||
->where('History.notification = :notification')
|
||||
->setParameter('notification', $notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AbstractRecipient $recipient A AbstractRecipient entity instance.
|
||||
* @param SortingOptions $sortingOptions A SortingOptions instance.
|
||||
* @param string $typeFilter Notification type filter.
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function getListForRecipient(
|
||||
AbstractRecipient $recipient,
|
||||
SortingOptions $sortingOptions,
|
||||
$typeFilter
|
||||
) {
|
||||
$qb = $this->createQueryBuilder('History')
|
||||
->select(
|
||||
'partial History.{id, date}',
|
||||
'partial Notification.{id, name, notificationType}',
|
||||
'Schedule'
|
||||
)
|
||||
->join('History.notification', 'Notification')
|
||||
->join('History.schedules', 'Schedule')
|
||||
->join('Notification.recipients', 'Recipient', Join::WITH, 'Recipient.id = :recipient')
|
||||
->setParameter('recipient', $recipient->getId());
|
||||
|
||||
$sortField = $sortingOptions->getFieldName();
|
||||
switch ($sortField) {
|
||||
case 'name':
|
||||
$sortField = 'Notification.name';
|
||||
break;
|
||||
|
||||
case 'type':
|
||||
$sortField = 'Notification.notificationType';
|
||||
break;
|
||||
|
||||
case 'scheduleTime':
|
||||
$countDql = $this->_em->createQueryBuilder()
|
||||
->select('COUNT(_Schedule.id)')
|
||||
->from(AbstractNotificationSchedule::class, '_Schedule')
|
||||
->where('_Schedule.history = History.id')
|
||||
->getDQL();
|
||||
|
||||
$qb->addSelect("($countDql) AS HIDDEN scheduleCount");
|
||||
$sortField = 'scheduleCount';
|
||||
break;
|
||||
|
||||
case 'sentTime':
|
||||
$sortField = 'History.date';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("Unknown field name '{$sortField}'.");
|
||||
}
|
||||
|
||||
switch ($typeFilter) {
|
||||
case NotificationTypeEnum::ALERT:
|
||||
$qb
|
||||
->andWhere('Notification.notificationType = :type')
|
||||
->setParameter('type', NotificationTypeEnum::ALERT);
|
||||
break;
|
||||
|
||||
case NotificationTypeEnum::NEWSLETTER:
|
||||
$qb
|
||||
->andWhere('Notification.notificationType = :type')
|
||||
->setParameter('type', NotificationTypeEnum::NEWSLETTER);
|
||||
break;
|
||||
}
|
||||
|
||||
return $qb->orderBy($sortField, $sortingOptions->getSortDirection());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Repository;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use UserBundle\Entity\Notification\NotificationTheme;
|
||||
|
||||
/**
|
||||
* NotificationThemeRepository
|
||||
*
|
||||
* This class was generated by the Doctrine ORM. Add your own custom
|
||||
* repository methods below.
|
||||
*/
|
||||
class NotificationThemeRepository extends EntityRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* Get default notification theme.
|
||||
*
|
||||
* @return NotificationTheme|null
|
||||
*/
|
||||
public function getDefault()
|
||||
{
|
||||
return $this->createQueryBuilder('Theme')
|
||||
->where('Theme.default = 1')
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace UserBundle\Repository;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use UserBundle\Entity\Subscription\OrganizationSubscription;
|
||||
|
||||
/**
|
||||
* OrganizationRepository
|
||||
*
|
||||
* This class was generated by the Doctrine ORM. Add your own custom
|
||||
* repository methods below.
|
||||
*/
|
||||
class OrganizationRepository extends EntityRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* @return \Doctrine\ORM\QueryBuilder
|
||||
*/
|
||||
public function getListQueryBuilder()
|
||||
{
|
||||
$subDQL = $this->_em->createQueryBuilder()
|
||||
->select('COUNT(_User.id)')
|
||||
->from(OrganizationSubscription::class, '_Subscription')
|
||||
->join('_Subscription.users', '_User')
|
||||
->where('_Subscription.organization = Organization')
|
||||
->getDQL();
|
||||
|
||||
return $this->createQueryBuilder('Organization')
|
||||
->select(
|
||||
'Organization.id, Organization.name',
|
||||
'COUNT(Subscription) as subscriptionCount',
|
||||
'('. $subDQL .') as usersCount'
|
||||
)
|
||||
->leftJoin('Organization.subscriptions', 'Subscription')
|
||||
->groupBy('Organization.id')
|
||||
->orderBy('Organization.id');
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user