-
-
Notifications
You must be signed in to change notification settings - Fork 449
Add CLI script for managing the admin notifications with advanced filtering #4973
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
addison74
wants to merge
7
commits into
OpenMage:main
Choose a base branch
from
addison74:maintenance/admin-notification-cleanup
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
c2b24e1
Add CLI script for cleaning admin notifications with advanced filtering
addison74 e1762d9
Implementing Copilot comments
addison74 4059708
Merge branch 'main' into maintenance/admin-notification-cleanup
addison74 3a087c8
Fixes Rector issues
addison74 01c3ccf
Merge remote-tracking branch 'origin/maintenance/admin-notification-c…
addison74 939bf0b
Replacing a nested ternary with clear conditional statements for read…
addison74 bcdd954
Renamed the file name for clarity and consistency with the other shel…
addison74 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
<?php | ||
|
||
/** | ||
* @copyright For copyright and license information, read the COPYING.txt file. | ||
* @link /COPYING.txt | ||
* @license Open Software License (OSL 3.0) | ||
* @package Mage_Shell | ||
*/ | ||
|
||
require_once 'abstract.php'; | ||
|
||
/** | ||
* Magento Admin Notification Cleaner Shell Script | ||
* | ||
* Provides CLI functionality to clean, preview, and delete admin notifications. | ||
* Supports filtering by date, read status, severity, and a dry-run mode with table output. | ||
* Severity is displayed with its textual meaning (Critical, Major, Minor, Notice). | ||
* IMPORTANT: For CLI arguments, use space (not =) between option and value, e.g. --before 2024-01-01 | ||
* | ||
* By default, unread notifications are protected and will NOT be deleted unless | ||
* --include-unread is explicitly specified. | ||
* If --all is used without --include-unread, the script aborts with an error. | ||
* | ||
* @package Mage_Shell | ||
*/ | ||
class Mage_Shell_CleanAdminNotifications extends Mage_Shell_Abstract | ||
{ | ||
/** | ||
* Severity mapping based on OpenMage/Magento LTS conventions. | ||
* | ||
* @var array<int, string> | ||
*/ | ||
protected $severityMap = [ | ||
0 => 'Notice', | ||
1 => 'Critical', | ||
2 => 'Major', | ||
3 => 'Minor', | ||
]; | ||
|
||
/** | ||
* Run the shell logic for cleaning admin notifications. | ||
* | ||
* Supports: | ||
* --before Delete notifications before a specific date (format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS) | ||
* --only-read Delete only notifications marked as read | ||
* --include-unread Allows deletion of unread notifications (use with caution!) | ||
* --severity-0 Only notifications with severity Notice | ||
* --severity-1 Only notifications with severity Critical | ||
* --severity-2 Only notifications with severity Major | ||
* --severity-3 Only notifications with severity Minor | ||
* --all Delete all notifications (requires --include-unread for unread notifications) | ||
* --dry-run Show notifications that would be deleted (table output) | ||
* help Display usage information | ||
* | ||
* Example: php shell/cleanAdminNotifications.php --before 2024-01-01 --severity-0 --dry-run | ||
*/ | ||
public function run(): void | ||
{ | ||
// Read CLI arguments, support fallback for direct _args usage | ||
$before = $this->getArg('before'); | ||
if (!$before && isset($this->_args['before'])) { | ||
$before = $this->_args['before']; | ||
} | ||
$onlyRead = $this->getArg('only-read') ?: (isset($this->_args['only-read']) ? $this->_args['only-read'] : null); | ||
$includeUnread = $this->getArg('include-unread') ?: (isset($this->_args['include-unread']) ? $this->_args['include-unread'] : null); | ||
$all = $this->getArg('all') ?: (isset($this->_args['all']) ? $this->_args['all'] : null); | ||
$dryRun = $this->getArg('dry-run') ?: (isset($this->_args['dry-run']) ? $this->_args['dry-run'] : null); | ||
|
||
// Parse severity options | ||
$severities = []; | ||
foreach ([0, 1, 2, 3] as $sev) { | ||
if ($this->getArg('severity-' . $sev) || isset($this->_args['severity-' . $sev])) { | ||
$severities[] = $sev; | ||
} | ||
} | ||
|
||
$conn = Mage::getSingleton('core/resource')->getConnection('core_write'); | ||
$table = Mage::getSingleton('core/resource')->getTableName('adminnotification/inbox'); | ||
|
||
// PROTECTION: By default, protect unread notifications unless --include-unread is present | ||
$protectUnread = !$includeUnread; | ||
|
||
// If --all is used and --include-unread is not present, abort with error and count | ||
if ($all && $protectUnread) { | ||
// Count unread notifications | ||
$countUnread = $conn->fetchOne("SELECT COUNT(*) FROM $table WHERE is_read = 0"); | ||
echo "ERROR: Cannot delete ALL notifications unless --include-unread is specified!\n"; | ||
if ($countUnread > 0) { | ||
echo "There are $countUnread unread notifications present in the database. Unread notifications are protected by default.\n"; | ||
} else { | ||
echo "Unread notifications are protected by default.\n"; | ||
} | ||
echo "To delete all notifications, including unread, use:\n"; | ||
echo " php shell/cleanAdminNotifications.php --all --include-unread\n"; | ||
return; | ||
} | ||
|
||
if ($dryRun) { | ||
// Build SELECT for dry-run | ||
$select = $conn->select() | ||
->from($table, [ | ||
'notification_id', | ||
'title', | ||
'description', | ||
'date_added', | ||
'is_read', | ||
'severity', | ||
]); | ||
if (!$all) { | ||
if ($before) { | ||
$select->where('date_added < ?', $before); | ||
} | ||
// Apply unread protection unless include-unread is present | ||
if ($protectUnread || $onlyRead) { | ||
$select->where('is_read = ?', 1); | ||
} | ||
if (!empty($severities)) { | ||
$select->where('severity IN (?)', $severities); | ||
} | ||
} | ||
$select->limit(50); | ||
|
||
$rows = $conn->fetchAll($select); | ||
|
||
if (count($rows)) { | ||
// Print table header | ||
printf("%-5s | %-40s | %-40s | %-20s | %-6s | %-8s\n", 'ID', 'Title', 'Description', 'Date Added', 'Read', 'Severity'); | ||
printf("%s\n", str_repeat('-', 140)); | ||
addison74 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
foreach ($rows as $row) { | ||
// Truncate description for display | ||
$desc = isset($row['description']) ? substr((string) $row['description'], 0, 40) : ''; | ||
$severityLabel = isset($this->severityMap[(int) $row['severity']]) ? $this->severityMap[(int) $row['severity']] : (string) $row['severity']; | ||
printf( | ||
"%-5d | %-40s | %-40s | %-20s | %-6s | %-8s\n", | ||
(int) $row['notification_id'], | ||
substr((string) $row['title'], 0, 40), | ||
$desc, | ||
(string) $row['date_added'], | ||
((int) $row['is_read'] === 1 ? 'Yes' : 'No'), | ||
$severityLabel, | ||
); | ||
} | ||
if (count($rows) == 50) { | ||
addison74 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
echo "(Showing first 50 results)\n"; | ||
} | ||
// Show total count of matching notifications | ||
$selectCount = $conn->select()->from($table, 'COUNT(*)'); | ||
if (!$all) { | ||
if ($before) { | ||
$selectCount->where('date_added < ?', $before); | ||
} | ||
if ($protectUnread || $onlyRead) { | ||
$selectCount->where('is_read = ?', 1); | ||
} | ||
if (!empty($severities)) { | ||
$selectCount->where('severity IN (?)', $severities); | ||
} | ||
} | ||
$countTotal = $conn->fetchOne($selectCount); | ||
echo "Total notifications that would be deleted: $countTotal\n"; | ||
} else { | ||
echo "No notifications would be deleted.\n"; | ||
} | ||
} else { | ||
// Prepare WHERE for delete | ||
$where = []; | ||
if (!$all) { | ||
if ($before) { | ||
$where[] = $conn->quoteInto('date_added < ?', $before); | ||
} | ||
// Apply unread protection unless include-unread is present | ||
if ($protectUnread || $onlyRead) { | ||
$where[] = $conn->quoteInto('is_read = ?', 1); | ||
} | ||
if (!empty($severities)) { | ||
$where[] = $conn->quoteInto('severity IN (?)', $severities); | ||
} | ||
} | ||
$whereClause = $all ? '' : (count($where) ? implode(' AND ', $where) : ''); | ||
if ($all) { | ||
addison74 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
$count = $conn->delete($table); // Delete everything (only possible if --include-unread) | ||
} elseif ($whereClause !== '') { | ||
$count = $conn->delete($table, $whereClause); // Delete with filter | ||
} else { | ||
echo "No filters specified, and --all not set. Nothing deleted.\n"; | ||
return; | ||
} | ||
echo "Deleted $count notifications.\n"; | ||
} | ||
} | ||
|
||
/** | ||
* Display usage/help for the CLI script. | ||
*/ | ||
public function usageHelp(): string | ||
{ | ||
return | ||
"Usage: php -f cleanAdminNotifications.php [options]\n" . | ||
" --before YYYY-MM-DD Delete notifications before this date (space, not =)\n" . | ||
" --only-read Delete only notifications marked as read (default: ON unless --include-unread is used)\n" . | ||
" --include-unread Allows deletion of unread notifications (use with caution!)\n" . | ||
" --severity-0 Only notifications with severity Notice\n" . | ||
" --severity-1 Only notifications with severity Critical\n" . | ||
" --severity-2 Only notifications with severity Major\n" . | ||
" --severity-3 Only notifications with severity Minor\n" . | ||
" --all Delete all notifications (requires --include-unread for unread notifications)\n" . | ||
" --dry-run Show what would be deleted, no changes\n" . | ||
" help This help message\n" . | ||
"\nIMPORTANT: For options with values, use space (not =) between option and value!\n" . | ||
"Example: php shell/cleanAdminNotifications.php --before 2024-01-01 --severity-0 --dry-run\n" . | ||
" php shell/cleanAdminNotifications.php --all --include-unread\n"; | ||
} | ||
} | ||
|
||
// Instantiate and run the shell script | ||
$shell = new Mage_Shell_CleanAdminNotifications(); | ||
$shell->run(); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.