Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Collection.php
Go to the documentation of this file.
1 <?php
8 
12 class Collection extends \Magento\Sales\Model\ResourceModel\Report\Collection\AbstractCollection
13 {
19  protected $_ratingLimit = 5;
20 
26  protected $_selectedColumns = [];
27 
33  protected $tableForPeriod = [
34  'daily' => 'sales_bestsellers_aggregated_daily',
35  'monthly' => 'sales_bestsellers_aggregated_monthly',
36  'yearly' => 'sales_bestsellers_aggregated_yearly',
37  ];
38 
47  public function __construct(
48  \Magento\Framework\Data\Collection\EntityFactory $entityFactory,
49  \Psr\Log\LoggerInterface $logger,
50  \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
51  \Magento\Framework\Event\ManagerInterface $eventManager,
53  \Magento\Framework\DB\Adapter\AdapterInterface $connection = null
54  ) {
55  $resource->init($this->getTableByAggregationPeriod('daily'));
56  parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $resource, $connection);
57  }
58 
64  protected function getOrderedField()
65  {
66  return 'qty_ordered';
67  }
68 
75  public function getTableByAggregationPeriod($period)
76  {
77  return $this->tableForPeriod[$period];
78  }
79 
85  protected function _getSelectedColumns()
86  {
87  $connection = $this->getConnection();
88 
89  if (!$this->_selectedColumns) {
90  if ($this->isTotals()) {
91  $this->_selectedColumns = $this->getAggregatedColumns();
92  } else {
93  $this->_selectedColumns = [
94  'period' => sprintf('MAX(%s)', $connection->getDateFormatSql('period', '%Y-%m-%d')),
95  $this->getOrderedField() => 'SUM(' . $this->getOrderedField() . ')',
96  'product_id' => 'product_id',
97  'product_name' => 'MAX(product_name)',
98  'product_price' => 'MAX(product_price)',
99  ];
100  if ('year' == $this->_period) {
101  $this->_selectedColumns['period'] = $connection->getDateFormatSql('period', '%Y');
102  } elseif ('month' == $this->_period) {
103  $this->_selectedColumns['period'] = $connection->getDateFormatSql('period', '%Y-%m');
104  }
105  }
106  }
108  }
109 
117  protected function _makeBoundarySelect($from, $to)
118  {
119  $connection = $this->getConnection();
120  $cols = $this->_getSelectedColumns();
121  $cols[$this->getOrderedField()] = 'SUM(' . $this->getOrderedField() . ')';
122  $select = $connection->select()->from(
123  $this->getResource()->getMainTable(),
124  $cols
125  )->where(
126  'period >= ?',
127  $from
128  )->where(
129  'period <= ?',
130  $to
131  )->group(
132  'product_id'
133  )->order(
134  $this->getOrderedField() . ' DESC'
135  )->limit(
136  $this->_ratingLimit
137  );
138 
140 
141  return $select;
142  }
143 
149  protected function _applyAggregatedTable()
150  {
151  $select = $this->getSelect();
152 
153  //if grouping by product, not by period
154  if (!$this->_period) {
155  $cols = $this->_getSelectedColumns();
156  $cols[$this->getOrderedField()] = 'SUM(' . $this->getOrderedField() . ')';
157  if ($this->_from || $this->_to) {
158  $mainTable = $this->getTable($this->getTableByAggregationPeriod('daily'));
159  $select->from($mainTable, $cols);
160  } else {
161  $mainTable = $this->getTable($this->getTableByAggregationPeriod('yearly'));
162  $select->from($mainTable, $cols);
163  }
164 
165  //exclude removed products
166  $select->where(new \Zend_Db_Expr($mainTable . '.product_id IS NOT NULL'))->group(
167  'product_id'
168  )->order(
169  $this->getOrderedField() . ' ' . \Magento\Framework\DB\Select::SQL_DESC
170  )->limit(
171  $this->_ratingLimit
172  );
173 
174  return $this;
175  }
176 
177  if ('year' == $this->_period) {
178  $mainTable = $this->getTable($this->getTableByAggregationPeriod('yearly'));
179  $select->from($mainTable, $this->_getSelectedColumns());
180  } elseif ('month' == $this->_period) {
181  $mainTable = $this->getTable($this->getTableByAggregationPeriod('monthly'));
182  $select->from($mainTable, $this->_getSelectedColumns());
183  } else {
184  $mainTable = $this->getTable($this->getTableByAggregationPeriod('daily'));
185  $select->from($mainTable, $this->_getSelectedColumns());
186  }
187  if (!$this->isTotals()) {
188  $select->group(['period', 'product_id']);
189  }
190  $select->where('rating_pos <= ?', $this->_ratingLimit);
191 
192  return $this;
193  }
194 
200  public function getSelectCountSql()
201  {
202  $this->_renderFilters();
203  $select = clone $this->getSelect();
204  $select->reset(\Magento\Framework\DB\Select::ORDER);
205  return $this->getConnection()->select()->from($select, 'COUNT(*)');
206  }
207 
214  public function addStoreRestrictions($storeIds)
215  {
216  if (!is_array($storeIds)) {
217  $storeIds = [$storeIds];
218  }
219  $currentStoreIds = $this->_storesIds;
220  if (isset(
221  $currentStoreIds
222  ) && $currentStoreIds != \Magento\Store\Model\Store::DEFAULT_STORE_ID && $currentStoreIds != [
223  \Magento\Store\Model\Store::DEFAULT_STORE_ID
224  ]
225  ) {
226  if (!is_array($currentStoreIds)) {
227  $currentStoreIds = [$currentStoreIds];
228  }
229  $this->_storesIds = array_intersect($currentStoreIds, $storeIds);
230  } else {
231  $this->_storesIds = $storeIds;
232  }
233 
234  return $this;
235  }
236 
246  protected function _beforeLoad()
247  {
248  parent::_beforeLoad();
249 
250  $this->_applyStoresFilter();
251 
252  if ($this->_period) {
253  $selectUnions = [];
254 
255  // apply date boundaries (before calling $this->_applyDateRangeFilter())
256  $periodFrom = $this->_from !== null ? new \DateTime($this->_from) : null;
257  $periodTo = $this->_to !== null ? new \DateTime($this->_to) : null;
258  if ('year' == $this->_period) {
259  if ($periodFrom) {
260  // not the first day of the year
261  if ($periodFrom->format('m') != 1 || $periodFrom->format('d') != 1) {
262  $dtFrom = clone $periodFrom;
263  // last day of the year
264  $dtTo = clone $periodFrom;
265  $dtTo->setDate($dtTo->format('Y'), 12, 31);
266  if (!$periodTo || $dtTo < $periodTo) {
267  $selectUnions[] = $this->_makeBoundarySelect(
268  $dtFrom->format('Y-m-d'),
269  $dtTo->format('Y-m-d')
270  );
271 
272  // first day of the next year
273  $this->_from = clone $periodFrom;
274  $this->_from->modify('+1 year');
275  $this->_from->setDate($this->_from->format('Y'), 1, 1);
276  $this->_from = $this->_from->format('Y-m-d');
277  }
278  }
279  }
280 
281  if ($periodTo) {
282  // not the last day of the year
283  if ($periodTo->format('m') != 12 || $periodTo->format('d') != 31) {
284  $dtFrom = clone $periodTo;
285  $dtFrom->setDate($dtFrom->format('Y'), 1, 1);
286  // first day of the year
287  $dtTo = clone $periodTo;
288  if (!$periodFrom || $dtFrom > $periodFrom) {
289  $selectUnions[] = $this->_makeBoundarySelect(
290  $dtFrom->format('Y-m-d'),
291  $dtTo->format('Y-m-d')
292  );
293 
294  // last day of the previous year
295  $this->_to = clone $periodTo;
296  $this->_to->modify('-1 year');
297  $this->_to->setDate($this->_to->format('Y'), 12, 31);
298  $this->_to = $this->_to->format('Y-m-d');
299  }
300  }
301  }
302 
303  if ($periodFrom && $periodTo) {
304  // the same year
305  if ($periodTo->format('Y') == $periodFrom->format('Y')) {
306  $dtFrom = clone $periodFrom;
307  $dtTo = clone $periodTo;
308  $selectUnions[] = $this->_makeBoundarySelect(
309  $dtFrom->format('Y-m-d'),
310  $dtTo->format('Y-m-d')
311  );
312 
313  $this->getSelect()->where('1<>1');
314  }
315  }
316  } elseif ('month' == $this->_period) {
317  if ($periodFrom) {
318  // not the first day of the month
319  if ($periodFrom->format('d') != 1) {
320  $dtFrom = clone $periodFrom;
321  // last day of the month
322  $dtTo = clone $periodFrom;
323  $dtTo->modify('+1 month');
324  $dtTo->setDate($dtTo->format('Y'), $dtTo->format('m'), 1);
325  $dtTo->modify('-1 day');
326  if (!$periodTo || $dtTo < $periodTo) {
327  $selectUnions[] = $this->_makeBoundarySelect(
328  $dtFrom->format('Y-m-d'),
329  $dtTo->format('Y-m-d')
330  );
331 
332  // first day of the next month
333  $this->_from = clone $periodFrom;
334  $this->_from->modify('+1 month');
335  $this->_from->setDate($this->_from->format('Y'), $this->_from->format('m'), 1);
336  $this->_from = $this->_from->format('Y-m-d');
337  }
338  }
339  }
340 
341  if ($periodTo) {
342  // not the last day of the month
343  if ($periodTo->format('d') != $periodTo->format('t')) {
344  $dtFrom = clone $periodTo;
345  $dtFrom->setDate($dtFrom->format('Y'), $dtFrom->format('m'), 1);
346  // first day of the month
347  $dtTo = clone $periodTo;
348  if (!$periodFrom || $dtFrom > $periodFrom) {
349  $selectUnions[] = $this->_makeBoundarySelect(
350  $dtFrom->format('Y-m-d'),
351  $dtTo->format('Y-m-d')
352  );
353 
354  // last day of the previous month
355  $this->_to = clone $periodTo;
356  $this->_to->setDate($this->_to->format('Y'), $this->_to->format('m'), 1);
357  $this->_to->modify('-1 day');
358  $this->_to = $this->_to->format('Y-m-d');
359  }
360  }
361  }
362 
363  if ($periodFrom && $periodTo) {
364  // the same month
365  if ($periodTo->format('Y') == $periodFrom->format('Y') &&
366  $periodTo->format('m') == $periodFrom->format('m')
367  ) {
368  $dtFrom = clone $periodFrom;
369  $dtTo = clone $periodTo;
370  $selectUnions[] = $this->_makeBoundarySelect(
371  $dtFrom->format('Y-m-d'),
372  $dtTo->format('Y-m-d')
373  );
374 
375  $this->getSelect()->where('1<>1');
376  }
377  }
378  }
379 
380  $this->_applyDateRangeFilter();
381 
382  // add unions to select
383  if ($selectUnions) {
384  $unionParts = [];
385  $cloneSelect = clone $this->getSelect();
386  $unionParts[] = '(' . $cloneSelect . ')';
387  foreach ($selectUnions as $union) {
388  $unionParts[] = '(' . $union . ')';
389  }
390  $this->getSelect()->reset()->union($unionParts, \Magento\Framework\DB\Select::SQL_UNION_ALL);
391  }
392 
393  if ($this->isTotals()) {
394  // calculate total
395  $cloneSelect = clone $this->getSelect();
396  $this->getSelect()->reset()->from($cloneSelect, $this->getAggregatedColumns());
397  } else {
398  // add sorting
399  $this->getSelect()->order(['period ASC', $this->getOrderedField() . ' DESC']);
400  }
401  }
402 
403  return $this;
404  }
405 }
const ORDER
Definition: Select.php:54
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
$resource
Definition: bulk.php:12
$logger
const SQL_UNION_ALL
Definition: Select.php:69
const SQL_DESC
Definition: Select.php:82
$connection
Definition: bulk.php:13
__construct(\Magento\Framework\Data\Collection\EntityFactory $entityFactory, \Psr\Log\LoggerInterface $logger, \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, \Magento\Framework\Event\ManagerInterface $eventManager, \Magento\Sales\Model\ResourceModel\Report $resource, \Magento\Framework\DB\Adapter\AdapterInterface $connection=null)
Definition: Collection.php:47