Advertisement
Guest User

Untitled

a guest
Oct 27th, 2016
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 9.45 KB | None | 0 0
  1. class OfferWithStatsQueryBuilder
  2. {
  3.  
  4.     const DATE_FORMAT = 'Y-m-d';
  5.  
  6.     const COLUMN_OFFER_ID = 0;
  7.     const COLUMN_KEYWORDS = 1;
  8.     const COLUMN_STATS = 2;
  9.     const COLUMN_ADURL_1 = 3;
  10.     const COLUMN_GEO_1 = 4;
  11.     const COLUMN_EPC = 5; // ?
  12.     const COLUMN_ADURL_2 = 6;
  13.     const COLUMN_GEO_2 = 7;
  14.  
  15.     private $offset;
  16.  
  17.     private $limit;
  18.  
  19.     private $keywords;
  20.  
  21.     private $dateFrom;
  22.  
  23.     private $dateTo;
  24.  
  25.     private $geos;
  26.     /**
  27.      * @var QueryBuilder
  28.      */
  29.     private $queryBuilder;
  30.  
  31.     /**
  32.      * @var bool
  33.      */
  34.     private $isOrderable = false;
  35.  
  36.     /**
  37.      * @var int @see self::COLUMN_* constants
  38.      */
  39.     private $orderColumn;
  40.  
  41.     /**
  42.      * @var string 'desc' or 'asc'
  43.      */
  44.     private $orderDirection;
  45.  
  46.     /**
  47.      * OfferWithStatsQueryBuilder constructor.
  48.      * @param QueryBuilder $queryBuilder
  49.      */
  50.     public function __construct(QueryBuilder $queryBuilder)
  51.     {
  52.         $this->queryBuilder = $queryBuilder;
  53.     }
  54.  
  55.     /**
  56.      * @param mixed $offset
  57.      */
  58.     public function setOffset($offset)
  59.     {
  60.         $this->offset = $offset;
  61.     }
  62.  
  63.     /**
  64.      * @param mixed $limit
  65.      */
  66.     public function setLimit($limit)
  67.     {
  68.         $this->limit = $limit;
  69.     }
  70.  
  71.     /**
  72.      * @param array $keywords
  73.      */
  74.     public function setKeywords($keywords = null)
  75.     {
  76.  
  77.         $this->keywords = null;
  78.  
  79.         if (!empty($keywords) && is_array($keywords)) {
  80.  
  81.             $this->keywords = array_map(function ($id) {
  82.                 return (int) $id;
  83.             }, $keywords);
  84.  
  85.         }
  86.  
  87.     }
  88.  
  89.     /**
  90.      * @param mixed $dateFrom
  91.      */
  92.     public function setDateFrom($dateFrom = null)
  93.     {
  94.  
  95.         if (!empty($dateFrom)) {
  96.             $dateFrom = new \DateTime($dateFrom);
  97.             $dateFrom = $dateFrom->format(self::DATE_FORMAT);
  98.         }
  99.  
  100.         $this->dateFrom = $dateFrom;
  101.     }
  102.  
  103.     /**
  104.      * @param mixed $dateTo
  105.      */
  106.     public function setDateTo($dateTo = null)
  107.     {
  108.         if (!empty($dateTo)) {
  109.             $dateTo = new \DateTime($dateTo);
  110.             $dateTo = $dateTo->format(self::DATE_FORMAT);
  111.         }
  112.  
  113.         $this->dateTo = $dateTo;
  114.     }
  115.  
  116.     /**
  117.      * @param array $geos
  118.      */
  119.     public function setGeos($geos = null)
  120.     {
  121.         $this->geos = null;
  122.  
  123.         if (!empty($geos) && is_array($geos)) {
  124.             $this->geos = array_map(function ($geo) {
  125.                 return (int) $geo;
  126.             }, $geos);
  127.         }
  128.     }
  129.  
  130.     /**
  131.      * @param mixed $order
  132.      */
  133.     public function setOrder($order = null)
  134.     {
  135.         $isOrderable = false;
  136.  
  137.         if (!empty($order) && is_array($order)) {
  138.             $this->orderDirection = $order[0]['dir'] == 'desc' ? 'desc' : 'asc';
  139.             $this->orderColumn = (int) $order[0]['column'];
  140.             $isOrderable = true;
  141.         }
  142.  
  143.         $this->isOrderable = $isOrderable;
  144.     }
  145.  
  146.     public function buildQueryBuilder()
  147.     {
  148.         $select = 'lo.id AS offer, la.id AS adurl, la.url as url, ls.stats, lolkr.keywords, lacr.countries';
  149.         $sql = $this->build($select);
  150.         $this->appendSorting($sql);
  151.         return $sql;
  152.     }
  153.  
  154.     public function buildQueryBuilderForCount()
  155.     {
  156.         $select = 'COUNT(DISTINCT lo.id) as count';
  157.         $notLimitQuery = false;
  158.         $sql = $this->build($select, $notLimitQuery);
  159.         return $sql;
  160.     }
  161.  
  162.     private function toSubQuerySelect(QueryBuilder $query)
  163.     {
  164.         return '(' . $query->getSQL() . ')';
  165.     }
  166.  
  167.     private function build($select = '*', $isLimited = true)
  168.     {
  169.         $main = clone $this->queryBuilder;
  170.  
  171.         $offerSubSelect = $this->getOfferSubQuery($isLimited);
  172.         $statJoinSubSelect = $this->getStatJoinSubQuery();
  173.         $keywordsSubSelect = $this->getKeywordsJoinSubQuery();
  174.         $geoSubSelect = $this->getGeoJoinSubQuery();
  175.        
  176.  
  177.         $main
  178.             ->select($select)
  179.             ->from($this->toSubQuerySelect($offerSubSelect), 'lo')
  180.             ->innerJoin('lo', 'leadgen_adurls', 'la', 'lo.id = la.offer_id')
  181.             ->leftJoin('lo', $this->toSubQuerySelect($statJoinSubSelect), 'ls', 'la.id = ls.url_id')
  182.             ->leftJoin('lo', $this->toSubQuerySelect($keywordsSubSelect), 'lolkr', 'lo.id = lolkr.offer_id')
  183.             ->leftJoin('lo', $this->toSubQuerySelect($geoSubSelect), 'lacr', 'la.id = lacr.leadgen_adurl_id');
  184.  
  185.         $this->appendConditions($main);
  186. //        dd($main->getSQL());
  187.         return $main;
  188.  
  189.         return '
  190.            SELECT *
  191.            FROM leadgen_offers lo
  192.            LEFT JOIN leadgen_adurls la ON lo.id = la.offer_id
  193.            -- STATS
  194.            INNER JOIN (
  195.                SELECT url_id, SUM(count) as stats
  196.                FROM leadgen_stats
  197.                GROUP BY url_id
  198.            ) as ls ON la.id = ls.url_id
  199.            -- KEYWORDS
  200.            LEFT JOIN (
  201.                SELECT offer_id, GROUP_CONCAT(keyword_id SEPARATOR \', \') as keywords
  202.                FROM leadgen_offers_leadgen_keywords_rel
  203.                GROUP BY offer_id
  204.            ) as lolkr ON lo.id = lolkr.offer_id
  205.            -- GEO
  206.            LEFT JOIN (
  207.                SELECT leadgen_adurl_id, GROUP_CONCAT(leadgen_country_id SEPARATOR \', \') as countries
  208.                FROM leadgen_adurls_countries_rel
  209.                GROUP BY leadgen_adurl_id
  210.            ) as lacr ON la.id = lacr.leadgen_adurl_id
  211.            
  212.            GROUP BY lo.id, la.id
  213.        ';
  214.     }
  215.  
  216.     /**
  217.      * @return QueryBuilder
  218.      */
  219.     private function getStatJoinSubQuery()
  220.     {
  221.         $statSubQuery = clone $this->queryBuilder;
  222.  
  223.         $statSubQuery
  224.             ->select('url_id, SUM(count) AS stats')
  225.             ->from('leadgen_stats')
  226.             ->groupBy('url_id');
  227.  
  228.         if ($this->dateFrom) {
  229.             // primary bind in STRING, when ::getSQL() doesNOT bind through ::setParameter()
  230.             $statSubQuery->andWhere('date >= DATE(\'' . $this->dateFrom . '\')');
  231.         }
  232.  
  233.         if ($this->dateTo) {
  234.             $statSubQuery->andWhere('date <= DATE( \'' . $this->dateTo . '\')');
  235.         }
  236.  
  237.         return $statSubQuery;
  238.     }
  239.  
  240.     private function getKeywordsJoinSubQuery()
  241.     {
  242.         $keywordsSubQuery = clone $this->queryBuilder;
  243.  
  244.         $keywordsSubQuery
  245.             ->select('offer_id, GROUP_CONCAT(keyword_id SEPARATOR \', \') as keywords')
  246.             ->from('leadgen_offers_leadgen_keywords_rel')
  247.             ->groupBy('offer_id');
  248.  
  249.         return $keywordsSubQuery;
  250.     }
  251.  
  252.     private function getGeoJoinSubQuery()
  253.     {
  254.         $geoSubQuery = clone $this->queryBuilder;
  255.  
  256.         $geoSubQuery
  257.             ->select('leadgen_adurl_id, GROUP_CONCAT(leadgen_country_id SEPARATOR \', \') as countries')
  258.             ->from('leadgen_adurls_countries_rel')
  259.             ->groupBy('leadgen_adurl_id');
  260.  
  261.         return $geoSubQuery;
  262.     }
  263.  
  264.     /**
  265.      * @param QueryBuilder $query
  266.      * @return QueryBuilder
  267.      */
  268.     private function appendConditions(QueryBuilder $query)
  269.     {
  270.         if (!empty($this->geos)) {
  271.             $joinTableAlias = 'geo_table_join';
  272.             $query
  273.                 ->innerJoin('lo', 'leadgen_adurls_countries_rel', $joinTableAlias, 'la.id = ' . $joinTableAlias . '.leadgen_adurl_id');
  274.  
  275.             $query
  276.                 ->andWhere($joinTableAlias . '.leadgen_country_id IN (' . implode(', ', $this->geos) . ')');
  277.         }
  278.        
  279.         if (!empty($this->keywords)) {
  280.             $joinTableAlias = 'keywords_table_join';
  281.  
  282.             $query
  283.                 ->innerJoin('lo', 'leadgen_offers_leadgen_keywords_rel', $joinTableAlias, 'lo.id = ' . $joinTableAlias . '.lolkr.offer_id');
  284.  
  285.             $query
  286.                 ->andWhere(
  287.                     $joinTableAlias . '.keyword_id IN (' . implode(', ', $this->keywords) . ')'
  288.                 );
  289.         }
  290.  
  291.         return $query;
  292.     }
  293.  
  294.     /**
  295.      * @param QueryBuilder $queryBuilder
  296.      * @return QueryBuilder
  297.      */
  298.     private function appendSorting(QueryBuilder $queryBuilder)
  299.     {
  300.  
  301.         if ($this->isOrderable) {
  302.             switch ($this->orderColumn) {
  303.                 case self::COLUMN_KEYWORDS:
  304.                     $column = 'keywords';
  305.                     break;
  306.  
  307.                 case self::COLUMN_ADURL_1:
  308.                 case self::COLUMN_ADURL_2:
  309.                     $column = 'url';
  310.                     break;
  311.  
  312.                 case self::COLUMN_STATS:
  313.                     $column = 'stats';
  314.                     break;
  315.  
  316.                 case self::COLUMN_GEO_1:
  317.                 case self::COLUMN_GEO_2:
  318.                     $column = 'stats';
  319.                     break;
  320.  
  321.                 default: // self::COLUMN_OFFER_ID:
  322.                     $column = 'offer';
  323.                     break;
  324.             }
  325.  
  326.             $queryBuilder->orderBy($column, $this->orderDirection);
  327.         }
  328.  
  329.         return $queryBuilder;
  330.     }
  331.  
  332.     /**
  333.      * @param bool $isLimited
  334.      * @return QueryBuilder
  335.      */
  336.     private function getOfferSubQuery(bool  $isLimited)
  337.     {
  338.         $offerSubQuery = clone $this->queryBuilder;
  339.  
  340.         $offerSubQuery
  341.             ->select('*')
  342.             ->from('leadgen_offers');
  343.  
  344.         if ($isLimited) {
  345.             if ($this->limit) {
  346.                 $offerSubQuery->setMaxResults((int) $this->limit);
  347.             }
  348.  
  349.             if ($this->offset) {
  350.                 $offerSubQuery->setFirstResult((int) $this->offset);
  351.             }
  352.         }
  353.  
  354.         return $offerSubQuery;
  355.     }
  356. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement