style updates
This commit is contained in:
@@ -11,8 +11,8 @@ class AnalyticsServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'analytics');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'analytics');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,8 +11,8 @@ class AuditServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'audit');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'audit');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,6 @@ if (! function_exists('audittrail_feature_enabled')) {
|
||||
*/
|
||||
function audittrail_feature_enabled(string $key): bool
|
||||
{
|
||||
return (bool) config(ModuleInfo::nameLower().".features.{$key}", false);
|
||||
return (bool) config(ModuleInfo::nameLower() . ".features.{$key}", false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,8 @@ class AuditTrailController extends Controller
|
||||
/**
|
||||
* Show the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
*
|
||||
* @return Renderable
|
||||
*/
|
||||
public function show($id)
|
||||
@@ -52,7 +53,8 @@ class AuditTrailController extends Controller
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
*
|
||||
* @return Renderable
|
||||
*/
|
||||
public function edit($id)
|
||||
@@ -63,7 +65,8 @@ class AuditTrailController extends Controller
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
*
|
||||
* @return Renderable
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
@@ -74,7 +77,8 @@ class AuditTrailController extends Controller
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
*
|
||||
* @return Renderable
|
||||
*/
|
||||
public function destroy($id)
|
||||
|
||||
@@ -47,7 +47,7 @@ class AuditTrailServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function registerHelpers(): void
|
||||
{
|
||||
foreach (glob(__DIR__.'/../Helpers/*.php') as $filename) {
|
||||
foreach (glob(__DIR__ . '/../Helpers/*.php') as $filename) {
|
||||
require_once $filename;
|
||||
}
|
||||
}
|
||||
@@ -60,10 +60,10 @@ class AuditTrailServiceProvider extends ServiceProvider
|
||||
if (! $this->app->runningInConsole()) {
|
||||
return;
|
||||
}
|
||||
$commandPath = __DIR__.'/../Console';
|
||||
$commandPath = __DIR__ . '/../Console';
|
||||
$commands = collect(File::allFiles($commandPath))
|
||||
->map(function ($file) {
|
||||
$class = 'Modules\\'.$this->moduleName.'\\Console\\'.$file->getFilenameWithoutExtension();
|
||||
$class = 'Modules\\' . $this->moduleName . '\\Console\\' . $file->getFilenameWithoutExtension();
|
||||
|
||||
return $class;
|
||||
})
|
||||
@@ -81,10 +81,11 @@ class AuditTrailServiceProvider extends ServiceProvider
|
||||
protected function registerConfig(): void
|
||||
{
|
||||
$this->publishes([
|
||||
module_path(ModuleInfo::name(), 'Config/config.php') => config_path(ModuleInfo::nameLower().'.php'),
|
||||
module_path(ModuleInfo::name(), 'Config/config.php') => config_path(ModuleInfo::nameLower() . '.php'),
|
||||
], 'config');
|
||||
$this->mergeConfigFrom(
|
||||
module_path(ModuleInfo::name(), 'Config/config.php'), ModuleInfo::nameLower()
|
||||
module_path(ModuleInfo::name(), 'Config/config.php'),
|
||||
ModuleInfo::nameLower(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -93,11 +94,11 @@ class AuditTrailServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function registerViews(): void
|
||||
{
|
||||
$viewPath = resource_path('views/modules/'.ModuleInfo::nameLower());
|
||||
$viewPath = resource_path('views/modules/' . ModuleInfo::nameLower());
|
||||
$sourcePath = module_path(ModuleInfo::name(), 'Resources/views');
|
||||
$this->publishes([
|
||||
$sourcePath => $viewPath,
|
||||
], ['views', ModuleInfo::nameLower().'-module-views']);
|
||||
], ['views', ModuleInfo::nameLower() . '-module-views']);
|
||||
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), ModuleInfo::nameLower());
|
||||
}
|
||||
|
||||
@@ -106,7 +107,7 @@ class AuditTrailServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function registerTranslations(): void
|
||||
{
|
||||
$langPath = resource_path('lang/modules/'.ModuleInfo::nameLower());
|
||||
$langPath = resource_path('lang/modules/' . ModuleInfo::nameLower());
|
||||
|
||||
if (is_dir($langPath)) {
|
||||
$this->loadTranslationsFrom($langPath, ModuleInfo::nameLower());
|
||||
@@ -122,8 +123,8 @@ class AuditTrailServiceProvider extends ServiceProvider
|
||||
{
|
||||
$paths = [];
|
||||
foreach (Config::get('view.paths') as $path) {
|
||||
if (is_dir($path.'/modules/'.ModuleInfo::nameLower())) {
|
||||
$paths[] = $path.'/modules/'.ModuleInfo::nameLower();
|
||||
if (is_dir($path . '/modules/' . ModuleInfo::nameLower())) {
|
||||
$paths[] = $path . '/modules/' . ModuleInfo::nameLower();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ class CarrierManagementServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'carriermanagement');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'carriermanagement');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,8 +11,8 @@ class ConfigurationServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'configuration');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'configuration');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -273,7 +273,7 @@ class IsoCountriesSeeder extends Seeder
|
||||
'iso_status' => 'official',
|
||||
'source' => 'bundled-iso-3166-1',
|
||||
'source_version' => '2026-06-15',
|
||||
])
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ class IsoCountrySubdivisionsSeeder extends Seeder
|
||||
'last_synced_at' => $now,
|
||||
'source' => 'bundled-bootstrap',
|
||||
'source_version' => '2026-06-15',
|
||||
]
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@ if (! function_exists('countries_feature_enabled')) {
|
||||
*/
|
||||
function countries_feature_enabled(string $key): bool
|
||||
{
|
||||
return (bool) config(ModuleInfo::nameLower().".features.{$key}", false);
|
||||
return (bool) config(ModuleInfo::nameLower() . ".features.{$key}", false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class CountriesServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function registerMigrations(): void
|
||||
{
|
||||
$path = dirname(__DIR__).'/Database/Migrations';
|
||||
$path = dirname(__DIR__) . '/Database/Migrations';
|
||||
|
||||
if (is_dir($path)) {
|
||||
$this->loadMigrationsFrom($path);
|
||||
@@ -51,7 +51,7 @@ class CountriesServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function registerHelpers(): void
|
||||
{
|
||||
foreach (glob(dirname(__DIR__).'/Helpers/*.php') ?: [] as $filename) {
|
||||
foreach (glob(dirname(__DIR__) . '/Helpers/*.php') ?: [] as $filename) {
|
||||
require_once $filename;
|
||||
}
|
||||
}
|
||||
@@ -61,14 +61,14 @@ class CountriesServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function registerCommands(): void
|
||||
{
|
||||
$commandPath = dirname(__DIR__).'/Console';
|
||||
$commandPath = dirname(__DIR__) . '/Console';
|
||||
|
||||
if (! is_dir($commandPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$commands = collect(File::allFiles($commandPath))
|
||||
->map(fn ($file): string => 'Modules\\'.$this->moduleName.'\\Console\\'.$file->getFilenameWithoutExtension())
|
||||
->map(fn ($file): string => 'Modules\\' . $this->moduleName . '\\Console\\' . $file->getFilenameWithoutExtension())
|
||||
->filter(fn (string $class): bool => class_exists($class))
|
||||
->values()
|
||||
->all();
|
||||
@@ -83,14 +83,14 @@ class CountriesServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function registerConfig(): void
|
||||
{
|
||||
$sourcePath = dirname(__DIR__).'/Config/config.php';
|
||||
$sourcePath = dirname(__DIR__) . '/Config/config.php';
|
||||
|
||||
if (! is_file($sourcePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->publishes([
|
||||
$sourcePath => config_path(ModuleInfo::nameLower().'.php'),
|
||||
$sourcePath => config_path(ModuleInfo::nameLower() . '.php'),
|
||||
], 'config');
|
||||
|
||||
$this->mergeConfigFrom($sourcePath, ModuleInfo::nameLower());
|
||||
@@ -101,8 +101,8 @@ class CountriesServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function registerViews(): void
|
||||
{
|
||||
$viewPath = resource_path('views/modules/'.ModuleInfo::nameLower());
|
||||
$sourcePath = dirname(__DIR__).'/Resources/views';
|
||||
$viewPath = resource_path('views/modules/' . ModuleInfo::nameLower());
|
||||
$sourcePath = dirname(__DIR__) . '/Resources/views';
|
||||
|
||||
if (! is_dir($sourcePath)) {
|
||||
return;
|
||||
@@ -110,7 +110,7 @@ class CountriesServiceProvider extends ServiceProvider
|
||||
|
||||
$this->publishes([
|
||||
$sourcePath => $viewPath,
|
||||
], ['views', ModuleInfo::nameLower().'-module-views']);
|
||||
], ['views', ModuleInfo::nameLower() . '-module-views']);
|
||||
|
||||
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), ModuleInfo::nameLower());
|
||||
}
|
||||
@@ -120,8 +120,8 @@ class CountriesServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function registerTranslations(): void
|
||||
{
|
||||
$publishedPath = resource_path('lang/modules/'.ModuleInfo::nameLower());
|
||||
$sourcePath = dirname(__DIR__).'/Resources/lang';
|
||||
$publishedPath = resource_path('lang/modules/' . ModuleInfo::nameLower());
|
||||
$sourcePath = dirname(__DIR__) . '/Resources/lang';
|
||||
|
||||
if (is_dir($publishedPath)) {
|
||||
$this->loadTranslationsFrom($publishedPath, ModuleInfo::nameLower());
|
||||
@@ -144,8 +144,8 @@ class CountriesServiceProvider extends ServiceProvider
|
||||
$paths = [];
|
||||
|
||||
foreach (Config::get('view.paths', []) as $path) {
|
||||
if (is_dir($path.'/modules/'.ModuleInfo::nameLower())) {
|
||||
$paths[] = $path.'/modules/'.ModuleInfo::nameLower();
|
||||
if (is_dir($path . '/modules/' . ModuleInfo::nameLower())) {
|
||||
$paths[] = $path . '/modules/' . ModuleInfo::nameLower();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function mapWebRoutes(): void
|
||||
{
|
||||
$path = dirname(__DIR__).'/Routes/web.php';
|
||||
$path = dirname(__DIR__) . '/Routes/web.php';
|
||||
|
||||
if (is_file($path)) {
|
||||
Route::middleware(['web', 'auth'])->group($path);
|
||||
@@ -33,7 +33,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function mapApiRoutes(): void
|
||||
{
|
||||
$path = dirname(__DIR__).'/Routes/api.php';
|
||||
$path = dirname(__DIR__) . '/Routes/api.php';
|
||||
|
||||
if (is_file($path)) {
|
||||
Route::middleware(['api'])->prefix('api/v1')->group($path);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
|
||||
use Modules\Countries\Http\Controllers\CountriesController;
|
||||
use Modules\Countries\Http\Controllers\CountrySyncController;
|
||||
use Modules\Countries\Http\Controllers\ReferenceDataController;
|
||||
|
||||
@@ -69,7 +69,7 @@ final class Iso3166
|
||||
$country = self::normaliseAlpha2($countryAlpha2);
|
||||
$code = strtoupper(trim($subdivisionCode));
|
||||
|
||||
if (str_starts_with($code, $country.'-')) {
|
||||
if (str_starts_with($code, $country . '-')) {
|
||||
return $code;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ final class Iso3166
|
||||
throw new InvalidArgumentException('ISO 3166-2 subdivision codes must contain 1 to 6 letters or numbers after the country prefix.');
|
||||
}
|
||||
|
||||
return $country.'-'.$code;
|
||||
return $country . '-' . $code;
|
||||
}
|
||||
|
||||
public static function flagEmoji(string $alpha2): string
|
||||
@@ -85,6 +85,6 @@ final class Iso3166
|
||||
$alpha2 = self::normaliseAlpha2($alpha2);
|
||||
$base = 127397;
|
||||
|
||||
return mb_chr($base + ord($alpha2[0]), 'UTF-8').mb_chr($base + ord($alpha2[1]), 'UTF-8');
|
||||
return mb_chr($base + ord($alpha2[0]), 'UTF-8') . mb_chr($base + ord($alpha2[1]), 'UTF-8');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ class DocumentArchiveServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'documentarchive');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'documentarchive');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,7 +31,7 @@ class DocumentationController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$search = '%'.$request->string('search')->trim()->toString().'%';
|
||||
$search = '%' . $request->string('search')->trim()->toString() . '%';
|
||||
$query->where(function ($builder) use ($search): void {
|
||||
$builder->where('title', 'like', $search)
|
||||
->orWhere('summary', 'like', $search)
|
||||
|
||||
@@ -33,9 +33,9 @@ class StoreDocumentationDocumentRequest extends FormRequest
|
||||
'is_featured' => ['nullable', 'boolean'],
|
||||
'version' => ['required', 'string', 'max:50'],
|
||||
'reference' => ['nullable', 'string', 'max:100'],
|
||||
'attachment' => ['nullable', 'file', 'max:'.config('documentation.max_upload_kb', 20480), 'mimes:'.implode(',', config('documentation.allowed_upload_mimes', []))],
|
||||
'attachment' => ['nullable', 'file', 'max:' . config('documentation.max_upload_kb', 20480), 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))],
|
||||
'attachments' => ['nullable', 'array'],
|
||||
'attachments.*' => ['file', 'max:'.config('documentation.max_upload_kb', 20480), 'mimes:'.implode(',', config('documentation.allowed_upload_mimes', []))],
|
||||
'attachments.*' => ['file', 'max:' . config('documentation.max_upload_kb', 20480), 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,9 +36,9 @@ class UpdateDocumentationDocumentRequest extends FormRequest
|
||||
'is_featured' => ['nullable', 'boolean'],
|
||||
'version' => ['required', 'string', 'max:50'],
|
||||
'reference' => ['nullable', 'string', 'max:100'],
|
||||
'attachment' => ['nullable', 'file', 'max:'.config('documentation.max_upload_kb', 20480), 'mimes:'.implode(',', config('documentation.allowed_upload_mimes', []))],
|
||||
'attachment' => ['nullable', 'file', 'max:' . config('documentation.max_upload_kb', 20480), 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))],
|
||||
'attachments' => ['nullable', 'array'],
|
||||
'attachments.*' => ['file', 'max:'.config('documentation.max_upload_kb', 20480), 'mimes:'.implode(',', config('documentation.allowed_upload_mimes', []))],
|
||||
'attachments.*' => ['file', 'max:' . config('documentation.max_upload_kb', 20480), 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))],
|
||||
'remove_attachment' => ['nullable', 'boolean'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -7,13 +7,13 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property int $documentation_document_id
|
||||
* @property string $disk
|
||||
* @property string $path
|
||||
* @property string $original_name
|
||||
* @property int $id
|
||||
* @property int $documentation_document_id
|
||||
* @property string $disk
|
||||
* @property string $path
|
||||
* @property string $original_name
|
||||
* @property string|null $mime_type
|
||||
* @property int|null $size
|
||||
* @property int|null $size
|
||||
*/
|
||||
class DocumentationAttachment extends Model
|
||||
{
|
||||
@@ -57,13 +57,13 @@ class DocumentationAttachment extends Model
|
||||
}
|
||||
|
||||
if ($bytes < 1024) {
|
||||
return $bytes.' B';
|
||||
return $bytes . ' B';
|
||||
}
|
||||
|
||||
if ($bytes < 1048576) {
|
||||
return number_format($bytes / 1024, 1).' KB';
|
||||
return number_format($bytes / 1024, 1) . ' KB';
|
||||
}
|
||||
|
||||
return number_format($bytes / 1048576, 1).' MB';
|
||||
return number_format($bytes / 1048576, 1) . ' MB';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,14 +9,14 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $slug
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $slug
|
||||
* @property string|null $icon
|
||||
* @property string $colour
|
||||
* @property string $colour
|
||||
* @property string|null $description
|
||||
* @property int $sort_order
|
||||
* @property bool $is_active
|
||||
* @property int $sort_order
|
||||
* @property bool $is_active
|
||||
*/
|
||||
class DocumentationCategory extends Model
|
||||
{
|
||||
@@ -66,7 +66,8 @@ class DocumentationCategory extends Model
|
||||
/**
|
||||
* Active category scope.
|
||||
*
|
||||
* @param Builder<DocumentationCategory> $query
|
||||
* @param Builder<DocumentationCategory> $query
|
||||
*
|
||||
* @return Builder<DocumentationCategory>
|
||||
*/
|
||||
public function scopeActive(Builder $query): Builder
|
||||
@@ -77,7 +78,8 @@ class DocumentationCategory extends Model
|
||||
/**
|
||||
* Ordered category scope.
|
||||
*
|
||||
* @param Builder<DocumentationCategory> $query
|
||||
* @param Builder<DocumentationCategory> $query
|
||||
*
|
||||
* @return Builder<DocumentationCategory>
|
||||
*/
|
||||
public function scopeOrdered(Builder $query): Builder
|
||||
|
||||
@@ -11,15 +11,15 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property int|null $documentation_category_id
|
||||
* @property string $title
|
||||
* @property string $slug
|
||||
* @property int $id
|
||||
* @property int|null $documentation_category_id
|
||||
* @property string $title
|
||||
* @property string $slug
|
||||
* @property string|null $summary
|
||||
* @property string|null $body
|
||||
* @property string $status
|
||||
* @property bool $is_featured
|
||||
* @property string $version
|
||||
* @property string $status
|
||||
* @property bool $is_featured
|
||||
* @property string $version
|
||||
* @property string|null $reference
|
||||
* @property-read string $rendered_body
|
||||
*/
|
||||
@@ -101,7 +101,8 @@ class DocumentationDocument extends Model
|
||||
/**
|
||||
* Published document scope.
|
||||
*
|
||||
* @param Builder<DocumentationDocument> $query
|
||||
* @param Builder<DocumentationDocument> $query
|
||||
*
|
||||
* @return Builder<DocumentationDocument>
|
||||
*/
|
||||
public function scopePublished(Builder $query): Builder
|
||||
@@ -112,7 +113,8 @@ class DocumentationDocument extends Model
|
||||
/**
|
||||
* Featured document scope.
|
||||
*
|
||||
* @param Builder<DocumentationDocument> $query
|
||||
* @param Builder<DocumentationDocument> $query
|
||||
*
|
||||
* @return Builder<DocumentationDocument>
|
||||
*/
|
||||
public function scopeFeatured(Builder $query): Builder
|
||||
@@ -138,7 +140,7 @@ class DocumentationDocument extends Model
|
||||
]);
|
||||
}
|
||||
|
||||
return '<p>'.nl2br(e($body), false).'</p>';
|
||||
return '<p>' . nl2br(e($body), false) . '</p>';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@ final class DocumentationServiceProvider extends ServiceProvider
|
||||
|
||||
$this->mergeConfigFrom(
|
||||
module_path('Documentation', 'Config/config.php'),
|
||||
'documentation'
|
||||
'documentation',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -47,12 +47,12 @@ final class DocumentationServiceProvider extends ServiceProvider
|
||||
$paths = [$sourcePath];
|
||||
|
||||
foreach (Config::get('view.paths', []) as $path) {
|
||||
if (is_dir($path.'/modules/documentation')) {
|
||||
array_unshift($paths, $path.'/modules/documentation');
|
||||
if (is_dir($path . '/modules/documentation')) {
|
||||
array_unshift($paths, $path . '/modules/documentation');
|
||||
}
|
||||
}
|
||||
|
||||
$this->loadViewsFrom($paths, 'documentation');
|
||||
Blade::anonymousComponentPath($sourcePath.'/components', 'documentation');
|
||||
Blade::anonymousComponentPath($sourcePath . '/components', 'documentation');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ class DocumentationModuleTest extends TestCase
|
||||
/**
|
||||
* Add a CSRF token for projects that keep web middleware enabled during tests.
|
||||
*
|
||||
* @param array<string, mixed> $payload
|
||||
* @param array<string, mixed> $payload
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function csrfPayload(array $payload): array
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ return new class extends Migration
|
||||
'sort_order' => ($index + 1) * 10,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -74,7 +74,7 @@ return new class extends Migration
|
||||
Comment::query()->orderBy('id')->chunkById(100, static function ($comments): void {
|
||||
foreach ($comments as $comment) {
|
||||
$guid = $comment->guid ?: (string) Str::uuid();
|
||||
$unid = $comment->unid ?: strtoupper(hash('sha256', $guid.'|'.$comment->ticket_id.'|'.$comment->id));
|
||||
$unid = $comment->unid ?: strtoupper(hash('sha256', $guid . '|' . $comment->ticket_id . '|' . $comment->id));
|
||||
$parent = $comment->parent_id ? Comment::query()->find($comment->parent_id) : null;
|
||||
$parentUnid = $parent?->unid;
|
||||
$rootUnid = $parent?->root_unid ?: $parentUnid ?: $unid;
|
||||
@@ -86,7 +86,7 @@ return new class extends Migration
|
||||
'unid' => $unid,
|
||||
'parent_unid' => $parentUnid,
|
||||
'root_unid' => $rootUnid,
|
||||
'originator_id' => $comment->originator_id ?: $unid.':1',
|
||||
'originator_id' => $comment->originator_id ?: $unid . ':1',
|
||||
'sync_sequence' => $comment->sync_sequence ?: 1,
|
||||
'sync_hash' => hash('sha256', (string) $comment->body),
|
||||
'body_text' => trim(strip_tags((string) $comment->body)),
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ return new class extends Migration
|
||||
$plain = trim(preg_replace('/\s+/', ' ', strip_tags((string) ($comment->body_text ?: $comment->body))) ?: '');
|
||||
$subject = (bool) $comment->is_internal
|
||||
? 'Internal note'
|
||||
: ((int) ($comment->parent_id ?? 0) > 0 ? 'RE: ' : '').Str::limit($plain !== '' ? $plain : 'Response', 120, '');
|
||||
: ((int) ($comment->parent_id ?? 0) > 0 ? 'RE: ' : '') . Str::limit($plain !== '' ? $plain : 'Response', 120, '');
|
||||
|
||||
DB::table('helpdesk_comments')
|
||||
->where('id', $comment->id)
|
||||
|
||||
@@ -89,7 +89,7 @@ final class HelpdeskDatabaseSeeder extends Seeder
|
||||
] as $row) {
|
||||
Category::query()->updateOrCreate(
|
||||
['company_id' => null, 'slug' => Str::slug($row['name'])],
|
||||
$row + ['company_id' => null, 'slug' => Str::slug($row['name'])]
|
||||
$row + ['company_id' => null, 'slug' => Str::slug($row['name'])],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ final class HelpdeskDatabaseSeeder extends Seeder
|
||||
'color' => 'blue',
|
||||
'description' => 'Default support team for triage, ownership and ticket routing.',
|
||||
'is_default' => true,
|
||||
]
|
||||
],
|
||||
);
|
||||
|
||||
Project::query()->updateOrCreate(
|
||||
@@ -132,7 +132,7 @@ final class HelpdeskDatabaseSeeder extends Seeder
|
||||
'color' => 'indigo',
|
||||
'description' => 'Default project for operational helpdesk tickets.',
|
||||
'is_default' => true,
|
||||
]
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ final class HelpdeskDatabaseSeeder extends Seeder
|
||||
'description' => 'Default Helpdesk workflow board covering new work through closure.',
|
||||
'is_default' => true,
|
||||
'sort_order' => 1,
|
||||
]
|
||||
],
|
||||
);
|
||||
|
||||
$statuses = Status::query()
|
||||
@@ -181,7 +181,7 @@ final class HelpdeskDatabaseSeeder extends Seeder
|
||||
] as $template) {
|
||||
WorkflowTemplate::query()->updateOrCreate(
|
||||
['name' => $template['name'], 'event' => $template['event']],
|
||||
$template + ['text_body' => null, 'cc' => null, 'bcc' => null, 'is_active' => true]
|
||||
$template + ['text_body' => null, 'cc' => null, 'bcc' => null, 'is_active' => true],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -207,7 +207,7 @@ final class HelpdeskDatabaseSeeder extends Seeder
|
||||
'business_hours_only' => false,
|
||||
'is_default' => true,
|
||||
'is_active' => true,
|
||||
]
|
||||
],
|
||||
);
|
||||
|
||||
CannedResponse::query()->updateOrCreate(
|
||||
@@ -223,7 +223,7 @@ final class HelpdeskDatabaseSeeder extends Seeder
|
||||
'body' => '<p>Hello {{ requester.name }},</p><p>Thank you for the update on {{ ticket.reference }}. I am reviewing this now and will come back with the next action shortly.</p><p>Regards,<br>{{ agent.name }}</p>',
|
||||
'is_active' => true,
|
||||
'sort_order' => 10,
|
||||
]
|
||||
],
|
||||
);
|
||||
|
||||
ChecklistTemplate::query()->updateOrCreate(
|
||||
@@ -236,7 +236,7 @@ final class HelpdeskDatabaseSeeder extends Seeder
|
||||
'slug' => 'bug-triage-checklist',
|
||||
'items' => ['Confirm reproduction steps', 'Check recent deployment/build', 'Identify affected tenant/company', 'Record fix or workaround'],
|
||||
'is_active' => true,
|
||||
]
|
||||
],
|
||||
);
|
||||
|
||||
foreach ([
|
||||
@@ -245,7 +245,7 @@ final class HelpdeskDatabaseSeeder extends Seeder
|
||||
] as $tag) {
|
||||
Tag::query()->updateOrCreate(
|
||||
['company_id' => null, 'slug' => $tag['slug']],
|
||||
$tag + ['company_id' => null]
|
||||
$tag + ['company_id' => null],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -267,7 +267,7 @@ final class HelpdeskDatabaseSeeder extends Seeder
|
||||
'release_channel' => 'core',
|
||||
'description' => 'Default service record for WMS platform support tickets.',
|
||||
'is_active' => true,
|
||||
]
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ final class HelpdeskLivewireAssetsTest extends TestCase
|
||||
self::assertLessThan(
|
||||
strpos($layout, '@fluxScripts'),
|
||||
strpos($layout, '@livewireScripts'),
|
||||
'Livewire scripts must be loaded before Flux scripts so settings CRUD actions fire in the browser.'
|
||||
'Livewire scripts must be loaded before Flux scripts so settings CRUD actions fire in the browser.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ final class GitWebhookController
|
||||
private function hasValidGitHubSignature(Request $request, string $secret, string $rawPayload): bool
|
||||
{
|
||||
$signature = (string) $request->header('X-Hub-Signature-256', '');
|
||||
$expected = 'sha256='.hash_hmac('sha256', $rawPayload, $secret);
|
||||
$expected = 'sha256=' . hash_hmac('sha256', $rawPayload, $secret);
|
||||
|
||||
return hash_equals($expected, $signature);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace Modules\Helpdesk\Http\Controllers;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Modules\Helpdesk\Models\Ticket;
|
||||
@@ -26,7 +27,7 @@ final class TicketAttachmentStoreController extends Controller
|
||||
|
||||
$request->validate([
|
||||
'attachments' => ['required', 'array', 'min:1'],
|
||||
'attachments.*' => ['required', 'file', 'max:'.$maxUploadKilobytes, 'mimes:'.implode(',', $allowedMimes)],
|
||||
'attachments.*' => ['required', 'file', 'max:' . $maxUploadKilobytes, 'mimes:' . implode(',', $allowedMimes)],
|
||||
]);
|
||||
|
||||
$user = Auth::user();
|
||||
@@ -34,12 +35,12 @@ final class TicketAttachmentStoreController extends Controller
|
||||
|
||||
$uploadedFiles = $request->file('attachments', []);
|
||||
$uploadedFiles = is_array($uploadedFiles) ? $uploadedFiles : [$uploadedFiles];
|
||||
$uploadedFiles = array_values(array_filter($uploadedFiles, static fn ($file): bool => $file instanceof \Illuminate\Http\UploadedFile && $file->isValid()));
|
||||
$uploadedFiles = array_values(array_filter($uploadedFiles, static fn ($file): bool => $file instanceof UploadedFile && $file->isValid()));
|
||||
|
||||
$attachments->storeMany($ticket, $uploadedFiles, (int) $user->id);
|
||||
|
||||
return redirect()
|
||||
->route('helpdesk.tickets.show', $ticket)
|
||||
->with('ticket-attachments-added', count($uploadedFiles).' supporting file'.(count($uploadedFiles) === 1 ? '' : 's').' uploaded.');
|
||||
->with('ticket-attachments-added', count($uploadedFiles) . ' supporting file' . (count($uploadedFiles) === 1 ? '' : 's') . ' uploaded.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace Modules\Helpdesk\Http\Controllers;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Str;
|
||||
@@ -42,7 +43,7 @@ final class TicketCommentStoreController extends Controller
|
||||
],
|
||||
'canned_response_id' => ['nullable', 'integer', Rule::exists('helpdesk_canned_responses', 'id')],
|
||||
'attachments' => ['nullable', 'array'],
|
||||
'attachments.*' => ['file', 'max:'.$maxUploadKilobytes, 'mimes:'.implode(',', $allowedMimes)],
|
||||
'attachments.*' => ['file', 'max:' . $maxUploadKilobytes, 'mimes:' . implode(',', $allowedMimes)],
|
||||
]);
|
||||
|
||||
$user = Auth::user();
|
||||
@@ -74,7 +75,7 @@ final class TicketCommentStoreController extends Controller
|
||||
|
||||
$uploadedFiles = $request->file('attachments', []);
|
||||
$uploadedFiles = is_array($uploadedFiles) ? $uploadedFiles : [$uploadedFiles];
|
||||
$uploadedFiles = array_values(array_filter($uploadedFiles, static fn ($file): bool => $file instanceof \Illuminate\Http\UploadedFile && $file->isValid()));
|
||||
$uploadedFiles = array_values(array_filter($uploadedFiles, static fn ($file): bool => $file instanceof UploadedFile && $file->isValid()));
|
||||
|
||||
$tickets->comment(
|
||||
ticket: $ticket,
|
||||
@@ -108,7 +109,7 @@ final class TicketCommentStoreController extends Controller
|
||||
return $isReply ? 'RE: Response' : 'Response';
|
||||
}
|
||||
|
||||
return ($isReply ? 'RE: ' : '').Str::limit($plain, 120, '');
|
||||
return ($isReply ? 'RE: ' : '') . Str::limit($plain, 120, '');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,7 +146,7 @@ final class TicketCommentStoreController extends Controller
|
||||
return collect(preg_split('/\R{2,}/', $body) ?: [])
|
||||
->map(static fn (string $paragraph): string => trim($paragraph))
|
||||
->filter(static fn (string $paragraph): bool => $paragraph !== '')
|
||||
->map(static fn (string $paragraph): string => '<p>'.nl2br(e($paragraph), false).'</p>')
|
||||
->map(static fn (string $paragraph): string => '<p>' . nl2br(e($paragraph), false) . '</p>')
|
||||
->implode('');
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ final class TicketControlsController extends Controller
|
||||
->route('helpdesk.tickets.show', $fresh)
|
||||
->with('ticket-action-updated', $agentId === null
|
||||
? 'Ticket is now unassigned.'
|
||||
: 'Ticket assigned to '.($fresh->agent?->name ?? 'selected agent').'.');
|
||||
: 'Ticket assigned to ' . ($fresh->agent?->name ?? 'selected agent') . '.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +107,7 @@ final class TicketControlsController extends Controller
|
||||
(bool) ($validated['closure_internal'] ?? false),
|
||||
[],
|
||||
null,
|
||||
'Closure comment'
|
||||
'Closure comment',
|
||||
);
|
||||
|
||||
$fresh = $this->freshTicketForAction($ticket);
|
||||
@@ -118,7 +118,7 @@ final class TicketControlsController extends Controller
|
||||
|
||||
return redirect()
|
||||
->route('helpdesk.tickets.show', $fresh)
|
||||
->with('ticket-action-updated', 'Status updated to '.($fresh->status?->name ?? 'selected status').'.');
|
||||
->with('ticket-action-updated', 'Status updated to ' . ($fresh->status?->name ?? 'selected status') . '.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,13 +144,13 @@ final class TicketControlsController extends Controller
|
||||
|
||||
return redirect()
|
||||
->route('helpdesk.tickets.show', $fresh)
|
||||
->with('ticket-action-updated', 'Priority updated to '.($fresh->priority?->name ?? 'selected priority').'.');
|
||||
->with('ticket-action-updated', 'Priority updated to ' . ($fresh->priority?->name ?? 'selected priority') . '.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a direct guarded ticket update without relying on Livewire hydration.
|
||||
*
|
||||
* @param array<string, mixed> $updates
|
||||
* @param array<string, mixed> $updates
|
||||
*/
|
||||
private function updateTicket(Ticket $ticket, array $updates): void
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@ final class TicketStoreController extends Controller
|
||||
'team_id' => ['nullable', 'integer', Rule::exists('helpdesk_teams', 'id')],
|
||||
'due_at' => ['nullable', 'date'],
|
||||
'attachments' => ['nullable', 'array'],
|
||||
'attachments.*' => ['file', 'max:'.$maxUploadKilobytes, 'mimes:'.implode(',', $allowedMimes)],
|
||||
'attachments.*' => ['file', 'max:' . $maxUploadKilobytes, 'mimes:' . implode(',', $allowedMimes)],
|
||||
]);
|
||||
|
||||
$user = Auth::user();
|
||||
@@ -59,6 +59,6 @@ final class TicketStoreController extends Controller
|
||||
|
||||
return redirect()
|
||||
->route('helpdesk.tickets.index')
|
||||
->with('success', 'Ticket '.$ticket->reference.' has been created.');
|
||||
->with('success', 'Ticket ' . $ticket->reference . ' has been created.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +66,10 @@ final class KanbanBoard extends Component
|
||||
$workflow->dispatch(
|
||||
$freshTicket,
|
||||
$status->is_closed ? 'ticket.closed' : 'ticket.updated',
|
||||
Auth::user()
|
||||
Auth::user(),
|
||||
);
|
||||
|
||||
$message = 'Ticket '.$freshTicket->reference.' moved from '.$oldStatusName.' to '.$status->name.'.';
|
||||
$message = 'Ticket ' . $freshTicket->reference . ' moved from ' . $oldStatusName . ' to ' . $status->name . '.';
|
||||
session()->flash('success', $message);
|
||||
|
||||
$this->refreshBoard();
|
||||
@@ -112,7 +112,7 @@ final class KanbanBoard extends Component
|
||||
$fresh = $ticket->fresh(['status', 'priority', 'category', 'project', 'team', 'board']) ?? $ticket;
|
||||
$workflow->dispatch($fresh, 'ticket.updated', Auth::user());
|
||||
|
||||
$message = 'Ticket '.$fresh->reference.' moved from '.$oldBoardName.' to '.$board->name.'.';
|
||||
$message = 'Ticket ' . $fresh->reference . ' moved from ' . $oldBoardName . ' to ' . $board->name . '.';
|
||||
session()->flash('success', $message);
|
||||
|
||||
$this->refreshBoard();
|
||||
@@ -213,7 +213,7 @@ final class KanbanBoard extends Component
|
||||
/**
|
||||
* Resolve the selected board from an already-loaded board collection.
|
||||
*
|
||||
* @param Collection<int, KanbanBoardModel> $boards
|
||||
* @param Collection<int, KanbanBoardModel> $boards
|
||||
*/
|
||||
private function resolveSelectedBoard(Collection $boards): ?KanbanBoardModel
|
||||
{
|
||||
@@ -241,7 +241,7 @@ final class KanbanBoard extends Component
|
||||
{
|
||||
DB::table('helpdesk_kanban_board_statuses')->updateOrInsert(
|
||||
['board_id' => $boardId, 'status_id' => $statusId],
|
||||
['sort_order' => 999, 'updated_at' => now(), 'created_at' => now()]
|
||||
['sort_order' => 999, 'updated_at' => now(), 'created_at' => now()],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ final class KanbanBoard extends Component
|
||||
'sort_order' => ($index + 1) * 10,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ namespace Modules\Helpdesk\Livewire;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Str;
|
||||
@@ -824,9 +826,11 @@ final class SettingsManager extends Component
|
||||
* which made every new Helpdesk settings CRUD form appear to do nothing.
|
||||
*
|
||||
* @template TModel of \Illuminate\Database\Eloquent\Model
|
||||
* @param class-string<TModel> $modelClass
|
||||
* @param int|string|null $id
|
||||
* @param array<string, mixed> $data
|
||||
*
|
||||
* @param class-string<TModel> $modelClass
|
||||
* @param int|string|null $id
|
||||
* @param array<string, mixed> $data
|
||||
*
|
||||
* @return TModel
|
||||
*/
|
||||
private function persistSettingModel(string $modelClass, int|string|null $id, array $data): object
|
||||
@@ -847,7 +851,7 @@ final class SettingsManager extends Component
|
||||
$model = $modelClass::query()->create($data);
|
||||
|
||||
return $model;
|
||||
} catch (\Illuminate\Database\QueryException $exception) {
|
||||
} catch (QueryException $exception) {
|
||||
throw ValidationException::withMessages([
|
||||
'settings' => 'The record could not be saved. Check the slug is unique for this section/company and try again.',
|
||||
]);
|
||||
@@ -857,7 +861,7 @@ final class SettingsManager extends Component
|
||||
/**
|
||||
* Clear the default flag on every other record without generating invalid null-id SQL.
|
||||
*
|
||||
* @param class-string<\Illuminate\Database\Eloquent\Model> $modelClass
|
||||
* @param class-string<Model> $modelClass
|
||||
*/
|
||||
private function clearOtherDefaults(string $modelClass, int|string|null $currentId, int|string|null $companyId = null): void
|
||||
{
|
||||
@@ -867,7 +871,7 @@ final class SettingsManager extends Component
|
||||
$query->whereKeyNot((int) $currentId);
|
||||
}
|
||||
|
||||
if (Schema::hasColumn((new $modelClass())->getTable(), 'company_id')) {
|
||||
if (Schema::hasColumn((new $modelClass)->getTable(), 'company_id')) {
|
||||
$query->where('company_id', filled($companyId) ? (int) $companyId : null);
|
||||
}
|
||||
|
||||
@@ -881,7 +885,7 @@ final class SettingsManager extends Component
|
||||
* nullable integer and exists rules expect a real null, so normalising here
|
||||
* keeps every settings CRUD form usable from the browser.
|
||||
*
|
||||
* @param array<int, string> $keys
|
||||
* @param array<int, string> $keys
|
||||
*/
|
||||
private function normalizeNullableFormValues(string $formProperty, array $keys): void
|
||||
{
|
||||
@@ -906,7 +910,8 @@ final class SettingsManager extends Component
|
||||
/**
|
||||
* Remove is_default before save when the database has not been migrated yet.
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
* @param array<string, mixed> $data
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function guardDefaultColumn(string $table, array $data): array
|
||||
|
||||
@@ -52,7 +52,6 @@ final class TicketCreate extends Component
|
||||
|
||||
public bool $isSaving = false;
|
||||
|
||||
|
||||
/**
|
||||
* Validation rules are intentionally evaluated only when the user submits
|
||||
* the form, not while rich-text/select widgets are synchronising.
|
||||
@@ -77,8 +76,8 @@ final class TicketCreate extends Component
|
||||
'attachments' => ['array'],
|
||||
'attachments.*' => [
|
||||
'file',
|
||||
'max:'.config('helpdesk.max_upload_kb'),
|
||||
'mimes:'.implode(',', config('helpdesk.allowed_mimes')),
|
||||
'max:' . config('helpdesk.max_upload_kb'),
|
||||
'mimes:' . implode(',', config('helpdesk.allowed_mimes')),
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -121,7 +120,7 @@ final class TicketCreate extends Component
|
||||
'tag_ids' => $this->tag_ids,
|
||||
], $this->attachments);
|
||||
|
||||
session()->flash('success', 'Ticket '.$ticket->reference.' has been created.');
|
||||
session()->flash('success', 'Ticket ' . $ticket->reference . ' has been created.');
|
||||
|
||||
return $this->redirectRoute('helpdesk.tickets.index', navigate: true);
|
||||
} finally {
|
||||
|
||||
@@ -109,7 +109,7 @@ final class TicketEdit extends Component
|
||||
$this->validate();
|
||||
$this->validate([
|
||||
'attachments' => 'array',
|
||||
'attachments.*' => 'file|max:'.config('helpdesk.max_upload_kb', 10240).'|mimes:'.implode(',', config('helpdesk.allowed_mimes', ['jpg', 'jpeg', 'png', 'pdf', 'txt', 'log', 'zip'])),
|
||||
'attachments.*' => 'file|max:' . config('helpdesk.max_upload_kb', 10240) . '|mimes:' . implode(',', config('helpdesk.allowed_mimes', ['jpg', 'jpeg', 'png', 'pdf', 'txt', 'log', 'zip'])),
|
||||
'tag_ids.*' => 'integer|exists:helpdesk_tags,id',
|
||||
]);
|
||||
|
||||
@@ -142,7 +142,7 @@ final class TicketEdit extends Component
|
||||
$fresh = $this->freshTicket($this->ticket);
|
||||
$workflow->dispatch($fresh, $status->is_closed ? 'ticket.closed' : 'ticket.updated', Auth::user());
|
||||
|
||||
session()->flash('success', 'Ticket '.$fresh->reference.' has been updated.');
|
||||
session()->flash('success', 'Ticket ' . $fresh->reference . ' has been updated.');
|
||||
|
||||
return redirect()->route('helpdesk.tickets.show', $fresh);
|
||||
}
|
||||
@@ -276,7 +276,7 @@ final class TicketEdit extends Component
|
||||
}
|
||||
|
||||
$disk = (string) config('helpdesk.disk', 'local');
|
||||
$path = $upload->store('tickets/'.$this->ticket->id, $disk);
|
||||
$path = $upload->store('tickets/' . $this->ticket->id, $disk);
|
||||
$this->ticket->attachments()->create($this->attachmentPayload($upload, $path, $disk));
|
||||
}
|
||||
|
||||
|
||||
@@ -133,9 +133,9 @@ final class TicketIndex extends Component
|
||||
->when($this->priority !== '', fn (Builder $query): Builder => $query->where('priority_id', (int) $this->priority))
|
||||
->when($search !== '', static function (Builder $query) use ($search): Builder {
|
||||
return $query->where(static function (Builder $subQuery) use ($search): void {
|
||||
$subQuery->where('reference', 'like', '%'.$search.'%')
|
||||
->orWhere('subject', 'like', '%'.$search.'%')
|
||||
->orWhere('body', 'like', '%'.$search.'%');
|
||||
$subQuery->where('reference', 'like', '%' . $search . '%')
|
||||
->orWhere('subject', 'like', '%' . $search . '%')
|
||||
->orWhere('body', 'like', '%' . $search . '%');
|
||||
});
|
||||
})
|
||||
->latest('last_activity_at')
|
||||
|
||||
@@ -92,7 +92,7 @@ final class TicketShow extends Component
|
||||
|
||||
$this->validate([
|
||||
'commentBody' => ['required', 'string', 'min:2'],
|
||||
'attachments.*' => 'file|max:'.config('helpdesk.max_upload_kb', 10240).'|mimes:'.implode(',', config('helpdesk.allowed_mimes', ['jpg', 'jpeg', 'png', 'pdf', 'txt', 'log', 'zip'])),
|
||||
'attachments.*' => 'file|max:' . config('helpdesk.max_upload_kb', 10240) . '|mimes:' . implode(',', config('helpdesk.allowed_mimes', ['jpg', 'jpeg', 'png', 'pdf', 'txt', 'log', 'zip'])),
|
||||
]);
|
||||
|
||||
$tickets->comment($this->ticket, Auth::user(), $this->commentBody, $this->internal, $this->attachments);
|
||||
@@ -120,7 +120,6 @@ final class TicketShow extends Component
|
||||
$this->dispatch('helpdesk-reply-added');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Refresh ticket aggregates and the time-log modal after the timer component starts or stops.
|
||||
*/
|
||||
@@ -143,7 +142,7 @@ final class TicketShow extends Component
|
||||
->findOrFail($this->canned_response_id);
|
||||
|
||||
$rendered = $renderer->render($response->body, $this->ticket, Auth::user());
|
||||
$this->commentBody = trim($this->commentBody."\n\n".$rendered);
|
||||
$this->commentBody = trim($this->commentBody . "\n\n" . $rendered);
|
||||
$this->dispatch('helpdesk-canned-response-applied', body: $this->commentBody);
|
||||
}
|
||||
|
||||
@@ -211,7 +210,7 @@ final class TicketShow extends Component
|
||||
$this->closureInternal,
|
||||
[],
|
||||
null,
|
||||
'Closure comment'
|
||||
'Closure comment',
|
||||
);
|
||||
|
||||
$this->reset(['closureComment', 'closureInternal']);
|
||||
@@ -221,7 +220,7 @@ final class TicketShow extends Component
|
||||
|
||||
$workflow->dispatch($this->ticket, $status->is_closed ? 'ticket.closed' : 'ticket.updated', Auth::user());
|
||||
|
||||
session()->flash('ticket-action-updated', 'Status updated to '.$this->ticket->status?->name.'.');
|
||||
session()->flash('ticket-action-updated', 'Status updated to ' . $this->ticket->status?->name . '.');
|
||||
$this->dispatch('helpdesk-status-updated', statusId: $this->status_id);
|
||||
}
|
||||
|
||||
@@ -254,7 +253,7 @@ final class TicketShow extends Component
|
||||
|
||||
$workflow->dispatch($this->ticket, 'ticket.updated', Auth::user());
|
||||
|
||||
session()->flash('ticket-action-updated', 'Priority updated to '.$this->ticket->priority?->name.'.');
|
||||
session()->flash('ticket-action-updated', 'Priority updated to ' . $this->ticket->priority?->name . '.');
|
||||
$this->dispatch('helpdesk-priority-updated', priorityId: $this->priority_id);
|
||||
}
|
||||
|
||||
@@ -291,7 +290,7 @@ final class TicketShow extends Component
|
||||
|
||||
session()->flash('ticket-action-updated', $this->agent_id === null
|
||||
? 'Ticket is now unassigned.'
|
||||
: 'Ticket assigned to '.$this->ticket->agent?->name.'.');
|
||||
: 'Ticket assigned to ' . $this->ticket->agent?->name . '.');
|
||||
|
||||
$this->dispatch('helpdesk-agent-updated', agentId: $this->agent_id);
|
||||
}
|
||||
@@ -305,7 +304,7 @@ final class TicketShow extends Component
|
||||
|
||||
$this->validate([
|
||||
'supportingFiles' => ['required', 'array', 'min:1'],
|
||||
'supportingFiles.*' => ['file', 'max:'.$maxUploadKilobytes, 'mimes:'.$allowedMimes],
|
||||
'supportingFiles.*' => ['file', 'max:' . $maxUploadKilobytes, 'mimes:' . $allowedMimes],
|
||||
]);
|
||||
|
||||
$user = Auth::user();
|
||||
@@ -398,7 +397,6 @@ final class TicketShow extends Component
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the first-response SLA headline for the SLA panel.
|
||||
*/
|
||||
@@ -421,14 +419,14 @@ final class TicketShow extends Component
|
||||
public function firstResponseSlaDetail(): string
|
||||
{
|
||||
if ($this->ticket->first_response_at !== null) {
|
||||
return 'Responded in '.$this->formatDurationBetween($this->ticket->created_at, $this->ticket->first_response_at);
|
||||
return 'Responded in ' . $this->formatDurationBetween($this->ticket->created_at, $this->ticket->first_response_at);
|
||||
}
|
||||
|
||||
if ($this->ticket->sla_first_response_due_at === null) {
|
||||
return 'No first-response target is set.';
|
||||
}
|
||||
|
||||
return 'Due '.$this->ticket->sla_first_response_due_at->format('d M Y H:i');
|
||||
return 'Due ' . $this->ticket->sla_first_response_due_at->format('d M Y H:i');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -489,14 +487,14 @@ final class TicketShow extends Component
|
||||
public function resolutionSlaDetail(): string
|
||||
{
|
||||
if ($this->ticket->completed_at !== null) {
|
||||
return 'Resolved in '.$this->formatDurationBetween($this->ticket->created_at, $this->ticket->completed_at);
|
||||
return 'Resolved in ' . $this->formatDurationBetween($this->ticket->created_at, $this->ticket->completed_at);
|
||||
}
|
||||
|
||||
if ($this->ticket->sla_resolution_due_at === null) {
|
||||
return 'No resolution target is set.';
|
||||
}
|
||||
|
||||
return 'Due '.$this->ticket->sla_resolution_due_at->format('d M Y H:i');
|
||||
return 'Due ' . $this->ticket->sla_resolution_due_at->format('d M Y H:i');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -539,7 +537,7 @@ final class TicketShow extends Component
|
||||
$seconds = max(0, $start->diffInSeconds($end));
|
||||
|
||||
if ($seconds < 60) {
|
||||
return $seconds.' seconds';
|
||||
return $seconds . ' seconds';
|
||||
}
|
||||
|
||||
return CarbonInterval::seconds($seconds)
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Modules\Helpdesk\Models;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@@ -23,10 +24,10 @@ final class Category extends Model
|
||||
/** @var array<string, string> */
|
||||
protected $casts = ['company_id' => 'integer', 'is_default' => 'boolean'];
|
||||
|
||||
/** @return BelongsTo<\App\Models\Company, Category> */
|
||||
/** @return BelongsTo<Company, Category> */
|
||||
public function company(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(\App\Models\Company::class, 'company_id');
|
||||
return $this->belongsTo(Company::class, 'company_id');
|
||||
}
|
||||
|
||||
/** @return HasMany<Ticket> */
|
||||
|
||||
@@ -5,10 +5,10 @@ declare(strict_types=1);
|
||||
namespace Modules\Helpdesk\Models;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
final class Comment extends Model
|
||||
{
|
||||
@@ -89,13 +89,10 @@ final class Comment extends Model
|
||||
}
|
||||
|
||||
/** @param Builder<Comment> $query */
|
||||
|
||||
public function scopeActive(Builder $query): Builder
|
||||
|
||||
{
|
||||
|
||||
return $query->whereNull('tombstoned_at');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Modules\Helpdesk\Models;
|
||||
|
||||
use App\Models\Company;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -23,10 +24,10 @@ final class Project extends Model
|
||||
/** @var array<string, string> */
|
||||
protected $casts = ['company_id' => 'integer', 'team_id' => 'integer', 'archived_at' => 'datetime', 'is_default' => 'boolean'];
|
||||
|
||||
/** @return BelongsTo<\App\Models\Company, Project> */
|
||||
/** @return BelongsTo<Company, Project> */
|
||||
public function company(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(\App\Models\Company::class, 'company_id');
|
||||
return $this->belongsTo(Company::class, 'company_id');
|
||||
}
|
||||
|
||||
/** @return BelongsTo<Team, Project> */
|
||||
|
||||
@@ -9,11 +9,11 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $slug
|
||||
* @property string $color
|
||||
* @property bool $is_closed
|
||||
* @property bool $is_closed
|
||||
*/
|
||||
final class Status extends Model
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Modules\Helpdesk\Models;
|
||||
|
||||
use App\Models\Company;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -27,10 +28,10 @@ final class Team extends Model
|
||||
'is_default' => 'boolean',
|
||||
];
|
||||
|
||||
/** @return BelongsTo<\App\Models\Company, Team> */
|
||||
/** @return BelongsTo<Company, Team> */
|
||||
public function company(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(\App\Models\Company::class, 'company_id');
|
||||
return $this->belongsTo(Company::class, 'company_id');
|
||||
}
|
||||
|
||||
/** @return HasMany<Project> */
|
||||
|
||||
@@ -13,7 +13,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property int $id
|
||||
* @property string $reference
|
||||
* @property string $subject
|
||||
* @property string $body
|
||||
|
||||
@@ -42,7 +42,7 @@ final class HelpdeskServiceProvider extends ServiceProvider
|
||||
|
||||
$this->mergeConfigFrom(
|
||||
module_path(ModuleInfo::name(), 'Config/config.php'),
|
||||
ModuleInfo::nameLower()
|
||||
ModuleInfo::nameLower(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ final class HelpdeskServiceProvider extends ServiceProvider
|
||||
}
|
||||
|
||||
$commands = collect(File::allFiles($commandPath))
|
||||
->map(fn ($file): string => 'Modules\\'.$this->moduleName.'\\Console\\'.$file->getFilenameWithoutExtension())
|
||||
->map(fn ($file): string => 'Modules\\' . $this->moduleName . '\\Console\\' . $file->getFilenameWithoutExtension())
|
||||
->filter(fn (string $class): bool => class_exists($class))
|
||||
->values()
|
||||
->all();
|
||||
@@ -127,7 +127,7 @@ final class HelpdeskServiceProvider extends ServiceProvider
|
||||
protected function registerConfig(): void
|
||||
{
|
||||
$this->publishes([
|
||||
module_path(ModuleInfo::name(), 'Config/config.php') => config_path(ModuleInfo::nameLower().'.php'),
|
||||
module_path(ModuleInfo::name(), 'Config/config.php') => config_path(ModuleInfo::nameLower() . '.php'),
|
||||
], 'config');
|
||||
}
|
||||
|
||||
@@ -136,17 +136,17 @@ final class HelpdeskServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function registerViews(): void
|
||||
{
|
||||
$viewPath = resource_path('views/modules/'.ModuleInfo::nameLower());
|
||||
$viewPath = resource_path('views/modules/' . ModuleInfo::nameLower());
|
||||
$sourcePath = module_path(ModuleInfo::name(), 'Resources/views');
|
||||
|
||||
$this->publishes([
|
||||
$sourcePath => $viewPath,
|
||||
], ['views', ModuleInfo::nameLower().'-module-views']);
|
||||
], ['views', ModuleInfo::nameLower() . '-module-views']);
|
||||
|
||||
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), ModuleInfo::nameLower());
|
||||
|
||||
Blade::componentNamespace('Modules\Helpdesk\View\Components', 'helpdesk');
|
||||
Blade::anonymousComponentPath($sourcePath.'/components', 'helpdesk');
|
||||
Blade::anonymousComponentPath($sourcePath . '/components', 'helpdesk');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,7 +154,7 @@ final class HelpdeskServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function registerTranslations(): void
|
||||
{
|
||||
$langPath = resource_path('lang/modules/'.ModuleInfo::nameLower());
|
||||
$langPath = resource_path('lang/modules/' . ModuleInfo::nameLower());
|
||||
|
||||
if (is_dir($langPath)) {
|
||||
$this->loadTranslationsFrom($langPath, ModuleInfo::nameLower());
|
||||
@@ -175,8 +175,8 @@ final class HelpdeskServiceProvider extends ServiceProvider
|
||||
$paths = [];
|
||||
|
||||
foreach (Config::get('view.paths') as $path) {
|
||||
if (is_dir($path.'/modules/'.ModuleInfo::nameLower())) {
|
||||
$paths[] = $path.'/modules/'.ModuleInfo::nameLower();
|
||||
if (is_dir($path . '/modules/' . ModuleInfo::nameLower())) {
|
||||
$paths[] = $path . '/modules/' . ModuleInfo::nameLower();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ declare(strict_types=1);
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Modules\Helpdesk\Http\Controllers\AttachmentDownloadController;
|
||||
use Modules\Helpdesk\Http\Controllers\HelpdeskController;
|
||||
use Modules\Helpdesk\Http\Controllers\TicketControlsController;
|
||||
use Modules\Helpdesk\Http\Controllers\TicketAttachmentStoreController;
|
||||
use Modules\Helpdesk\Http\Controllers\TicketCommentDeleteController;
|
||||
use Modules\Helpdesk\Http\Controllers\TicketCommentStoreController;
|
||||
use Modules\Helpdesk\Http\Controllers\TicketAttachmentStoreController;
|
||||
use Modules\Helpdesk\Http\Controllers\TicketControlsController;
|
||||
use Modules\Helpdesk\Http\Controllers\TicketStoreController;
|
||||
use Modules\Helpdesk\Http\Controllers\TicketTimeLogController;
|
||||
use Modules\Helpdesk\Http\Controllers\WorkflowOpenController;
|
||||
|
||||
@@ -26,7 +26,7 @@ final class AgentAssignmentService
|
||||
->selectRaw('count(*)')
|
||||
->whereColumn('helpdesk_tickets.agent_id', 'users.id')
|
||||
->whereNull('helpdesk_tickets.completed_at'),
|
||||
'open_helpdesk_tickets_count'
|
||||
'open_helpdesk_tickets_count',
|
||||
);
|
||||
|
||||
if ($categoryId !== null) {
|
||||
|
||||
@@ -24,7 +24,7 @@ final class AttachmentService
|
||||
$mimeType = $file->getClientMimeType();
|
||||
$size = (int) ($file->getSize() ?: 0);
|
||||
|
||||
$path = $file->store('tickets/'.$ticket->id, $disk);
|
||||
$path = $file->store('tickets/' . $ticket->id, $disk);
|
||||
|
||||
if ($size === 0 && $path !== false) {
|
||||
$size = (int) Storage::disk($disk)->size($path);
|
||||
|
||||
@@ -19,7 +19,8 @@ final class GitWebhookIngestionService
|
||||
/**
|
||||
* Persist supported Git provider commits and link them to matching Helpdesk ticket references.
|
||||
*
|
||||
* @param array<string, mixed> $payload
|
||||
* @param array<string, mixed> $payload
|
||||
*
|
||||
* @return array{status: string, message: string, commit_count: int, linked_count: int, ignored_count: int}
|
||||
*/
|
||||
public function ingest(GitRepository $repository, array $payload, string $provider, ?string $deliveryId, ?string $event): array
|
||||
@@ -76,7 +77,7 @@ final class GitWebhookIngestionService
|
||||
'message' => $message,
|
||||
'url' => $url,
|
||||
'committed_at' => $committedAt,
|
||||
]
|
||||
],
|
||||
);
|
||||
|
||||
$commitCount++;
|
||||
@@ -102,8 +103,8 @@ final class GitWebhookIngestionService
|
||||
/**
|
||||
* Record a provider webhook acceptance, rejection or ignore decision for auditability.
|
||||
*
|
||||
* @param array{status: string, message: string, commit_count?: int, linked_count?: int, ignored_count?: int} $result
|
||||
* @param array<string, mixed>|null $payload
|
||||
* @param array{status: string, message: string, commit_count?: int, linked_count?: int, ignored_count?: int} $result
|
||||
* @param array<string, mixed>|null $payload
|
||||
*/
|
||||
public function logWebhook(GitRepository $repository, string $provider, ?string $deliveryId, ?string $event, array $result, ?array $payload = null): void
|
||||
{
|
||||
@@ -170,7 +171,8 @@ final class GitWebhookIngestionService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $payload
|
||||
* @param array<string, mixed> $payload
|
||||
*
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private function commitsFromPayload(array $payload): array
|
||||
@@ -186,7 +188,7 @@ final class GitWebhookIngestionService
|
||||
|
||||
private function ticketForCommit(GitRepository $repository, string $message, ?string $branch, ?string $url): ?Ticket
|
||||
{
|
||||
$reference = $this->extractTicketReference(trim($message.' '.($branch ?? '').' '.($url ?? '')));
|
||||
$reference = $this->extractTicketReference(trim($message . ' ' . ($branch ?? '') . ' ' . ($url ?? '')));
|
||||
|
||||
if ($reference === null) {
|
||||
return null;
|
||||
|
||||
@@ -5,8 +5,9 @@ declare(strict_types=1);
|
||||
namespace Modules\Helpdesk\Services;
|
||||
|
||||
use App\Models\User;
|
||||
use Modules\Helpdesk\Models\SlaPolicy;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Modules\Helpdesk\Models\Comment;
|
||||
use Modules\Helpdesk\Models\SlaPolicy;
|
||||
use Modules\Helpdesk\Models\Ticket;
|
||||
use Modules\Helpdesk\Models\TicketSlaEvent;
|
||||
|
||||
@@ -89,7 +90,7 @@ final class SlaService
|
||||
|
||||
private function markFirstResponse(Ticket $ticket, mixed $respondedAt, ?User $actor = null): void
|
||||
{
|
||||
$respondedAt = $respondedAt instanceof \Illuminate\Support\Carbon
|
||||
$respondedAt = $respondedAt instanceof Carbon
|
||||
? $respondedAt
|
||||
: now();
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ final class TicketReferenceService
|
||||
{
|
||||
$year = (int) now()->format('Y');
|
||||
$prefix = 'HD';
|
||||
$seriesPrefix = $prefix.'-'.$year.'-';
|
||||
$seriesPrefix = $prefix . '-' . $year . '-';
|
||||
|
||||
$this->lockReferenceSeries($seriesPrefix);
|
||||
|
||||
@@ -76,7 +76,7 @@ final class TicketReferenceService
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return $seriesPrefix.str_pad((string) $nextNumber, 5, '0', STR_PAD_LEFT);
|
||||
return $seriesPrefix . str_pad((string) $nextNumber, 5, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,7 +84,7 @@ final class TicketReferenceService
|
||||
*/
|
||||
private function nextFromExistingReferences(string $seriesPrefix): string
|
||||
{
|
||||
return $seriesPrefix.str_pad((string) ($this->highestExistingSuffix($seriesPrefix) + 1), 5, '0', STR_PAD_LEFT);
|
||||
return $seriesPrefix . str_pad((string) ($this->highestExistingSuffix($seriesPrefix) + 1), 5, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,9 +96,9 @@ final class TicketReferenceService
|
||||
$existingReferences = Ticket::query()
|
||||
->withoutGlobalScopes()
|
||||
->withTrashed()
|
||||
->where('reference', 'like', $seriesPrefix.'%')
|
||||
->where('reference', 'like', $seriesPrefix . '%')
|
||||
->pluck('reference')
|
||||
->filter(static fn (mixed $reference): bool => is_string($reference) && preg_match('/^'.preg_quote($seriesPrefix, '/').'\d+$/', $reference) === 1)
|
||||
->filter(static fn (mixed $reference): bool => is_string($reference) && preg_match('/^' . preg_quote($seriesPrefix, '/') . '\d+$/', $reference) === 1)
|
||||
->values()
|
||||
->all();
|
||||
|
||||
@@ -121,7 +121,7 @@ final class TicketReferenceService
|
||||
}
|
||||
|
||||
DB::select('select pg_advisory_xact_lock(hashtext(?))', [
|
||||
'helpdesk-ticket-reference:'.$seriesPrefix,
|
||||
'helpdesk-ticket-reference:' . $seriesPrefix,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ declare(strict_types=1);
|
||||
namespace Modules\Helpdesk\Services;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Str;
|
||||
@@ -30,8 +30,8 @@ final class TicketService
|
||||
/**
|
||||
* Create a ticket and store initial attachments.
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
* @param array<int, UploadedFile> $files
|
||||
* @param array<string, mixed> $data
|
||||
* @param array<int, UploadedFile> $files
|
||||
*/
|
||||
public function create(User $user, array $data, array $files = []): Ticket
|
||||
{
|
||||
@@ -51,8 +51,8 @@ final class TicketService
|
||||
/**
|
||||
* Create the ticket while the caller owns the database transaction.
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
* @param array<int, UploadedFile> $files
|
||||
* @param array<string, mixed> $data
|
||||
* @param array<int, UploadedFile> $files
|
||||
*/
|
||||
private function createInsideTransaction(User $user, array $data, array $files = []): Ticket
|
||||
{
|
||||
@@ -132,7 +132,7 @@ final class TicketService
|
||||
/**
|
||||
* Add a public or internal comment and optional attachments.
|
||||
*
|
||||
* @param array<int, UploadedFile> $files
|
||||
* @param array<int, UploadedFile> $files
|
||||
*/
|
||||
public function comment(Ticket $ticket, User $user, string $body, bool $internal = false, array $files = [], ?int $parentId = null, ?string $subject = null): Comment
|
||||
{
|
||||
@@ -144,7 +144,7 @@ final class TicketService
|
||||
->findOrFail($parentId);
|
||||
|
||||
$guid = (string) Str::uuid();
|
||||
$unid = strtoupper(hash('sha256', $guid.'|'.$ticket->id.'|'.microtime(true)));
|
||||
$unid = strtoupper(hash('sha256', $guid . '|' . $ticket->id . '|' . microtime(true)));
|
||||
$parentUnid = $parent?->unid;
|
||||
$rootUnid = $parent?->root_unid ?: $parentUnid ?: $unid;
|
||||
$plainTextBody = trim(preg_replace('/\s+/', ' ', strip_tags($body)) ?: '');
|
||||
@@ -159,7 +159,7 @@ final class TicketService
|
||||
'unid' => $unid,
|
||||
'parent_unid' => $parentUnid,
|
||||
'root_unid' => $rootUnid,
|
||||
'originator_id' => $unid.':1',
|
||||
'originator_id' => $unid . ':1',
|
||||
'sync_sequence' => 1,
|
||||
'sync_hash' => hash('sha256', $body),
|
||||
'source_system' => 'wms-helpdesk',
|
||||
|
||||
@@ -133,16 +133,16 @@ final class WorkflowNotificationService
|
||||
private function wrapHtml(string $body, Ticket $ticket, ?string $trackingToken = null): string
|
||||
{
|
||||
return '<div style="font-family:Inter,Arial,sans-serif;background:#f6f8fb;padding:24px">'
|
||||
.'<div style="max-width:720px;margin:0 auto;background:#ffffff;border:1px solid #d8dee8;border-radius:18px;overflow:hidden">'
|
||||
.'<div style="background:#0f172a;color:#ffffff;padding:24px 28px">'
|
||||
.'<div style="font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:#bfdbfe">Helpdesk notification</div>'
|
||||
.'<h1 style="margin:8px 0 0;font-size:22px">'.e($ticket->reference).'</h1>'
|
||||
.'<p style="margin:8px 0 0;color:#dbeafe">'.e($ticket->subject).'</p>'
|
||||
.'</div><div style="padding:28px;color:#1f2937;line-height:1.65">'
|
||||
.$body
|
||||
.'<p style="margin-top:28px"><a href="'.e(route('helpdesk.tickets.show', ['ticket' => $ticket->getKey()])).'" style="display:inline-block;background:#2563eb;color:#ffffff;text-decoration:none;padding:11px 16px;border-radius:10px">Open ticket</a></p>'
|
||||
.$this->trackingPixel($trackingToken)
|
||||
.'</div></div></div>';
|
||||
. '<div style="max-width:720px;margin:0 auto;background:#ffffff;border:1px solid #d8dee8;border-radius:18px;overflow:hidden">'
|
||||
. '<div style="background:#0f172a;color:#ffffff;padding:24px 28px">'
|
||||
. '<div style="font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:#bfdbfe">Helpdesk notification</div>'
|
||||
. '<h1 style="margin:8px 0 0;font-size:22px">' . e($ticket->reference) . '</h1>'
|
||||
. '<p style="margin:8px 0 0;color:#dbeafe">' . e($ticket->subject) . '</p>'
|
||||
. '</div><div style="padding:28px;color:#1f2937;line-height:1.65">'
|
||||
. $body
|
||||
. '<p style="margin-top:28px"><a href="' . e(route('helpdesk.tickets.show', ['ticket' => $ticket->getKey()])) . '" style="display:inline-block;background:#2563eb;color:#ffffff;text-decoration:none;padding:11px 16px;border-radius:10px">Open ticket</a></p>'
|
||||
. $this->trackingPixel($trackingToken)
|
||||
. '</div></div></div>';
|
||||
}
|
||||
|
||||
private function trackingPixel(?string $trackingToken): string
|
||||
@@ -153,9 +153,9 @@ final class WorkflowNotificationService
|
||||
|
||||
$url = Route::has('helpdesk.workflow.open')
|
||||
? route('helpdesk.workflow.open', ['token' => $trackingToken])
|
||||
: URL::to('/'.trim((string) config('helpdesk.route_prefix', 'helpdesk'), '/').'/workflow/open/'.$trackingToken);
|
||||
: URL::to('/' . trim((string) config('helpdesk.route_prefix', 'helpdesk'), '/') . '/workflow/open/' . $trackingToken);
|
||||
|
||||
return '<img src="'.e($url).'" width="1" height="1" alt="" style="display:none" />';
|
||||
return '<img src="' . e($url) . '" width="1" height="1" alt="" style="display:none" />';
|
||||
}
|
||||
|
||||
private function log(WorkflowTemplate $template, Ticket $ticket, string $event, ?string $recipient, string $status, ?string $error = null, ?string $subject = null, ?string $trackingToken = null): void
|
||||
|
||||
@@ -41,7 +41,7 @@ final class HelpdeskSettingsBrowserTest extends DuskTestCase
|
||||
private function openSettingsSection(Browser $browser, string $section, string $expectedHeading): Browser
|
||||
{
|
||||
return $browser
|
||||
->click('@helpdesk-settings-section-'.$section)
|
||||
->click('@helpdesk-settings-section-' . $section)
|
||||
->waitForText($expectedHeading, 10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||
namespace Modules\Helpdesk\Tests\Browser;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Modules\Helpdesk\Models\CannedResponse;
|
||||
use Modules\Helpdesk\Models\Comment;
|
||||
use Modules\Helpdesk\Tests\Concerns\BuildsHelpdeskFixtures;
|
||||
use Tests\DuskTestCase;
|
||||
@@ -19,7 +18,7 @@ final class HelpdeskTicketBrowserTest extends DuskTestCase
|
||||
$fixtures = $this->seedLookupData();
|
||||
$user = $this->user(['name' => 'Ticket Browser User']);
|
||||
|
||||
$subject = 'Browser created helpdesk ticket '.uniqid();
|
||||
$subject = 'Browser created helpdesk ticket ' . uniqid();
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user, $fixtures, $subject): void {
|
||||
$browser->loginAs($user)
|
||||
@@ -65,11 +64,10 @@ final class HelpdeskTicketBrowserTest extends DuskTestCase
|
||||
'user_id' => $user->id,
|
||||
'parent_id' => null,
|
||||
'title' => 'Browser canned response',
|
||||
'body' => '<p>Hello Response Browser User</p><p>Inserted canned browser response for '.$ticket->reference.'</p>',
|
||||
'body' => '<p>Hello Response Browser User</p><p>Inserted canned browser response for ' . $ticket->reference . '</p>',
|
||||
'is_internal' => false,
|
||||
]);
|
||||
|
||||
|
||||
Comment::query()->create([
|
||||
'ticket_id' => $ticket->id,
|
||||
'user_id' => $user->id,
|
||||
@@ -91,7 +89,7 @@ final class HelpdeskTicketBrowserTest extends DuskTestCase
|
||||
$this->assertDatabaseHas('helpdesk_comments', [
|
||||
'ticket_id' => $ticket->id,
|
||||
'parent_id' => null,
|
||||
'body' => '<p>Hello Response Browser User</p><p>Inserted canned browser response for '.$ticket->reference.'</p>',
|
||||
'body' => '<p>Hello Response Browser User</p><p>Inserted canned browser response for ' . $ticket->reference . '</p>',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('helpdesk_comments', [
|
||||
@@ -137,7 +135,7 @@ document.body.appendChild(form);
|
||||
form.submit();
|
||||
JS);
|
||||
|
||||
$browser->waitForLocation('/helpdesk/tickets/'.$ticketId, 10);
|
||||
$browser->waitForLocation('/helpdesk/tickets/' . $ticketId, 10);
|
||||
}
|
||||
|
||||
private function setHelpdeskEditor(Browser $browser, string $dusk, string $html): void
|
||||
|
||||
@@ -134,7 +134,7 @@ trait BuildsHelpdeskFixtures
|
||||
unset($attributes['owner'], $attributes['agent']);
|
||||
|
||||
return Ticket::query()->create(array_merge([
|
||||
'reference' => 'HD-'.now()->format('Y').'-'.str_pad((string) random_int(1, 99999), 5, '0', STR_PAD_LEFT),
|
||||
'reference' => 'HD-' . now()->format('Y') . '-' . str_pad((string) random_int(1, 99999), 5, '0', STR_PAD_LEFT),
|
||||
'user_id' => $owner->id,
|
||||
'agent_id' => $agent?->id,
|
||||
'status_id' => $this->ticketStatus()->id,
|
||||
|
||||
@@ -32,7 +32,7 @@ final class GitAndAttachmentTest extends TestCase
|
||||
'branch' => 'develop',
|
||||
'author_name' => 'Mark Gregory',
|
||||
'author_email' => 'mark@example.com',
|
||||
'message' => 'Resolve '.$ticket->reference.' ticket save redirect',
|
||||
'message' => 'Resolve ' . $ticket->reference . ' ticket save redirect',
|
||||
'url' => 'https://example.com/commit/b',
|
||||
'committed_at' => now(),
|
||||
]);
|
||||
|
||||
@@ -25,12 +25,12 @@ final class GitWebhookIngestionTest extends TestCase
|
||||
]);
|
||||
$ticket = $this->ticket(['project_id' => $fixtures['project']->id]);
|
||||
$payload = [
|
||||
'ref' => 'refs/heads/feature/'.$ticket->reference.'-automation',
|
||||
'ref' => 'refs/heads/feature/' . $ticket->reference . '-automation',
|
||||
'commits' => [
|
||||
[
|
||||
'id' => str_repeat('a', 40),
|
||||
'message' => $ticket->reference.' Add webhook ingestion',
|
||||
'url' => 'https://github.example.test/org/repo/commit/'.str_repeat('a', 40),
|
||||
'message' => $ticket->reference . ' Add webhook ingestion',
|
||||
'url' => 'https://github.example.test/org/repo/commit/' . str_repeat('a', 40),
|
||||
'timestamp' => '2026-06-15T10:00:00+00:00',
|
||||
'author' => ['name' => 'Mark Gregory', 'email' => 'mark@example.com'],
|
||||
],
|
||||
@@ -43,7 +43,7 @@ final class GitWebhookIngestionTest extends TestCase
|
||||
'HTTP_ACCEPT' => 'application/json',
|
||||
'HTTP_X_GITHUB_EVENT' => 'push',
|
||||
'HTTP_X_GITHUB_DELIVERY' => 'delivery-123',
|
||||
'HTTP_X_HUB_SIGNATURE_256' => 'sha256='.hash_hmac('sha256', $json, 'github-secret'),
|
||||
'HTTP_X_HUB_SIGNATURE_256' => 'sha256=' . hash_hmac('sha256', $json, 'github-secret'),
|
||||
], $json);
|
||||
|
||||
$response->assertStatus(202)->assertJsonPath('status', 'accepted')->assertJsonPath('linked_count', 1);
|
||||
@@ -53,7 +53,7 @@ final class GitWebhookIngestionTest extends TestCase
|
||||
'ticket_id' => $ticket->id,
|
||||
'hash' => str_repeat('a', 40),
|
||||
'short_hash' => str_repeat('a', 12),
|
||||
'branch' => 'feature/'.$ticket->reference.'-automation',
|
||||
'branch' => 'feature/' . $ticket->reference . '-automation',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('helpdesk_git_webhook_logs', [
|
||||
@@ -96,7 +96,7 @@ final class GitWebhookIngestionTest extends TestCase
|
||||
'CONTENT_TYPE' => 'application/json',
|
||||
'HTTP_ACCEPT' => 'application/json',
|
||||
'HTTP_X_GITHUB_EVENT' => 'ping',
|
||||
'HTTP_X_HUB_SIGNATURE_256' => 'sha256='.hash_hmac('sha256', $json, 'github-secret'),
|
||||
'HTTP_X_HUB_SIGNATURE_256' => 'sha256=' . hash_hmac('sha256', $json, 'github-secret'),
|
||||
], $json);
|
||||
|
||||
$response->assertStatus(202)->assertJsonPath('status', 'ignored');
|
||||
@@ -125,8 +125,8 @@ final class GitWebhookIngestionTest extends TestCase
|
||||
'commits' => [
|
||||
[
|
||||
'id' => str_repeat('c', 40),
|
||||
'message' => 'Fix '.$ticket->reference.' SLA report',
|
||||
'url' => 'https://gitlab.example.test/org/repo/-/commit/'.str_repeat('c', 40),
|
||||
'message' => 'Fix ' . $ticket->reference . ' SLA report',
|
||||
'url' => 'https://gitlab.example.test/org/repo/-/commit/' . str_repeat('c', 40),
|
||||
'timestamp' => '2026-06-15T11:00:00+00:00',
|
||||
'author' => ['name' => 'Support Agent', 'email' => 'agent@example.com'],
|
||||
],
|
||||
|
||||
@@ -21,7 +21,7 @@ final class HelpdeskLivewireAssetsTest extends TestCase
|
||||
self::assertLessThan(
|
||||
strpos($layout, '@fluxScripts'),
|
||||
strpos($layout, '@livewireScripts'),
|
||||
'Livewire scripts must be loaded before Flux scripts so settings CRUD actions fire in the browser.'
|
||||
'Livewire scripts must be loaded before Flux scripts so settings CRUD actions fire in the browser.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ final class RedmineInspiredHelpdeskFeatureTest extends TestCase
|
||||
->test(TicketShow::class, ['ticket' => $ticket])
|
||||
->set('canned_response_id', $response->id)
|
||||
->call('applyCannedResponse')
|
||||
->assertSet('commentBody', 'Hello Customer Jane, ticket '.$ticket->reference.' is being reviewed by Agent Smith.');
|
||||
->assertSet('commentBody', 'Hello Customer Jane, ticket ' . $ticket->reference . ' is being reviewed by Agent Smith.');
|
||||
}
|
||||
|
||||
public function test_sla_service_records_first_response_and_resolution_breaches(): void
|
||||
|
||||
@@ -214,7 +214,7 @@ final class SettingsCrudTest extends TestCase
|
||||
$checklist = ChecklistTemplate::query()->where('slug', 'release-checklist')->firstOrFail();
|
||||
Livewire::test(SettingsManager::class)
|
||||
->call('editChecklistTemplate', $checklist->id)
|
||||
->set('checklistTemplateForm.items_text', "Updated item")
|
||||
->set('checklistTemplateForm.items_text', 'Updated item')
|
||||
->call('saveChecklistTemplate')
|
||||
->assertHasNoErrors();
|
||||
$this->assertDatabaseHas('helpdesk_checklist_templates', ['id' => $checklist->id]);
|
||||
|
||||
@@ -4,8 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace Modules\Helpdesk\Tests\Feature;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use App\Models\Company;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -13,6 +13,7 @@ use Livewire\Livewire;
|
||||
use Modules\Helpdesk\Livewire\TicketShow;
|
||||
use Modules\Helpdesk\Models\Attachment;
|
||||
use Modules\Helpdesk\Models\Comment;
|
||||
use Modules\Helpdesk\Services\TicketService;
|
||||
use Modules\Helpdesk\Tests\Concerns\BuildsHelpdeskFixtures;
|
||||
use Tests\TestCase;
|
||||
|
||||
@@ -69,7 +70,6 @@ final class TicketConversationTest extends TestCase
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function test_comment_post_endpoint_creates_lotus_identity_and_search_text(): void
|
||||
{
|
||||
$fixtures = $this->seedLookupData();
|
||||
@@ -98,7 +98,7 @@ final class TicketConversationTest extends TestCase
|
||||
$fixtures = $this->seedLookupData();
|
||||
$owner = $this->user();
|
||||
$ticket = $this->ticket(['owner' => $owner, 'status_id' => $fixtures['open']->id, 'priority_id' => $fixtures['normal']->id]);
|
||||
$parent = app(\Modules\Helpdesk\Services\TicketService::class)->comment($ticket, $owner, '<p>Parent response</p>');
|
||||
$parent = app(TicketService::class)->comment($ticket, $owner, '<p>Parent response</p>');
|
||||
|
||||
$this->actingAs($owner)
|
||||
->post(route('helpdesk.tickets.comments.store', $ticket), [
|
||||
@@ -115,8 +115,6 @@ final class TicketConversationTest extends TestCase
|
||||
self::assertSame('RE: Parent response', $reply->subject);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function test_existing_ticket_accepts_multiple_supporting_file_attachments(): void
|
||||
{
|
||||
Storage::fake((string) config('helpdesk.disk', 'public'));
|
||||
@@ -187,7 +185,7 @@ final class TicketConversationTest extends TestCase
|
||||
$admin = $this->user(['company_id' => $company->id, 'is_platform_admin' => true]);
|
||||
$owner = $this->user(['company_id' => $company->id]);
|
||||
$ticket = $this->ticket(['owner' => $owner, 'status_id' => $fixtures['open']->id, 'priority_id' => $fixtures['normal']->id]);
|
||||
$comment = app(\Modules\Helpdesk\Services\TicketService::class)->comment($ticket, $owner, '<p>Delete me</p>');
|
||||
$comment = app(TicketService::class)->comment($ticket, $owner, '<p>Delete me</p>');
|
||||
|
||||
$this->actingAs($admin)
|
||||
->delete(route('helpdesk.tickets.comments.destroy', [$ticket, $comment]))
|
||||
|
||||
@@ -44,7 +44,6 @@ final class TicketCrudTest extends TestCase
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function test_ticket_create_does_not_validate_before_submit(): void
|
||||
{
|
||||
$this->seedLookupData();
|
||||
@@ -137,7 +136,7 @@ final class TicketCrudTest extends TestCase
|
||||
|
||||
$ticket = Ticket::query()->where('subject', 'Reference check')->firstOrFail();
|
||||
|
||||
self::assertStringStartsWith('HD-'.now()->format('Y').'-', $ticket->reference);
|
||||
self::assertStringStartsWith('HD-' . now()->format('Y') . '-', $ticket->reference);
|
||||
self::assertNotNull($ticket->last_activity_at);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ final class TicketFirstResponseSlaFilesTest extends TestCase
|
||||
*/
|
||||
public function test_public_response_updates_first_response_sla_state(): void
|
||||
{
|
||||
$servicePath = dirname(__DIR__, 2).'/Services/SlaService.php';
|
||||
$servicePath = dirname(__DIR__, 2) . '/Services/SlaService.php';
|
||||
|
||||
self::assertFileExists($servicePath);
|
||||
|
||||
@@ -30,8 +30,8 @@ final class TicketFirstResponseSlaFilesTest extends TestCase
|
||||
*/
|
||||
public function test_ticket_show_synchronises_first_response_from_existing_public_comments(): void
|
||||
{
|
||||
$componentPath = dirname(__DIR__, 2).'/Livewire/TicketShow.php';
|
||||
$servicePath = dirname(__DIR__, 2).'/Services/SlaService.php';
|
||||
$componentPath = dirname(__DIR__, 2) . '/Livewire/TicketShow.php';
|
||||
$servicePath = dirname(__DIR__, 2) . '/Services/SlaService.php';
|
||||
|
||||
$component = file_get_contents($componentPath);
|
||||
$service = file_get_contents($servicePath);
|
||||
@@ -48,7 +48,7 @@ final class TicketFirstResponseSlaFilesTest extends TestCase
|
||||
*/
|
||||
public function test_sla_card_has_clear_responded_and_awaiting_public_reply_states(): void
|
||||
{
|
||||
$viewPath = dirname(__DIR__, 2).'/Resources/views/livewire/ticket-show.blade.php';
|
||||
$viewPath = dirname(__DIR__, 2) . '/Resources/views/livewire/ticket-show.blade.php';
|
||||
|
||||
$view = file_get_contents($viewPath);
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ final class TicketPublicResponseVisibilityFilesTest extends TestCase
|
||||
*/
|
||||
public function test_main_ticket_response_form_has_public_visibility_control(): void
|
||||
{
|
||||
$viewPath = dirname(__DIR__, 2).'/Resources/views/livewire/ticket-show.blade.php';
|
||||
$viewPath = dirname(__DIR__, 2) . '/Resources/views/livewire/ticket-show.blade.php';
|
||||
|
||||
self::assertFileExists($viewPath);
|
||||
|
||||
@@ -33,7 +33,7 @@ final class TicketPublicResponseVisibilityFilesTest extends TestCase
|
||||
*/
|
||||
public function test_threaded_responses_have_public_visibility_control_and_badges(): void
|
||||
{
|
||||
$partialPath = dirname(__DIR__, 2).'/Resources/views/partials/comment-thread.blade.php';
|
||||
$partialPath = dirname(__DIR__, 2) . '/Resources/views/partials/comment-thread.blade.php';
|
||||
|
||||
self::assertFileExists($partialPath);
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ final class TicketSlaOperationalDetailFilesTest extends TestCase
|
||||
*/
|
||||
public function test_first_response_sla_card_shows_duration_responder_and_timestamp(): void
|
||||
{
|
||||
$componentPath = dirname(__DIR__, 2).'/Livewire/TicketShow.php';
|
||||
$viewPath = dirname(__DIR__, 2).'/Resources/views/livewire/ticket-show.blade.php';
|
||||
$componentPath = dirname(__DIR__, 2) . '/Livewire/TicketShow.php';
|
||||
$viewPath = dirname(__DIR__, 2) . '/Resources/views/livewire/ticket-show.blade.php';
|
||||
|
||||
$component = file_get_contents($componentPath);
|
||||
$view = file_get_contents($viewPath);
|
||||
@@ -33,8 +33,8 @@ final class TicketSlaOperationalDetailFilesTest extends TestCase
|
||||
*/
|
||||
public function test_sla_cards_have_colour_coded_state_helpers(): void
|
||||
{
|
||||
$componentPath = dirname(__DIR__, 2).'/Livewire/TicketShow.php';
|
||||
$viewPath = dirname(__DIR__, 2).'/Resources/views/livewire/ticket-show.blade.php';
|
||||
$componentPath = dirname(__DIR__, 2) . '/Livewire/TicketShow.php';
|
||||
$viewPath = dirname(__DIR__, 2) . '/Resources/views/livewire/ticket-show.blade.php';
|
||||
|
||||
$component = file_get_contents($componentPath);
|
||||
$view = file_get_contents($viewPath);
|
||||
@@ -55,8 +55,8 @@ final class TicketSlaOperationalDetailFilesTest extends TestCase
|
||||
*/
|
||||
public function test_sla_audit_trail_is_visible_on_ticket_page(): void
|
||||
{
|
||||
$servicePath = dirname(__DIR__, 2).'/Services/SlaService.php';
|
||||
$viewPath = dirname(__DIR__, 2).'/Resources/views/livewire/ticket-show.blade.php';
|
||||
$servicePath = dirname(__DIR__, 2) . '/Services/SlaService.php';
|
||||
$viewPath = dirname(__DIR__, 2) . '/Resources/views/livewire/ticket-show.blade.php';
|
||||
|
||||
$service = file_get_contents($servicePath);
|
||||
$view = file_get_contents($viewPath);
|
||||
@@ -75,7 +75,7 @@ final class TicketSlaOperationalDetailFilesTest extends TestCase
|
||||
*/
|
||||
public function test_public_reply_count_uses_all_ticket_comments(): void
|
||||
{
|
||||
$componentPath = dirname(__DIR__, 2).'/Livewire/TicketShow.php';
|
||||
$componentPath = dirname(__DIR__, 2) . '/Livewire/TicketShow.php';
|
||||
|
||||
$component = file_get_contents($componentPath);
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ final class TicketTimerButtonSizeFilesTest extends TestCase
|
||||
self::assertStringNotContainsString('px-3 py-1.5 text-xs', $view);
|
||||
self::assertStringNotContainsString('ticket-timer.js', $view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the active timer action also remains readable and single-line.
|
||||
*/
|
||||
|
||||
@@ -16,7 +16,7 @@ class TicketTimerFilesTest extends TestCase
|
||||
$this->assertStringStartsWith('<div', $view);
|
||||
$this->assertFalse(
|
||||
str_starts_with($view, '<style'),
|
||||
'The ticket timer Livewire view must not start with a <style> tag.'
|
||||
'The ticket timer Livewire view must not start with a <style> tag.',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ final class WorkflowNotificationTest extends TestCase
|
||||
'event' => 'ticket.created',
|
||||
'recipient' => 'requester@example.com',
|
||||
'status' => 'sent',
|
||||
'subject' => 'Ticket '.$ticket->reference.' raised for Requester Name',
|
||||
'subject' => 'Ticket ' . $ticket->reference . ' raised for Requester Name',
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,39 +18,39 @@ final class TicketReferenceServiceTest extends TestCase
|
||||
{
|
||||
$reference = app(TicketReferenceService::class)->next();
|
||||
|
||||
self::assertSame('HD-'.now()->format('Y').'-00001', $reference);
|
||||
self::assertSame('HD-' . now()->format('Y') . '-00001', $reference);
|
||||
}
|
||||
|
||||
public function test_it_generates_the_next_reference_after_existing_tickets(): void
|
||||
{
|
||||
$this->ticket(['reference' => 'HD-'.now()->format('Y').'-00041']);
|
||||
$this->ticket(['reference' => 'HD-' . now()->format('Y') . '-00041']);
|
||||
|
||||
$reference = app(TicketReferenceService::class)->next();
|
||||
|
||||
self::assertSame('HD-'.now()->format('Y').'-00042', $reference);
|
||||
self::assertSame('HD-' . now()->format('Y') . '-00042', $reference);
|
||||
}
|
||||
|
||||
public function test_it_does_not_reuse_soft_deleted_ticket_references(): void
|
||||
{
|
||||
$year = now()->format('Y');
|
||||
$ticket = $this->ticket(['reference' => 'HD-'.$year.'-00002']);
|
||||
$ticket = $this->ticket(['reference' => 'HD-' . $year . '-00002']);
|
||||
|
||||
$ticket->delete();
|
||||
|
||||
$reference = app(TicketReferenceService::class)->next();
|
||||
|
||||
self::assertSame('HD-'.$year.'-00003', $reference);
|
||||
self::assertSame('HD-' . $year . '-00003', $reference);
|
||||
}
|
||||
|
||||
public function test_it_uses_the_highest_reference_suffix_instead_of_latest_database_id(): void
|
||||
{
|
||||
$year = now()->format('Y');
|
||||
|
||||
$this->ticket(['reference' => 'HD-'.$year.'-00042']);
|
||||
$this->ticket(['reference' => 'HD-'.$year.'-00002']);
|
||||
$this->ticket(['reference' => 'HD-' . $year . '-00042']);
|
||||
$this->ticket(['reference' => 'HD-' . $year . '-00002']);
|
||||
|
||||
$reference = app(TicketReferenceService::class)->next();
|
||||
|
||||
self::assertSame('HD-'.$year.'-00043', $reference);
|
||||
self::assertSame('HD-' . $year . '-00043', $reference);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class InternalApiServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
Route::middleware('api')->prefix('api/internal')->group(__DIR__.'/../routes/api.php');
|
||||
Route::middleware('api')->prefix('api/internal')->group(__DIR__ . '/../routes/api.php');
|
||||
app('router')->aliasMiddleware('internal.signed', VerifyInternalApiSignature::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@ class VerifyInternalApiSignature
|
||||
|
||||
$body = $request->getContent();
|
||||
$payloads = array_unique([
|
||||
$timestamp.'.'.$body,
|
||||
$timestamp.'.',
|
||||
$timestamp.'.[]',
|
||||
$timestamp . '.' . $body,
|
||||
$timestamp . '.',
|
||||
$timestamp . '.[]',
|
||||
]);
|
||||
|
||||
foreach ($payloads as $payload) {
|
||||
|
||||
@@ -19,7 +19,7 @@ class InternalApiSignatureTest extends TestCase
|
||||
config(['platform.internal_api_key' => 'testing-secret']);
|
||||
$timestamp = now()->toIso8601String();
|
||||
$body = '';
|
||||
$signature = hash_hmac('sha256', $timestamp.'.'.$body, 'testing-secret');
|
||||
$signature = hash_hmac('sha256', $timestamp . '.' . $body, 'testing-secret');
|
||||
|
||||
$this->withHeaders([
|
||||
'X-WMS-Timestamp' => $timestamp,
|
||||
|
||||
@@ -11,8 +11,8 @@ class InventoryManagementServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'inventorymanagement');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'inventorymanagement');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,8 +11,8 @@ class M3IntegrationServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'm3integration');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'm3integration');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,7 @@ class PlatformServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
$this->mergeConfigFrom(__DIR__.'/../config/platform.php', 'platform');
|
||||
$this->mergeConfigFrom(__DIR__ . '/../config/platform.php', 'platform');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -23,10 +23,10 @@ class PlatformServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadViewsFrom(__DIR__.'/../resources/views', 'platform');
|
||||
$this->loadMigrationsFrom(__DIR__.'/../database/migrations');
|
||||
$this->loadViewsFrom(__DIR__ . '/../resources/views', 'platform');
|
||||
$this->loadMigrationsFrom(__DIR__ . '/../database/migrations');
|
||||
|
||||
Route::middleware('web')->group(__DIR__.'/../routes/web.php');
|
||||
Route::middleware('web')->group(__DIR__ . '/../routes/web.php');
|
||||
|
||||
app('router')->aliasMiddleware('tenant.assigned', EnsureTenantAssigned::class);
|
||||
app('router')->aliasMiddleware('tenant.licensed', EnsureLicensedTenant::class);
|
||||
|
||||
@@ -97,7 +97,7 @@ class PlatformPriceController extends Controller
|
||||
private function validatedPriceData(Request $request, ?PlatformPrice $price = null): array
|
||||
{
|
||||
$data = $request->validate([
|
||||
'code' => ['nullable', 'string', 'max:40', 'unique:platform_prices,code,'.($price?->id ?? 'NULL')],
|
||||
'code' => ['nullable', 'string', 'max:40', 'unique:platform_prices,code,' . ($price?->id ?? 'NULL')],
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'strapline' => ['nullable', 'string', 'max:255'],
|
||||
'description' => ['nullable', 'string', 'max:2000'],
|
||||
|
||||
@@ -32,7 +32,7 @@ class StripeWebhookController extends Controller
|
||||
'description' => 'Stripe payment received',
|
||||
'paid_at' => now(),
|
||||
'metadata' => $intent,
|
||||
]
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class LicenseKey extends Model
|
||||
|
||||
public static function issueFor(Company $company, string $label, string $plan = 'standard', int $maxUsers = 10): string
|
||||
{
|
||||
$plainKey = 'WMS-'.Str::upper(Str::random(32));
|
||||
$plainKey = 'WMS-' . Str::upper(Str::random(32));
|
||||
|
||||
self::create([
|
||||
'company_id' => $company->id,
|
||||
|
||||
@@ -48,7 +48,7 @@ class PlatformPrice extends Model
|
||||
'gbp' => '£',
|
||||
'eur' => '€',
|
||||
'usd' => '$',
|
||||
default => strtoupper($this->currency).' ',
|
||||
default => strtoupper($this->currency) . ' ',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ class PlatformPrice extends Model
|
||||
return '—';
|
||||
}
|
||||
|
||||
return $this->currencySymbol().number_format($amount / 100, 2);
|
||||
return $this->currencySymbol() . number_format($amount / 100, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@ class PlatformSeeder extends Seeder
|
||||
'timezone' => 'Europe/London',
|
||||
'is_system_company' => true,
|
||||
'billing_email' => 'mark.gregory@mpba.co.uk',
|
||||
]
|
||||
],
|
||||
);
|
||||
|
||||
$user = User::updateOrCreate(
|
||||
@@ -55,7 +55,7 @@ class PlatformSeeder extends Seeder
|
||||
'is_company_admin' => true,
|
||||
'status' => 'active',
|
||||
'email_verified_at' => now(),
|
||||
]
|
||||
],
|
||||
);
|
||||
$user->assignRole($role);
|
||||
$warehouse = Warehouse::firstOrNew([
|
||||
@@ -72,7 +72,7 @@ class PlatformSeeder extends Seeder
|
||||
|
||||
WarehouseValidationRule::updateOrCreate(
|
||||
['warehouse_id' => $warehouse->id, 'rule_key' => 'stock.location.required'],
|
||||
['name' => 'Stock location required', 'severity' => 'error', 'is_active' => true, 'configuration' => ['required' => true]]
|
||||
['name' => 'Stock location required', 'severity' => 'error', 'is_active' => true, 'configuration' => ['required' => true]],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ final class PricingDatabaseSeeder extends Seeder
|
||||
|
||||
DB::table('platform_prices')->updateOrInsert(
|
||||
['code' => $plan['code']],
|
||||
$payload
|
||||
$payload,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@ if (! function_exists('pricing_feature_enabled')) {
|
||||
*/
|
||||
function pricing_feature_enabled(string $key): bool
|
||||
{
|
||||
return (bool) config(ModuleInfo::nameLower().".features.{$key}", false);
|
||||
return (bool) config(ModuleInfo::nameLower() . ".features.{$key}", false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class PricingServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function registerHelpers(): void
|
||||
{
|
||||
foreach (glob(__DIR__.'/../Helpers/*.php') as $filename) {
|
||||
foreach (glob(__DIR__ . '/../Helpers/*.php') as $filename) {
|
||||
require_once $filename;
|
||||
}
|
||||
}
|
||||
@@ -60,10 +60,10 @@ class PricingServiceProvider extends ServiceProvider
|
||||
if (! $this->app->runningInConsole()) {
|
||||
return;
|
||||
}
|
||||
$commandPath = __DIR__.'/../Console';
|
||||
$commandPath = __DIR__ . '/../Console';
|
||||
$commands = collect(File::allFiles($commandPath))
|
||||
->map(function ($file) {
|
||||
$class = 'Modules\\'.$this->moduleName.'\\Console\\'.$file->getFilenameWithoutExtension();
|
||||
$class = 'Modules\\' . $this->moduleName . '\\Console\\' . $file->getFilenameWithoutExtension();
|
||||
|
||||
return $class;
|
||||
})
|
||||
@@ -81,10 +81,11 @@ class PricingServiceProvider extends ServiceProvider
|
||||
protected function registerConfig(): void
|
||||
{
|
||||
$this->publishes([
|
||||
module_path(ModuleInfo::name(), 'Config/config.php') => config_path(ModuleInfo::nameLower().'.php'),
|
||||
module_path(ModuleInfo::name(), 'Config/config.php') => config_path(ModuleInfo::nameLower() . '.php'),
|
||||
], 'config');
|
||||
$this->mergeConfigFrom(
|
||||
module_path(ModuleInfo::name(), 'Config/config.php'), ModuleInfo::nameLower()
|
||||
module_path(ModuleInfo::name(), 'Config/config.php'),
|
||||
ModuleInfo::nameLower(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -93,11 +94,11 @@ class PricingServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function registerViews(): void
|
||||
{
|
||||
$viewPath = resource_path('views/modules/'.ModuleInfo::nameLower());
|
||||
$viewPath = resource_path('views/modules/' . ModuleInfo::nameLower());
|
||||
$sourcePath = module_path(ModuleInfo::name(), 'Resources/views');
|
||||
$this->publishes([
|
||||
$sourcePath => $viewPath,
|
||||
], ['views', ModuleInfo::nameLower().'-module-views']);
|
||||
], ['views', ModuleInfo::nameLower() . '-module-views']);
|
||||
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), ModuleInfo::nameLower());
|
||||
}
|
||||
|
||||
@@ -106,7 +107,7 @@ class PricingServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function registerTranslations(): void
|
||||
{
|
||||
$langPath = resource_path('lang/modules/'.ModuleInfo::nameLower());
|
||||
$langPath = resource_path('lang/modules/' . ModuleInfo::nameLower());
|
||||
|
||||
if (is_dir($langPath)) {
|
||||
$this->loadTranslationsFrom($langPath, ModuleInfo::nameLower());
|
||||
@@ -122,8 +123,8 @@ class PricingServiceProvider extends ServiceProvider
|
||||
{
|
||||
$paths = [];
|
||||
foreach (Config::get('view.paths') as $path) {
|
||||
if (is_dir($path.'/modules/'.ModuleInfo::nameLower())) {
|
||||
$paths[] = $path.'/modules/'.ModuleInfo::nameLower();
|
||||
if (is_dir($path . '/modules/' . ModuleInfo::nameLower())) {
|
||||
$paths[] = $path . '/modules/' . ModuleInfo::nameLower();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ class ReplenishmentServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'replenishment');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'replenishment');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,8 +11,8 @@ class ReportingServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'reporting');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'reporting');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,8 +11,8 @@ class SecurityServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'security');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'security');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,8 +11,8 @@ class SentinelIntegrationServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'sentinelintegration');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'sentinelintegration');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,8 +11,8 @@ class ShippingServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'shipping');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'shipping');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,8 +11,8 @@ class TransportationServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadRoutesFrom(__DIR__.'/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'transportation');
|
||||
$this->loadRoutesFrom(__DIR__ . '/../Routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'transportation');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,8 +12,8 @@ class WarehouseServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadViewsFrom(__DIR__.'/../resources/views', 'warehouse');
|
||||
$this->loadMigrationsFrom(__DIR__.'/../database/migrations');
|
||||
Route::middleware('web')->group(__DIR__.'/../routes/web.php');
|
||||
$this->loadViewsFrom(__DIR__ . '/../resources/views', 'warehouse');
|
||||
$this->loadMigrationsFrom(__DIR__ . '/../database/migrations');
|
||||
Route::middleware('web')->group(__DIR__ . '/../routes/web.php');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ use App\Http\Controllers\Controller;
|
||||
use Modules\Warehouse\app\Models\Warehouse;
|
||||
use Modules\Warehouse\app\Models\WarehouseValidationRule;
|
||||
|
||||
|
||||
class WarehouseDashboardController extends Controller
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,7 @@ class Warehouse extends Model
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'settings' => 'array'
|
||||
'settings' => 'array',
|
||||
];
|
||||
|
||||
protected static function booted(): void
|
||||
|
||||
@@ -18,7 +18,7 @@ class CreateNewUser implements CreatesNewUsers
|
||||
/**
|
||||
* Validate and create a newly registered user with an isolated company tenant.
|
||||
*
|
||||
* @param array<string, string> $input
|
||||
* @param array<string, string> $input
|
||||
*/
|
||||
public function create(array $input): User
|
||||
{
|
||||
@@ -29,11 +29,11 @@ class CreateNewUser implements CreatesNewUsers
|
||||
])->validate();
|
||||
|
||||
return DB::transaction(function () use ($input): User {
|
||||
$companyName = $input['company_name'] ?? ($input['name'].' Company');
|
||||
$companyName = $input['company_name'] ?? ($input['name'] . ' Company');
|
||||
|
||||
$company = Company::create([
|
||||
'name' => $companyName,
|
||||
'slug' => Str::slug($companyName.'-'.Str::random(6)),
|
||||
'slug' => Str::slug($companyName . '-' . Str::random(6)),
|
||||
'status' => 'active',
|
||||
'timezone' => 'Europe/London',
|
||||
]);
|
||||
|
||||
@@ -14,7 +14,7 @@ class ResetUserPassword implements ResetsUserPasswords
|
||||
/**
|
||||
* Validate and reset the user's forgotten password.
|
||||
*
|
||||
* @param array<string, string> $input
|
||||
* @param array<string, string> $input
|
||||
*/
|
||||
public function reset(User $user, array $input): void
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ class UpdateUserPassword implements UpdatesUserPasswords
|
||||
/**
|
||||
* Validate and update the user's password.
|
||||
*
|
||||
* @param array<string, string> $input
|
||||
* @param array<string, string> $input
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@ class UpdateUserProfileInformation implements UpdatesUserProfileInformation
|
||||
/**
|
||||
* Validate and update the given user's profile information.
|
||||
*
|
||||
* @param array<string, string> $input
|
||||
* @param array<string, string> $input
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
@@ -46,7 +46,7 @@ class UpdateUserProfileInformation implements UpdatesUserProfileInformation
|
||||
/**
|
||||
* Update the given verified user's profile information.
|
||||
*
|
||||
* @param array<string, string> $input
|
||||
* @param array<string, string> $input
|
||||
*/
|
||||
protected function updateVerifiedUser(User $user, array $input): void
|
||||
{
|
||||
|
||||
@@ -37,7 +37,8 @@ class AppServiceProvider extends ServiceProvider
|
||||
app()->isProduction(),
|
||||
);
|
||||
|
||||
Password::defaults(fn (): ?Password => app()->isProduction()
|
||||
Password::defaults(
|
||||
fn (): ?Password => app()->isProduction()
|
||||
? Password::min(12)
|
||||
->mixedCase()
|
||||
->letters()
|
||||
|
||||
@@ -64,7 +64,7 @@ class FortifyServiceProvider extends ServiceProvider
|
||||
});
|
||||
|
||||
RateLimiter::for('login', function (Request $request) {
|
||||
$throttleKey = Str::transliterate(Str::lower($request->input(Fortify::username())).'|'.$request->ip());
|
||||
$throttleKey = Str::transliterate(Str::lower($request->input(Fortify::username())) . '|' . $request->ip());
|
||||
|
||||
return Limit::perMinute(5)->by($throttleKey);
|
||||
});
|
||||
@@ -73,7 +73,7 @@ class FortifyServiceProvider extends ServiceProvider
|
||||
$credentialId = $request->input('credential.id');
|
||||
|
||||
return Limit::perMinute(10)->by(
|
||||
($credentialId ?: $request->session()->getId()).'|'.$request->ip(),
|
||||
($credentialId ?: $request->session()->getId()) . '|' . $request->ip(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user