Skip to content

Commit b01665e

Browse files
authored
Merge pull request #3 from DeployEcommerce/reorg-and-improvements
Improve extension and reorganise
2 parents 84d36eb + 7d782cf commit b01665e

File tree

19 files changed

+1628
-164
lines changed

19 files changed

+1628
-164
lines changed
Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,95 @@
11
<?php
22
/**
3-
* Copyright © Deploy Ecommerce All rights reserved.
4-
*
3+
* Copyright © Deploy Ecommerce. All rights reserved.
4+
* See LICENSE.txt for license details.
55
*/
6+
67
declare(strict_types=1);
78

89
namespace DeployEcommerce\RedisFlush\Block\Adminhtml\Cache;
910

11+
use DeployEcommerce\RedisFlush\Service\RedisStatisticsService;
1012
use Magento\Backend\Block\Widget\Button;
13+
use Magento\Backend\Block\Widget\Context;
1114

15+
/**
16+
* Enhanced Redis flush button with statistics-aware confirmation
17+
*
18+
* Displays flush button with detailed confirmation dialog showing
19+
* current Redis statistics and warnings about impact.
20+
*/
1221
class FlushButton extends Button
1322
{
1423
/**
24+
* @param Context $context
25+
* @param RedisStatisticsService $redisStatisticsService
26+
* @param array $data
27+
*/
28+
public function __construct(
29+
Context $context,
30+
private readonly RedisStatisticsService $redisStatisticsService,
31+
array $data = []
32+
) {
33+
parent::__construct($context, $data);
34+
}
35+
36+
/**
37+
* Configure flush button
38+
*
1539
* @return void
1640
*/
17-
protected function _construct()
41+
protected function _construct(): void
1842
{
1943
parent::_construct();
2044

45+
$statistics = $this->redisStatisticsService->getStatistics();
46+
47+
if ($statistics === null) {
48+
// Redis not available - show disabled button
49+
$this->setData([
50+
'id' => 'flush_redis_cache',
51+
'label' => __('Flush Redis Cache'),
52+
'class' => 'action-secondary disabled',
53+
'title' => __('Redis is not configured or not available'),
54+
'disabled' => true,
55+
]);
56+
return;
57+
}
58+
59+
// Build confirmation message with current statistics
60+
$confirmMessage = $this->buildConfirmationMessage($statistics);
61+
62+
// Add form key to URL for CSRF protection
63+
$url = $this->getUrl('rediscache/cache/flushredis', [
64+
'form_key' => $this->getFormKey()
65+
]);
66+
2167
$this->setData([
22-
'id' => 'flush_redis',
23-
'label' => __('Flush Redis'),
24-
'class' => 'primary',
25-
'onclick' => "setLocation('" . $this->getUrl('redisflush/cache/flushredis') . "')"
68+
'id' => 'flush_redis_cache',
69+
'label' => __('Flush Redis Cache'),
70+
'class' => 'action-secondary',
71+
'onclick' => sprintf("return confirm('%s') && (window.location.href='%s');", $confirmMessage, $url),
2672
]);
2773
}
74+
75+
/**
76+
* Build detailed confirmation message with statistics
77+
*
78+
* @param \DeployEcommerce\RedisFlush\Model\Data\RedisStatistics $statistics
79+
* @return string
80+
*/
81+
private function buildConfirmationMessage(\DeployEcommerce\RedisFlush\Model\Data\RedisStatistics $statistics): string
82+
{
83+
$memoryInfo = sprintf('%.2f MB', $statistics->usedMemoryMb);
84+
if ($statistics->maxMemoryMb !== null) {
85+
$percentage = $statistics->getMemoryUsagePercentage();
86+
$memoryInfo .= sprintf(' (%.1f%%)', $percentage);
87+
}
88+
89+
$keysInfo = number_format($statistics->getTotalKeys());
90+
91+
$message = __('This action will cause temporary performance degradation and remove '.$keysInfo.' keys and '.$memoryInfo.' of data. Are you sure you want to continue?')->render();
92+
93+
return addslashes($message);
94+
}
2895
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
/**
3+
* Copyright © Deploy Ecommerce. All rights reserved.
4+
* See LICENSE.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace DeployEcommerce\RedisFlush\Block\Adminhtml\Cache;
10+
11+
use DeployEcommerce\RedisFlush\Service\RedisStatisticsService;
12+
use Magento\Backend\Block\Template;
13+
use Magento\Backend\Block\Template\Context;
14+
15+
/**
16+
* Redis statistics display block for admin Cache Management page
17+
*
18+
* Displays real-time Redis memory usage, keyspace info, and connection status.
19+
*/
20+
class RedisStatistics extends Template
21+
{
22+
/**
23+
* Template file
24+
*
25+
* @var string
26+
*/
27+
protected $_template = 'DeployEcommerce_RedisFlush::cache/redis_statistics.phtml';
28+
29+
/**
30+
* @param Context $context
31+
* @param RedisStatisticsService $redisStatisticsService
32+
* @param array $data
33+
*/
34+
public function __construct(
35+
Context $context,
36+
private readonly RedisStatisticsService $redisStatisticsService,
37+
array $data = []
38+
) {
39+
parent::__construct($context, $data);
40+
}
41+
42+
/**
43+
* Get Redis statistics
44+
*
45+
* @return \DeployEcommerce\RedisFlush\Model\Data\RedisStatistics|null
46+
*/
47+
public function getStatistics(): ?\DeployEcommerce\RedisFlush\Model\Data\RedisStatistics
48+
{
49+
return $this->redisStatisticsService->getStatistics();
50+
}
51+
52+
/**
53+
* Check if Redis is available
54+
*
55+
* @return bool
56+
*/
57+
public function isRedisAvailable(): bool
58+
{
59+
return $this->getStatistics() !== null;
60+
}
61+
62+
/**
63+
* Format number with thousand separators
64+
*
65+
* @param int $number
66+
* @return string
67+
*/
68+
public function formatNumber(int $number): string
69+
{
70+
return number_format($number);
71+
}
72+
73+
/**
74+
* Format bytes to human-readable size
75+
*
76+
* @param float $mb
77+
* @return string
78+
*/
79+
public function formatMemory(float $mb): string
80+
{
81+
if ($mb >= 1024) {
82+
return sprintf('%.2f GB', $mb / 1024);
83+
}
84+
return sprintf('%.2f MB', $mb);
85+
}
86+
87+
/**
88+
* Get memory usage bar width percentage
89+
*
90+
* @param float|null $percentage
91+
* @return float
92+
*/
93+
public function getMemoryBarWidth(?float $percentage): float
94+
{
95+
if ($percentage === null) {
96+
return 0.0;
97+
}
98+
return min(100.0, max(0.0, $percentage));
99+
}
100+
101+
/**
102+
* Get memory usage bar color class based on usage percentage
103+
*
104+
* @param float|null $percentage
105+
* @return string
106+
*/
107+
public function getMemoryBarColorClass(?float $percentage): string
108+
{
109+
if ($percentage === null) {
110+
return 'memory-bar-unknown';
111+
}
112+
113+
if ($percentage >= 90) {
114+
return 'memory-bar-critical';
115+
}
116+
117+
if ($percentage >= 75) {
118+
return 'memory-bar-warning';
119+
}
120+
121+
return 'memory-bar-normal';
122+
}
123+
124+
/**
125+
* Get refresh URL for statistics
126+
*
127+
* @return string
128+
*/
129+
public function getRefreshUrl(): string
130+
{
131+
return $this->getUrl('adminhtml/cache/index');
132+
}
133+
}
Lines changed: 59 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,103 @@
11
<?php
2-
32
/**
4-
* Copyright © Deploy Ecommerce All rights reserved.
5-
*
3+
* Copyright © Deploy Ecommerce. All rights reserved.
4+
* See LICENSE.txt for license details.
65
*/
6+
77
declare(strict_types=1);
88

99
namespace DeployEcommerce\RedisFlush\Controller\Adminhtml\Cache;
1010

11+
use DeployEcommerce\RedisFlush\Service\RedisCacheFlushService;
1112
use Magento\Backend\App\Action;
1213
use Magento\Backend\App\Action\Context;
13-
use Magento\Framework\App\Cache\Frontend\Pool;
1414
use Magento\Framework\Controller\Result\Redirect;
1515

16+
/**
17+
* Admin controller for flushing Redis cache
18+
*
19+
* Handles Redis flush requests from admin with ACL and CSRF protection.
20+
*/
1621
class FlushRedis extends Action
1722
{
1823
/**
19-
* Authorization level of a basic admin session
20-
*/
21-
const ADMIN_RESOURCE = 'Magento_Backend::cache';
22-
23-
/**
24-
* @var Pool
24+
* Authorization level required for this action
25+
*
26+
* @see _isAllowed()
2527
*/
26-
protected $cacheFrontendPool;
28+
public const ADMIN_RESOURCE = 'DeployEcommerce_RedisFlush::flush_redis';
2729

2830
/**
2931
* @param Context $context
30-
* @param Pool $cacheFrontendPool
32+
* @param RedisCacheFlushService $redisCacheFlushService
3133
*/
3234
public function __construct(
3335
Context $context,
34-
Pool $cacheFrontendPool
36+
private readonly RedisCacheFlushService $redisCacheFlushService
3537
) {
3638
parent::__construct($context);
37-
$this->cacheFrontendPool = $cacheFrontendPool;
3839
}
3940

4041
/**
41-
* Flush all Redis data
42+
* Execute Redis flush action
4243
*
4344
* @return Redirect
4445
*/
45-
public function execute()
46+
public function execute(): Redirect
4647
{
47-
try {
48-
$flushed = false;
49-
50-
/** @var \Magento\Framework\Cache\FrontendInterface $cacheFrontend */
51-
foreach ($this->cacheFrontendPool as $cacheFrontend) {
52-
$backend = $cacheFrontend->getBackend();
48+
/** @var Redirect $resultRedirect */
49+
$resultRedirect = $this->resultRedirectFactory->create();
50+
$resultRedirect->setPath('adminhtml/cache/index');
5351

54-
// Use reflection to access the protected _redis property
55-
$reflection = new \ReflectionClass($backend);
56-
$redisProperty = $reflection->getProperty('_redis');
57-
$redisProperty->setAccessible(true);
58-
$redis = $redisProperty->getValue($backend);
52+
// Validate form key for CSRF protection
53+
if (!$this->_formKeyValidator->validate($this->getRequest())) {
54+
$this->messageManager->addErrorMessage(
55+
__('Invalid form key. Please refresh the page and try again.')
56+
);
57+
return $resultRedirect;
58+
}
5959

60-
if ($redis) {
61-
$redis->flushAll();
62-
$flushed = true;
63-
break;
64-
}
65-
}
60+
try {
61+
// Execute flush operation
62+
$result = $this->redisCacheFlushService->flushAll();
6663

67-
if ($flushed) {
64+
if ($result->success) {
65+
// Success message with statistics
6866
$this->messageManager->addSuccessMessage(
69-
__('Redis cache has been flushed successfully.')
67+
__(
68+
'Redis cache flushed successfully. %1 keys deleted, %2 MB freed in %3s.',
69+
number_format($result->keysDeleted),
70+
number_format($result->getMemoryFreedMb(), 2),
71+
$result->getExecutionTimeSeconds()
72+
)
73+
);
74+
75+
// Add detailed info message
76+
$this->messageManager->addNoticeMessage(
77+
__(
78+
'Memory before: %1 MB | Memory after: %2 MB | Freed: %3%',
79+
number_format($result->memoryBeforeMb, 2),
80+
number_format($result->memoryAfterMb, 2),
81+
number_format($result->getMemoryFreedPercentage(), 1)
82+
)
7083
);
7184
} else {
72-
$this->messageManager->addWarningMessage(
73-
__('Redis backend not found. Please ensure Redis is configured as your cache backend.')
85+
// Failure message
86+
$this->messageManager->addErrorMessage(
87+
__(
88+
'Failed to flush Redis cache: %1',
89+
$result->errorMessage ?? 'Unknown error'
90+
)
7491
);
7592
}
7693
} catch (\Exception $e) {
77-
$this->messageManager->addErrorMessage(
78-
__('An error occurred while flushing Redis: %1', $e->getMessage())
94+
// Catch any unexpected exceptions
95+
$this->messageManager->addExceptionMessage(
96+
$e,
97+
__('An unexpected error occurred while flushing Redis cache: %1', $e->getMessage())
7998
);
8099
}
81100

82-
/** @var Redirect $resultRedirect */
83-
$resultRedirect = $this->resultRedirectFactory->create();
84-
return $resultRedirect->setPath('adminhtml/cache/index');
101+
return $resultRedirect;
85102
}
86103
}

0 commit comments

Comments
 (0)