1717use InvalidArgumentException ;
1818use RuntimeException ;
1919
20+ use function strlen ;
21+ use function ord ;
22+ use function in_array ;
23+ use function count ;
24+ use function array_key_exists ;
25+
2026class Sqids implements SqidsInterface
2127{
2228 final public const DEFAULT_ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ' ;
@@ -606,16 +612,12 @@ public function __construct(
606612 throw new InvalidArgumentException ('Alphabet length must be at least 3 ' );
607613 }
608614
609- if (count ( array_unique ( str_split ( $ alphabet ))) !== strlen ( $ alphabet )) {
615+ if (preg_match ( ' /(.).*\1/ ' , $ alphabet )) {
610616 throw new InvalidArgumentException ('Alphabet must contain unique characters ' );
611617 }
612618
613619 $ minLengthLimit = 255 ;
614- if (
615- !is_int ($ minLength ) ||
616- $ minLength < 0 ||
617- $ minLength > $ minLengthLimit
618- ) {
620+ if ($ minLength < 0 || $ minLength > $ minLengthLimit ) {
619621 throw new InvalidArgumentException (
620622 'Minimum length has to be between 0 and ' . $ minLengthLimit ,
621623 );
@@ -635,7 +637,6 @@ public function __construct(
635637 }
636638
637639 $ this ->alphabet = $ this ->shuffle ($ alphabet );
638- $ this ->minLength = $ minLength ;
639640 $ this ->blocklist = $ filteredBlocklist ;
640641 }
641642
@@ -655,11 +656,12 @@ public function encode(array $numbers): string
655656 return '' ;
656657 }
657658
658- $ inRangeNumbers = array_filter ($ numbers , fn ($ n ) => $ n >= 0 && $ n <= self ::maxValue ());
659- if (count ($ inRangeNumbers ) != count ($ numbers )) {
660- throw new InvalidArgumentException (
661- 'Encoding supports numbers between 0 and ' . self ::maxValue (),
662- );
659+ foreach ($ numbers as $ n ) {
660+ if ($ n < 0 || $ n > self ::maxValue ()) {
661+ throw new InvalidArgumentException (
662+ 'Encoding supports numbers between 0 and ' . self ::maxValue (),
663+ );
664+ }
663665 }
664666
665667 return $ this ->encodeNumbers ($ numbers );
@@ -688,26 +690,24 @@ protected function encodeNumbers(array $numbers, int $increment = 0): string
688690 $ alphabet = substr ($ this ->alphabet , $ offset ) . substr ($ this ->alphabet , 0 , $ offset );
689691 $ prefix = $ alphabet [0 ];
690692 $ alphabet = strrev ($ alphabet );
691- $ ret = [ $ prefix] ;
693+ $ id = $ prefix ;
692694
693695 for ($ i = 0 ; $ i != count ($ numbers ); $ i ++) {
694696 $ num = $ numbers [$ i ];
695697
696- $ ret [] = $ this ->toId ($ num , substr ($ alphabet , 1 ));
698+ $ id . = $ this ->toId ($ num , substr ($ alphabet , 1 ));
697699 if ($ i < count ($ numbers ) - 1 ) {
698- $ ret [] = $ alphabet [0 ];
700+ $ id . = $ alphabet [0 ];
699701 $ alphabet = $ this ->shuffle ($ alphabet );
700702 }
701703 }
702704
703- $ id = implode ('' , $ ret );
704-
705705 if ($ this ->minLength > strlen ($ id )) {
706706 $ id .= $ alphabet [0 ];
707707
708708 while ($ this ->minLength - strlen ($ id ) > 0 ) {
709709 $ alphabet = $ this ->shuffle ($ alphabet );
710- $ id .= substr ($ alphabet , 0 , min ($ this ->minLength - strlen ($ id ), strlen ($ alphabet )));
710+ $ id .= substr ($ alphabet , 0 , min ($ this ->minLength - strlen ($ id ), strlen ($ this -> alphabet )));
711711 }
712712 }
713713
@@ -736,11 +736,8 @@ public function decode(string $id): array
736736 return $ ret ;
737737 }
738738
739- $ alphabetChars = str_split ($ this ->alphabet );
740- foreach (str_split ($ id ) as $ c ) {
741- if (!in_array ($ c , $ alphabetChars )) {
742- return $ ret ;
743- }
739+ if (!preg_match ('/^[ ' . preg_quote ($ this ->alphabet , '/ ' ) . ']+$/ ' , $ id )) {
740+ return $ ret ;
744741 }
745742
746743 $ prefix = $ id [0 ];
@@ -753,13 +750,13 @@ public function decode(string $id): array
753750 $ separator = $ alphabet [0 ];
754751
755752 $ chunks = explode ($ separator , $ id , 2 );
756- if (! empty ( $ chunks )) {
753+ if (array_key_exists ( 0 , $ chunks )) {
757754 if ($ chunks [0 ] == '' ) {
758755 return $ ret ;
759756 }
760757
761758 $ ret [] = $ this ->toNumber ($ chunks [0 ], substr ($ alphabet , 1 ));
762- if (count ( $ chunks ) > 1 ) {
759+ if (array_key_exists ( 1 , $ chunks )) {
763760 $ alphabet = $ this ->shuffle ($ alphabet );
764761 }
765762 }
@@ -772,40 +769,36 @@ public function decode(string $id): array
772769
773770 protected function shuffle (string $ alphabet ): string
774771 {
775- $ chars = str_split ($ alphabet );
776-
777- for ($ i = 0 , $ j = count ($ chars ) - 1 ; $ j > 0 ; $ i ++, $ j --) {
778- $ r = ($ i * $ j + ord ($ chars [$ i ]) + ord ($ chars [$ j ])) % count ($ chars );
779- [$ chars [$ i ], $ chars [$ r ]] = [$ chars [$ r ], $ chars [$ i ]];
772+ for ($ i = 0 , $ j = strlen ($ alphabet ) - 1 ; $ j > 0 ; $ i ++, $ j --) {
773+ $ r = ($ i * $ j + ord ($ alphabet [$ i ]) + ord ($ alphabet [$ j ])) % strlen ($ alphabet );
774+ [$ alphabet [$ i ], $ alphabet [$ r ]] = [$ alphabet [$ r ], $ alphabet [$ i ]];
780775 }
781776
782- return implode ( '' , $ chars ) ;
777+ return $ alphabet ;
783778 }
784779
785780 protected function toId (int $ num , string $ alphabet ): string
786781 {
787- $ id = [];
788- $ chars = str_split ($ alphabet );
789-
790- $ result = $ num ;
791-
782+ $ id = '' ;
792783 do {
793- array_unshift ( $ id, $ chars [$ this ->math ->intval ($ this ->math ->mod ($ result , count ( $ chars )))]) ;
794- $ result = $ this ->math ->divide ($ result , count ( $ chars ));
795- } while ($ this ->math ->greaterThan ($ result , 0 ));
784+ $ id = $ alphabet [$ this ->math ->intval ($ this ->math ->mod ($ num , strlen ( $ alphabet )))] . $ id ;
785+ $ num = $ this ->math ->divide ($ num , strlen ( $ alphabet ));
786+ } while ($ this ->math ->greaterThan ($ num , 0 ));
796787
797- return implode ( '' , $ id) ;
788+ return $ id ;
798789 }
799790
800791 protected function toNumber (string $ id , string $ alphabet ): int
801792 {
802- $ chars = str_split ($ alphabet );
803- return $ this ->math ->intval (array_reduce (str_split ($ id ), function ($ a , $ v ) use ($ chars ) {
804- $ number = $ this ->math ->multiply ($ a , count ($ chars ));
805- $ number = $ this ->math ->add ($ number , array_search ($ v , $ chars ));
793+ $ number = 0 ;
794+ for ($ i = 0 ; $ i < strlen ($ id ); $ i ++) {
795+ $ number = $ this ->math ->add (
796+ $ this ->math ->multiply ($ number , strlen ($ alphabet )),
797+ strpos ($ alphabet , $ id [$ i ]),
798+ );
799+ }
806800
807- return $ number ;
808- }, 0 ));
801+ return $ this ->math ->intval ($ number );
809802 }
810803
811804 protected function isBlockedId (string $ id ): bool
0 commit comments