Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add team support #28

Merged
merged 1 commit into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@
"laravel/pint": "^1.2",
"mockery/mockery": "^1.4.2",
"orchestra/testbench": "^6.5|^7.0|^8.0",
"pestphp/pest": "^1.22",
"pestphp/pest-plugin-laravel": "^1.3",
"pestphp/pest-plugin-parallel": "^1.0|^1.2",
"phpunit/phpunit": "^9.4",
"pestphp/pest": "^1.22|^2.10",
"pestphp/pest-plugin-laravel": "^1.3|^2.2",
"spatie/laravel-ray": "^1.0|^1.31"
},
"autoload": {
Expand Down
31 changes: 31 additions & 0 deletions config/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,35 @@
'model' => \Rawilk\Settings\Models\Setting::class,
],
],

/*
|--------------------------------------------------------------------------
| Teams
|--------------------------------------------------------------------------
|
| When set to true the package implements teams using the `team_foreign_key`.
|
| If you want the migrations to register the `team_foreign_key`, you must
| set this to true before running the migration.
|
| If you already ran the migrations, then you must make a new migration to
| add the `team_foreign_key` column to the settings table, and update the
| unique constraint on the table. See the `add_settings_team_field` migration
| for how to do this.
|
*/
'teams' => false,

/*
|--------------------------------------------------------------------------
| Team Foreign Key
|--------------------------------------------------------------------------
|
| When teams is set to true, our database/eloquent drivers will use this
| column as a team foreign key to scope queries to.
|
| The team id will also be included in a cache key when caching is enabled.
|
*/
'team_foreign_key' => 'team_id',
];
29 changes: 29 additions & 0 deletions database/migrations/add_settings_team_field.php.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
if (! config('settings.teams')) {
return;
}

Schema::table(config('settings.table'), function (Blueprint $table) {
$table->unsignedBigInteger(config('settings.team_foreign_key'))->nullable()->after('id');
$table->index(config('settings.team_foreign_key'), 'settings_team_id_index');

$table->dropUnique('settings_key_unique');

$table->unique([
'key',
config('settings.team_foreign_key'),
]);
});
}
};
15 changes: 5 additions & 10 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
verbose="true"
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Laravel Settings Test Suite">
Expand Down
8 changes: 4 additions & 4 deletions src/Contracts/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

interface Driver
{
public function forget($key);
public function forget($key, $teamId = null);

public function get(string $key, $default = null);
public function get(string $key, $default = null, $teamId = null);

public function has($key): bool;
public function has($key, $teamId = null): bool;

public function set(string $key, $value = null);
public function set(string $key, $value = null, $teamId = null);
}
8 changes: 4 additions & 4 deletions src/Contracts/Setting.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

interface Setting
{
public static function getValue(string $key, $default = null);
public static function getValue(string $key, $default = null, $teamId = null);

public static function has($key): bool;
public static function has($key, $teamId = null): bool;

public static function removeSetting($key);
public static function removeSetting($key, $teamId = null);

public static function set(string $key, $value = null);
public static function set(string $key, $value = null, $teamId = null);
}
54 changes: 39 additions & 15 deletions src/Drivers/DatabaseDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,65 @@
use Illuminate\Database\Connection;
use Illuminate\Database\Query\Builder;
use Rawilk\Settings\Contracts\Driver;
use Throwable;

