Skip to content

Commit

Permalink
Merge pull request #4 from nextapps-be/bugfixes-and-changes-for-v2
Browse files Browse the repository at this point in the history
Bugfixes and changes for v2
  • Loading branch information
gdebrauwer authored Feb 3, 2021
2 parents cfab14b + 98113aa commit a9debb7
Show file tree
Hide file tree
Showing 5 changed files with 269 additions and 143 deletions.
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ use NextApps\UniqueCodes\UniqueCodes;

// Generate 100 unique codes for numbers 1 to 100
$codes = (new UniqueCodes())
->setPrime(184259)
->setObfuscatingPrime(9006077)
->setMaxPrime(7230323)
->setCharacters('LQJCKZM4WDPT69S7XRGANY23VBH58F1')
->setCharacters('LQJCKZMWDPTSXRGANYVBHF')
->setLength(6)
->generate(1, 100);

// Result: H2ZMLL (1), YST6LL (2), XMRGLL (3), ... , 9ZCDKL (100)
// Result: LWXNHJ (1), LACSVK (2), QLNMNM (3), ... , LYMJHL (100), QJVBVJ (101), LQXGQC (102), ... , LJQ5DJ (7230320), LC17CS (7230321), LZ8J8H (7230322)
```

## Installation
Expand All @@ -28,6 +28,7 @@ You can install the package via composer:
```bash
composer require nextapps/unique-codes
```
> Do not use v1 of this package, as it contains bugs. If you currently use v1, you should upgrade to v2 (Read the upgrading guide!).
## Usage

Expand All @@ -51,19 +52,19 @@ If a lot of codes need to be generated at the same time, it can cause a lot of m
### Setters

Certain setters are required to generate unique codes:
* `setPrime()`
* `setObfuscatingPrime()`
* `setMaxPrime()`
* `setCharacters()`
* `setLength()`

#### setPrime($number)
#### setObfuscatingPrime($number)

This prime number is used to obfuscate a number between 1 and the max prime number.
This prime number is used to obfuscate a number between 1 and the max prime number. This prime number must be bigger than your max prime number (which you provide to the `setMaxPrime` method).

#### setMaxPrime($number)

The max prime determines the maximum amount of unique codes you can generate. If you provide `101`, then you can generate codes from 1 to 100.
This prime number must be bigger than the prime number you provide to the `setPrime` method.
This prime number must be smaller than the prime number you provide to the `setObfuscatingPrime` method.

#### setCharacters($string)

Expand Down Expand Up @@ -95,10 +96,10 @@ The code generation consists of 2 steps:

If you encode sequential numbers, you will still see that the encoded strings are sequential. To remove the sequential nature, we use 'modular multiplicative inverse'.

You define the upper limit of your range. This determines the maximum number you can obfuscate. Then every number is mapped to a unique obfuscated number between 1 and the upper limit. You multiply the input number with a random prime number, and you determine the remainder of the division of your multiplied input number by the upper limit of the range.
You define the upper limit of your range. This determines the maximum number you can obfuscate. Then every number is mapped to a unique obfuscated number between 1 and the upper limit. You multiply the input number with a random (larger) prime number, and you determine the remainder of the division of your multiplied input number by the upper limit of the range.

```
$obfuscatedNumber = ($inputNumber * $primeNumber) % $maxPrimeNumber
$obfuscatedNumber = ($inputNumber * $obfuscatingPrimeNumber) % $maxPrimeNumber
```

#### Encoding the obfuscated number
Expand Down
7 changes: 7 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Upgrading

## From v1 to v2

- The `setPrime` method has been renamed to `setObfuscatingPrime'`. The number you provide to this method should also be larger than the prime number you provide to the `setMaxPrime` number.
- You should change the code length you use (if you can not regenerate all the codes you created in v1). If you generate code using a number in v2 you will not receive the same code as in v1. This means there could be collisions between your v1 and v2 codes. Changing the code length of your v2 codes will prevent such collisions.
- The encoding mechanism in v1 could sometimes generate duplicates because it tried to prevent duplicate characters in the encoded result. This logic has been removed, which also means that codes will now contain duplicate characters. If you don't want that, you could always just skip the numbers that are converted in a unique code with duplicate characters.
3 changes: 3 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@
<log type="coverage-text" target="build/coverage.txt"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
<php>
<ini name="memory_limit" value="-1" />
</php>
</phpunit>
26 changes: 10 additions & 16 deletions src/UniqueCodes.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class UniqueCodes
*
* @var int
*/
protected $prime;
protected $obfuscatingPrime;

/**
* The prime number that is one larger than the maximum number that can be converted to a code.
Expand Down Expand Up @@ -63,15 +63,15 @@ class UniqueCodes
protected $length;

/**
* Set the prime number.
* Set the obfuscating prime number.
*
* @param int $prime
*
* @return self
*/
public function setPrime(int $prime)
public function setObfuscatingPrime(int $obfuscatingPrime)
{
$this->prime = $prime;
$this->obfuscatingPrime = $obfuscatingPrime;

return $this;
}
Expand Down Expand Up @@ -208,7 +208,7 @@ public function generate(int $start, int $end = null, bool $toArray = false)
*/
protected function obfuscateNumber(int $number)
{
return ($number * $this->prime) % $this->maxPrime;
return ($number * $this->obfuscatingPrime) % $this->maxPrime;
}

/**
Expand All @@ -226,7 +226,7 @@ protected function encodeNumber(int $number)
for ($i = 0; $i < $this->length; $i++) {
$digit = $number % strlen($characters);

$string .= $characters[$digit];
$string = $characters[$digit].$string;

$number = $number / strlen($characters);
}
Expand Down Expand Up @@ -274,8 +274,8 @@ protected function constructCode($string)
*/
protected function validateInput(int $start, int $end = null)
{
if (empty($this->prime)) {
throw new RuntimeException('Prime number must be specified');
if (empty($this->obfuscatingPrime)) {
throw new RuntimeException('Obfuscating prime number must be specified');
}

if (empty($this->maxPrime)) {
Expand All @@ -290,14 +290,8 @@ protected function validateInput(int $start, int $end = null)
throw new RuntimeException('Length must be specified');
}

if ($this->prime >= $this->maxPrime) {
throw new RuntimeException('Prime number must be smaller than the max prime number');
}

if (strlen($this->characters) <= $this->length) {
throw new RuntimeException(
'The size of the character list must be bigger or equal to the length of the code'
);
if ($this->obfuscatingPrime <= $this->maxPrime) {
throw new RuntimeException('Obfuscating prime number must be larger than the max prime number');
}

if (count(array_unique(str_split($this->characters))) !== strlen($this->characters)) {
Expand Down
Loading

0 comments on commit a9debb7

Please sign in to comment.