Skip to content

Commit 16169dc

Browse files
committed
feat: implement unique handle generation and validation for icon sets
1 parent 5d29ac1 commit 16169dc

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

src/controllers/IconSetsController.php

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ public function actionSave(): ?Response
190190

191191
// Populate model
192192
$iconSet->name = $request->getBodyParam('name');
193-
$iconSet->handle = $request->getBodyParam('handle');
193+
$iconSet->handle = $this->_generateUniqueHandle($request->getBodyParam('handle'), $iconSetId);
194194
$iconSet->type = $request->getBodyParam('type');
195195
$iconSet->enabled = (bool)$request->getBodyParam('enabled');
196196

@@ -619,4 +619,52 @@ public function actionDeleteBackup(): Response
619619

620620
return $this->redirectToPostedUrl();
621621
}
622+
623+
/**
624+
* Generate a unique handle by appending a number if needed
625+
*
626+
* @param string $handle The desired handle
627+
* @param int|null $currentIconSetId The current icon set ID (to exclude from duplicate check)
628+
* @return string A unique handle
629+
*/
630+
private function _generateUniqueHandle(string $handle, ?int $currentIconSetId = null): string
631+
{
632+
// Check if handle already exists
633+
$query = (new \craft\db\Query())
634+
->from('{{%iconmanager_iconsets}}')
635+
->where(['handle' => $handle]);
636+
637+
// Exclude current icon set if editing
638+
if ($currentIconSetId) {
639+
$query->andWhere(['not', ['id' => $currentIconSetId]]);
640+
}
641+
642+
// If handle is unique, return as-is
643+
if (!$query->exists()) {
644+
return $handle;
645+
}
646+
647+
// Handle is taken, generate unique one by appending number
648+
$baseHandle = $handle;
649+
$i = 1;
650+
651+
// Keep incrementing until we find a unique handle
652+
while (true) {
653+
$newHandle = $baseHandle . $i;
654+
655+
$query = (new \craft\db\Query())
656+
->from('{{%iconmanager_iconsets}}')
657+
->where(['handle' => $newHandle]);
658+
659+
if ($currentIconSetId) {
660+
$query->andWhere(['not', ['id' => $currentIconSetId]]);
661+
}
662+
663+
if (!$query->exists()) {
664+
return $newHandle;
665+
}
666+
667+
$i++;
668+
}
669+
}
622670
}

src/models/IconSet.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,36 @@ protected function defineRules(): array
8181
[['name', 'handle', 'type'], 'required'],
8282
[['name', 'handle'], 'string', 'max' => 255],
8383
[['handle'], 'match', 'pattern' => '/^[a-zA-Z][a-zA-Z0-9_]*$/'],
84+
[['handle'], 'validateUniqueHandle'],
8485
[['type'], 'in', 'range' => ['svg-folder', 'svg-sprite', 'font-awesome', 'material-icons', 'web-font', 'custom']],
8586
[['enabled'], 'boolean'],
8687
[['sortOrder'], 'integer'],
8788
[['settings'], 'safe'],
8889
];
8990
}
9091

92+
/**
93+
* Validate that the handle is unique
94+
*/
95+
public function validateUniqueHandle($attribute)
96+
{
97+
$handle = $this->$attribute;
98+
99+
// Build query to check for existing handle
100+
$query = (new \craft\db\Query())
101+
->from('{{%iconmanager_iconsets}}')
102+
->where(['handle' => $handle]);
103+
104+
// Exclude current record if editing
105+
if ($this->id) {
106+
$query->andWhere(['not', ['id' => $this->id]]);
107+
}
108+
109+
if ($query->exists()) {
110+
$this->addError($attribute, Craft::t('icon-manager', 'Handle "{handle}" is already in use.', ['handle' => $handle]));
111+
}
112+
}
113+
91114
/**
92115
* Get the display name for this icon set type
93116
*/

0 commit comments

Comments
 (0)