1 | <?php |
||||
2 | |||||
3 | namespace LeKoala\SparkPost; |
||||
4 | |||||
5 | use Exception; |
||||
6 | use SilverStripe\Forms\Tab; |
||||
7 | use SilverStripe\Forms\Form; |
||||
8 | use SilverStripe\Forms\TabSet; |
||||
9 | use SilverStripe\ORM\ArrayLib; |
||||
10 | use SilverStripe\ORM\ArrayList; |
||||
11 | use SilverStripe\ORM\DataObject; |
||||
12 | use SilverStripe\View\ArrayData; |
||||
13 | use SilverStripe\Control\Session; |
||||
14 | use SilverStripe\Forms\DateField; |
||||
15 | use SilverStripe\Forms\FieldList; |
||||
16 | use SilverStripe\Forms\FormField; |
||||
17 | use SilverStripe\Forms\TextField; |
||||
18 | use SilverStripe\Control\Director; |
||||
19 | use SilverStripe\Core\Environment; |
||||
20 | use SilverStripe\Forms\FormAction; |
||||
21 | use SilverStripe\Admin\LeftAndMain; |
||||
22 | use SilverStripe\Forms\HiddenField; |
||||
23 | use SilverStripe\Security\Security; |
||||
24 | use SilverStripe\View\ViewableData; |
||||
25 | use SilverStripe\Forms\LiteralField; |
||||
26 | use SilverStripe\Control\Email\Email; |
||||
27 | use SilverStripe\Control\HTTPRequest; |
||||
28 | use SilverStripe\Forms\DropdownField; |
||||
29 | use SilverStripe\Security\Permission; |
||||
30 | use LeKoala\SparkPost\SparkPostHelper; |
||||
31 | use SilverStripe\Control\HTTPResponse; |
||||
32 | use SilverStripe\Core\Convert; |
||||
33 | use SilverStripe\Forms\CompositeField; |
||||
34 | use SilverStripe\SiteConfig\SiteConfig; |
||||
35 | use SilverStripe\Forms\GridField\GridField; |
||||
36 | use SilverStripe\Security\PermissionProvider; |
||||
37 | use SilverStripe\Security\DefaultAdminService; |
||||
38 | use SilverStripe\Forms\GridField\GridFieldConfig; |
||||
39 | use SilverStripe\Forms\GridField\GridFieldConfig_RecordViewer; |
||||
40 | use SilverStripe\Forms\GridField\GridFieldFooter; |
||||
41 | use SilverStripe\Forms\GridField\GridFieldDetailForm; |
||||
42 | use SilverStripe\Forms\GridField\GridFieldDataColumns; |
||||
43 | use Symbiote\GridFieldExtensions\GridFieldTitleHeader; |
||||
44 | use SilverStripe\Forms\GridField\GridFieldToolbarHeader; |
||||
45 | use SilverStripe\Forms\GridField\GridFieldSortableHeader; |
||||
46 | use SilverStripe\Forms\GridField\GridFieldFilterHeader; |
||||
47 | |||||
48 | /** |
||||
49 | * Allow you to see messages sent through the api key used to send messages |
||||
50 | * |
||||
51 | * @author LeKoala <[email protected]> |
||||
52 | */ |
||||
53 | class SparkPostAdmin extends LeftAndMain implements PermissionProvider |
||||
54 | { |
||||
55 | const MESSAGE_CACHE_MINUTES = 5; |
||||
56 | const WEBHOOK_CACHE_MINUTES = 1440; // 1 day |
||||
57 | const SENDINGDOMAIN_CACHE_MINUTES = 1440; // 1 day |
||||
58 | |||||
59 | /** |
||||
60 | * @var string |
||||
61 | */ |
||||
62 | private static $menu_title = "SparkPost"; |
||||
0 ignored issues
–
show
introduced
by
![]() |
|||||
63 | |||||
64 | /** |
||||
65 | * @var string |
||||
66 | */ |
||||
67 | private static $url_segment = "sparkpost"; |
||||
0 ignored issues
–
show
|
|||||
68 | |||||
69 | /** |
||||
70 | * @var string |
||||
71 | */ |
||||
72 | private static $menu_icon = "sparkpost/images/sparkpost-icon.png"; |
||||
0 ignored issues
–
show
|
|||||
73 | |||||
74 | /** |
||||
75 | * @var string |
||||
76 | */ |
||||
77 | private static $url_rule = '/$Action/$ID/$OtherID'; |
||||
0 ignored issues
–
show
|
|||||
78 | |||||
79 | /** |
||||
80 | * @var array<string> |
||||
81 | */ |
||||
82 | private static $allowed_actions = [ |
||||
0 ignored issues
–
show
|
|||||
83 | 'settings', |
||||
84 | 'SearchForm', |
||||
85 | 'doSearch', |
||||
86 | "doInstallHook", |
||||
87 | "doUninstallHook", |
||||
88 | "doInstallDomain", |
||||
89 | "doUninstallDomain", |
||||
90 | "send_test", |
||||
91 | ]; |
||||
92 | |||||
93 | /** |
||||
94 | * @var boolean |
||||
95 | */ |
||||
96 | private static $cache_enabled = true; |
||||
97 | |||||
98 | /** |
||||
99 | * @var bool |
||||
100 | */ |
||||
101 | protected $subaccountKey = false; |
||||
102 | |||||
103 | /** |
||||
104 | * @var Exception|null |
||||
105 | */ |
||||
106 | protected $lastException = null; |
||||
107 | |||||
108 | /** |
||||
109 | * @var ViewableData|null |
||||
110 | */ |
||||
111 | protected $currentMessage = null; |
||||
112 | |||||
113 | /** |
||||
114 | * Inject public dependencies into the controller |
||||
115 | * |
||||
116 | * @var array<string,string> |
||||
117 | */ |
||||
118 | private static $dependencies = [ |
||||
0 ignored issues
–
show
|
|||||
119 | 'logger' => '%$Psr\Log\LoggerInterface', |
||||
120 | 'cache' => '%$Psr\SimpleCache\CacheInterface.sparkpost', // see _config/cache.yml |
||||
121 | ]; |
||||
122 | |||||
123 | /** |
||||
124 | * @var \Psr\Log\LoggerInterface |
||||
125 | */ |
||||
126 | public $logger; |
||||
127 | |||||
128 | /** |
||||
129 | * @var \Psr\SimpleCache\CacheInterface |
||||
130 | */ |
||||
131 | public $cache; |
||||
132 | |||||
133 | /** |
||||
134 | * @return void |
||||
135 | */ |
||||
136 | public function init() |
||||
137 | { |
||||
138 | parent::init(); |
||||
139 | |||||
140 | if (isset($_GET['refresh'])) { |
||||
141 | $this->getCache()->clear(); |
||||
142 | } |
||||
143 | } |
||||
144 | |||||
145 | /** |
||||
146 | * @param HTTPRequest $request |
||||
147 | * @return HTTPResponse |
||||
148 | */ |
||||
149 | public function settings($request) |
||||
150 | { |
||||
151 | return parent::index($request); |
||||
152 | } |
||||
153 | |||||
154 | /** |
||||
155 | * @param HTTPRequest $request |
||||
156 | * @return HTTPResponse|string |
||||
157 | */ |
||||
158 | public function send_test($request) |
||||
159 | { |
||||
160 | if (!$this->CanConfigureApi()) { |
||||
161 | return $this->httpError(404); |
||||
162 | } |
||||
163 | $service = DefaultAdminService::create(); |
||||
164 | $to = $request->getVar('to'); |
||||
165 | if (!$to) { |
||||
166 | $to = $service->findOrCreateDefaultAdmin()->Email; |
||||
167 | } |
||||
168 | $email = Email::create(); |
||||
169 | $email->setSubject("Test email"); |
||||
170 | $email->setBody("Test " . date('Y-m-d H:i:s')); |
||||
171 | $email->setTo($to); |
||||
172 | |||||
173 | $email->send(); |
||||
174 | return 'Email sent'; |
||||
175 | } |
||||
176 | |||||
177 | /** |
||||
178 | * @return Session |
||||
179 | */ |
||||
180 | public function getSession() |
||||
181 | { |
||||
182 | return $this->getRequest()->getSession(); |
||||
183 | } |
||||
184 | |||||
185 | /** |
||||
186 | * Returns a GridField of messages |
||||
187 | * @param mixed $id |
||||
188 | * @param mixed $fields |
||||
189 | * @return null|Form |
||||
190 | */ |
||||
191 | public function getEditForm($id = null, $fields = null) |
||||
192 | { |
||||
193 | if (!$id) { |
||||
194 | $id = $this->currentPageID(); |
||||
0 ignored issues
–
show
The function
SilverStripe\Admin\LeftAndMain::currentPageID() has been deprecated: 5.4.0 use currentRecordID() instead.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
195 | } |
||||
196 | |||||
197 | /** @var DataObject|null $record */ |
||||
198 | $record = $this->getRecord($id); |
||||
199 | |||||
200 | // Check if this record is viewable |
||||
201 | if ($record && !$record->canView()) { |
||||
202 | $response = Security::permissionFailure($this); |
||||
203 | $this->setResponse($response); |
||||
204 | return null; |
||||
205 | } |
||||
206 | |||||
207 | // Build gridfield |
||||
208 | $messageListConfig = GridFieldConfig::create()->addComponents( |
||||
209 | new GridFieldSortableHeader(), |
||||
210 | new GridFieldDataColumns(), |
||||
211 | new GridFieldFooter() |
||||
212 | ); |
||||
213 | |||||
214 | $messages = $this->Messages(); |
||||
215 | if (is_string($messages)) { |
||||
216 | // The api returned an error |
||||
217 | $messagesList = new LiteralField("MessageAlert", $this->MessageHelper($messages, 'bad')); |
||||
218 | } else { |
||||
219 | $messagesList = GridField::create( |
||||
220 | 'Messages', |
||||
221 | false, |
||||
222 | $messages, |
||||
223 | $messageListConfig |
||||
224 | )->addExtraClass("messages_grid"); |
||||
225 | |||||
226 | /** @var GridFieldDataColumns $columns */ |
||||
227 | $columns = $messageListConfig->getComponentByType(GridFieldDataColumns::class); |
||||
228 | $columns->setDisplayFields([ |
||||
229 | 'transmission_id' => _t('SparkPostAdmin.EventTransmissionId', 'Id'), |
||||
230 | 'timestamp' => _t('SparkPostAdmin.EventDate', 'Date'), |
||||
231 | 'type' => _t('SparkPostAdmin.EventType', 'Type'), |
||||
232 | 'rcpt_to' => _t('SparkPostAdmin.EventRecipient', 'Recipient'), |
||||
233 | 'subject' => _t('SparkPostAdmin.EventSubject', 'Subject'), |
||||
234 | 'friendly_from' => _t('SparkPostAdmin.EventSender', 'Sender'), |
||||
235 | ]); |
||||
236 | |||||
237 | $columns->setFieldFormatting([ |
||||
238 | 'timestamp' => function ($value, &$item) { |
||||
239 | return date('Y-m-d H:i:s', strtotime($value)); |
||||
240 | }, |
||||
241 | ]); |
||||
242 | |||||
243 | // Validator setup |
||||
244 | $validator = null; |
||||
245 | if ($record && method_exists($record, 'getValidator')) { |
||||
246 | $validator = $record->getValidator(); |
||||
247 | } |
||||
248 | |||||
249 | if ($validator) { |
||||
250 | /** @var GridFieldDetailForm|null $detailForm */ |
||||
251 | $detailForm = $messageListConfig->getComponentByType(GridFieldDetailForm::class); |
||||
252 | if ($detailForm) { |
||||
253 | $detailForm->setValidator($validator); |
||||
254 | } |
||||
255 | } |
||||
256 | } |
||||
257 | |||||
258 | // Create tabs |
||||
259 | $messagesTab = new Tab( |
||||
260 | 'Messages', |
||||
261 | _t('SparkPostAdmin.Messages', 'Messages'), |
||||
262 | $this->SearchFields(), |
||||
263 | $messagesList, |
||||
264 | // necessary for tree node selection in LeftAndMain.EditForm.js |
||||
265 | new HiddenField('ID', null, 0) |
||||
266 | ); |
||||
267 | |||||
268 | $fields = new FieldList([ |
||||
269 | $root = new TabSet('Root', $messagesTab) |
||||
270 | ]); |
||||
271 | |||||
272 | $suppressionsTab = new Tab('Suppressions', _t('SparkPostAdmin.Suppressions', 'Suppressions')); |
||||
273 | |||||
274 | // Show the summary |
||||
275 | $summary = $this->getCachedData('suppressionSummary'); |
||||
276 | if ($summary) { |
||||
277 | $callback = function ($k, $v) { |
||||
278 | return ArrayData::create([ |
||||
279 | 'Title' => $k, |
||||
280 | 'Value' => $v, |
||||
281 | ]); |
||||
282 | }; |
||||
283 | $summaryArray = array_map($callback, array_keys($summary), array_values($summary)); |
||||
284 | $summaryGrid = GridField::create( |
||||
285 | 'SuppressionSummary', |
||||
286 | _t('SparkPostAdmin.Suppressionsummary', 'Suppression summary'), |
||||
287 | new ArrayList($summaryArray) |
||||
0 ignored issues
–
show
The class
SilverStripe\ORM\ArrayList has been deprecated: 5.4.0 Will be renamed to SilverStripe\Model\List\ArrayList
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
288 | ); |
||||
289 | //@link https://docs.silverstripe.org/en/5/developer_guides/forms/using_gridfield_with_arbitrary_data/ |
||||
290 | $summaryGrid->getConfig()->removeComponentsByType(GridFieldFilterHeader::class); |
||||
291 | /** @var GridFieldDataColumns $columns */ |
||||
292 | $columns = $summaryGrid->getConfig()->getComponentByType(GridFieldDataColumns::class); |
||||
293 | $columns->setDisplayFields([ |
||||
294 | 'Title' => _t('SparkPostAdmin.Title', 'Title'), |
||||
295 | 'Value' => _t('SparkPostAdmin.Value', 'Value'), |
||||
296 | ]); |
||||
297 | $suppressionsTab->push($summaryGrid); |
||||
298 | } |
||||
299 | |||||
300 | |||||
301 | // Show recent suppressions |
||||
302 | $client = SparkPostHelper::getClient(); |
||||
303 | $suppressions = $this->getCachedData('searchSuppressions', [ |
||||
304 | 'from' => $client->createValidDatetime('-90 days') |
||||
305 | ]); |
||||
306 | if ($suppressions) { |
||||
307 | $suppressionGrid = GridField::create( |
||||
308 | 'RecentSuppressions', |
||||
309 | _t('SparkPostAdmin.RecentSuppressions', 'Recent suppressions'), |
||||
310 | new ArrayList(array_map(function ($item) { |
||||
0 ignored issues
–
show
The class
SilverStripe\ORM\ArrayList has been deprecated: 5.4.0 Will be renamed to SilverStripe\Model\List\ArrayList
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
311 | return ArrayData::create($item); |
||||
312 | }, $suppressions)) |
||||
313 | ); |
||||
314 | //@link https://docs.silverstripe.org/en/5/developer_guides/forms/using_gridfield_with_arbitrary_data/ |
||||
315 | $suppressionGrid->getConfig()->removeComponentsByType(GridFieldFilterHeader::class); |
||||
316 | /** @var GridFieldDataColumns $columns */ |
||||
317 | $columns = $suppressionGrid->getConfig()->getComponentByType(GridFieldDataColumns::class); |
||||
318 | $columns->setDisplayFields([ |
||||
319 | 'recipient' => _t('SparkPostAdmin.Recipient', 'Recipient'), |
||||
320 | 'type' => _t('SparkPostAdmin.Type', 'Type'), |
||||
321 | 'source' => _t('SparkPostAdmin.Source', 'Source'), |
||||
322 | 'description' => _t('SparkPostAdmin.Description', 'Description'), |
||||
323 | 'created' => _t('SparkPostAdmin.Created', 'Created'), |
||||
324 | // 'updated' => _t('SparkPostAdmin.Updated', 'Updated'), |
||||
325 | ]); |
||||
326 | $suppressionsTab->push($suppressionGrid); |
||||
327 | } |
||||
328 | |||||
329 | $fields->addFieldToTab('Root', $suppressionsTab); |
||||
330 | |||||
331 | $settingsTab = new Tab('Settings', _t('SparkPostAdmin.Settings', 'Settings')); |
||||
332 | if ($this->CanConfigureApi()) { |
||||
333 | $domainTabData = $this->DomainTab(); |
||||
334 | $settingsTab->push($domainTabData); |
||||
335 | |||||
336 | // Show webhook options if not using a subaccount key |
||||
337 | if (!SparkPostHelper::getSubaccountId() && self::config()->show_webhook_tab) { |
||||
338 | $webhookTabData = $this->WebhookTab(); |
||||
339 | $settingsTab->push($webhookTabData); |
||||
340 | } |
||||
341 | |||||
342 | $toolsHtml = '<h2>Tools</h2>'; |
||||
343 | |||||
344 | // Show default from email |
||||
345 | $defaultEmail = SparkPostHelper::resolveDefaultFromEmail(); |
||||
346 | $defaultEmailDisplayed = EmailUtils::stringify($defaultEmail); |
||||
347 | $toolsHtml .= "<p>Default sending email: " . Convert::raw2xml($defaultEmailDisplayed) . " (" . SparkPostHelper::resolveDefaultFromEmailType() . ")</p>"; |
||||
348 | if (!SparkPostHelper::isEmailDomainReady($defaultEmailDisplayed)) { |
||||
349 | $toolsHtml .= '<p style="color:red">The default email is not ready to send emails</p>'; |
||||
350 | } |
||||
351 | |||||
352 | // Show constants |
||||
353 | if (SparkPostHelper::getEnvSendingDisabled()) { |
||||
354 | $toolsHtml .= '<p style="color:red">Sending is disabled by .env configuration</p>'; |
||||
355 | } |
||||
356 | if (SparkPostHelper::getEnvEnableLogging()) { |
||||
357 | $toolsHtml .= '<p style="color:orange">Logging is enabled by .env configuration</p>'; |
||||
358 | } |
||||
359 | if (SparkPostHelper::getSubaccountId()) { |
||||
360 | $toolsHtml .= '<p style="color:orange">Using subaccount id</p>'; |
||||
361 | } |
||||
362 | if (SparkPostHelper::getEnvForceSender()) { |
||||
363 | $toolsHtml .= '<p style="color:orange">Sender is forced to ' . SparkPostHelper::getEnvForceSender() . '</p>'; |
||||
364 | } |
||||
365 | |||||
366 | // Add a refresh button |
||||
367 | $toolsHtml .= $this->ButtonHelper( |
||||
368 | $this->Link() . '?refresh=true', |
||||
369 | _t('SparkPostAdmin.REFRESH', 'Force data refresh from the API') |
||||
370 | ); |
||||
371 | |||||
372 | $toolsHtml = $this->FormGroupHelper($toolsHtml); |
||||
373 | $Tools = new LiteralField('Tools', $toolsHtml); |
||||
374 | $settingsTab->push($Tools); |
||||
375 | |||||
376 | $fields->addFieldToTab('Root', $settingsTab); |
||||
377 | } |
||||
378 | |||||
379 | // Tab nav in CMS is rendered through separate template |
||||
380 | $root->setTemplate('SilverStripe\\Forms\\CMSTabSet'); |
||||
381 | |||||
382 | // Manage tabs state |
||||
383 | $actionParam = $this->getRequest()->param('Action'); |
||||
384 | if ($actionParam == 'setting') { |
||||
385 | $settingsTab->addExtraClass('ui-state-active'); |
||||
386 | } elseif ($actionParam == 'messages') { |
||||
387 | $messagesTab->addExtraClass('ui-state-active'); |
||||
388 | } |
||||
389 | |||||
390 | // Build replacement form |
||||
391 | $form = Form::create( |
||||
392 | $this, |
||||
393 | 'EditForm', |
||||
394 | $fields, |
||||
395 | new FieldList() |
||||
396 | )->setHTMLID('Form_EditForm'); |
||||
397 | $form->addExtraClass('cms-edit-form fill-height'); |
||||
398 | $form->setTemplate($this->getTemplatesWithSuffix('_EditForm')); |
||||
399 | $form->addExtraClass('ss-tabset cms-tabset ' . $this->BaseCSSClasses()); |
||||
400 | $form->setAttribute('data-pjax-fragment', 'CurrentForm'); |
||||
401 | |||||
402 | $this->extend('updateEditForm', $form); |
||||
403 | |||||
404 | return $form; |
||||
405 | } |
||||
406 | |||||
407 | /** |
||||
408 | * Get logger |
||||
409 | * |
||||
410 | * @return \Psr\Log\LoggerInterface |
||||
411 | */ |
||||
412 | public function getLogger() |
||||
413 | { |
||||
414 | return $this->logger; |
||||
415 | } |
||||
416 | |||||
417 | /** |
||||
418 | * Get the cache |
||||
419 | * |
||||
420 | * @return \Psr\SimpleCache\CacheInterface |
||||
421 | */ |
||||
422 | public function getCache() |
||||
423 | { |
||||
424 | return $this->cache; |
||||
425 | } |
||||
426 | |||||
427 | /** |
||||
428 | * @return boolean |
||||
429 | */ |
||||
430 | public function getCacheEnabled() |
||||
431 | { |
||||
432 | if (isset($_GET['disable_cache'])) { |
||||
433 | return false; |
||||
434 | } |
||||
435 | if (Environment::getEnv('SPARKPOST_DISABLE_CACHE')) { |
||||
436 | return false; |
||||
437 | } |
||||
438 | $v = $this->config()->cache_enabled; |
||||
439 | if ($v === null) { |
||||
440 | $v = self::$cache_enabled; |
||||
441 | } |
||||
442 | return $v; |
||||
443 | } |
||||
444 | |||||
445 | /** |
||||
446 | * A simple cache helper |
||||
447 | * |
||||
448 | * @param string $method |
||||
449 | * @param array<mixed>|null|string|bool $params |
||||
450 | * @param int $expireInSeconds |
||||
451 | * @return array<mixed>|false |
||||
452 | */ |
||||
453 | protected function getCachedData($method, $params = null, $expireInSeconds = 60) |
||||
454 | { |
||||
455 | $enabled = $this->getCacheEnabled(); |
||||
456 | $cacheResult = false; |
||||
457 | $cache = $this->getCache(); |
||||
458 | if ($enabled) { |
||||
459 | $key = $method . '_' . md5(serialize($params)); |
||||
460 | $cacheResult = $cache->get($key); |
||||
461 | } |
||||
462 | if ($enabled && $cacheResult) { |
||||
463 | $data = unserialize($cacheResult); |
||||
464 | } else { |
||||
465 | try { |
||||
466 | $client = SparkPostHelper::getClient(); |
||||
467 | $data = $client->$method($params); |
||||
468 | } catch (Exception $ex) { |
||||
469 | $this->lastException = $ex; |
||||
470 | $this->getLogger()->debug($ex); |
||||
471 | $data = false; |
||||
472 | } |
||||
473 | |||||
474 | //5 minutes cache |
||||
475 | if ($enabled) { |
||||
476 | $cache->set($key, serialize($data), $expireInSeconds); |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
477 | } |
||||
478 | } |
||||
479 | |||||
480 | return $data; |
||||
481 | } |
||||
482 | |||||
483 | /** |
||||
484 | * @return array<mixed> |
||||
485 | */ |
||||
486 | public function getParams() |
||||
487 | { |
||||
488 | $params = $this->config()->default_search_params; |
||||
489 | if (!$params) { |
||||
490 | $params = []; |
||||
491 | } |
||||
492 | $data = $this->getSession()->get(__class__ . '.Search'); |
||||
493 | if (!$data) { |
||||
494 | $data = []; |
||||
495 | } |
||||
496 | |||||
497 | $params = array_merge($params, $data); |
||||
498 | |||||
499 | // Respect api formats |
||||
500 | if (!empty($params['to'])) { |
||||
501 | //@phpstan-ignore-next-line |
||||
502 | $params['to'] = date('Y-m-d', strtotime(str_replace('/', '-', $params['to']))) . 'T00:00'; |
||||
503 | } |
||||
504 | if (!empty($params['from'])) { |
||||
505 | //@phpstan-ignore-next-line |
||||
506 | $params['from'] = date('Y-m-d', strtotime(str_replace('/', '-', $params['from']))) . 'T23:59'; |
||||
507 | } |
||||
508 | |||||
509 | $params = array_filter($params); |
||||
510 | |||||
511 | return $params; |
||||
512 | } |
||||
513 | |||||
514 | /** |
||||
515 | * @param string $name |
||||
516 | * @param mixed $default |
||||
517 | * @return mixed |
||||
518 | */ |
||||
519 | public function getParam($name, $default = null) |
||||
520 | { |
||||
521 | $data = $this->getSession()->get(__class__ . '.Search'); |
||||
522 | if (!$data) { |
||||
523 | return $default; |
||||
524 | } |
||||
525 | return (isset($data[$name]) && strlen($data[$name])) ? $data[$name] : $default; |
||||
526 | } |
||||
527 | |||||
528 | /** |
||||
529 | * @return CompositeField |
||||
530 | */ |
||||
531 | public function SearchFields() |
||||
532 | { |
||||
533 | $disabled_filters = $this->config()->disabled_search_filters; |
||||
534 | if (!$disabled_filters) { |
||||
535 | $disabled_filters = []; |
||||
536 | } |
||||
537 | |||||
538 | $fields = new CompositeField(); |
||||
539 | $fields->push($from = new DateField('params[from]', _t('SparkPostAdmin.DATEFROM', 'From'), $this->getParam('from'))); |
||||
540 | // $from->setConfig('min', date('Y-m-d', strtotime('-10 days'))); |
||||
541 | |||||
542 | $fields->push(new DateField('params[to]', _t('SparkPostAdmin.DATETO', 'To'), $to = $this->getParam('to'))); |
||||
543 | |||||
544 | if (!in_array('friendly_froms', $disabled_filters)) { |
||||
545 | $fields->push($friendly_froms = new TextField('params[friendly_froms]', _t('SparkPostAdmin.FRIENDLYFROM', 'Sender'), $this->getParam('friendly_froms'))); |
||||
546 | $friendly_froms->setAttribute('placeholder', '[email protected],[email protected]'); |
||||
547 | } |
||||
548 | |||||
549 | if (!in_array('recipients', $disabled_filters)) { |
||||
550 | $fields->push($recipients = new TextField('params[recipients]', _t('SparkPostAdmin.RECIPIENTS', 'Recipients'), $this->getParam('recipients'))); |
||||
551 | $recipients->setAttribute('placeholder', '[email protected],[email protected]'); |
||||
552 | } |
||||
553 | |||||
554 | // Only allow filtering by subaccount if a master key is defined |
||||
555 | if (SparkPostHelper::config()->master_api_key && !in_array('subaccounts', $disabled_filters)) { |
||||
556 | $fields->push($subaccounts = new TextField('params[subaccounts]', _t('SparkPostAdmin.SUBACCOUNTS', 'Subaccounts'), $this->getParam('subaccounts'))); |
||||
557 | $subaccounts->setAttribute('placeholder', '101,102'); |
||||
558 | } |
||||
559 | |||||
560 | $fields->push(new DropdownField('params[per_page]', _t('SparkPostAdmin.PERPAGE', 'Number of results'), array( |
||||
561 | 100 => 100, |
||||
562 | 500 => 500, |
||||
563 | 1000 => 1000, |
||||
564 | 10000 => 10000, |
||||
565 | ), $this->getParam('per_page', 100))); |
||||
566 | |||||
567 | foreach ($fields->FieldList() as $field) { |
||||
568 | $field->addExtraClass('no-change-track'); |
||||
569 | } |
||||
570 | |||||
571 | // This is a ugly hack to allow embedding a form into another form |
||||
572 | $fields->push($doSearch = new FormAction('doSearch', _t('SparkPostAdmin.DOSEARCH', 'Search'))); |
||||
573 | $doSearch->addExtraClass("btn-primary"); |
||||
574 | $doSearch->setAttribute('onclick', "jQuery('#Form_SearchForm').append(jQuery('#Form_EditForm input,#Form_EditForm select').clone()).submit();"); |
||||
575 | |||||
576 | return $fields; |
||||
577 | } |
||||
578 | |||||
579 | /** |
||||
580 | * @return Form |
||||
581 | */ |
||||
582 | public function SearchForm() |
||||
583 | { |
||||
584 | $SearchForm = new Form($this, 'SearchForm', new FieldList(), new FieldList([ |
||||
585 | new FormAction('doSearch') |
||||
586 | ])); |
||||
587 | $SearchForm->setAttribute('style', 'display:none'); |
||||
588 | return $SearchForm; |
||||
589 | } |
||||
590 | |||||
591 | /** |
||||
592 | * @param array<mixed> $data |
||||
593 | * @param Form $form |
||||
594 | * @return HTTPResponse |
||||
595 | */ |
||||
596 | public function doSearch($data, Form $form) |
||||
597 | { |
||||
598 | $post = $this->getRequest()->postVar('params'); |
||||
599 | if (!$post) { |
||||
600 | return $this->redirectBack(); |
||||
601 | } |
||||
602 | $params = []; |
||||
603 | |||||
604 | $validFields = []; |
||||
605 | foreach ($this->SearchFields()->FieldList()->dataFields() as $field) { |
||||
606 | $validFields[] = str_replace(['params[', ']'], '', $field->getName()); |
||||
607 | } |
||||
608 | |||||
609 | foreach ($post as $k => $v) { |
||||
610 | if (in_array($k, $validFields)) { |
||||
611 | $params[$k] = $v; |
||||
612 | } |
||||
613 | } |
||||
614 | |||||
615 | $this->getSession()->set(__class__ . '.Search', $params); |
||||
616 | $this->getSession()->save($this->getRequest()); |
||||
617 | |||||
618 | return $this->redirectBack(); |
||||
619 | } |
||||
620 | |||||
621 | /** |
||||
622 | * List of messages events |
||||
623 | * |
||||
624 | * Messages are cached to avoid hammering the api |
||||
625 | * |
||||
626 | * @return ArrayList|string |
||||
627 | */ |
||||
628 | public function Messages() |
||||
629 | { |
||||
630 | $params = $this->getParams(); |
||||
631 | |||||
632 | $messages = $this->getCachedData('searchEvents', $params, 60 * self::MESSAGE_CACHE_MINUTES); |
||||
633 | if ($messages === false || !$messages) { |
||||
0 ignored issues
–
show
The expression
$messages of type array<mixed,mixed> is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||||
634 | if ($this->lastException) { |
||||
635 | return $this->lastException->getMessage(); |
||||
636 | } |
||||
637 | return _t('SparkpostAdmin.NO_MESSAGES', 'No messages'); |
||||
638 | } |
||||
639 | |||||
640 | // Consolidate Subject/Sender for open and click events |
||||
641 | $transmissions = []; |
||||
642 | foreach ($messages as $message) { |
||||
643 | if (empty($message['transmission_id']) || empty($message['subject'])) { |
||||
644 | continue; |
||||
645 | } |
||||
646 | if (isset($transmissions[$message['transmission_id']])) { |
||||
647 | continue; |
||||
648 | } |
||||
649 | $transmissions[$message['transmission_id']] = $message; |
||||
650 | } |
||||
651 | |||||
652 | $list = new ArrayList(); |
||||
0 ignored issues
–
show
The class
SilverStripe\ORM\ArrayList has been deprecated: 5.4.0 Will be renamed to SilverStripe\Model\List\ArrayList
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
653 | foreach ($messages as $message) { |
||||
654 | // If we have a transmission id but no subject, try to find the transmission details |
||||
655 | if (isset($message['transmission_id']) && empty($message['subject']) && isset($transmissions[$message['transmission_id']])) { |
||||
656 | $message = array_merge($transmissions[$message['transmission_id']], $message); |
||||
657 | } |
||||
658 | // In some case (errors, etc) we don't have a friendly from |
||||
659 | if (empty($message['friendly_from']) && isset($message['msg_from'])) { |
||||
660 | $message['friendly_from'] = $message['msg_from']; |
||||
661 | } |
||||
662 | $m = new ArrayData($message); |
||||
0 ignored issues
–
show
The class
SilverStripe\View\ArrayData has been deprecated: 5.4.0 Will be renamed to SilverStripe\Model\ArrayData
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
663 | $list->push($m); |
||||
664 | } |
||||
665 | |||||
666 | return $list; |
||||
667 | } |
||||
668 | |||||
669 | /** |
||||
670 | * Provides custom permissions to the Security section |
||||
671 | * |
||||
672 | * @return array<string,mixed> |
||||
673 | */ |
||||
674 | public function providePermissions() |
||||
675 | { |
||||
676 | $title = _t("SparkPostAdmin.MENUTITLE", LeftAndMain::menu_title('SparkPost')); |
||||
677 | return [ |
||||
678 | "CMS_ACCESS_SparkPost" => [ |
||||
679 | 'name' => _t('SparkPostAdmin.ACCESS', "Access to '{title}' section", ['title' => $title]), |
||||
680 | 'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access'), |
||||
681 | 'help' => _t( |
||||
682 | 'SparkPostAdmin.ACCESS_HELP', |
||||
683 | 'Allow use of SparkPost admin section' |
||||
684 | ) |
||||
685 | ], |
||||
686 | ]; |
||||
687 | } |
||||
688 | |||||
689 | /** |
||||
690 | * Message helper |
||||
691 | * |
||||
692 | * @param string $message |
||||
693 | * @param string $status |
||||
694 | * @return string |
||||
695 | */ |
||||
696 | protected function MessageHelper($message, $status = 'info') |
||||
697 | { |
||||
698 | return '<div class="message ' . $status . '">' . $message . '</div>'; |
||||
699 | } |
||||
700 | |||||
701 | /** |
||||
702 | * Button helper |
||||
703 | * |
||||
704 | * @param string $link |
||||
705 | * @param string $text |
||||
706 | * @param boolean $confirm |
||||
707 | * @return string |
||||
708 | */ |
||||
709 | protected function ButtonHelper($link, $text, $confirm = false) |
||||
710 | { |
||||
711 | $link = '<a class="btn btn-primary" href="' . $link . '"'; |
||||
712 | if ($confirm) { |
||||
713 | $link .= ' onclick="return confirm(\'' . _t('SparkPostAdmin.CONFIRM_MSG', 'Are you sure?') . '\')"'; |
||||
714 | } |
||||
715 | $link .= '>' . $text . '</a>'; |
||||
716 | return $link; |
||||
717 | } |
||||
718 | |||||
719 | /** |
||||
720 | * Wrap html in a form group |
||||
721 | * |
||||
722 | * @param string $html |
||||
723 | * @return string |
||||
724 | */ |
||||
725 | protected function FormGroupHelper($html) |
||||
726 | { |
||||
727 | return '<div class="form-group"><div class="form__fieldgroup form__field-holder form__field-holder--no-label">' . $html . '</div></div>'; |
||||
728 | } |
||||
729 | |||||
730 | /** |
||||
731 | * A template accessor to check the ADMIN permission |
||||
732 | * |
||||
733 | * @return bool |
||||
734 | */ |
||||
735 | public function IsAdmin() |
||||
736 | { |
||||
737 | return boolval(Permission::check("ADMIN")); |
||||
738 | } |
||||
739 | |||||
740 | /** |
||||
741 | * Check the permission for current user |
||||
742 | * |
||||
743 | * @return bool |
||||
744 | */ |
||||
745 | public function canView($member = null) |
||||
746 | { |
||||
747 | $mailer = SparkPostHelper::getMailer(); |
||||
748 | $transport = SparkPostHelper::getTransportFromMailer($mailer); |
||||
749 | // Another custom mailer has been set |
||||
750 | if (!($transport instanceof SparkPostApiTransport)) { |
||||
751 | return false; |
||||
752 | } |
||||
753 | return boolval(Permission::check("CMS_ACCESS_SparkPost", 'any', $member)); |
||||
754 | } |
||||
755 | |||||
756 | /** |
||||
757 | * @return bool |
||||
758 | */ |
||||
759 | public function CanConfigureApi() |
||||
760 | { |
||||
761 | return Permission::check('ADMIN') || Director::isDev(); |
||||
762 | } |
||||
763 | |||||
764 | /** |
||||
765 | * Check if webhook is installed |
||||
766 | * |
||||
767 | * @return array<mixed>|false |
||||
768 | */ |
||||
769 | public function WebhookInstalled() |
||||
770 | { |
||||
771 | $list = $this->getCachedData('listAllWebhooks', null, 60 * self::WEBHOOK_CACHE_MINUTES); |
||||
772 | |||||
773 | if (empty($list)) { |
||||
774 | return false; |
||||
775 | } |
||||
776 | $url = $this->WebhookUrl(); |
||||
777 | foreach ($list as $el) { |
||||
778 | if (!empty($el['target']) && $el['target'] === $url) { |
||||
779 | /* |
||||
780 | ^ array:13 [â–¼ |
||||
781 | "auth_token" => false |
||||
782 | "auth_type" => "basic" |
||||
783 | "name" => "Testing Webhook" |
||||
784 | "auth_credentials" => array:2 [â–¶] |
||||
785 | "events" => array:19 [â–¶] |
||||
786 | "target" => "https://mydomain.com/sparkpost/incoming" |
||||
787 | "custom_headers" => [] |
||||
788 | "auth_request_details" => [] |
||||
789 | "id" => "xxxxxx" |
||||
790 | "last_successful" => null |
||||
791 | "last_failure" => null |
||||
792 | "active" => false |
||||
793 | "links" => array:1 [â–¼ |
||||
794 | 0 => array:3 [â–¶] |
||||
795 | ] |
||||
796 | ] |
||||
797 | */ |
||||
798 | return $el; |
||||
799 | } |
||||
800 | } |
||||
801 | return false; |
||||
802 | } |
||||
803 | |||||
804 | /** |
||||
805 | * Hook details for template |
||||
806 | * @return ArrayData|null |
||||
807 | */ |
||||
808 | public function WebhookDetails() |
||||
809 | { |
||||
810 | $el = $this->WebhookInstalled(); |
||||
811 | if ($el) { |
||||
812 | return new ArrayData($el); |
||||
0 ignored issues
–
show
The class
SilverStripe\View\ArrayData has been deprecated: 5.4.0 Will be renamed to SilverStripe\Model\ArrayData
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
813 | } |
||||
814 | return null; |
||||
815 | } |
||||
816 | |||||
817 | /** |
||||
818 | * Get content of the tab |
||||
819 | * |
||||
820 | * @return FormField |
||||
821 | */ |
||||
822 | public function WebhookTab() |
||||
823 | { |
||||
824 | $webhook = $this->WebhookInstalled(); |
||||
825 | if ($webhook) { |
||||
826 | return $this->UninstallHookForm($webhook); |
||||
827 | } |
||||
828 | return $this->InstallHookForm(); |
||||
829 | } |
||||
830 | |||||
831 | /** |
||||
832 | * @return string |
||||
833 | */ |
||||
834 | public function WebhookUrl() |
||||
835 | { |
||||
836 | if (self::config()->webhook_base_url) { |
||||
837 | return rtrim(self::config()->webhook_base_url, '/') . '/sparkpost/incoming'; |
||||
838 | } |
||||
839 | if (Director::isLive()) { |
||||
840 | $absurl = Director::absoluteURL('/sparkpost/incoming'); |
||||
841 | if ($absurl && is_string($absurl)) { |
||||
842 | return $absurl; |
||||
843 | } |
||||
844 | } |
||||
845 | $protocol = Director::protocol(); |
||||
846 | $domain = $this->getDomain(); |
||||
847 | if (!$domain) { |
||||
848 | throw new Exception("No domain for webhook"); |
||||
849 | } |
||||
850 | return $protocol . $domain . '/sparkpost/incoming'; |
||||
851 | } |
||||
852 | |||||
853 | /** |
||||
854 | * Install hook form |
||||
855 | * |
||||
856 | * @return FormField |
||||
857 | */ |
||||
858 | public function InstallHookForm() |
||||
859 | { |
||||
860 | $fields = new CompositeField(); |
||||
861 | $fields->push(new LiteralField('Info', $this->MessageHelper( |
||||
862 | _t('SparkPostAdmin.WebhookNotInstalled', 'Webhook is not installed. It should be configured using the following url {url}. This url must be publicly visible to be used as a hook.', ['url' => $this->WebhookUrl()]), |
||||
863 | 'bad' |
||||
864 | ))); |
||||
865 | $fields->push(new LiteralField('doInstallHook', $this->ButtonHelper( |
||||
866 | $this->Link('doInstallHook'), |
||||
867 | _t('SparkPostAdmin.DOINSTALL_WEBHOOK', 'Install webhook') |
||||
868 | ))); |
||||
869 | return $fields; |
||||
870 | } |
||||
871 | |||||
872 | /** |
||||
873 | * @return HTTPResponse |
||||
874 | */ |
||||
875 | public function doInstallHook() |
||||
876 | { |
||||
877 | if (!$this->CanConfigureApi()) { |
||||
878 | return $this->redirectBack(); |
||||
879 | } |
||||
880 | |||||
881 | $client = SparkPostHelper::getClient(); |
||||
882 | |||||
883 | $url = $this->WebhookUrl(); |
||||
884 | $description = SiteConfig::current_site_config()->Title; |
||||
885 | |||||
886 | $webhookUser = Environment::getEnv('SS_DEFAULT_ADMIN_USERNAME'); |
||||
887 | $webhookPassword = Environment::getEnv('SS_DEFAULT_ADMIN_PASSWORD'); |
||||
888 | |||||
889 | if (SparkPostHelper::getWebhookUsername()) { |
||||
890 | $webhookUser = SparkPostHelper::getWebhookUsername(); |
||||
891 | $webhookPassword = SparkPostHelper::getWebhookPassword(); |
||||
892 | } |
||||
893 | |||||
894 | try { |
||||
895 | if ($webhookUser && $webhookPassword) { |
||||
896 | $client->createSimpleWebhook($description, $url, null, true, ['username' => $webhookUser, 'password' => $webhookPassword]); |
||||
897 | } else { |
||||
898 | $client->createSimpleWebhook($description, $url); // This will add a default credentials that is sparkpost/sparkpost |
||||
899 | } |
||||
900 | $this->getCache()->clear(); |
||||
901 | } catch (Exception $ex) { |
||||
902 | $this->getLogger()->debug($ex); |
||||
903 | } |
||||
904 | |||||
905 | return $this->redirectBack(); |
||||
906 | } |
||||
907 | |||||
908 | /** |
||||
909 | * Uninstall hook form |
||||
910 | * |
||||
911 | * @param array<mixed> $data |
||||
912 | * @return FormField |
||||
913 | */ |
||||
914 | public function UninstallHookForm($data) |
||||
915 | { |
||||
916 | $fields = new CompositeField(); |
||||
917 | |||||
918 | if ($data['active']) { |
||||
919 | $fields->push(new LiteralField('Info', $this->MessageHelper( |
||||
920 | _t('SparkPostAdmin.WebhookInstalled', 'Webhook is installed but inactive at the following url {url}.', ['url' => $this->WebhookUrl()]), |
||||
921 | 'warning' |
||||
922 | ))); |
||||
923 | } else { |
||||
924 | $fields->push(new LiteralField('Info', $this->MessageHelper( |
||||
925 | _t('SparkPostAdmin.WebhookInstalled', 'Webhook is installed and accessible at the following url {url}.', ['url' => $this->WebhookUrl()]), |
||||
926 | 'good' |
||||
927 | ))); |
||||
928 | } |
||||
929 | |||||
930 | if ($data['last_successful']) { |
||||
931 | $fields->push(new LiteralField('LastSuccess', $this->MessageHelper( |
||||
932 | _t('SparkPostAdmin.WebhookLastSuccess', 'Webhook was last called successfully at {date}.', ['date' => $data['last_successful']]), |
||||
933 | 'good' |
||||
934 | ))); |
||||
935 | } |
||||
936 | if ($data['last_failure']) { |
||||
937 | $fields->push(new LiteralField('LastFailure', $this->MessageHelper( |
||||
938 | _t('SparkPostAdmin.WebhookLastFailure', 'Webhook last failure was at {date}.', ['date' => $data['last_failure']]), |
||||
939 | 'bad' |
||||
940 | ))); |
||||
941 | } |
||||
942 | |||||
943 | $fields->push(new LiteralField('doUninstallHook', $this->ButtonHelper( |
||||
944 | $this->Link('doUninstallHook'), |
||||
945 | _t('SparkPostAdmin.DOUNINSTALL_WEBHOOK', 'Uninstall webhook'), |
||||
946 | true |
||||
947 | ))); |
||||
948 | return $fields; |
||||
949 | } |
||||
950 | |||||
951 | /** |
||||
952 | * @param array<mixed> $data |
||||
953 | * @param Form $form |
||||
954 | * @return HTTPResponse |
||||
955 | */ |
||||
956 | public function doUninstallHook($data, Form $form) |
||||
957 | { |
||||
958 | if (!$this->CanConfigureApi()) { |
||||
959 | return $this->redirectBack(); |
||||
960 | } |
||||
961 | |||||
962 | $client = SparkPostHelper::getClient(); |
||||
963 | |||||
964 | try { |
||||
965 | $el = $this->WebhookInstalled(); |
||||
966 | if ($el && !empty($el['id'])) { |
||||
967 | $client->deleteWebhook($el['id']); |
||||
968 | } |
||||
969 | $this->getCache()->clear(); |
||||
970 | } catch (Exception $ex) { |
||||
971 | $this->getLogger()->debug($ex); |
||||
972 | } |
||||
973 | |||||
974 | return $this->redirectBack(); |
||||
975 | } |
||||
976 | |||||
977 | /** |
||||
978 | * Check if sending domain is installed |
||||
979 | * |
||||
980 | * @return array<mixed>|false |
||||
981 | */ |
||||
982 | public function SendingDomainInstalled() |
||||
983 | { |
||||
984 | $domain = $this->getCachedData('getSendingDomain', $this->getDomain(), 60 * self::SENDINGDOMAIN_CACHE_MINUTES); |
||||
985 | |||||
986 | if (empty($domain)) { |
||||
987 | return false; |
||||
988 | } |
||||
989 | return $domain; |
||||
990 | } |
||||
991 | |||||
992 | /** |
||||
993 | * Trigger request to check if sending domain is verified |
||||
994 | * |
||||
995 | * @return array<mixed>|false |
||||
996 | */ |
||||
997 | public function VerifySendingDomain() |
||||
998 | { |
||||
999 | $client = SparkPostHelper::getClient(); |
||||
1000 | |||||
1001 | $host = $this->getDomain(); |
||||
1002 | if (!$host || is_bool($host)) { |
||||
1003 | return false; |
||||
1004 | } |
||||
1005 | |||||
1006 | $verification = $client->verifySendingDomain($host); |
||||
1007 | if (empty($verification)) { |
||||
1008 | return false; |
||||
1009 | } |
||||
1010 | return $verification; |
||||
1011 | } |
||||
1012 | |||||
1013 | /** |
||||
1014 | * Get content of the tab |
||||
1015 | * |
||||
1016 | * @return FormField |
||||
1017 | */ |
||||
1018 | public function DomainTab() |
||||
1019 | { |
||||
1020 | $defaultDomain = $this->getDomain(); |
||||
1021 | $defaultDomainInfos = null; |
||||
1022 | |||||
1023 | $domains = $this->getCachedData('listAllSendingDomains', null, 60 * self::SENDINGDOMAIN_CACHE_MINUTES); |
||||
1024 | |||||
1025 | $fields = new CompositeField(); |
||||
1026 | |||||
1027 | $list = new ArrayList(); |
||||
0 ignored issues
–
show
The class
SilverStripe\ORM\ArrayList has been deprecated: 5.4.0 Will be renamed to SilverStripe\Model\List\ArrayList
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1028 | if ($domains) { |
||||
1029 | foreach ($domains as $domain) { |
||||
1030 | // Sometimes the api or the cache returns invalid data... |
||||
1031 | if (!is_array($domain)) { |
||||
1032 | continue; |
||||
1033 | } |
||||
1034 | $list->push(new ArrayData([ |
||||
0 ignored issues
–
show
The class
SilverStripe\View\ArrayData has been deprecated: 5.4.0 Will be renamed to SilverStripe\Model\ArrayData
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1035 | 'Domain' => $domain['domain'], |
||||
1036 | 'SPF' => $domain['status']['spf_status'], |
||||
1037 | 'DKIM' => $domain['status']['dkim_status'], |
||||
1038 | 'Compliance' => $domain['status']['compliance_status'], |
||||
1039 | 'Verified' => $domain['status']['ownership_verified'], |
||||
1040 | ])); |
||||
1041 | |||||
1042 | if ($domain['domain'] == $defaultDomain) { |
||||
1043 | $defaultDomainInfos = $domain; |
||||
1044 | } |
||||
1045 | } |
||||
1046 | } |
||||
1047 | |||||
1048 | $config = GridFieldConfig::create(); |
||||
1049 | $config->addComponent(new GridFieldToolbarHeader()); |
||||
1050 | $config->addComponent(new GridFieldTitleHeader()); |
||||
1051 | $config->addComponent($columns = new GridFieldDataColumns()); |
||||
1052 | $columns->setDisplayFields(ArrayLib::valuekey(['Domain', 'SPF', 'DKIM', 'Compliance', 'Verified'])); |
||||
0 ignored issues
–
show
The function
SilverStripe\ORM\ArrayLib::valuekey() has been deprecated: 5.4.0 Will be renamed to SilverStripe\Core\ArrayLib::valuekey()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
1053 | $domainsList = new GridField('SendingDomains', _t('SparkPostAdmin.ALL_SENDING_DOMAINS', 'Configured sending domains'), $list, $config); |
||||
1054 | $domainsList->addExtraClass('mb-2'); |
||||
1055 | $fields->push($domainsList); |
||||
1056 | |||||
1057 | if (!$defaultDomainInfos) { |
||||
1058 | $this->InstallDomainForm($fields); |
||||
1059 | } else { |
||||
1060 | $this->UninstallDomainForm($fields); |
||||
1061 | } |
||||
1062 | |||||
1063 | return $fields; |
||||
1064 | } |
||||
1065 | |||||
1066 | /** |
||||
1067 | * @return ?string |
||||
1068 | */ |
||||
1069 | public function InboundUrl() |
||||
1070 | { |
||||
1071 | $subdomain = self::config()->inbound_subdomain; |
||||
1072 | $domain = $this->getDomain(); |
||||
1073 | if ($domain) { |
||||
1074 | return $subdomain . '.' . $domain; |
||||
1075 | } |
||||
1076 | return null; |
||||
1077 | } |
||||
1078 | |||||
1079 | /** |
||||
1080 | * Get domain name from current host |
||||
1081 | * |
||||
1082 | * @return boolean|string |
||||
1083 | */ |
||||
1084 | public function getDomainFromHost() |
||||
1085 | { |
||||
1086 | $base = Environment::getEnv('SS_BASE_URL'); |
||||
1087 | if (!$base) { |
||||
1088 | $base = Director::protocolAndHost(); |
||||
1089 | } |
||||
1090 | $host = parse_url($base, PHP_URL_HOST); |
||||
1091 | if (!$host) { |
||||
1092 | return false; |
||||
1093 | } |
||||
1094 | $hostParts = explode('.', $host); |
||||
1095 | $parts = count($hostParts); |
||||
1096 | if ($parts < 2) { |
||||
1097 | return false; |
||||
1098 | } |
||||
1099 | $domain = $hostParts[$parts - 2] . "." . $hostParts[$parts - 1]; |
||||
1100 | return $domain; |
||||
1101 | } |
||||
1102 | |||||
1103 | /** |
||||
1104 | * Get domain from admin email |
||||
1105 | * |
||||
1106 | * @return boolean|string |
||||
1107 | */ |
||||
1108 | public function getDomainFromEmail() |
||||
1109 | { |
||||
1110 | $email = SparkPostHelper::resolveDefaultFromEmail(null, false); |
||||
1111 | if ($email && is_string($email)) { |
||||
1112 | $emailat = (string)strrchr($email, "@"); |
||||
1113 | $domain = substr($emailat, 1); |
||||
1114 | if (!$domain) { |
||||
1115 | return false; |
||||
1116 | } |
||||
1117 | return $domain; |
||||
1118 | } |
||||
1119 | return false; |
||||
1120 | } |
||||
1121 | |||||
1122 | /** |
||||
1123 | * Get domain |
||||
1124 | * |
||||
1125 | * @return boolean|string |
||||
1126 | */ |
||||
1127 | public function getDomain() |
||||
1128 | { |
||||
1129 | $domain = $this->getDomainFromEmail(); |
||||
1130 | if (!$domain) { |
||||
1131 | return $this->getDomainFromHost(); |
||||
1132 | } |
||||
1133 | return $domain; |
||||
1134 | } |
||||
1135 | |||||
1136 | /** |
||||
1137 | * Install domain form |
||||
1138 | * |
||||
1139 | * @param CompositeField $fields |
||||
1140 | * @return void |
||||
1141 | */ |
||||
1142 | public function InstallDomainForm(CompositeField $fields) |
||||
1143 | { |
||||
1144 | $host = $this->getDomain(); |
||||
1145 | |||||
1146 | $fields->push(new LiteralField('Info', $this->MessageHelper( |
||||
1147 | _t('SparkPostAdmin.DomainNotInstalled', 'Default sending domain {domain} is not installed.', ['domain' => $host]), |
||||
1148 | "bad" |
||||
1149 | ))); |
||||
1150 | $fields->push(new LiteralField('doInstallDomain', $this->ButtonHelper( |
||||
1151 | $this->Link('doInstallDomain'), |
||||
1152 | _t('SparkPostAdmin.DOINSTALLDOMAIN', 'Install domain') |
||||
1153 | ))); |
||||
1154 | } |
||||
1155 | |||||
1156 | /** |
||||
1157 | * @return HTTPResponse |
||||
1158 | */ |
||||
1159 | public function doInstallDomain() |
||||
1160 | { |
||||
1161 | if (!$this->CanConfigureApi()) { |
||||
1162 | return $this->redirectBack(); |
||||
1163 | } |
||||
1164 | |||||
1165 | $client = SparkPostHelper::getClient(); |
||||
1166 | |||||
1167 | $domain = $this->getDomain(); |
||||
1168 | |||||
1169 | if (!$domain || is_bool($domain)) { |
||||
1170 | return $this->redirectBack(); |
||||
1171 | } |
||||
1172 | |||||
1173 | try { |
||||
1174 | $client->createSimpleSendingDomain($domain); |
||||
1175 | $this->getCache()->clear(); |
||||
1176 | } catch (Exception $ex) { |
||||
1177 | $this->getLogger()->debug($ex); |
||||
1178 | } |
||||
1179 | |||||
1180 | return $this->redirectBack(); |
||||
1181 | } |
||||
1182 | |||||
1183 | /** |
||||
1184 | * Uninstall domain form |
||||
1185 | * |
||||
1186 | * @param CompositeField $fields |
||||
1187 | * @return void |
||||
1188 | */ |
||||
1189 | public function UninstallDomainForm(CompositeField $fields) |
||||
1190 | { |
||||
1191 | $domainInfos = $this->SendingDomainInstalled(); |
||||
1192 | |||||
1193 | $domain = $this->getDomain(); |
||||
1194 | |||||
1195 | if ($domainInfos && $domainInfos['status']['ownership_verified']) { |
||||
1196 | $fields->push(new LiteralField('Info', $this->MessageHelper( |
||||
1197 | _t('SparkPostAdmin.DomainInstalled', 'Default domain {domain} is installed.', ['domain' => $domain]), |
||||
1198 | 'good' |
||||
1199 | ))); |
||||
1200 | } else { |
||||
1201 | $fields->push(new LiteralField('Info', $this->MessageHelper( |
||||
1202 | _t('SparkPostAdmin.DomainInstalledBut', 'Default domain {domain} is installed, but is not properly configured.'), |
||||
1203 | 'warning' |
||||
1204 | ))); |
||||
1205 | } |
||||
1206 | $fields->push(new LiteralField('doUninstallHook', $this->ButtonHelper( |
||||
1207 | $this->Link('doUninstallHook'), |
||||
1208 | _t('SparkPostAdmin.DOUNINSTALLDOMAIN', 'Uninstall domain'), |
||||
1209 | true |
||||
1210 | ))); |
||||
1211 | } |
||||
1212 | |||||
1213 | /** |
||||
1214 | * @param array<mixed> $data |
||||
1215 | * @param Form $form |
||||
1216 | * @return HTTPResponse |
||||
1217 | */ |
||||
1218 | public function doUninstallDomain($data, Form $form) |
||||
1219 | { |
||||
1220 | if (!$this->CanConfigureApi()) { |
||||
1221 | return $this->redirectBack(); |
||||
1222 | } |
||||
1223 | |||||
1224 | $client = SparkPostHelper::getClient(); |
||||
1225 | |||||
1226 | $domain = $this->getDomain(); |
||||
1227 | |||||
1228 | if (!$domain || is_bool($domain)) { |
||||
1229 | return $this->redirectBack(); |
||||
1230 | } |
||||
1231 | |||||
1232 | try { |
||||
1233 | $el = $this->SendingDomainInstalled(); |
||||
1234 | if ($el) { |
||||
1235 | $client->deleteSendingDomain($domain); |
||||
1236 | } |
||||
1237 | $this->getCache()->clear(); |
||||
1238 | } catch (Exception $ex) { |
||||
1239 | $this->getLogger()->debug($ex); |
||||
1240 | } |
||||
1241 | |||||
1242 | return $this->redirectBack(); |
||||
1243 | } |
||||
1244 | } |
||||
1245 |