Skip to content

Commit

Permalink
refactor: generate unique alphabet for each model
Browse files Browse the repository at this point in the history
  • Loading branch information
bensherred committed Nov 27, 2023
1 parent a25f07d commit 9542f5e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 30 deletions.
13 changes: 0 additions & 13 deletions config/sqids.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,6 @@

return [

/*
|--------------------------------------------------------------------------
| Alphabet
|--------------------------------------------------------------------------
|
| This option controls the default "alphabet" used for generating sqids.
| The characters and numbers listed below will be included. You must
| have at least 3 unique characters or numbers.
|
*/

'alphabet' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',

/*
|--------------------------------------------------------------------------
| Length
Expand Down
10 changes: 1 addition & 9 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

class Config
{
protected static string $defaultAlphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';

protected static int $defaultMinLength = 10;

protected static array $defaultBlacklist = [];
Expand All @@ -20,13 +18,7 @@ class Config

public static function alphabet(): string
{
$alphabet = config(key: 'sqids.alphabet', default: static::$defaultAlphabet);

if (!$alphabet || !is_string(value: $alphabet)) {
return static::$defaultAlphabet;
}

return $alphabet;
return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
}

public static function minLength(): int
Expand Down
2 changes: 1 addition & 1 deletion src/HasSqids.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ public static function keyFromSqid(string $sqid): ?int
return null;
}

return Sqids::decodeId(id: $sqid)[0] ?? null;
return Sqids::decodeId(model: __CLASS__, id: $sqid)[0] ?? null;
}
}
46 changes: 39 additions & 7 deletions src/Sqids.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static function forModel(Model $model): string

$prefix = static::prefixForModel(model: $model::class);
$separator = $prefix ? Config::separator() : null;
$sqid = static::encodeId(id: $id);
$sqid = static::encodeId(model: $model::class, id: $id);

return "{$prefix}{$separator}{$sqid}";
}
Expand Down Expand Up @@ -46,22 +46,54 @@ public static function prefixForModel(string $model): ?string
};
}

public static function encodeId(int $id): string
public static function encodeId(string $model, int $id): string
{
return static::encoder()->encode(numbers: [$id]);
return static::encoder(model: $model)->encode(numbers: [$id]);
}

public static function decodeId(string $id): array
public static function decodeId(string $model, string $id): array
{
return static::encoder()->decode(id: $id);
return static::encoder(model: $model)->decode(id: $id);
}

public static function encoder(): SqidsCore
public static function encoder(string $model): SqidsCore
{
$model = mb_strtolower(string: class_basename($model));

return new SqidsCore(
alphabet: Config::alphabet(),
alphabet: static::alphabetForModel(model: $model),
minLength: Config::minLength(),
blocklist: Config::blacklist(),
);
}

public static function alphabetForModel(string $model): string
{
$alphabet = Config::alphabet();
$modelLength = mb_strlen(string: $model);

if (!$modelLength) {
return Config::alphabet();
}

$alphabetArray = static::multiByteSplit(string: Config::alphabet());
$modelArray = static::multiByteSplit(string: $model);

for ($i = mb_strlen($alphabet) - 1, $v = 0, $p = 0; $i > 0; $i--, $v++) {
$v %= $modelLength;
$p += $int = mb_ord($modelArray[$v], 'UTF-8');
$j = ($int + $v + $p) % $i;

$temp = $alphabetArray[$j];
$alphabetArray[$j] = $alphabetArray[$i];
$alphabetArray[$i] = $temp;
}

return implode(separator: '', array: $alphabetArray);
}

protected static function multiByteSplit(string $string): array
{
return preg_split(pattern: '/(?!^)(?=.)/u', subject: $string) ?: [];
}
}

0 comments on commit 9542f5e

Please sign in to comment.