1: | <?php declare(strict_types=1); |
2: | |
3: | namespace Salient\Sync\Http; |
4: | |
5: | use Salient\Contract\Core\DateFormatterInterface; |
6: | use Salient\Contract\Curler\Exception\RequestExceptionInterface; |
7: | use Salient\Contract\Curler\CurlerInterface; |
8: | use Salient\Contract\Curler\CurlerPagerInterface; |
9: | use Salient\Contract\Http\HttpHeadersInterface; |
10: | use Salient\Contract\Sync\SyncDefinitionInterface; |
11: | use Salient\Contract\Sync\SyncEntityInterface; |
12: | use Salient\Core\Exception\MethodNotImplementedException; |
13: | use Salient\Core\Facade\Cache; |
14: | use Salient\Curler\Curler; |
15: | use Salient\Http\HttpHeaders; |
16: | use Salient\Sync\Exception\UnreachableBackendException; |
17: | use Salient\Sync\AbstractSyncProvider; |
18: | use Salient\Utility\Get; |
19: | |
20: | |
21: | |
22: | |
23: | abstract class HttpSyncProvider extends AbstractSyncProvider |
24: | { |
25: | |
26: | |
27: | |
28: | |
29: | |
30: | |
31: | |
32: | |
33: | |
34: | |
35: | final public function getCurler( |
36: | string $path, |
37: | ?int $expiry = -1, |
38: | ?HttpHeadersInterface $headers = null, |
39: | ?CurlerPagerInterface $pager = null, |
40: | bool $alwaysPaginate = false, |
41: | ?DateFormatterInterface $dateFormatter = null |
42: | ): CurlerInterface { |
43: | $builder = Curler::build() |
44: | ->uri($this->getEndpointUrl($path)) |
45: | ->headers($headers ?? $this->getHeaders($path)) |
46: | ->pager($pager ?? $this->getPager($path)) |
47: | ->alwaysPaginate($pager ? $alwaysPaginate : $this->getAlwaysPaginate($path)) |
48: | ->dateFormatter($dateFormatter ?? $this->getDateFormatter()); |
49: | |
50: | if ($expiry === -1) { |
51: | $expiry = $this->getExpiry($path); |
52: | } |
53: | |
54: | if ($expiry !== null) { |
55: | $builder = $builder->cacheResponses()->cacheLifetime($expiry); |
56: | } |
57: | |
58: | return $this->filterCurler($builder->build(), $path); |
59: | } |
60: | |
61: | |
62: | |
63: | |
64: | final public function getEndpointUrl(string $path): string |
65: | { |
66: | return $this->getBaseUrl($path) . $path; |
67: | } |
68: | |
69: | |
70: | |
71: | |
72: | |
73: | |
74: | |
75: | abstract protected function getBaseUrl(string $path): string; |
76: | |
77: | |
78: | |
79: | |
80: | |
81: | |
82: | protected function getHeaders(string $path): ?HttpHeadersInterface |
83: | { |
84: | return null; |
85: | } |
86: | |
87: | |
88: | |
89: | |
90: | final protected function headers(): HttpHeaders |
91: | { |
92: | return new HttpHeaders(); |
93: | } |
94: | |
95: | |
96: | |
97: | |
98: | |
99: | |
100: | protected function getPager(string $path): ?CurlerPagerInterface |
101: | { |
102: | return null; |
103: | } |
104: | |
105: | |
106: | |
107: | |
108: | |
109: | |
110: | |
111: | protected function getAlwaysPaginate(string $path): bool |
112: | { |
113: | return false; |
114: | } |
115: | |
116: | |
117: | |
118: | |
119: | |
120: | |
121: | |
122: | |
123: | |
124: | |
125: | protected function getExpiry(string $path): ?int |
126: | { |
127: | return null; |
128: | } |
129: | |
130: | |
131: | |
132: | |
133: | |
134: | |
135: | |
136: | |
137: | |
138: | |
139: | protected function filterCurler(CurlerInterface $curler, string $path): CurlerInterface |
140: | { |
141: | return $curler; |
142: | } |
143: | |
144: | |
145: | |
146: | |
147: | final public function getDefinition(string $entity): SyncDefinitionInterface |
148: | { |
149: | return $this->getHttpDefinition($entity); |
150: | } |
151: | |
152: | |
153: | |
154: | |
155: | |
156: | |
157: | |
158: | |
159: | |
160: | |
161: | |
162: | |
163: | protected function getHttpDefinition(string $entity): HttpSyncDefinition |
164: | { |
165: | return $this->builderFor($entity)->build(); |
166: | } |
167: | |
168: | |
169: | |
170: | |
171: | |
172: | |
173: | |
174: | |
175: | |
176: | final protected function builderFor(string $entity): HttpSyncDefinitionBuilder |
177: | { |
178: | return HttpSyncDefinition::build() |
179: | ->entity($entity) |
180: | ->provider($this); |
181: | } |
182: | |
183: | |
184: | |
185: | |
186: | final public function checkHeartbeat(int $ttl = 300) |
187: | { |
188: | $key = implode(':', [ |
189: | static::class, |
190: | __FUNCTION__, |
191: | Get::hash(implode("\0", $this->getBackendIdentifier())), |
192: | ]); |
193: | |
194: | if (!Cache::has($key)) { |
195: | try { |
196: | $resource = $this->getHeartbeat(); |
197: | |
198: | } catch (RequestExceptionInterface $ex) { |
199: | throw new UnreachableBackendException( |
200: | $this, |
201: | $ex->getMessage(), |
202: | $ex, |
203: | ); |
204: | |
205: | } |
206: | Cache::set($key, $resource, $ttl); |
207: | } |
208: | |
209: | return $this; |
210: | } |
211: | |
212: | |
213: | |
214: | |
215: | |
216: | |
217: | |
218: | |
219: | protected function getHeartbeat() |
220: | { |
221: | throw new MethodNotImplementedException( |
222: | static::class, |
223: | __FUNCTION__, |
224: | HttpSyncProvider::class, |
225: | ); |
226: | } |
227: | } |
228: | |