src/Service/FlightCpcBanner.php line 39

Open in your IDE?
  1. <?php
  2. namespace App\Service;
  3. use App\Entity\Campaign;
  4. use App\Repository\BidRulesRepository;
  5. use App\Repository\CampaignRepository;
  6. use App\Repository\MediaRepository;
  7. use Doctrine\ORM\EntityManagerInterface;
  8. use Symfony\Component\Cache\Adapter\RedisAdapter;
  9. use Symfony\Contracts\Cache\ItemInterface;
  10. class FlightCpcBanner
  11. {
  12.     private $mediaRepository;
  13.     private $campaignRepository;
  14.     private $bid;
  15.     private $em;
  16.     public function __construct(MediaRepository $mediaRepositoryCampaignRepository $campaignRepositoryBidRulesRepository $bidEntityManagerInterface $em)
  17.     {
  18.         $this->mediaRepository $mediaRepository;
  19.         $this->campaignRepository $campaignRepository;
  20.         $this->bid $bid;
  21.         $this->em $em;
  22.     }
  23.     private function getTimeMatrix()
  24.     {
  25.         $weekDays = ['Saturday' => 'a''Sunday' => 'b''Monday' => 'c''Tuesday' => 'd''Wednesday' => 'e''Thursday' => 'f''Friday' => 'g'];
  26.         return $weekDays[date('l')] . date('G');;
  27.     }
  28.     public function getBanner(string $dimensionstring $zonestring $originstring $destinationstring $device)
  29.     {
  30.         $cache = new RedisAdapter(
  31.             RedisAdapter::createConnection('redis://localhost'),
  32.             'flight-cpc-view',
  33.             $defaultLifetime 60
  34.         );
  35.         $cacheKey "{$dimension}-{$zone}-{$origin}-{$destination}-{$device}";
  36.         $cachedMedia $cache->get($cacheKey, function (ItemInterface $item) use ($origin$destination$zone$dimension$device) {
  37.             $item->expiresAfter(120);
  38.             $origin strtoupper($origin);
  39.             $destination strtoupper($destination);
  40.             /** Get minimum possible bid according to DB */
  41.             $bids $this->bid->findBy(['type' => 'flight'], ['bid' => 'DESC']);
  42.             $minBid 0;
  43.             foreach ($bids as $bid) {
  44.                 if (!empty($bid->getOrigin()) && !empty($bid->getDestination())) {
  45.                     if ($bid->getOrigin() == $origin && $bid->getDestination() == $destination) {
  46.                         $minBid $bid->getBid();
  47.                         break;
  48.                     }
  49.                 } elseif (!empty($bid->getOrigin()) && empty($bid->getDestination())) {
  50.                     if ($bid->getOrigin() == $origin) {
  51.                         $minBid $bid->getBid();
  52.                         break;
  53.                     }
  54.                 } elseif (empty($bid->getOrigin()) && !empty($bid->getDestination())) {
  55.                     if ($bid->getDestination() == $destination) {
  56.                         $minBid $bid->getBid();
  57.                         break;
  58.                     }
  59.                 } else {
  60.                     if ($bid->getZone() == $zone) {
  61.                         $minBid $bid->getBid();
  62.                     }
  63.                 }
  64.             }
  65.             /** find availbale campaigns */
  66.             $currentTime $this->getTimeMatrix();
  67.             $campaigns $this->campaignRepository->createQueryBuilder('c');
  68.             $campaigns->select(['c.id''c.bid']);
  69.             $campaigns->where('c.type = :type')->setParameter('type''flight_cpc');
  70.             $campaigns->andWhere('c.device = :all or c.device = :device')->setParameter('all''all')->setParameter('device'$device);
  71.             $campaigns->andWhere('c.start_date < :startdate or c.start_date is null')->setParameter('startdate', new \DateTime());
  72.             $campaigns->andWhere('c.end_date > :enddate or c.end_date is null')->setParameter('enddate', new \DateTime());
  73.             $campaigns->andWhere('c.time_matrix like :currentTime or c.time_matrix is null')->setParameter('currentTime'"%$currentTime%");
  74.             $campaigns->andWhere('c.origin = :origin or c.origin is null')->setParameter('origin'$origin);
  75.             $campaigns->andWhere('c.destination = :destination or c.destination is null')->setParameter('destination'$destination);
  76.             $campaigns->andWhere('c.bid >= :minbid')->setParameter('minbid'$minBid);
  77.             $campaigns->andWhere('c.daily_budget > c.daily_spent');
  78.             if (!empty($zone)) {
  79.                 $campaigns->andWhere('c.zone = :zone or c.zone=:all')->setParameter('zone'$zone)->setParameter('all''all');
  80.             }
  81.             $campaigns->andWhere('c.has_fund = true');
  82.             $campaigns->andWhere('c.status = :active')->setParameter('active''active');
  83.             $campaignsOBJ $campaigns->getQuery()->getResult();
  84.             $campaignsId array_map(function ($c) {
  85.                 return $c['id'];
  86.             }, $campaignsOBJ);
  87.             /** Get available assosiataed medias */
  88.             $mediasQuery $this->mediaRepository->createQueryBuilder('m');
  89.             $mediasQuery->select(['m.id''m.uid''m.dimension''m.title''m.file''m.url''m.impression''m.click''c.ctr''identity(m.created_by) as user''c.bid']);
  90.             $mediasQuery->addSelect(['c.utm_source''c.utm_medium''c.utm_campaign''c.id as campaign']);
  91.             $mediasQuery->where('m.type = :type')->setParameter('type''flight_cpc');
  92.             $mediasQuery->andWhere('m.campaign in (:campaigns)')->setParameter('campaigns'$campaignsId);
  93.             $mediasQuery->andWhere('m.dimension = :dimension')->setParameter('dimension'$dimension);
  94.             $mediasQuery->andWhere('m.status = :active')->setParameter('active''active');
  95.             $mediasQuery->innerJoin(Campaign::class, 'c''WITH''c.id = m.campaign');
  96.             $mediasQuery->orderBy('c.bid''DESC');
  97.             $medias $mediasQuery->getQuery()->getResult();
  98.             /** categorize medias to virgin and not virgin medias */
  99.             $virginMedias $notVirginMedia = [];
  100.             foreach ($medias as $media) {
  101.                 if ($media['impression'] < 10000) {
  102.                     $virginMedias[] = $media;
  103.                 } else {
  104.                     $notVirginMedia[] = array_merge($media, [
  105.                         'score' => (($media['click'] / $media['impression']) + 0.0001) * $media['bid']
  106.                     ]);
  107.                 }
  108.             }
  109.             usort($notVirginMedia, function ($item1$item2) {
  110.                 return $item2['score'] <=> $item1['score'];
  111.             });
  112.             /** avialable banners */
  113.             $outPutmedia = !empty($notVirginMedia) ? array_merge([$notVirginMedia[0]], $virginMedias) : $virginMedias;
  114.             return $outPutmedia;
  115.         }, 1.1);
  116.         /** not to be cached */
  117.         if (!empty($cachedMedia)) {
  118.             $pickedBannerKey array_rand($cachedMedia);
  119.             $pickedBanner $cachedMedia[$pickedBannerKey];
  120.             $con $this->em->getConnection();
  121.             $con->executeQuery('update campaign set impression = impression + 3, ctr=(cast(click as float)/cast(GREATEST(impression,1) as float )) * 100 where id= ?', [$pickedBanner['campaign']]);
  122.             $con->executeQuery('update media set impression = impression + 3, ctr=(cast(click as float)/cast(GREATEST(impression,1) as float )) * 100 where id= ?', [$pickedBanner['id']]);
  123.             $con->executeQuery("insert into campaign_stat (id,campaign_id,date,stat_id,impression,ctr,created_at) values (nextval('campaign_stat_id_seq'),?,?,?,?,?,current_timestamp) on conflict (stat_id) do update set impression = campaign_stat.impression + 3 ,ctr = (cast(campaign_stat.click as float)/cast(campaign_stat.impression as float )) * 100", [
  124.                 $pickedBanner['campaign'],
  125.                 date('Y-m-d'),
  126.                 $pickedBanner['campaign'] . "-" date('Ymd'),
  127.                 1,
  128.                 0
  129.             ]);
  130.         } else {
  131.             $pickedBanner = [];
  132.         }
  133.         if (empty($pickedBanner)) {
  134.             return null;
  135.         } else {
  136.             return [
  137.                 'id' => $pickedBanner['id'],
  138.                 'uid' => $pickedBanner['uid'],
  139.                 'file' => $_ENV['BASE_URL'] . $pickedBanner['file'],
  140.                 'link' => $pickedBanner['url'],
  141.                 'dim' => $pickedBanner['dimension']
  142.             ];
  143.         }
  144.     }
  145. }