Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117741013
D3116.1775162360.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
27 KB
Referenced Files
None
Subscribers
None
D3116.1775162360.diff
View Options
diff --git a/src/app/Entitlement.php b/src/app/Entitlement.php
--- a/src/app/Entitlement.php
+++ b/src/app/Entitlement.php
@@ -2,7 +2,6 @@
namespace App;
-use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Traits\UuidStrKeyTrait;
@@ -146,32 +145,6 @@
}
/**
- * Restore object entitlements.
- *
- * @param \App\User|\App\Domain|\App\Group $object The user|domain|group object
- */
- public static function restoreEntitlementsFor($object): void
- {
- // We'll restore only these that were deleted last. So, first we get
- // the maximum deleted_at timestamp and then use it to select
- // entitlements for restore
- $deleted_at = $object->entitlements()->withTrashed()->max('deleted_at');
-
- if ($deleted_at) {
- $threshold = (new \Carbon\Carbon($deleted_at))->subMinute();
-
- // Restore object entitlements
- $object->entitlements()->withTrashed()
- ->where('deleted_at', '>=', $threshold)
- ->update(['updated_at' => now(), 'deleted_at' => null]);
-
- // Note: We're assuming that cost of entitlements was correct
- // on deletion, so we don't have to re-calculate it again.
- // TODO: We should probably re-calculate the cost
- }
- }
-
- /**
* The SKU concerned.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
diff --git a/src/app/Observers/DomainObserver.php b/src/app/Observers/DomainObserver.php
--- a/src/app/Observers/DomainObserver.php
+++ b/src/app/Observers/DomainObserver.php
@@ -36,22 +36,6 @@
}
/**
- * Handle the domain "deleting" event.
- *
- * @param \App\Domain $domain The domain.
- *
- * @return void
- */
- public function deleting(Domain $domain)
- {
- // Entitlements do not have referential integrity on the entitled object, so this is our
- // way of doing an onDelete('cascade') without the foreign key.
- \App\Entitlement::where('entitleable_id', $domain->id)
- ->where('entitleable_type', Domain::class)
- ->delete();
- }
-
- /**
* Handle the domain "deleted" event.
*
* @param \App\Domain $domain The domain.
@@ -114,22 +98,7 @@
*/
public function restored(Domain $domain)
{
- // Restore domain entitlements
- \App\Entitlement::restoreEntitlementsFor($domain);
-
// Create the domain in LDAP again
\App\Jobs\Domain\CreateJob::dispatch($domain->id);
}
-
- /**
- * Handle the domain "force deleted" event.
- *
- * @param \App\Domain $domain The domain.
- *
- * @return void
- */
- public function forceDeleted(Domain $domain)
- {
- //
- }
}
diff --git a/src/app/Observers/EntitlementObserver.php b/src/app/Observers/EntitlementObserver.php
--- a/src/app/Observers/EntitlementObserver.php
+++ b/src/app/Observers/EntitlementObserver.php
@@ -79,10 +79,12 @@
$sf->removeFactors();
}
- $entitlement->entitleable->updated_at = Carbon::now();
- $entitlement->entitleable->save();
+ if ($entitlement->entitleable && !$entitlement->entitleable->trashed()) {
+ $entitlement->entitleable->updated_at = Carbon::now();
+ $entitlement->entitleable->save();
- $entitlement->createTransaction(\App\Transaction::ENTITLEMENT_DELETED);
+ $entitlement->createTransaction(\App\Transaction::ENTITLEMENT_DELETED);
+ }
}
/**
diff --git a/src/app/Observers/GroupObserver.php b/src/app/Observers/GroupObserver.php
--- a/src/app/Observers/GroupObserver.php
+++ b/src/app/Observers/GroupObserver.php
@@ -36,22 +36,6 @@
}
/**
- * Handle the group "deleting" event.
- *
- * @param \App\Group $group The group
- *
- * @return void
- */
- public function deleting(Group $group)
- {
- // Entitlements do not have referential integrity on the entitled object, so this is our
- // way of doing an onDelete('cascade') without the foreign key.
- \App\Entitlement::where('entitleable_id', $group->id)
- ->where('entitleable_type', Group::class)
- ->delete();
- }
-
- /**
* Handle the group "deleted" event.
*
* @param \App\Group $group The group
@@ -113,25 +97,6 @@
*/
public function restored(Group $group)
{
- // Restore group entitlements
- \App\Entitlement::restoreEntitlementsFor($group);
-
\App\Jobs\Group\CreateJob::dispatch($group->id);
}
-
- /**
- * Handle the group "force deleting" event.
- *
- * @param \App\Group $group The group
- *
- * @return void
- */
- public function forceDeleted(Group $group)
- {
- // A group can be force-deleted separately from the owner
- // we have to force-delete entitlements
- \App\Entitlement::where('entitleable_id', $group->id)
- ->where('entitleable_type', Group::class)
- ->forceDelete();
- }
}
diff --git a/src/app/Observers/ResourceObserver.php b/src/app/Observers/ResourceObserver.php
--- a/src/app/Observers/ResourceObserver.php
+++ b/src/app/Observers/ResourceObserver.php
@@ -66,22 +66,6 @@
}
/**
- * Handle the resource "deleting" event.
- *
- * @param \App\Resource $resource The resource
- *
- * @return void
- */
- public function deleting(Resource $resource)
- {
- // Entitlements do not have referential integrity on the entitled object, so this is our
- // way of doing an onDelete('cascade') without the foreign key.
- \App\Entitlement::where('entitleable_id', $resource->id)
- ->where('entitleable_type', Resource::class)
- ->delete();
- }
-
- /**
* Handle the resource "deleted" event.
*
* @param \App\Resource $resource The resource
@@ -117,20 +101,4 @@
$resource->settings()->where('key', 'folder')->update(['value' => $folder]);
}
}
-
- /**
- * Handle the resource "force deleted" event.
- *
- * @param \App\Resource $resource The resource
- *
- * @return void
- */
- public function forceDeleted(Resource $resource)
- {
- // A group can be force-deleted separately from the owner
- // we have to force-delete entitlements
- \App\Entitlement::where('entitleable_id', $resource->id)
- ->where('entitleable_type', Resource::class)
- ->forceDelete();
- }
}
diff --git a/src/app/Observers/SharedFolderObserver.php b/src/app/Observers/SharedFolderObserver.php
--- a/src/app/Observers/SharedFolderObserver.php
+++ b/src/app/Observers/SharedFolderObserver.php
@@ -70,22 +70,6 @@
}
/**
- * Handle the shared folder "deleting" event.
- *
- * @param \App\SharedFolder $folder The folder
- *
- * @return void
- */
- public function deleting(SharedFolder $folder)
- {
- // Entitlements do not have referential integrity on the entitled object, so this is our
- // way of doing an onDelete('cascade') without the foreign key.
- \App\Entitlement::where('entitleable_id', $folder->id)
- ->where('entitleable_type', SharedFolder::class)
- ->delete();
- }
-
- /**
* Handle the shared folder "deleted" event.
*
* @param \App\SharedFolder $folder The folder
@@ -121,20 +105,4 @@
$folder->settings()->where('key', 'folder')->update(['value' => $folderName]);
}
}
-
- /**
- * Handle the shared folder "force deleted" event.
- *
- * @param \App\SharedFolder $folder The folder
- *
- * @return void
- */
- public function forceDeleted(SharedFolder $folder)
- {
- // A folder can be force-deleted separately from the owner
- // we have to force-delete entitlements
- \App\Entitlement::where('entitleable_id', $folder->id)
- ->where('entitleable_type', SharedFolder::class)
- ->forceDelete();
- }
}
diff --git a/src/app/Observers/UserObserver.php b/src/app/Observers/UserObserver.php
--- a/src/app/Observers/UserObserver.php
+++ b/src/app/Observers/UserObserver.php
@@ -2,15 +2,8 @@
namespace App\Observers;
-use App\Entitlement;
-use App\Domain;
-use App\Group;
-use App\Resource;
-use App\SharedFolder;
-use App\Transaction;
use App\User;
use App\Wallet;
-use Illuminate\Support\Facades\DB;
class UserObserver
{
@@ -102,18 +95,6 @@
}
});
}
-
- // Debit the reseller's wallet with the user negative balance
- $balance = 0;
- foreach ($user->wallets as $wallet) {
- // Note: here we assume all user wallets are using the same currency.
- // It might get changed in the future
- $balance += $wallet->balance;
- }
-
- if ($balance < 0 && $user->tenant && ($wallet = $user->tenant->wallet())) {
- $wallet->debit($balance * -1, "Deleted user {$user->email}");
- }
}
/**
@@ -125,177 +106,31 @@
*/
public function deleting(User $user)
{
- if ($user->isForceDeleting()) {
- $this->forceDeleting($user);
- return;
- }
+ // Remove owned users/domains/groups/resources/etc
+ self::removeRelatedObjects($user, $user->isForceDeleting());
// TODO: Especially in tests we're doing delete() on a already deleted user.
// Should we escape here - for performance reasons?
- // TODO: I think all of this should use database transactions
-
- // Entitlements do not have referential integrity on the entitled object, so this is our
- // way of doing an onDelete('cascade') without the foreign key.
- $entitlements = Entitlement::where('entitleable_id', $user->id)
- ->where('entitleable_type', User::class)->get();
-
- foreach ($entitlements as $entitlement) {
- $entitlement->delete();
- }
-
- // Remove owned users/domains
- $wallets = $user->wallets()->pluck('id')->all();
- $assignments = Entitlement::whereIn('wallet_id', $wallets)->get();
- $users = [];
- $domains = [];
- $groups = [];
- $resources = [];
- $folders = [];
- $entitlements = [];
-
- foreach ($assignments as $entitlement) {
- if ($entitlement->entitleable_type == Domain::class) {
- $domains[] = $entitlement->entitleable_id;
- } elseif ($entitlement->entitleable_type == User::class && $entitlement->entitleable_id != $user->id) {
- $users[] = $entitlement->entitleable_id;
- } elseif ($entitlement->entitleable_type == Group::class) {
- $groups[] = $entitlement->entitleable_id;
- } elseif ($entitlement->entitleable_type == Resource::class) {
- $resources[] = $entitlement->entitleable_id;
- } elseif ($entitlement->entitleable_type == SharedFolder::class) {
- $folders[] = $entitlement->entitleable_id;
- } else {
- $entitlements[] = $entitlement;
- }
- }
-
- // Domains/users/entitlements need to be deleted one by one to make sure
- // events are fired and observers can do the proper cleanup.
- if (!empty($users)) {
- foreach (User::whereIn('id', array_unique($users))->get() as $_user) {
- $_user->delete();
- }
- }
-
- if (!empty($domains)) {
- foreach (Domain::whereIn('id', array_unique($domains))->get() as $_domain) {
- $_domain->delete();
- }
- }
- if (!empty($groups)) {
- foreach (Group::whereIn('id', array_unique($groups))->get() as $_group) {
- $_group->delete();
- }
- }
-
- if (!empty($resources)) {
- foreach (Resource::whereIn('id', array_unique($resources))->get() as $_resource) {
- $_resource->delete();
- }
- }
+ if (!$user->isForceDeleting()) {
+ \App\Jobs\User\DeleteJob::dispatch($user->id);
- if (!empty($folders)) {
- foreach (SharedFolder::whereIn('id', array_unique($folders))->get() as $_folder) {
- $_folder->delete();
+ if (\App\Tenant::getConfig($user->tenant_id, 'pgp.enable')) {
+ \App\Jobs\PGP\KeyDeleteJob::dispatch($user->id, $user->email);
}
- }
-
- foreach ($entitlements as $entitlement) {
- $entitlement->delete();
- }
-
- // FIXME: What do we do with user wallets?
-
- \App\Jobs\User\DeleteJob::dispatch($user->id);
-
- if (\App\Tenant::getConfig($user->tenant_id, 'pgp.enable')) {
- \App\Jobs\PGP\KeyDeleteJob::dispatch($user->id, $user->email);
- }
- }
-
- /**
- * Handle the "deleting" event on forceDelete() call.
- *
- * @param User $user The user that is being deleted.
- *
- * @return void
- */
- public function forceDeleting(User $user)
- {
- // TODO: We assume that at this moment all belongings are already soft-deleted.
-
- // Remove owned users/domains
- $wallets = $user->wallets()->pluck('id')->all();
- $assignments = Entitlement::withTrashed()->whereIn('wallet_id', $wallets)->get();
- $entitlements = [];
- $domains = [];
- $groups = [];
- $resources = [];
- $folders = [];
- $users = [];
- foreach ($assignments as $entitlement) {
- $entitlements[] = $entitlement->id;
-
- if ($entitlement->entitleable_type == Domain::class) {
- $domains[] = $entitlement->entitleable_id;
- } elseif (
- $entitlement->entitleable_type == User::class
- && $entitlement->entitleable_id != $user->id
- ) {
- $users[] = $entitlement->entitleable_id;
- } elseif ($entitlement->entitleable_type == Group::class) {
- $groups[] = $entitlement->entitleable_id;
- } elseif ($entitlement->entitleable_type == Resource::class) {
- $resources[] = $entitlement->entitleable_id;
- } elseif ($entitlement->entitleable_type == SharedFolder::class) {
- $folders[] = $entitlement->entitleable_id;
+ // Debit the reseller's wallet with the user negative balance
+ $balance = 0;
+ foreach ($user->wallets as $wallet) {
+ // Note: here we assume all user wallets are using the same currency.
+ // It might get changed in the future
+ $balance += $wallet->balance;
}
- }
- // Remove the user "direct" entitlements explicitely, if they belong to another
- // user's wallet they will not be removed by the wallets foreign key cascade
- Entitlement::withTrashed()
- ->where('entitleable_id', $user->id)
- ->where('entitleable_type', User::class)
- ->forceDelete();
-
- // Users need to be deleted one by one to make sure observers can do the proper cleanup.
- if (!empty($users)) {
- foreach (User::withTrashed()->whereIn('id', array_unique($users))->get() as $_user) {
- $_user->forceDelete();
+ if ($balance < 0 && $user->tenant && ($wallet = $user->tenant->wallet())) {
+ $wallet->debit($balance * -1, "Deleted user {$user->email}");
}
}
-
- // Domains can be just removed
- if (!empty($domains)) {
- Domain::withTrashed()->whereIn('id', array_unique($domains))->forceDelete();
- }
-
- // Groups can be just removed
- if (!empty($groups)) {
- Group::withTrashed()->whereIn('id', array_unique($groups))->forceDelete();
- }
-
- // Resources can be just removed
- if (!empty($resources)) {
- Resource::withTrashed()->whereIn('id', array_unique($resources))->forceDelete();
- }
-
- // Shared folders can be just removed
- if (!empty($folders)) {
- SharedFolder::withTrashed()->whereIn('id', array_unique($folders))->forceDelete();
- }
-
- // Remove transactions, they also have no foreign key constraint
- Transaction::where('object_type', Entitlement::class)
- ->whereIn('object_id', $entitlements)
- ->delete();
-
- Transaction::where('object_type', Wallet::class)
- ->whereIn('object_id', $wallets)
- ->delete();
}
/**
@@ -335,9 +170,6 @@
*/
public function restored(User $user)
{
- // Restore user entitlements
- \App\Entitlement::restoreEntitlementsFor($user);
-
// We need at least the user domain so it can be created in ldap.
// FIXME: What if the domain is owned by someone else?
$domain = $user->domain();
@@ -357,28 +189,53 @@
}
/**
- * Handle the "retrieving" event.
- *
- * @param User $user The user that is being retrieved.
+ * Handle the "updating" event.
*
- * @todo This is useful for audit.
+ * @param User $user The user that is being updated.
*
* @return void
*/
- public function retrieving(User $user)
+ public function updating(User $user)
{
- // TODO \App\Jobs\User\ReadJob::dispatch($user->id);
+ \App\Jobs\User\UpdateJob::dispatch($user->id);
}
/**
- * Handle the "updating" event.
- *
- * @param User $user The user that is being updated.
+ * Remove entitleables/transactions related to the user (in user's wallets)
*
- * @return void
+ * @param \App\User $user The user
+ * @param bool $force Force-delete mode
*/
- public function updating(User $user)
+ private static function removeRelatedObjects(User $user, $force = false): void
{
- \App\Jobs\User\UpdateJob::dispatch($user->id);
+ $wallets = $user->wallets->pluck('id')->all();
+
+ \App\Entitlement::withTrashed()
+ ->select('entitleable_id', 'entitleable_type')
+ ->distinct()
+ ->whereIn('wallet_id', $wallets)
+ ->get()
+ ->each(function ($entitlement) use ($user, $force) {
+ // Skip the current user (infinite recursion loop)
+ if ($entitlement->entitleable_type == User::class && $entitlement->entitleable_id == $user->id) {
+ return;
+ }
+
+ // Objects need to be deleted one by one to make sure observers can do the proper cleanup
+ if ($entitlement->entitleable) {
+ if ($force) {
+ $entitlement->entitleable->forceDelete();
+ } elseif (!$entitlement->entitleable->trashed()) {
+ $entitlement->entitleable->delete();
+ }
+ }
+ });
+
+ if ($force) {
+ // Remove "wallet" transactions, they have no foreign key constraint
+ \App\Transaction::where('object_type', Wallet::class)
+ ->whereIn('object_id', $wallets)
+ ->delete();
+ }
}
}
diff --git a/src/app/Traits/EntitleableTrait.php b/src/app/Traits/EntitleableTrait.php
--- a/src/app/Traits/EntitleableTrait.php
+++ b/src/app/Traits/EntitleableTrait.php
@@ -110,6 +110,45 @@
}
/**
+ * Boot function from Laravel.
+ */
+ protected static function bootEntitleableTrait()
+ {
+ // Soft-delete and force-delete object's entitlements on object's delete
+ static::deleting(function ($model) {
+ $force = $model->isForceDeleting();
+ $entitlements = $model->entitlements();
+
+ if ($force) {
+ $entitlements = $entitlements->withTrashed();
+ }
+
+ $list = $entitlements->get()
+ ->map(function ($entitlement) use ($force) {
+ if ($force) {
+ $entitlement->forceDelete();
+ } else {
+ $entitlement->delete();
+ }
+ return $entitlement->id;
+ })
+ ->all();
+
+ // Remove transactions, they have no foreign key constraint
+ if ($force && !empty($list)) {
+ \App\Transaction::where('object_type', \App\Entitlement::class)
+ ->whereIn('object_id', $list)
+ ->delete();
+ }
+ });
+
+ // Restore object's entitlements on restore
+ static::restored(function ($model) {
+ $model->restoreEntitlements();
+ });
+ }
+
+ /**
* Entitlements for this object.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
@@ -172,6 +211,30 @@
}
/**
+ * Restore object entitlements.
+ */
+ public function restoreEntitlements(): void
+ {
+ // We'll restore only these that were deleted last. So, first we get
+ // the maximum deleted_at timestamp and then use it to select
+ // entitlements for restore
+ $deleted_at = $this->entitlements()->withTrashed()->max('deleted_at');
+
+ if ($deleted_at) {
+ $threshold = (new \Carbon\Carbon($deleted_at))->subMinute();
+
+ // Restore object entitlements
+ $this->entitlements()->withTrashed()
+ ->where('deleted_at', '>=', $threshold)
+ ->update(['updated_at' => now(), 'deleted_at' => null]);
+
+ // Note: We're assuming that cost of entitlements was correct
+ // on deletion, so we don't have to re-calculate it again.
+ // TODO: We should probably re-calculate the cost
+ }
+ }
+
+ /**
* Returns the wallet by which the object is controlled
*
* @return ?\App\Wallet A wallet object
diff --git a/src/app/Transaction.php b/src/app/Transaction.php
--- a/src/app/Transaction.php
+++ b/src/app/Transaction.php
@@ -153,7 +153,7 @@
{
$result = [
'user_email' => $this->user_email,
- 'description' => $this->{'description'},
+ 'description' => $this->description,
];
$amount = $this->amount * ($this->amount < 0 ? -1 : 1);
@@ -165,12 +165,12 @@
$result['entitlement_cost'] = $cost * $discount;
$result['object'] = $entitlement->entitleableTitle();
- $result['sku_title'] = $entitlement->sku->{'title'};
+ $result['sku_title'] = $entitlement->sku->title;
} else {
$wallet = $this->wallet();
}
- $result['wallet'] = $wallet->{'description'} ?: 'Default wallet';
+ $result['wallet'] = $wallet->description ?: 'Default wallet';
$result['amount'] = $wallet->money($amount);
return $result;
diff --git a/src/tests/Feature/Console/User/ForceDeleteTest.php b/src/tests/Feature/Console/User/ForceDeleteTest.php
--- a/src/tests/Feature/Console/User/ForceDeleteTest.php
+++ b/src/tests/Feature/Console/User/ForceDeleteTest.php
@@ -86,6 +86,7 @@
0,
\App\Entitlement::withTrashed()->where('entitleable_id', $user->id)->get()
);
+
$this->assertCount(
0,
\App\Transaction::whereIn('object_id', $entitlements)
diff --git a/src/tests/Feature/EntitlementTest.php b/src/tests/Feature/EntitlementTest.php
--- a/src/tests/Feature/EntitlementTest.php
+++ b/src/tests/Feature/EntitlementTest.php
@@ -106,32 +106,6 @@
}
/**
- * @todo This really should be in User tests file
- */
- public function testEntitlementFunctions(): void
- {
- $user = $this->getTestUser('entitlement-test@kolabnow.com');
-
- $package = \App\Package::withEnvTenantContext()->where('title', 'kolab')->first();
-
- $user->assignPackage($package);
-
- $wallet = $user->wallets()->first();
- $this->assertNotNull($wallet);
-
- $sku = \App\Sku::withEnvTenantContext()->where('title', 'mailbox')->first();
-
- $entitlement = Entitlement::where('wallet_id', $wallet->id)
- ->where('sku_id', $sku->id)->first();
-
- $this->assertNotNull($entitlement);
- $this->assertSame($sku->id, $entitlement->sku->id);
- $this->assertSame($wallet->id, $entitlement->wallet->id);
- $this->assertEquals($user->id, $entitlement->entitleable->id);
- $this->assertTrue($entitlement->entitleable instanceof \App\User);
- }
-
- /**
* Test Entitlement::entitleableTitle()
*/
public function testEntitleableTitle(): void
diff --git a/src/tests/Feature/UserTest.php b/src/tests/Feature/UserTest.php
--- a/src/tests/Feature/UserTest.php
+++ b/src/tests/Feature/UserTest.php
@@ -46,7 +46,24 @@
*/
public function testAssignPackage(): void
{
- $this->markTestIncomplete();
+ $user = $this->getTestUser('user-test@' . \config('app.domain'));
+ $wallet = $user->wallets()->first();
+
+ $package = \App\Package::withEnvTenantContext()->where('title', 'kolab')->first();
+
+ $user->assignPackage($package);
+
+ $sku = \App\Sku::withEnvTenantContext()->where('title', 'mailbox')->first();
+
+ $entitlement = \App\Entitlement::where('wallet_id', $wallet->id)
+ ->where('sku_id', $sku->id)->first();
+
+ $this->assertNotNull($entitlement);
+ $this->assertSame($sku->id, $entitlement->sku->id);
+ $this->assertSame($wallet->id, $entitlement->wallet->id);
+ $this->assertEquals($user->id, $entitlement->entitleable->id);
+ $this->assertTrue($entitlement->entitleable instanceof \App\User);
+ $this->assertCount(7, $user->entitlements()->get());
}
/**
@@ -496,6 +513,13 @@
$this->assertSame(0, $entitlementsGroup->count());
$this->assertSame(0, $entitlementsResource->count());
$this->assertSame(0, $entitlementsFolder->count());
+ $this->assertSame(7, $entitlementsA->withTrashed()->count());
+ $this->assertSame(7, $entitlementsB->withTrashed()->count());
+ $this->assertSame(7, $entitlementsC->withTrashed()->count());
+ $this->assertSame(1, $entitlementsDomain->withTrashed()->count());
+ $this->assertSame(1, $entitlementsGroup->withTrashed()->count());
+ $this->assertSame(1, $entitlementsResource->withTrashed()->count());
+ $this->assertSame(1, $entitlementsFolder->withTrashed()->count());
$this->assertTrue($userA->fresh()->trashed());
$this->assertTrue($userB->fresh()->trashed());
$this->assertTrue($domain->fresh()->trashed());
@@ -512,8 +536,10 @@
$userA->forceDelete();
$all_entitlements = \App\Entitlement::where('wallet_id', $userA->wallets->first()->id);
+ $transactions = \App\Transaction::where('object_id', $userA->wallets->first()->id);
$this->assertSame(0, $all_entitlements->withTrashed()->count());
+ $this->assertSame(0, $transactions->count());
$this->assertCount(0, User::withTrashed()->where('id', $userA->id)->get());
$this->assertCount(0, User::withTrashed()->where('id', $userB->id)->get());
$this->assertCount(0, User::withTrashed()->where('id', $userC->id)->get());
diff --git a/src/tests/Unit/EntitlementTest.php b/src/tests/Unit/EntitlementTest.php
new file mode 100644
--- /dev/null
+++ b/src/tests/Unit/EntitlementTest.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Tests\Unit;
+
+use App\Entitlement;
+use Tests\TestCase;
+
+class EntitlementTest extends TestCase
+{
+ /**
+ * Test basic cost mutator
+ */
+ public function testSetCostAttribute(): void
+ {
+ $ent = new Entitlement();
+
+ // We probably don't have to test this, as phpstan warns us anyway
+
+ $ent->cost = 1.1; // @phpstan-ignore-line
+ $this->assertSame(1, $ent->cost);
+
+ $ent->cost = 1.5; // @phpstan-ignore-line
+ $this->assertSame(2, $ent->cost);
+
+ $ent->cost = '10'; // @phpstan-ignore-line
+ $this->assertSame(10, $ent->cost);
+ }
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Apr 2, 8:39 PM (3 d, 21 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18820750
Default Alt Text
D3116.1775162360.diff (27 KB)
Attached To
Mode
D3116: Unify entitleables' events handling
Attached
Detach File
Event Timeline