diff --git a/README.md b/README.md index 892a75c..b1bdf95 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ If you think this package helped you in any way, you can sponsor me on GitHub! - [Create multiple invite codes](#create-multiple-invite-codes) - [Redeeming invite codes](#redeeming-invite-codes) - [Redeeming invite codes without dispatching events](#redeeming-invite-codes-without-dispatching-events) +- [Customizing how invite codes are generated](#customizing-how-invite-codes-are-generated) +- [Extending the `Invite` model](#extending-the-invite-model) - [Handling invite codes exceptions](#handling-invite-codes-exceptions) - [Using artisan commands](#using-artisan-commands) - [Tests](#tests) @@ -228,6 +230,22 @@ you can use the `withoutEvents()` method: \Junges\InviteCodes\Facades\InviteCodes::withoutEvents()->redeem('YOUR-INVITE-CODE'); ``` +# Customizing how invite codes are generated +By default, this package generates a random 16 characters string that. Sometimes, you may want to customize how your invitation code is generated, +for adding a prefix to the invitation code or anything you need. + +If you need to customize how your invite codes are generated, you can add a call to the InviteCodes facade `createInviteCodesusing` method, in your service provider: + +```php +\Junges\InviteCodes\Facades\InviteCodes::createInviteCodeUsing(static function () { + return 'THIS-IS-MY-INVITE-'.\Illuminate\Support\Str::random(); +}); +``` + +From now on, all of your invites will have the `THIS-IS-MY-INVITE-` prefix. + +Also, the package itself will handle duplicate invites, so you don't need to take care of that yourself. + # Extending the `Invite` model The `\Junges\InviteCodes\Models\Invite` is fully extendable and replaceable. You can extend or create a new model to be used instead of the default one, and the only thing you need to do is implement the `\Junges\InviteCodes\Contracts\InviteContract` interface, which contains some required methods for this package to work. diff --git a/src/Facades/InviteCodes.php b/src/Facades/InviteCodes.php index fe06877..9e3614c 100644 --- a/src/Facades/InviteCodes.php +++ b/src/Facades/InviteCodes.php @@ -5,23 +5,23 @@ use Illuminate\Support\Collection; use Illuminate\Support\Facades\Facade; use Junges\InviteCodes\Contracts\InviteCodesFactory; +use Junges\InviteCodes\Contracts\InviteContract; use Junges\InviteCodes\Models\Invite; /** - * Class Factory. - * - * @method static $this withoutEvents() Will dispatch no events. - * @method static $this redeem(string $code) Redeem an invite code. - * @method static $this create() Create an invite code. - * @method static $this maxUsages(int $usages = null) Set the max allowed usages for invite codes. - * @method static $this restrictUsageTo(string $email) Set the user who can use the invite code. - * @method static $this expiresAt($date) Set the invite code expiration date. - * @method static $this expiresIn(int $days) Set the invite code expiration date to $days from now. + * @method static InviteCodesFactory withoutEvents() Will dispatch no events. + * @method static InviteContract redeem(string $code) Redeem an invite code. + * @method static InviteCodesFactory create() Create an invite code. + * @method static InviteCodesFactory maxUsages(int $usages = null) Set the max allowed usages for invite codes. + * @method static InviteCodesFactory restrictUsageTo(string $email) Set the user who can use the invite code. + * @method static InviteCodesFactory expiresAt($date) Set the invite code expiration date. + * @method static InviteCodesFactory expiresIn(int $days) Set the invite code expiration date to $days from now. * @method static Invite save() Save the invite code. - * @method static Collection make(int $quantity) Save $quantity invite codes. + * @method static Collection make(int $quantity) Save $quantity invite codes. * @method static void macro($name, $macro) * @method static bool hasMacro($name) - * @method static $this canBeUsedOnce() + * @method static void createInviteCodeUsing(?callable $callable = null) + * @method static InviteCodesFactory canBeUsedOnce() */ class InviteCodes extends Facade { diff --git a/src/Factory.php b/src/Factory.php index 1968213..ee4d6db 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -32,6 +32,12 @@ class Factory implements InviteCodesFactory protected ?string $to = null; protected ?CarbonInterface $expires_at; protected bool $dispatch_events = true; + protected static ?\Closure $createInviteCodeUsing = null; + + public static function createInviteCodeUsing(callable $callable = null): void + { + self::$createInviteCodeUsing = $callable !== null ? $callable(...) : null; + } /** If used, no events will be dispatched. */ public function withoutEvents(): self @@ -54,7 +60,7 @@ public function redeem(string $code): Invite $model = app(config('invite-codes.models.invite_model', Invite::class)); /** @var Invite|null $invite */ - $invite = $model->where('code', Str::upper($code))->first(); + $invite = $model->where('code', $code)->first(); if (! $invite instanceof InviteContract || ! $this->inviteCanBeRedeemed($invite)) { throw new InvalidInviteCodeException('Your invite code is invalid'); @@ -139,7 +145,7 @@ public function save(): Invite $model = app(config('invite-codes.models.invite_model', Invite::class)); do { - $code = Str::upper(Str::random(16)); + $code = $this->createInvitationCode(); } while ($model->where('code', $code)->first() instanceof $model); return $model->create([ @@ -209,4 +215,13 @@ private function shouldDispatchEvents(): bool { return $this->dispatch_events; } + + private function createInvitationCode(): string + { + if (self::$createInviteCodeUsing instanceof \Closure) { + return call_user_func(self::$createInviteCodeUsing); + } + + return Str::upper(Str::random(16)); + } } diff --git a/tests/FactoryTest.php b/tests/FactoryTest.php index 22722f0..d7e7b35 100644 --- a/tests/FactoryTest.php +++ b/tests/FactoryTest.php @@ -3,9 +3,11 @@ namespace Junges\InviteCodes\Tests; use Illuminate\Support\Facades\Event; +use Illuminate\Support\Str; use Junges\InviteCodes\Contracts\InviteContract; use Junges\InviteCodes\Events\InviteRedeemedEvent; use Junges\InviteCodes\Facades\InviteCodes; +use Junges\InviteCodes\Models\Invite; class FactoryTest extends TestCase { @@ -42,4 +44,17 @@ public function test_macro(): void $this->assertInstanceOf(InviteContract::class, $invite); $this->assertTrue($invite->usageRestrictedToEmail('test@example.com')); } + + public function test_it_can_customize_how_invite_code_is_created(): void + { + InviteCodes::createInviteCodeUsing(static function () { + return 'PREFIX-12345'; + }); + + $invite = InviteCodes::create()->save(); + + $this->assertSame('PREFIX-12345', $invite->code); + + InviteCodes::createInviteCodeUsing(null); + } }