9
9
namespace Xibo\Factory;
12
use Jenssegers\Date\Date;
13
use Stash\Interfaces\PoolInterface;
14
12
use Xibo\Entity\Schedule;
15
13
use Xibo\Exception\NotFoundException;
16
use Xibo\Service\ConfigServiceInterface;
17
use Xibo\Service\DateServiceInterface;
18
use Xibo\Service\LogServiceInterface;
19
use Xibo\Service\SanitizerServiceInterface;
20
use Xibo\Storage\StorageServiceInterface;
15
use Xibo\Helper\Sanitize;
16
use Xibo\Storage\PDOConnect;
23
* Class ScheduleFactory
24
* @package Xibo\Factory
26
18
class ScheduleFactory extends BaseFactory
29
* @var ConfigServiceInterface
33
/** @var PoolInterface */
36
/** @var DateServiceInterface */
40
* @var DisplayGroupFactory
42
private $displayGroupFactory;
44
/** @var DayPartFactory */
45
private $dayPartFactory;
49
* @param StorageServiceInterface $store
50
* @param LogServiceInterface $log
51
* @param SanitizerServiceInterface $sanitizerService
52
* @param ConfigServiceInterface $config
53
* @param PoolInterface $pool
54
* @param DateServiceInterface $date
55
* @param DisplayGroupFactory $displayGroupFactory
56
* @param DayPartFactory $dayPartFactory
58
public function __construct($store, $log, $sanitizerService, $config, $pool, $date, $displayGroupFactory, $dayPartFactory)
60
$this->setCommonDependencies($store, $log, $sanitizerService);
61
$this->config = $config;
63
$this->dateService = $date;
64
$this->displayGroupFactory = $displayGroupFactory;
65
$this->dayPartFactory = $dayPartFactory;
72
public function createEmpty()
80
$this->displayGroupFactory,
86
21
* @param int $eventId
88
23
* @throws NotFoundException
90
public function getById($eventId)
25
public static function getById($eventId)
92
$events = $this->query(null, ['disableUserCheck' => 1, 'eventId' => $eventId]);
27
$events = ScheduleFactory::query(null, ['disableUserCheck' => 1, 'eventId' => $eventId]);
94
29
if (count($events) <= 0)
95
30
throw new NotFoundException();
113
48
* @return array[Schedule]
114
49
* @throws NotFoundException
116
public function getByCampaignId($campaignId)
51
public static function getByCampaignId($campaignId)
118
return $this->query(null, ['disableUserCheck' => 1, 'campaignId' => $campaignId]);
53
return ScheduleFactory::query(null, ['disableUserCheck' => 1, 'campaignId' => $campaignId]);
123
57
* @param int $ownerId
124
58
* @return array[Schedule]
125
59
* @throws NotFoundException
127
public function getByOwnerId($ownerId)
129
return $this->query(null, ['disableUserCheck' => 1, 'ownerId' => $ownerId]);
134
* @param int $dayPartId
136
* @throws NotFoundException
138
public function getByDayPartId($dayPartId)
140
return $this->query(null, ['disableUserCheck' => 1, 'dayPartId' => $dayPartId]);
144
* @param int $displayId
145
* @param Date $fromDt
147
* @param array $options
150
public function getForXmds($displayId, $fromDt, $toDt, $options = [])
152
$options = array_merge(['useGroupId' => false], $options);
154
// We dial the fromDt back to the top of the day, so that we include dayPart events that start on this
156
$adjustedFromDt = clone $fromDt;
159
'fromDt' => $adjustedFromDt->startOfDay()->format('U'),
160
'toDt' => $toDt->format('U')
163
$this->getLog()->debug('Get events for XMDS - with options: ' . json_encode($options));
165
// Add file nodes to the $fileElements
166
// Firstly get all the scheduled layouts
168
SELECT `schedule`.eventTypeId,
174
schedule.recurrence_type AS recurrenceType,
175
schedule.recurrence_detail AS recurrenceDetail,
176
schedule.recurrence_range AS recurrenceRange,
177
schedule.recurrenceRepeatsOn,
178
schedule.lastRecurrenceWatermark,
180
schedule.is_priority AS isPriority,
181
`schedule`.displayOrder,
183
`schedule`.campaignId,
184
`schedule`.commandId,
185
schedule.syncTimezone,
188
`lkscheduledisplaygroup`.displayGroupId,
193
ON `daypart`.dayPartId = `schedule`.dayPartId
194
INNER JOIN `lkscheduledisplaygroup`
195
ON `lkscheduledisplaygroup`.eventId = `schedule`.eventId
197
ON `lkdgdg`.parentId = `lkscheduledisplaygroup`.displayGroupId
200
if (!$options['useGroupId']) {
201
// Only join in the display/display group link table if we are requesting this data for a display
202
// otherwise the group we are looking for might not have any displays, and this join would therefore
203
// remove any records.
205
INNER JOIN `lkdisplaydg`
206
ON lkdisplaydg.DisplayGroupID = `lkdgdg`.childId
211
LEFT OUTER JOIN `campaign`
212
ON `schedule`.CampaignID = campaign.CampaignID
213
LEFT OUTER JOIN `lkcampaignlayout`
214
ON lkcampaignlayout.CampaignID = campaign.CampaignID
215
LEFT OUTER JOIN `layout`
216
ON lkcampaignlayout.LayoutID = layout.LayoutID
217
AND layout.retired = 0
218
LEFT OUTER JOIN `command`
219
ON `command`.commandId = `schedule`.commandId
222
if ($options['useGroupId']) {
223
$SQL .= ' WHERE `lkdgdg`.childId = :displayGroupId ';
224
$params['displayGroupId'] = $options['displayGroupId'];
226
$SQL .= ' WHERE `lkdisplaydg`.DisplayID = :displayId ';
227
$params['displayId'] = $displayId;
230
// Are we requesting a range or a single date/time?
231
// only the inclusive range changes, but it is clearer to have the whole statement reprinted.
235
(schedule.FromDT <= :toDt AND IFNULL(`schedule`.toDt, `schedule`.fromDt) >= :fromDt)
236
OR `schedule`.recurrence_range >= :fromDt
238
IFNULL(`schedule`.recurrence_range, 0) = 0 AND IFNULL(`schedule`.recurrence_type, \'\') <> \'\'
242
ORDER BY schedule.DisplayOrder, IFNULL(lkcampaignlayout.DisplayOrder, 0), schedule.FromDT, schedule.eventId
245
return $this->getStore()->select($SQL, $params);
61
public static function getByOwnerId($ownerId)
63
return ScheduleFactory::query(null, ['disableUserCheck' => 1, 'ownerId' => $ownerId]);
250
68
* @param array $filterBy
251
69
* @return array[Schedule]
253
public function query($sortOrder = null, $filterBy = [])
71
public static function query($sortOrder = null, $filterBy = null)
76
$useDetail = Sanitize::getInt('useDetail', $filterBy) == 1;
259
SELECT `schedule`.eventId,
260
`schedule`.eventTypeId,
79
SELECT `schedule`.eventId, `schedule`.eventTypeId, ';
83
`schedule_detail`.fromDt,
84
`schedule_detail`.toDt,
261
88
`schedule`.fromDt,
263
94
`schedule`.userId,
264
95
`schedule`.displayOrder,
265
96
`schedule`.is_priority AS isPriority,
266
97
`schedule`.recurrence_type AS recurrenceType,
267
98
`schedule`.recurrence_detail AS recurrenceDetail,
268
99
`schedule`.recurrence_range AS recurrenceRange,
269
`schedule`.recurrenceRepeatsOn,
270
`schedule`.lastRecurrenceWatermark,
271
100
campaign.campaignId,
272
101
campaign.campaign,
273
102
`command`.commandId,
275
`schedule`.dayPartId,
276
`schedule`.syncTimezone,
281
ON `daypart`.dayPartId = `schedule`.dayPartId
282
105
LEFT OUTER JOIN `campaign`
283
106
ON campaign.CampaignID = `schedule`.CampaignID
284
107
LEFT OUTER JOIN `command`
285
108
ON `command`.commandId = `schedule`.commandId
113
INNER JOIN `schedule_detail`
114
ON schedule_detail.EventID = `schedule`.EventID
289
if ($this->getSanitizer()->getInt('eventId', $filterBy) !== null) {
122
if (Sanitize::getInt('eventId', $filterBy) !== null) {
290
123
$sql .= ' AND `schedule`.eventId = :eventId ';
291
$params['eventId'] = $this->getSanitizer()->getInt('eventId', $filterBy);
124
$params['eventId'] = Sanitize::getInt('eventId', $filterBy);
294
if ($this->getSanitizer()->getInt('campaignId', $filterBy) !== null) {
127
if (Sanitize::getInt('campaignId', $filterBy) !== null) {
295
128
$sql .= ' AND `schedule`.campaignId = :campaignId ';
296
$params['campaignId'] = $this->getSanitizer()->getInt('campaignId', $filterBy);
299
if ($this->getSanitizer()->getInt('ownerId', $filterBy) !== null) {
300
$sql .= ' AND `schedule`.userId = :ownerId ';
301
$params['ownerId'] = $this->getSanitizer()->getInt('ownerId', $filterBy);
304
if ($this->getSanitizer()->getInt('dayPartId', $filterBy) !== null) {
305
$sql .= ' AND `schedule`.dayPartId = :dayPartId ';
306
$params['dayPartId'] = $this->getSanitizer()->getInt('dayPartId', $filterBy);
129
$params['campaignId'] = Sanitize::getInt('campaignId', $filterBy);
310
if ($this->getSanitizer()->getInt('fromDt', $filterBy) !== null && $this->getSanitizer()->getInt('toDt', $filterBy) === null) {
133
if (!$useDetail && Sanitize::getInt('fromDt', $filterBy) !== null && Sanitize::getInt('toDt', $filterBy) === null) {
311
134
$sql .= ' AND schedule.fromDt > :fromDt ';
312
$params['fromDt'] = $this->getSanitizer()->getInt('fromDt', $filterBy);
135
$params['fromDt'] = Sanitize::getInt('fromDt', $filterBy);
315
if ($this->getSanitizer()->getInt('toDt', $filterBy) !== null && $this->getSanitizer()->getInt('fromDt', $filterBy) === null) {
138
if (!$useDetail && Sanitize::getInt('toDt', $filterBy) !== null && Sanitize::getInt('fromDt', $filterBy) === null) {
316
139
$sql .= ' AND IFNULL(schedule.toDt, schedule.fromDt) <= :toDt ';
317
$params['toDt'] = $this->getSanitizer()->getInt('toDt', $filterBy);
140
$params['toDt'] = Sanitize::getInt('toDt', $filterBy);
143
if ($useDetail && Sanitize::getInt('fromDt', $filterBy) !== null && Sanitize::getInt('toDt', $filterBy) === null) {
144
$sql .= ' AND schedule_detail.fromDt > :fromDt ';
145
$params['fromDt'] = Sanitize::getInt('fromDt', $filterBy);
148
if ($useDetail && Sanitize::getInt('toDt', $filterBy) !== null && Sanitize::getInt('fromDt', $filterBy) === null) {
149
$sql .= ' AND IFNULL(schedule_detail.toDt, schedule_detail.fromDt) <= :toDt ';
150
$params['toDt'] = Sanitize::getInt('toDt', $filterBy);
319
152
// End only 1 date
322
if ($this->getSanitizer()->getInt('fromDt', $filterBy) !== null && $this->getSanitizer()->getInt('toDt', $filterBy) !== null) {
323
$sql .= ' AND schedule.fromDt < :toDt ';
324
$sql .= ' AND IFNULL(schedule.toDt, schedule.fromDt) >= :fromDt ';
325
$params['fromDt'] = $this->getSanitizer()->getInt('fromDt', $filterBy);
326
$params['toDt'] = $this->getSanitizer()->getInt('toDt', $filterBy);
155
if (!$useDetail && Sanitize::getInt('fromDt', $filterBy) !== null && Sanitize::getInt('toDt', $filterBy) !== null) {
156
$sql .= ' AND schedule.fromDt > :fromDt ';
157
$sql .= ' AND IFNULL(schedule.toDt, schedule.fromDt) <= :toDt ';
158
$params['fromDt'] = Sanitize::getInt('fromDt', $filterBy);
159
$params['toDt'] = Sanitize::getInt('toDt', $filterBy);
162
if ($useDetail && Sanitize::getInt('fromDt', $filterBy) !== null && Sanitize::getInt('toDt', $filterBy) !== null) {
163
$sql .= ' AND schedule_detail.fromDt < :toDt ';
164
$sql .= ' AND IFNULL(schedule_detail.toDt, schedule_detail.fromDt) >= :fromDt ';
165
$params['fromDt'] = Sanitize::getInt('fromDt', $filterBy);
166
$params['toDt'] = Sanitize::getInt('toDt', $filterBy);
328
168
// End both dates
330
if ($this->getSanitizer()->getIntArray('displayGroupIds', $filterBy) != null) {
331
$sql .= ' AND `schedule`.eventId IN (SELECT `lkscheduledisplaygroup`.eventId FROM `lkscheduledisplaygroup` WHERE displayGroupId IN (' . implode(',', $this->getSanitizer()->getIntArray('displayGroupIds', $filterBy)) . ')) ';
335
if ($this->getSanitizer()->getInt('futureSchedulesFrom', $filterBy) !== null && $this->getSanitizer()->getInt('futureSchedulesTo', $filterBy) === null) {
336
// Get schedules that end after this date, or that recur after this date
337
$sql .= ' AND (IFNULL(`schedule`.toDt, `schedule`.fromDt) >= :futureSchedulesFrom OR `schedule`.recurrence_range >= :futureSchedulesFrom OR (IFNULL(`schedule`.recurrence_range, 0) = 0) AND IFNULL(`schedule`.recurrence_type, \'\') <> \'\') ';
338
$params['futureSchedulesFrom'] = $this->getSanitizer()->getInt('futureSchedulesFrom', $filterBy);
341
if ($this->getSanitizer()->getInt('futureSchedulesFrom', $filterBy) !== null && $this->getSanitizer()->getInt('futureSchedulesTo', $filterBy) !== null) {
342
// Get schedules that end after this date, or that recur after this date
343
$sql .= ' AND ((schedule.fromDt < :futureSchedulesTo AND IFNULL(`schedule`.toDt, `schedule`.fromDt) >= :futureSchedulesFrom) OR `schedule`.recurrence_range >= :futureSchedulesFrom OR (IFNULL(`schedule`.recurrence_range, 0) = 0 AND IFNULL(`schedule`.recurrence_type, \'\') <> \'\') ) ';
344
$params['futureSchedulesFrom'] = $this->getSanitizer()->getInt('futureSchedulesFrom', $filterBy);
345
$params['futureSchedulesTo'] = $this->getSanitizer()->getInt('futureSchedulesTo', $filterBy);
348
// Restrict to mediaId - meaning layout schedules of which the layouts contain the selected mediaId
349
if ($this->getSanitizer()->getInt('mediaId', $filterBy) !== null) {
351
AND schedule.campaignId IN (
352
SELECT `lkcampaignlayout`.campaignId
355
ON `widget`.widgetId = `lkwidgetmedia`.widgetId
356
INNER JOIN `lkregionplaylist`
357
ON `lkregionplaylist`.playlistId = `widget`.playlistId
359
ON `region`.regionId = `lkregionplaylist`.regionId
361
ON layout.LayoutID = region.layoutId
362
INNER JOIN `lkcampaignlayout`
363
ON lkcampaignlayout.layoutId = layout.layoutId
364
WHERE lkwidgetmedia.mediaId = :mediaId
366
SELECT `lkcampaignlayout`.campaignId
368
INNER JOIN `lkcampaignlayout`
369
ON lkcampaignlayout.layoutId = layout.layoutId
370
WHERE `layout`.backgroundImageId = :mediaId
373
$params['mediaId'] = $this->getSanitizer()->getInt('mediaId', $filterBy);
170
if (Sanitize::getIntArray('displayGroupIds', $filterBy) != null) {
171
$sql .= ' AND `schedule`.eventId IN (SELECT `lkscheduledisplaygroup`.eventId FROM `lkscheduledisplaygroup` WHERE displayGroupId IN (' . implode(',', Sanitize::getIntArray('displayGroupIds', $filterBy)) . ')) ';
377
175
if (is_array($sortOrder))
378
176
$sql .= 'ORDER BY ' . implode(',', $sortOrder);
380
foreach ($this->getStore()->select($sql, $params) as $row) {
381
$entries[] = $this->createEmpty()->hydrate($row, ['intProperties' => ['isPriority', 'syncTimezone', 'isAlways', 'isCustom']]);
178
Log::sql($sql, $params);
180
foreach (PDOConnect::select($sql, $params) as $row) {
181
$entries[] = (new Schedule())->hydrate($row, ['intProperties' => ['isPriority']]);