Skip to content

Commit 1acc7ed

Browse files
committed
Add optional polling behaviour
1 parent 3cf3669 commit 1acc7ed

9 files changed

Lines changed: 174 additions & 0 deletions

File tree

Config/Config.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ public function __construct(
1313
) {
1414
}
1515

16+
public function getPollingInterval(): int
17+
{
18+
return (int)$this->scopeConfig->getValue(
19+
'loki_components/general/polling_interval',
20+
ScopeInterface::SCOPE_STORE
21+
);
22+
}
23+
1624
public function isDebug(): bool
1725
{
1826
return (bool)$this->scopeConfig->getValue(

Controller/Index/Polling.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Loki\Components\Controller\Index;
6+
7+
use Loki\Components\Polling\PollingHandlerListing;
8+
use Magento\Framework\App\Action\HttpGetActionInterface;
9+
use Magento\Framework\App\ResponseInterface;
10+
use Magento\Framework\Controller\Result\JsonFactory as JsonResultFactory;
11+
use Magento\Framework\Controller\ResultInterface;
12+
13+
class Polling implements HttpGetActionInterface
14+
{
15+
public function __construct(
16+
private readonly JsonResultFactory $jsonResultFactory,
17+
private readonly PollingHandlerListing $pollingHandlerListing,
18+
) {
19+
}
20+
21+
public function execute(): ResultInterface|ResponseInterface
22+
{
23+
$data = [];
24+
foreach ($this->pollingHandlerListing->getHandlers() as $handler) {
25+
$data = array_merge($data, $handler->execute());
26+
}
27+
28+
$jsonResult = $this->jsonResultFactory->create();
29+
$jsonResult->setData($data);
30+
return $jsonResult;
31+
}
32+
}

Polling/AbstractPollingHandler.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Loki\Components\Polling;
5+
6+
abstract class AbstractPollingHandler implements PollingHandlerInterface
7+
{
8+
abstract public function execute(): array;
9+
10+
public function getMessageData(string $messageType, string $message): array
11+
{
12+
return ['messageType' => $messageType, 'message' => $message];
13+
}
14+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Loki\Components\Polling;
5+
6+
interface PollingHandlerInterface
7+
{
8+
public function execute(): array;
9+
}

Polling/PollingHandlerListing.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Loki\Components\Polling;
5+
6+
class PollingHandlerListing
7+
{
8+
public function __construct(
9+
private readonly array $handlers,
10+
) {
11+
}
12+
13+
/**
14+
* @return PollingHandlerInterface[]
15+
*/
16+
public function getHandlers(): array
17+
{
18+
return $this->handlers;
19+
}
20+
}

Util/ComponentUtil.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ public function getPostUrl(): string
6363
return $this->urlFactory->create()->getUrl('loki_components/index/html');
6464
}
6565

66+
public function getPollingUrl(): string
67+
{
68+
return $this->urlFactory->create()->getUrl('loki_components/index/polling');
69+
}
70+
6671
public function getFormHtml(AbstractBlock $block): string
6772
{
6873
/** @var AbstractBlock $formBlock */

etc/adminhtml/system.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@
2222
<tooltip>When debugging is enabled, on various levels, detailed information comes available. For instance, in the browser Error Console, more debugging messages are displayed, allowing you to inspect issues on the JavaScript level. Whenever an exception occurs within the AJAX call, the exception message is appended to the AJAX output.</tooltip>
2323
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
2424
</field>
25+
<field id="polling_interval"
26+
translate="label"
27+
type="text"
28+
sortOrder="1"
29+
showInDefault="1"
30+
showInWebsite="1"
31+
showInStore="0">
32+
<label>Polling Interval</label>
33+
<tooltip>If you have added polling handlers, set this to an interval with which you want those polling handlers to act.</tooltip>
34+
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
35+
</field>
2536
</group>
2637
</section>
2738
</system>

view/base/layout/loki_components.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
</block>
1414

1515
<referenceBlock name="loki.script">
16+
<block
17+
name="loki-components.script.polling"
18+
template="Loki_Components::script/polling.phtml"/>
19+
1620
<block
1721
name="loki-components.script.logger"
1822
template="Loki_Components::script/logger.phtml"/>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php declare(strict_types=1);
2+
3+
use Loki\Components\Util\ComponentUtil;
4+
use Magento\Framework\Escaper;
5+
use Magento\Framework\View\Element\Template;
6+
use Loki\Components\Config\Config;
7+
use Loki\Components\Factory\ViewModelFactory;
8+
9+
/** @var Template $block */
10+
/** @var ViewModelFactory $viewModelFactory */
11+
/** @var Config $config */
12+
/** @var Config $componentUtil */
13+
/** @var ComponentUtil $componentUtil */
14+
/** @var Escaper $escaper */
15+
16+
$config = $viewModelFactory->create(Config::class);
17+
$componentUtil = $viewModelFactory->create(ComponentUtil::class);
18+
$interval = $this->getPollingInterval();
19+
if ($interval < 500) {
20+
return;
21+
}
22+
?>
23+
<script>
24+
(() => {
25+
setInterval(() => {
26+
fetch('<?= $escaper->escapeUrl($componentUtil->getPollingUrl()) ?>?form_key=' + LokiComponentFormKey + '&isAjax=true', {
27+
method: 'GET',
28+
headers: {
29+
'X-Requested-With': 'XMLHttpRequest',
30+
'Content-Type': 'application/json'
31+
},
32+
})
33+
.then(response => {
34+
if (response.ok) {
35+
return response.text()
36+
}
37+
38+
LokiComponentsLogger.error('Fetch error', response);
39+
throw new Error(response.statusText);
40+
})
41+
.then(html => {
42+
try {
43+
const data = JSON.parse(html);
44+
if (data) {
45+
data.forEach(dataPart => {
46+
if (dataPart.message) {
47+
const messageType = dataPart.messageType ?? 'notice';
48+
Alpine.store('Message').addMessage(messageType, dataPart.message);
49+
}
50+
51+
if (dataPart.redirectUrl) {
52+
if (dataPart.redirectMessage) {
53+
Alpine.store('Message').addWarningMessage(dataPart.redirectMessage);
54+
}
55+
56+
const seconds = 3;
57+
setTimeout(() => {
58+
window.location = dataPart.redirectUrl;
59+
}, seconds * 1000)
60+
}
61+
});
62+
}
63+
} catch (e) {
64+
}
65+
})
66+
.catch(error => {
67+
Alpine.store('Message').addErrorMessage(error);
68+
});
69+
}, <?= $interval ?>);
70+
})();
71+
</script>

0 commit comments

Comments
 (0)