controller refactoring part 17

This commit is contained in:
Peter Papp
2021-07-21 11:20:41 +02:00
parent e0eaf5cede
commit dccf98602d
21 changed files with 370 additions and 94 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+1
View File
@@ -30,6 +30,7 @@
"league/flysystem-cached-adapter": "^1.1.0", "league/flysystem-cached-adapter": "^1.1.0",
"madnest/madzipper": "^1.1.0", "madnest/madzipper": "^1.1.0",
"spatie/laravel-backup": "^6.16.1", "spatie/laravel-backup": "^6.16.1",
"spatie/laravel-query-builder": "^3.5",
"spatie/laravel-tail": "^4.3.3", "spatie/laravel-tail": "^4.3.3",
"teamtnt/laravel-scout-tntsearch-driver": "^11.5.0.0", "teamtnt/laravel-scout-tntsearch-driver": "^11.5.0.0",
"vimeo/psalm": "^4.8.1" "vimeo/psalm": "^4.8.1"
Generated
+71 -1
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "fabf10158fc42e399bd575125ff57b4c", "content-hash": "50eedc067d37499da24bee315d3008da",
"packages": [ "packages": [
{ {
"name": "amphp/amp", "name": "amphp/amp",
@@ -7213,6 +7213,76 @@
], ],
"time": "2021-05-23T15:12:33+00:00" "time": "2021-05-23T15:12:33+00:00"
}, },
{
"name": "spatie/laravel-query-builder",
"version": "3.5.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-query-builder.git",
"reference": "4e5257be24139836dc092f618d7c73bcb1c00302"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-query-builder/zipball/4e5257be24139836dc092f618d7c73bcb1c00302",
"reference": "4e5257be24139836dc092f618d7c73bcb1c00302",
"shasum": ""
},
"require": {
"illuminate/database": "^6.20.13|^7.30.4|^8.22.2",
"illuminate/http": "^6.20.13|7.30.4|^8.22.2",
"illuminate/support": "^6.20.13|7.30.4|^8.22.2",
"php": "^7.3|^8.0"
},
"require-dev": {
"ext-json": "*",
"laravel/legacy-factories": "^1.0.4",
"mockery/mockery": "^1.4",
"orchestra/testbench": "^4.9|^5.8|^6.3",
"phpunit/phpunit": "^9.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Spatie\\QueryBuilder\\QueryBuilderServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Spatie\\QueryBuilder\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Alex Vanderbist",
"email": "alex@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
}
],
"description": "Easily build Eloquent queries from API requests",
"homepage": "https://github.com/spatie/laravel-query-builder",
"keywords": [
"laravel-query-builder",
"spatie"
],
"support": {
"issues": "https://github.com/spatie/laravel-query-builder/issues",
"source": "https://github.com/spatie/laravel-query-builder"
},
"funding": [
{
"url": "https://spatie.be/open-source/support-us",
"type": "custom"
}
],
"time": "2021-07-05T14:17:44+00:00"
},
{ {
"name": "spatie/laravel-tail", "name": "spatie/laravel-tail",
"version": "4.3.3", "version": "4.3.3",
+1 -1
View File
@@ -8,7 +8,7 @@ use Domain\SetupWizard\Controllers\StoreDatabaseCredentialsController;
use Domain\SetupWizard\Controllers\StoreEnvironmentSettingsController; use Domain\SetupWizard\Controllers\StoreEnvironmentSettingsController;
use Domain\SetupWizard\Controllers\StoreSubscriptionServiceCredentialsController; use Domain\SetupWizard\Controllers\StoreSubscriptionServiceCredentialsController;
// TODO: create middleware for setup wizard protection after successfull installation // TODO: create middleware for setup wizard protection after successful installation
Route::post('/stripe-credentials', StoreSubscriptionServiceCredentialsController::class); Route::post('/stripe-credentials', StoreSubscriptionServiceCredentialsController::class);
Route::post('/environment-setup', StoreEnvironmentSettingsController::class); Route::post('/environment-setup', StoreEnvironmentSettingsController::class);
Route::post('/database', StoreDatabaseCredentialsController::class); Route::post('/database', StoreDatabaseCredentialsController::class);
+1 -1
View File
@@ -34,8 +34,8 @@ Route::group(['prefix' => 'browse'], function () {
Route::post('/authenticate/{shared}', AuthenticateProtectedSharedItemController::class); Route::post('/authenticate/{shared}', AuthenticateProtectedSharedItemController::class);
Route::get('/folders/{id}/{shared}', VisitorBrowseFolderContentController::class); Route::get('/folders/{id}/{shared}', VisitorBrowseFolderContentController::class);
Route::get('/navigation/{shared}', VisitorNavigationFolderTreeController::class); Route::get('/navigation/{shared}', VisitorNavigationFolderTreeController::class);
Route::get('/file/{shared}', VisitorGetSingleFileResourceController::class);
Route::get('/search/{shared}', VisitorSearchFilesAndFoldersController::class); Route::get('/search/{shared}', VisitorSearchFilesAndFoldersController::class);
Route::get('/file/{shared}', VisitorGetSingleFileResourceController::class);
Route::get('/share/{shared}', [ShareController::class, 'show']); Route::get('/share/{shared}', [ShareController::class, 'show']);
}); });
+1 -1
View File
@@ -2,7 +2,7 @@
use Domain\Homepage\Controllers\IndexController; use Domain\Homepage\Controllers\IndexController;
use Domain\Sharing\Controllers\OGSiteController; use Domain\Sharing\Controllers\OGSiteController;
use Domain\Admin\Controllers\AdminInvoiceController; use Domain\Invoices\Controllers\AdminInvoiceController;
use Domain\Sharing\Controllers\SharePublicIndexController; use Domain\Sharing\Controllers\SharePublicIndexController;
use Domain\Subscriptions\Controllers\StripeWebhookController; use Domain\Subscriptions\Controllers\StripeWebhookController;
use Domain\SetupWizard\Controllers\CreateAdminAccountController; use Domain\SetupWizard\Controllers\CreateAdminAccountController;
-33
View File
@@ -16,7 +16,6 @@ use App\Users\Notifications\ResetPassword;
use Domain\Subscriptions\Traits\Subscription; use Domain\Subscriptions\Traits\Subscription;
use Laravel\Fortify\TwoFactorAuthenticatable; use Laravel\Fortify\TwoFactorAuthenticatable;
use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Contracts\Auth\MustVerifyEmail;
use Domain\Traffic\Models\Traffic as TrafficModel;
use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -128,38 +127,6 @@ class User extends Authenticatable implements MustVerifyEmail
return $this->hasOne(UserSettings::class); return $this->hasOne(UserSettings::class);
} }
/**
* Record user upload filesize
*/
public function recordUpload(int $file_size): void
{
$record = TrafficModel::whereYear('created_at', '=', now()->year)
->whereMonth('created_at', '=', now()->month)
->firstOrCreate([
'user_id' => $this->id,
]);
$record->update([
'upload' => $record->upload + $file_size,
]);
}
/**
* Record user download filesize
*/
public function recordDownload(int $file_size): void
{
$record = TrafficModel::whereYear('created_at', '=', now()->year)
->whereMonth('created_at', '=', now()->month)
->firstOrCreate([
'user_id' => $this->id,
]);
$record->update([
'download' => $record->download + $file_size,
]);
}
/** /**
* Get user favourites folder * Get user favourites folder
*/ */
@@ -1,7 +1,6 @@
<?php <?php
namespace Domain\Files\Actions; namespace Domain\Files\Actions;
use App\Users\Models\User;
use Domain\Sharing\Models\Share; use Domain\Sharing\Models\Share;
use Support\Services\HelperService; use Support\Services\HelperService;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
@@ -9,11 +8,13 @@ use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Domain\Files\Requests\UploadRequest; use Domain\Files\Requests\UploadRequest;
use Domain\Files\Models\File as UserFile; use Domain\Files\Models\File as UserFile;
use Domain\Traffic\Actions\RecordUploadAction;
class UploadFilesAction class UploadFileAction
{ {
public function __construct( public function __construct(
public HelperService $helper, public HelperService $helper,
public RecordUploadAction $recordUpload,
) { ) {
} }
@@ -77,8 +78,7 @@ class UploadFilesAction
} }
// Store user upload size // Store user upload size
User::find($user_id) ($this->recordUpload)($file_size, $user_id);
->recordUpload($file_size);
// Return new file // Return new file
return UserFile::create([ return UserFile::create([
@@ -7,7 +7,7 @@ use Support\Services\HelperService;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Support\Demo\Actions\DemoService; use Support\Demo\Actions\DemoService;
use Domain\Files\Requests\UploadRequest; use Domain\Files\Requests\UploadRequest;
use Domain\Files\Actions\UploadFilesAction; use Domain\Files\Actions\UploadFileAction;
/** /**
* guest user upload file into shared folder * guest user upload file into shared folder
@@ -21,7 +21,7 @@ class EditorUploadFilesController extends Controller
} }
public function __invoke( public function __invoke(
UploadFilesAction $uploadFile, UploadFileAction $uploadFile,
UploadRequest $request, UploadRequest $request,
Share $shared, Share $shared,
): Response | array { ): Response | array {
@@ -8,11 +8,13 @@ use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Domain\Files\Models\File as UserFile; use Domain\Files\Models\File as UserFile;
use Domain\Traffic\Actions\RecordDownloadAction;
class FileAccessController extends Controller class FileAccessController extends Controller
{ {
public function __construct( public function __construct(
public HelperService $helper, public HelperService $helper,
public RecordDownloadAction $recordDownload,
) { ) {
} }
@@ -79,8 +81,9 @@ class FileAccessController extends Controller
}*/ }*/
// Store user download size // Store user download size
$request->user()->recordDownload( ($this->recordDownload)(
(int) $file->getRawOriginal('filesize') (int) $file->getRawOriginal('filesize'),
Auth::id()
); );
return $this->helper->download_file($file, Auth::id()); return $this->helper->download_file($file, Auth::id());
@@ -100,11 +103,11 @@ class FileAccessController extends Controller
->where('user_id', Auth::id()) ->where('user_id', Auth::id())
->firstOrFail(); ->firstOrFail();
$zip // Store user download size
->user ($this->recordDownload)(
->recordDownload( $disk->size("zip/$zip->basename"),
$disk->size("zip/$zip->basename") $zip->user_id
); );
return $disk->download("zip/$zip->basename", $zip->basename, [ return $disk->download("zip/$zip->basename", $zip->basename, [
'Content-Type' => 'application/zip', 'Content-Type' => 'application/zip',
@@ -4,7 +4,7 @@ namespace Domain\Files\Controllers;
use Domain\Files\Models\File; use Domain\Files\Models\File;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Domain\Files\Requests\UploadRequest; use Domain\Files\Requests\UploadRequest;
use Domain\Files\Actions\UploadFilesAction; use Domain\Files\Actions\UploadFileAction;
class UploadFilesController extends Controller class UploadFilesController extends Controller
{ {
@@ -13,7 +13,7 @@ class UploadFilesController extends Controller
*/ */
public function __invoke( public function __invoke(
UploadRequest $request, UploadRequest $request,
UploadFilesAction $uploadFiles, UploadFileAction $uploadFiles,
): File { ): File {
if (is_demo_account('howdy@hi5ve.digital')) { if (is_demo_account('howdy@hi5ve.digital')) {
return $this->demo->upload($request); return $this->demo->upload($request);
@@ -12,8 +12,8 @@ class UserProfileInvoiceController extends Controller
*/ */
public function __invoke(): InvoiceCollection public function __invoke(): InvoiceCollection
{ {
return new InvoiceCollection( $user = Auth::user()->invoices();
Auth::user()->invoices()
); return new InvoiceCollection($user);
} }
} }
@@ -7,11 +7,13 @@ use Support\Services\HelperService;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Domain\Files\Models\File as UserFile; use Domain\Files\Models\File as UserFile;
use Domain\Traffic\Actions\RecordDownloadAction;
class FileSharedAccessController extends Controller class FileSharedAccessController extends Controller
{ {
public function __construct( public function __construct(
private HelperService $helper, private HelperService $helper,
public RecordDownloadAction $recordDownload,
) { ) {
} }
@@ -30,11 +32,11 @@ class FileSharedAccessController extends Controller
->where('shared_token', $token) ->where('shared_token', $token)
->first(); ->first();
$zip // Store user download size
->user ($this->recordDownload)(
->recordDownload( $disk->size("zip/$zip->basename"),
$disk->size("zip/$zip->basename") $zip->user_id
); );
return $disk return $disk
->download("zip/$zip->basename", $zip->basename, [ ->download("zip/$zip->basename", $zip->basename, [
@@ -67,11 +69,10 @@ class FileSharedAccessController extends Controller
$this->helper->check_guest_access_to_shared_items($shared, $file); $this->helper->check_guest_access_to_shared_items($shared, $file);
// Store user download size // Store user download size
$shared ($this->recordDownload)(
->user (int) $file->getRawOriginal('filesize'),
->recordDownload( $shared->user_id
(int) $file->getRawOriginal('filesize') );
);
return $this->helper->download_file($file, $shared->user_id); return $this->helper->download_file($file, $shared->user_id);
} }
@@ -97,11 +98,10 @@ class FileSharedAccessController extends Controller
$this->helper->check_guest_access_to_shared_items($shared, $file); $this->helper->check_guest_access_to_shared_items($shared, $file);
// Store user download size // Store user download size
$shared ($this->recordDownload)(
->user (int) $file->getRawOriginal('filesize'),
->recordDownload( $shared->user_id
(int) $file->getRawOriginal('filesize') );
);
return $this->helper->download_thumbnail_file($file, $shared->user_id); return $this->helper->download_thumbnail_file($file, $shared->user_id);
} }
@@ -6,15 +6,21 @@ use Domain\Files\Models\File;
use Domain\Sharing\Models\Share; use Domain\Sharing\Models\Share;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Domain\Traffic\Actions\RecordDownloadAction;
use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpFoundation\StreamedResponse;
class SharePublicIndexController extends Controller class SharePublicIndexController extends Controller
{ {
public function __construct(
public RecordDownloadAction $recordDownload,
) {
}
/** /**
* Show page index and delete share_session cookie * Show page index and delete share_session cookie
*/ */
public function __invoke( public function __invoke(
Share $shared Share $shared,
): View | StreamedResponse { ): View | StreamedResponse {
// Delete share_session if exist // Delete share_session if exist
if ($shared->is_protected) { if ($shared->is_protected) {
@@ -29,12 +35,11 @@ class SharePublicIndexController extends Controller
->first(); ->first();
if ($image) { if ($image) {
// Get image filesize
$fileSize = (int) $image->getRawOriginal('filesize');
// Store user download size // Store user download size
$shared ($this->recordDownload)($fileSize, $shared->user->id);
->user
->recordDownload(
(int) $image->getRawOriginal('filesize')
);
return $this->get_single_image($image, $shared->user_id); return $this->get_single_image($image, $shared->user_id);
} }
@@ -0,0 +1,24 @@
<?php
namespace Domain\Traffic\Actions;
use Domain\Traffic\Models\Traffic;
class RecordDownloadAction
{
/**
* Record user download filesize
*/
public function __invoke(
int $file_size,
string $user_id,
): void {
$record = Traffic::currentMonth()
->firstOrCreate([
'user_id' => $user_id,
]);
$record->update([
'download' => $record->download + $file_size,
]);
}
}
@@ -0,0 +1,24 @@
<?php
namespace Domain\Traffic\Actions;
use Domain\Traffic\Models\Traffic;
class RecordUploadAction
{
/**
* Record user upload filesize
*/
public function __invoke(
int $file_size,
string $user_id,
): void {
$record = Traffic::currentMonth()
->firstOrCreate([
'user_id' => $user_id,
]);
$record->update([
'upload' => $record->upload + $file_size,
]);
}
}
+9
View File
@@ -3,10 +3,12 @@ namespace Domain\Traffic\Models;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
/** /**
* @method static whereYear(string $string, string $string1, int $year) * @method static whereYear(string $string, string $string1, int $year)
* @method static currentMonth()
*/ */
class Traffic extends Model class Traffic extends Model
{ {
@@ -22,6 +24,13 @@ class Traffic extends Model
protected $keyType = 'string'; protected $keyType = 'string';
public function scopeCurrentMonth($query): Builder
{
return $query
->whereYear('created_at', '=', now()->year)
->whereMonth('created_at', '=', now()->month);
}
protected static function boot() protected static function boot()
{ {
parent::boot(); parent::boot();
+1 -9
View File
@@ -65,10 +65,6 @@ class FileTest extends TestCase
$disk->assertExists( $disk->assertExists(
"files/$user->id/thumbnail-fake-image.jpg" "files/$user->id/thumbnail-fake-image.jpg"
); );
$this->assertDatabaseHas('traffic', [
'user_id' => $user->id,
]);
} }
/** /**
@@ -77,7 +73,7 @@ class FileTest extends TestCase
public function it_upload_new_file() public function it_upload_new_file()
{ {
$file = UploadedFile::fake() $file = UploadedFile::fake()
->create('fake-file.pdf', 1200, 'application/pdf'); ->create('fake-file.pdf', 12000000, 'application/pdf');
$user = User::factory(User::class) $user = User::factory(User::class)
->create(); ->create();
@@ -100,10 +96,6 @@ class FileTest extends TestCase
$disk->assertExists( $disk->assertExists(
"files/$user->id/fake-file.pdf" "files/$user->id/fake-file.pdf"
); );
$this->assertDatabaseHas('traffic', [
'user_id' => $user->id,
]);
} }
/** /**
@@ -68,10 +68,6 @@ class VisitorAccessToItemsTest extends TestCase
$this->get("/file/$document->name/$share->token") $this->get("/file/$document->name/$share->token")
->assertStatus(200); ->assertStatus(200);
} }
$this->assertDatabaseHas('traffic', [
'user_id' => $user->id,
]);
}); });
} }
@@ -349,10 +349,6 @@ class VisitorManipulatingTest extends TestCase
])->assertStatus(201); ])->assertStatus(201);
} }
$this->assertDatabaseHas('traffic', [
'user_id' => $user->id,
]);
$this->assertDatabaseHas('files', [ $this->assertDatabaseHas('files', [
'author' => 'visitor', 'author' => 'visitor',
]); ]);
+189
View File
@@ -0,0 +1,189 @@
<?php
namespace Tests\Domain\Traffic;
use Storage;
use Tests\TestCase;
use App\Users\Models\User;
use Illuminate\Support\Str;
use Domain\Files\Models\File;
use Domain\Sharing\Models\Share;
use Domain\Folders\Models\Folder;
use Illuminate\Http\UploadedFile;
class TrafficTest extends TestCase
{
public UploadedFile $file;
public User $user;
public function setUp(): void
{
parent::setUp();
$this->file = UploadedFile::fake()
->image('fake-file.jpg', 1200);
$this->user = User::factory()
->create();
}
/**
* @test
*/
public function it_record_user_file_upload()
{
$this
->actingAs($this->user)
->postJson('/api/upload', [
'filename' => $this->file->name,
'file' => $this->file,
'folder_id' => null,
'is_last' => 'true',
])->assertStatus(201);
$this->assertDatabaseHas('traffic', [
'user_id' => $this->user->id,
'upload' => 991,
]);
}
/**
* @test
*/
public function it_record_current_month_and_go_to_the_next_month_and_record_it()
{
$this
->actingAs($this->user)
->postJson('/api/upload', [
'filename' => $this->file->name,
'file' => $this->file,
'folder_id' => null,
'is_last' => 'true',
])->assertStatus(201);
$this->assertDatabaseHas('traffic', [
'user_id' => $this->user->id,
'upload' => 991,
'created_at' => now(),
]);
$this->travel(1)->months();
$secondFile = UploadedFile::fake()
->image('fake-file-2.jpg', 1200);
$this
->actingAs($this->user)
->postJson('/api/upload', [
'filename' => $secondFile->name,
'file' => $secondFile,
'folder_id' => null,
'is_last' => 'true',
])->assertStatus(201);
$this->assertDatabaseHas('traffic', [
'user_id' => $this->user->id,
'upload' => 991,
'created_at' => now(),
]);
$this->assertDatabaseCount('traffic', 2);
}
/**
* @test
*/
public function editor_upload_file_into_shared_folder()
{
$folder = Folder::factory(Folder::class)
->create([
'user_id' => $this->user->id,
'author' => 'user',
]);
$share = Share::factory(Share::class)
->create([
'item_id' => $folder->id,
'user_id' => $this->user->id,
'type' => 'folder',
'is_protected' => false,
'permission' => 'editor',
]);
// Check public shared item
$this->postJson("/api/editor/upload/$share->token", [
'filename' => $this->file->name,
'file' => $this->file,
'folder_id' => $folder->id,
'is_last' => 'true',
])->assertStatus(201);
$this->assertDatabaseHas('traffic', [
'user_id' => $this->user->id,
'upload' => 991,
]);
}
/**
* @test
*/
public function user_download_file()
{
$document = UploadedFile::fake()
->create(Str::random() . '-fake-file.pdf', 1200, 'application/pdf');
Storage::putFileAs("files/{$this->user->id}", $document, $document->name);
File::factory(File::class)
->create([
'filesize' => $document->getSize(),
'user_id' => $this->user->id,
'basename' => $document->name,
'name' => $document->name,
]);
$this
->actingAs($this->user)
->get("/file/$document->name")
->assertStatus(200);
$this->assertDatabaseHas('traffic', [
'user_id' => $this->user->id,
'download' => $document->getSize(),
]);
}
/**
* @test
*/
public function visitor_download_file()
{
$document = UploadedFile::fake()
->create(Str::random() . '-fake-file.pdf', 1200, 'application/pdf');
Storage::putFileAs("files/{$this->user->id}", $document, $document->name);
$file = File::factory(File::class)
->create([
'filesize' => $document->getSize(),
'user_id' => $this->user->id,
'basename' => $document->name,
'name' => $document->name,
]);
$share = Share::factory(Share::class)
->create([
'item_id' => $file->id,
'user_id' => $this->user->id,
'type' => 'file',
'is_protected' => false,
]);
$this->get("/file/$document->name/$share->token")
->assertStatus(200);
$this->assertDatabaseHas('traffic', [
'user_id' => $this->user->id,
'download' => $document->getSize(),
]);
}
}