class DatabaseDriver implements Driver
{
public function __construct(protected Connection $connection, protected string $table)
{
public function __construct(
protected Connection $connection,
protected string $table,
protected ?string $teamForeignKey = null,
) {
}

public function forget($key): void
public function forget($key, $teamId = null): void
{
$this->table()->where('key', $key)->delete();
$this->db()
->where('key', $key)
->when(
$teamId !== false,
fn (Builder $query) => $query->where("{$this->table}.{$this->teamForeignKey}", $teamId)
)
->delete();
}

public function get(string $key, $default = null)
public function get(string $key, $default = null, $teamId = null)
{
$value = $this->table()->where('key', $key)->value('value');
$value = $this->db()
->where('key', $key)
->when(
$teamId !== false,
fn (Builder $query) => $query->where("{$this->table}.{$this->teamForeignKey}", $teamId)
)
->value('value');

return $value ?? $default;
}

public function has($key): bool
public function has($key, $teamId = null): bool
{
return $this->table()->where('key', $key)->exists();
return $this->db()
->where('key', $key)
->when(
$teamId !== false,
fn (Builder $query) => $query->where("{$this->table}.{$this->teamForeignKey}", $teamId)
)
->exists();
}

public function set(string $key, $value = null): void
public function set(string $key, $value = null, $teamId = null): void
{
try {
$this->table()->insert(compact('key', 'value'));
} catch (Throwable) {
$this->table()->where('key', $key)->update(compact('value'));
$data = [
'key' => $key,
];

if ($teamId !== false) {
$data[$this->teamForeignKey] = $teamId;
}

$this->db()->updateOrInsert($data, compact('value'));
}

protected function table(): Builder
protected function db(): Builder
{
return $this->connection->table($this->table);
}
Expand Down
16 changes: 8 additions & 8 deletions src/Drivers/EloquentDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ public function __construct(protected Setting $model)
{
}

public function forget($key): void
public function forget($key, $teamId = null): void
{
$this->model::removeSetting($key);
$this->model::removeSetting($key, $teamId);
}

public function get(string $key, $default = null)
public function get(string $key, $default = null, $teamId = null)
{
return $this->model::getValue($key, $default);
return $this->model::getValue($key, $default, $teamId);
}

public function has($key): bool
public function has($key, $teamId = null): bool
{
return $this->model::has($key);
return $this->model::has($key, $teamId);
}

public function set(string $key, $value = null): void
public function set(string $key, $value = null, $teamId = null): void
{
$this->model::set($key, $value);
$this->model::set($key, $value, $teamId);
}
}
9 changes: 6 additions & 3 deletions src/Drivers/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,17 @@ public function extend(string $driver, Closure $callback): self
protected function createDatabaseDriver(array $config): DatabaseDriver
{
return new DatabaseDriver(
$this->app['db']->connection(Arr::get($config, 'connection')),
$this->app['config']['settings.table']
connection: $this->app['db']->connection(Arr::get($config, 'connection')),
table: $this->app['config']['settings.table'],
teamForeignKey: $this->app['config']['settings.team_foreign_key'] ?? null,
);
}

protected function createEloquentDriver(): EloquentDriver
{
return new EloquentDriver(app(SettingContract::class));
return new EloquentDriver(
model: app(SettingContract::class),
);
}

protected function getDefaultDriver(): string
Expand Down
5 changes: 5 additions & 0 deletions src/Facades/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
* @method static self temporarilyDisableCache()
* @method static self disableEncryption()
* @method static self enableEncryption()
* @method static null|mixed getTeamId()
* @method static self setTeamId(mixed $id)
* @method static self enableTeams()
* @method static self disableTeams()
* @method static bool teamsAreEnabled()
*/
class Settings extends Facade
{
Expand Down
53 changes: 45 additions & 8 deletions src/Models/Setting.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,78 @@

namespace Rawilk\Settings\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Rawilk\Settings\Contracts\Setting as SettingContract;

class Setting extends Model implements SettingContract
{
protected ?string $teamForeignKey = null;

public function __construct(array $attributes = [])
{
parent::__construct($attributes);

$this->setTable(config('settings.table'));
$this->teamForeignKey = config('settings.team_foreign_key');
}

protected $guarded = ['id'];

public $timestamps = false;

public static function getValue(string $key, $default = null)
public static function getValue(string $key, $default = null, $teamId = null)
{
$value = self::where('key', $key)->value('value');
$value = static::query()
->where('key', $key)
->when(
$teamId !== false,
fn (Builder $query) => $query->where(
static::make()->getTable() . '.' . config('settings.team_foreign_key'),
$teamId,
),
)
->value('value');

return $value ?? $default;
}

public static function has($key): bool
public static function has($key, $teamId = null): bool
{
return self::where('key', $key)->exists();
return static::query()
->where('key', $key)
->when(
$teamId !== false,
fn (Builder $query) => $query->where(
static::make()->getTable() . '.' . config('settings.team_foreign_key'),
$teamId,
),
)
->exists();
}

public static function removeSetting($key): void
public static function removeSetting($key, $teamId = null): void
{
self::where('key', $key)->delete();
static::query()
->where('key', $key)
->when(
$teamId !== false,
fn (Builder $query) => $query->where(
static::make()->getTable() . '.' . config('settings.team_foreign_key'),
$teamId,
),
)
->delete();
}

public static function set(string $key, $value = null)
public static function set(string $key, $value = null, $teamId = null)
{
return self::updateOrCreate(compact('key'), compact('value'));
$data = ['key' => $key];

if ($teamId !== false) {
$data[config('settings.team_foreign_key')] = $teamId;
}

return static::updateOrCreate($data, compact('value'));
}
}
Loading
Loading