vendor/bugbuster/contao-banner-bundle/src/Resources/contao/controllers/FrontendBanner.php line 285

Open in your IDE?
  1. <?php
  2. /**
  3.  * @copyright  Glen Langer 2022 <http://contao.ninja>
  4.  * @author     Glen Langer (BugBuster)
  5.  * @license    LGPL-3.0+
  6.  * @see           https://github.com/BugBuster1701/contao-banner-bundle
  7.  */
  8. namespace BugBuster\Banner;
  9. use BugBuster\Banner\BannerChecks;
  10. use BugBuster\Banner\BannerHelper;
  11. use Symfony\Component\HttpFoundation\RedirectResponse;
  12. use Symfony\Component\HttpFoundation\Response;
  13. /**
  14.  * Front end banner controller
  15.  * for route: bugbuster_banner_frontend_clicks
  16.  *
  17.  * @author     Glen Langer (BugBuster)
  18.  */
  19. class FrontendBanner extends \Frontend
  20. {
  21.     /**
  22.      * Banner ID
  23.      * @var int
  24.      */
  25.     protected $intBID;
  26.     protected $intDEFBID;
  27.     /**
  28.      * Session
  29.      *
  30.      * @var string
  31.      */
  32.     private $_session   = [];
  33.     /**
  34.      * Initialize the object (do not remove)
  35.      */
  36.     public function __construct()
  37.     {
  38.         parent::__construct();
  39.         // See #4099
  40.         if (!\defined('BE_USER_LOGGED_IN')) {
  41.             \define('BE_USER_LOGGED_IN'false);
  42.         }
  43.         if (!\defined('FE_USER_LOGGED_IN')) {
  44.             \define('FE_USER_LOGGED_IN'false);
  45.         }
  46.         $this->intBID    0;
  47.         $this->intDEFBID 0;
  48.     }
  49.     /**
  50.      * Run the controller
  51.      *
  52.      * @return Response
  53.      */
  54.     public function run($strbid$bid)
  55.     {
  56.         if ($strbid == 'bid') {
  57.             $this->intBID $bid;
  58.         } else {
  59.             $this->intDEFBID $bid;
  60.         }
  61.         $banner_category_id $this->getBannerCategory($this->intBID);
  62.         $objBannerHelper    = new BannerHelper();
  63.         $objBannerHelper->setDebugSettings($banner_category_id);
  64.         //Banner oder Kategorie Banner (Default Banner)
  65.         if ($this->intBID) {
  66.             //normaler Banner
  67.             $banner_not_viewed false;
  68.             // Check whether the Banner ID exists
  69.             $objBanners \Database::getInstance()
  70.                                     ->prepare("SELECT
  71.                                                 tb.id
  72.                                               , tb.banner_url
  73.                                               , tb.banner_jumpTo
  74.                                               , tbs.banner_clicks
  75.                                            FROM
  76.                                                 tl_banner tb
  77.                                               , tl_banner_stat tbs
  78.                                            WHERE
  79.                                                 tb.id=tbs.id
  80.                                            AND
  81.                                                 tb.id=?")
  82.                                     ->execute($this->intBID);
  83.             if (!$objBanners->next()) {
  84.                 $objBanners \Database::getInstance()
  85.                                         ->prepare("SELECT
  86.                                                     tb.id
  87.                                                   , tb.banner_url
  88.                                                   , tb.banner_jumpTo
  89.                                                FROM
  90.                                                     tl_banner tb
  91.                                                WHERE
  92.                                                     tb.id=?")
  93.                                         ->execute($this->intBID);
  94.                 if (!$objBanners->next()) {
  95.                     $objResponse = new Response('Banner ID not found'501);
  96.                     return $objResponse;
  97.                 } else {
  98.                     $banner_not_viewed true;
  99.                 }
  100.             }
  101.             $BannerChecks = new BannerChecks();
  102.             $banner_stat_update false;
  103.             if ($BannerChecks->checkUserAgent() === false
  104.                 && $BannerChecks->checkBot()       === false
  105.                 && $BannerChecks->checkBE()        === false
  106.                 && $this->getSetReClickBlocker()   === false
  107.             ) {
  108.                 // keine User Agent Filterung, kein Bot, kein ReClick, kein BE Login
  109.                 $banner_stat_update true;
  110.             }
  111.             $BannerChecks null;
  112.             unset($BannerChecks);
  113.             //Zählung
  114.             $this->countClicks($banner_stat_update$banner_not_viewed$objBanners);
  115.             //Banner Ziel per Page?
  116.             if ($objBanners->banner_jumpTo >0) {
  117.                 //url generieren
  118.                 $objBannerNextPage \Database::getInstance()
  119.                                                 ->prepare("SELECT
  120.                                                                 id
  121.                                                               , alias
  122.                                                            FROM
  123.                                                                 tl_page
  124.                                                            WHERE
  125.                                                                 id=?")
  126.                                                 ->limit(1)
  127.                                                 ->execute($objBanners->banner_jumpTo);
  128.                 if ($objBannerNextPage->numRows) {
  129.                     $objPage \PageModel::findWithDetails($objBanners->banner_jumpTo);
  130.                     // deprecated #8 $objBanners->banner_url = \Controller::generateFrontendUrl($objBannerNextPage->fetchAssoc(), null, $objPage->rootLanguage);
  131.                     $objBanners->banner_url BannerHelper::frontendUrlGenerator($objBannerNextPage->fetchAssoc(), null$objPage->rootLanguage);
  132.                 }
  133.             }
  134.             $banner_redirect $this->getRedirectType($this->intBID);
  135.         } else {
  136.             // Default Banner from Category
  137.             // Check whether the Banner ID exists
  138.             $objBanners \Database::getInstance()
  139.                                     ->prepare("SELECT
  140.                                                     id
  141.                                                   , banner_default_url AS banner_url
  142.                                                FROM
  143.                                                     tl_banner_category
  144.                                                WHERE
  145.                                                     id=?")
  146.                                     ->execute($this->intDEFBID);
  147.             if (!$objBanners->next()) {
  148.                 $objResponse = new Response('Default Banner ID not found'501);
  149.                 return $objResponse;
  150.             }
  151.             $banner_redirect '303';
  152.         }
  153.         $banner_url $objBanners->banner_url;
  154.         BannerLog::writeLog(__METHOD____LINE__'banner_url: '$banner_url);
  155.         // 301 Moved Permanently
  156.         // 302 Found
  157.         // 303 See Other
  158.         // 307 Temporary Redirect (ab Contao 3.1)
  159.         //$this->redirect($banner_url, $banner_redirect);
  160.         // Make the location an absolute URL
  161.         if (!preg_match('@^https?://@i'$banner_url)) {
  162.             $banner_url \Environment::get('base') . ltrim($banner_url'/');
  163.         }
  164.         $objResponse = new RedirectResponse($banner_url$banner_redirect);
  165.         $objResponse->setPrivate();
  166.         $objResponse->setMaxAge(0);
  167.         $objResponse->setSharedMaxAge(0);
  168.         $objResponse->headers->addCacheControlDirective('must-revalidate'true);
  169.         $objResponse->headers->addCacheControlDirective('no-store'true);
  170.         return $objResponse;
  171.     }
  172.     protected function countClicks($banner_stat_update$banner_not_viewed$objBanners)
  173.     {
  174.         if ($banner_stat_update === true) {
  175.             if ($banner_not_viewed === false) {
  176.                 //Update
  177.                 $tstamp time();
  178.                 $banner_clicks $objBanners->banner_clicks 1;
  179.                 \Database::getInstance()->prepare("UPDATE
  180.                                                         tl_banner_stat
  181.                                                    SET
  182.                                                         tstamp=?
  183.                                                       , banner_clicks=?
  184.                                                    WHERE
  185.                                                         id=?")
  186.                                         ->execute($tstamp$banner_clicks$this->intBID);
  187.             } else {
  188.                 //Insert
  189.                 $arrSet =
  190.                 [
  191.                     'id'     => $this->intBID,
  192.                     'tstamp' => time(),
  193.                     'banner_clicks' => 1
  194.                 ];
  195.                 \Database::getInstance()->prepare("INSERT IGNORE INTO tl_banner_stat %s")
  196.                                         ->set($arrSet)
  197.                                         ->execute();
  198.             }
  199.         }
  200.         return;
  201.     }
  202.     /**
  203.      * Search Banner Redirect Definition
  204.      *
  205.      * @return int 301,302
  206.      */
  207.     protected function getRedirectType($banner_id)
  208.     {
  209.         // aus $banner_id die CatID
  210.         // über CatID in tl_module.banner_categories die tl_module.banner_redirect
  211.         // Schleife über alle zeilen, falls mehrere
  212.         $CatID $this->getBannerCategory($banner_id);
  213.         if (== $CatID) {
  214.             return '301'// error, but the show must go on
  215.         }
  216.         $objBRT \Database::getInstance()->prepare("SELECT
  217.                                                         `banner_categories`
  218.                                                        ,`banner_redirect`
  219.                                                      FROM
  220.                                                         `tl_module`
  221.                                                      WHERE
  222.                                                         type=?
  223.                                                      AND
  224.                                                         banner_categories=?")
  225.                                         ->execute('banner'$CatID);
  226.         if (== $objBRT->numRows) {
  227.             return '301'// error, but the show must go on
  228.         }
  229.         $arrBRT = [];
  230.         while ($objBRT->next()) {
  231.             $arrBRT[] = ($objBRT->banner_redirect == 'temporary') ? '302' '301';
  232.         }
  233.         if (\count($arrBRT) == 1) {
  234.             return $arrBRT[0];    // Nur ein Modul importiert, eindeutig
  235.         } else {
  236.             // mindestens 2 FE Module mit derselben Kategorie, zaehlen
  237.             $anz301=$anz302=0;
  238.             foreach ($arrBRT as $type) {
  239.                 if ($type=='301') {
  240.                     $anz301++;
  241.                 } else {
  242.                     $anz302++;
  243.                 }
  244.             }
  245.             if ($anz301 >= $anz302) {        // 301 hat bei Gleichstand Vorrang
  246.                 return '301';
  247.             } else {
  248.                 return '302';
  249.             }
  250.         }
  251.     }
  252.     /**
  253.      * ReClick Blocker
  254.      *
  255.      * @return bool false/true  =   no ban / ban
  256.      */
  257.     protected function getSetReClickBlocker()
  258.     {
  259.         //$ClientIP = bin2hex(sha1(\Environment::get('remoteAddr'),true)); // sha1 20 Zeichen, bin2hex 40 zeichen
  260.         $BannerID $this->intBID;
  261.         if ($this->getReClickBlockerId($BannerID) === false) {
  262.             // nichts geblockt, also blocken fürs den nächsten Aufruf
  263.             $this->setReClickBlockerId($BannerID);
  264.             // kein ReClickBlocker block gefunden, Zaehlung erlaubt, nicht blocken
  265.             BannerLog::writeLog(__METHOD____LINE__': False: Banner ID '.$BannerID.' Klick nicht geblockt');
  266.             return false;
  267.         } else {
  268.             // Eintrag innerhalb der Blockzeit, blocken
  269.             BannerLog::writeLog(__METHOD____LINE__': True: Banner ID '.$BannerID.' Klick geblockt');
  270.             return true;
  271.         }
  272.     }
  273.     protected function getBannerCategory($banner_id)
  274.     {
  275.         $objCat \Database::getInstance()->prepare("SELECT
  276.                                                         pid as CatID
  277.                                                      FROM
  278.                                                         `tl_banner`
  279.                                                      WHERE
  280.                                                         id=?")
  281.                                         ->execute($banner_id);
  282.         if (== $objCat->numRows) {
  283.             return 0// error, but the show must go on
  284.         }
  285.         $objCat->next();
  286.         return $objCat->CatID;
  287.     }
  288.     /*  _____               _
  289.        / ____|             (_)
  290.       | (___   ___  ___ ___ _  ___  _ __
  291.        \___ \ / _ \/ __/ __| |/ _ \| '_ \
  292.        ____) |  __/\__ \__ \ | (_) | | | |
  293.       |_____/ \___||___/___/_|\___/|_| |_|s
  294.      */
  295.     /**
  296.      * Set ReClick Blocker, Set Banner ID and timestamp
  297.      *
  298.      * @param integer $banner_id
  299.      */
  300.     protected function setReClickBlockerId($banner_id=0)
  301.     {
  302.         if ($banner_id==0) {
  303.             return;
  304.         }// keine Banner ID, nichts zu tun
  305.         //das können mehrere sein!, mergen!
  306.         $this->setSession('ReClickBlocker', [$banner_id => time()], true);
  307.         return;
  308.     }
  309.     /**
  310.      * Get ReClick Blocker, Get Banner ID if the timestamp ....
  311.      *
  312.      * @param boolean    true if blocked | false
  313.      */
  314.     protected function getReClickBlockerId($banner_id=0)
  315.     {
  316.         $this->getSession('ReClickBlocker');
  317.         if (\count($this->_session)) {
  318.             reset($this->_session);
  319.             foreach ($this->_session as $key => $val) {
  320.                 if ($key == $banner_id &&
  321.                     $this->removeReClickBlockerId($key$val) === true) {
  322.                     // Key ist noch gültig und es muss daher geblockt werden
  323.                     //fuer debug log_message('getReClickBlockerId Banner ID:'.$key,'Banner.log');
  324.                     return true;
  325.                 }
  326.             }
  327.         }
  328.         return false;
  329.     }
  330.     /**
  331.      * ReClick Blocker, Remove old Banner ID
  332.      *
  333.      * @param  integer $banner_id
  334.      * @return boolean true = Key is valid, it must be blocked | false = key is invalid
  335.      */
  336.     protected function removeReClickBlockerId($banner_id$tstmap)
  337.     {
  338.         $BannerBlockTime time() - 60*5;  // 5 Minuten, 0-5 min wird geblockt
  339.         if (isset($GLOBALS['TL_CONFIG']['mod_banner_block_time'])
  340.             && (int) ($GLOBALS['TL_CONFIG']['mod_banner_block_time'])>0
  341.         ) {
  342.             $BannerBlockTime time() - 60*1*(int) ($GLOBALS['TL_CONFIG']['mod_banner_block_time']);
  343.         }
  344.         if ($tstmap >  $BannerBlockTime) {
  345.             BannerLog::writeLog(__METHOD____LINE__': BannerBlockTime: '.date("Y-m-d H:i:s"$BannerBlockTime));
  346.             BannerLog::writeLog(__METHOD____LINE__': BannerSessiTime: '.date("Y-m-d H:i:s"$tstmap));
  347.             return true;
  348.         } else {
  349.             //wenn mehrere dann nur den Teil, nicht die ganze Session
  350.             unset($this->_session[$banner_id]);
  351.             //wenn Anzahl Banner in Session nun 0 dann Session loeschen
  352.             if (\count($this->_session) == 0) {
  353.                 //komplett löschen
  354.                 \Session::getInstance()->remove('ReClickBlocker');
  355.             } else { //sonst neu setzen
  356.                 //gekuerzte Session neu setzen
  357.                 $this->setSession('ReClickBlocker'$this->_sessionfalse);
  358.             }
  359.         }
  360.         return false;
  361.     }
  362.     /**
  363.      * Get session
  364.      *
  365.      * @param  string $session_name e.g.: 'ReClickBlocker'
  366.      * @return void
  367.      */
  368.     protected function getSession($session_name)
  369.     {
  370.         $this->_session = (array) \Session::getInstance()->get($session_name);
  371.     }
  372.     /**
  373.      * Set session
  374.      *
  375.      * @param  string $session_name e.g.: 'ReClickBlocker'
  376.      * @param  array  $arrData      array('key' => array(Value1,Value2,...))
  377.      * @return void
  378.      */
  379.     protected function setSession($session_name$arrData$merge false)
  380.     {
  381.         if ($merge) {
  382.             $this->_session \Session::getInstance()->get($session_name);
  383.             // numerische Schlüssel werden neu numeriert, daher
  384.             // geht nicht: array_merge($this->_session, $arrData)
  385.             $merge_array = (array) $this->_session $arrData;
  386.             \Session::getInstance()->set($session_name$merge_array);
  387.         } else {
  388.             \Session::getInstance()->set($session_name$arrData);
  389.         }
  390.     }
  391. }