Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
23.53% covered (danger)
23.53%
4 / 17
28.57% covered (danger)
28.57%
2 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
ScheduleProvider
23.53% covered (danger)
23.53%
4 / 17
28.57% covered (danger)
28.57%
2 / 7
54.72
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getDb
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getPredis
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getScheduleForDate
n/a
0 / 0
n/a
0 / 0
0
 getEmployeeShift
n/a
0 / 0
n/a
0 / 0
0
 syncScheduleToCache
n/a
0 / 0
n/a
0 / 0
0
 getProviderName
n/a
0 / 0
n/a
0 / 0
0
 isEnabled
n/a
0 / 0
n/a
0 / 0
0
 getCacheKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFromCache
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 saveToCache
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 clearCache
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace BuyerKiosk\Workbook;
4
5/**
6 * Abstract Schedule Provider
7 *
8 * Base class for all schedule providers (WhenIWork, Homebase, etc.)
9 * Handles caching, data retrieval, and synchronization to database.
10 *
11 * @package BuyerKiosk\Workbook
12 */
13abstract class ScheduleProvider
14{
15    /**
16     * @var \Store Store instance
17     */
18    protected $store;
19
20    /**
21     * @var \Predis\ClientInterface|null Redis client for caching (lazy-loaded)
22     */
23    protected $predis = null;
24
25    /**
26     * @var int Cache TTL in seconds (5 minutes)
27     */
28    protected $cacheTTL = 300;
29
30    /**
31     * @var \PDO|null Database connection (lazy-loaded)
32     */
33    protected $db = null;
34
35    /**
36     * Constructor
37     *
38     * @param \Store $store Store instance
39     * @param \PDO|null $db Optional database connection for dependency injection (testing)
40     * @param \Predis\ClientInterface|null $predis Optional Redis client for dependency injection (testing)
41     */
42    public function __construct(\Store $store, ?\PDO $db = null, ?\Predis\ClientInterface $predis = null)
43    {
44        $this->store = $store;
45        $this->db = $db;
46        $this->predis = $predis;
47    }
48
49    /**
50     * Get database connection (lazy-loaded)
51     *
52     * @return \PDO Database connection
53     */
54    protected function getDb(): \PDO
55    {
56        if ($this->db === null) {
57            $this->db = dbConnectByName($this->store->getDbName());
58        }
59        return $this->db;
60    }
61
62    /**
63     * Get Redis client (lazy-loaded)
64     *
65     * @return \Predis\ClientInterface Redis client
66     */
67    protected function getPredis(): \Predis\ClientInterface
68    {
69        if ($this->predis === null) {
70            $this->predis = new \Predis\Client($_ENV['REDIS_URL']);
71        }
72        return $this->predis;
73    }
74
75    /**
76     * Get schedule for a specific date
77     *
78     * @param \DateTime $date Date to retrieve schedule for
79     * @return array Array of shift data
80     */
81    abstract public function getScheduleForDate(\DateTime $date): array;
82
83    /**
84     * Get a specific employee's shift for a date
85     *
86     * @param int $employeeId Local employee ID
87     * @param \DateTime $date Date to check
88     * @return array|null Shift data or null if not scheduled
89     */
90    abstract public function getEmployeeShift(int $employeeId, \DateTime $date): ?array;
91
92    /**
93     * Sync schedule data to database cache
94     *
95     * @param \DateTime $date Date to sync
96     * @return bool Success status
97     */
98    abstract public function syncScheduleToCache(\DateTime $date): bool;
99
100    /**
101     * Get provider name identifier
102     *
103     * @return string Provider name (e.g., 'wheniwork', 'homebase')
104     */
105    abstract public function getProviderName(): string;
106
107    /**
108     * Check if this provider is enabled for the store
109     *
110     * @return bool True if enabled
111     */
112    abstract public function isEnabled(): bool;
113
114    /**
115     * Generate Redis cache key for a date
116     *
117     * Includes provider name to prevent collision when switching providers
118     *
119     * @param \DateTime $date Date for cache key
120     * @return string Cache key
121     */
122    protected function getCacheKey(\DateTime $date): string
123    {
124        return $this->store->getTypeNum() . '_schedule_' . $this->getProviderName() . '_' . $date->format('Y-m-d');
125    }
126
127    /**
128     * Get schedule from Redis cache
129     *
130     * @param \DateTime $date Date to retrieve
131     * @return array|null Cached data or null if not found
132     */
133    protected function getFromCache(\DateTime $date): ?array
134    {
135        $key = $this->getCacheKey($date);
136        $cached = $this->getPredis()->get($key);
137        return $cached ? json_decode($cached, true) : null;
138    }
139
140    /**
141     * Save schedule to Redis cache
142     *
143     * @param \DateTime $date Date of schedule
144     * @param array $data Schedule data to cache
145     * @return void
146     */
147    protected function saveToCache(\DateTime $date, array $data): void
148    {
149        $key = $this->getCacheKey($date);
150        $this->getPredis()->setex($key, $this->cacheTTL, json_encode($data));
151    }
152
153    /**
154     * Clear cache for a specific date
155     *
156     * @param \DateTime $date Date to clear
157     * @return void
158     */
159    protected function clearCache(\DateTime $date): void
160    {
161        $key = $this->getCacheKey($date);
162        $this->getPredis()->del($key);
163    }
164}