From ae8dfde69d5170fd9495f0075a06510ae9f2bb50 Mon Sep 17 00:00:00 2001 From: Djamil Legato Date: Thu, 23 Sep 2021 21:40:21 -0700 Subject: [PATCH] Added true unique `Utils::uniqueId()` / `{{ unique_id() }}`utilities with length, prefix, and suffix support. --- CHANGELOG.md | 1 + .../Common/Twig/Extension/GravExtension.php | 15 +++++++++++++++ system/src/Grav/Common/Utils.php | 17 +++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a57dbdce..d35404b10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ 1. [](#new) * Added method `Pages::referrerRoute()` to get the referrer route and language + * Added true unique `Utils::uniqueId()` / `{{ unique_id() }}`utilities with length, prefix, and suffix support. 2. [](#improved) * Replaced GPL `SVG-Sanitizer` with MIT licensed `DOM-Sanitizer` * `Uri::referrer()` now accepts third parameter, if set to `true`, it returns route without base or language code [#3411](https://github.com/getgrav/grav/issues/3411) diff --git a/system/src/Grav/Common/Twig/Extension/GravExtension.php b/system/src/Grav/Common/Twig/Extension/GravExtension.php index d21c8b188..94e735d68 100644 --- a/system/src/Grav/Common/Twig/Extension/GravExtension.php +++ b/system/src/Grav/Common/Twig/Extension/GravExtension.php @@ -217,6 +217,7 @@ class GravExtension extends AbstractExtension implements GlobalsInterface new TwigFunction('cron', [$this, 'cronFunc']), new TwigFunction('svg_image', [$this, 'svgImageFunction']), new TwigFunction('xss', [$this, 'xssFunc']), + new TwigFunction('unique_id', [$this, 'uniqueId']), // Translations new TwigFunction('t', [$this, 'translate'], ['needs_environment' => true]), @@ -654,6 +655,20 @@ class GravExtension extends AbstractExtension implements GlobalsInterface return implode(', ', $results_parts); } + /** + * Generates a random string with configurable length, prefix and suffix. + * Unlike the built-in `uniqid()`, this string is non-conflicting and safe + * + * @param int $length + * @param array $options + * @return string + * @throws \Exception + */ + public function uniqueId(int $length = 9, array $options = ['prefix' => '', 'suffix' => '']): string + { + return Utils::uniqueId($length, $options); + } + /** * @param string $string * @return string diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php index edc093e4f..34b6e0f13 100644 --- a/system/src/Grav/Common/Utils.php +++ b/system/src/Grav/Common/Utils.php @@ -628,6 +628,23 @@ abstract class Utils return substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, $length); } + /** + * Generates a random string with configurable length, prefix and suffix. + * Unlike the built-in `uniqid()`, this string is non-conflicting and safe + * + * @param int $length + * @param array $options + * @return string + * @throws Exception + */ + public static function uniqueId(int $length = 13, array $options = []): string + { + $options = array_merge(['prefix' => '', 'suffix' => ''], $options); + $bytes = random_bytes(ceil($length / 2)); + + return $options['prefix'] . substr(bin2hex($bytes), 0, $length) . $options['suffix']; + } + /** * Provides the ability to download a file to the browser *