Init
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Spatie\Sitemap\Sitemap;
|
||||
use Spatie\Sitemap\Tags\Url;
|
||||
|
||||
class GenerateSitemap extends Command
|
||||
{
|
||||
protected $signature = 'sitemap:generate';
|
||||
|
||||
protected $description = 'Generate the sitemap dynamically using config routes';
|
||||
|
||||
private const PRIORITY = 0.5;
|
||||
|
||||
private const CHANGE_FREQUENCY = 'weekly';
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$sitemap = Sitemap::create();
|
||||
$routes = config('routes.web', []);
|
||||
|
||||
foreach ($routes as $route) {
|
||||
if (isset($route['path'])) {
|
||||
$this->info('Adding '.$route['path'].' to sitemap.');
|
||||
$sitemap->add(Url::create($route['path'])
|
||||
->setPriority($route['priority'] ?? static::PRIORITY)
|
||||
->setLastModificationDate($route['last_modified'] ?? now())
|
||||
->setChangeFrequency($route['frequency'] ?? static::CHANGE_FREQUENCY));
|
||||
}
|
||||
}
|
||||
|
||||
$sitemap->writeToFile(public_path('sitemap.xml'));
|
||||
$this->info('Sitemap has been successfully generated!');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Contact;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class ContactController extends Controller
|
||||
{
|
||||
private const SUBJECT = 'New Contact us page message';
|
||||
|
||||
public function email(Request $request): RedirectResponse
|
||||
{
|
||||
$request->validate([
|
||||
'name' => 'required',
|
||||
'email' => 'required|email',
|
||||
'message' => 'required',
|
||||
]);
|
||||
|
||||
$this->createRecord([
|
||||
'name' => $request->input('name'),
|
||||
'email' => $request->input('email'),
|
||||
'subject' => self::SUBJECT,
|
||||
'message' => $request->input('message'),
|
||||
]);
|
||||
|
||||
Mail::raw($this->formatMessage($request), function ($message) use ($request) {
|
||||
$message->to(config('app.email'))->subject(self::SUBJECT.' from '.$request->input('email'));
|
||||
$message->from(config('app.email'), $request->input('name'));
|
||||
});
|
||||
|
||||
return redirect()->back()->with('success', 'Your message has been sent.');
|
||||
}
|
||||
|
||||
public function trial(Request $request): RedirectResponse
|
||||
{
|
||||
$request->validate([
|
||||
'name' => 'required',
|
||||
'email' => 'required|email',
|
||||
]);
|
||||
|
||||
$this->createRecord([
|
||||
'name' => $request->input('name'),
|
||||
'email' => $request->input('email'),
|
||||
'subject' => 'New Trial class request',
|
||||
'message' => 'Contact to book a trial class.',
|
||||
]);
|
||||
|
||||
Mail::raw($this->formatMessage($request), function ($message) use ($request) {
|
||||
$message->to(config('app.email'))->subject('New Trial class request from '.$request->input('email'));
|
||||
$message->from(config('app.email'), $request->input('name'));
|
||||
});
|
||||
|
||||
return redirect()->back()->with('success', "We'll be in touch to book your trial class.");
|
||||
}
|
||||
|
||||
public function formatMessage(Request $request): string
|
||||
{
|
||||
return <<<EOF
|
||||
You have received a new contact message.
|
||||
Name: {$request->input('name')}
|
||||
Email: {$request->input('email')}
|
||||
Message: {$request->input('message')}
|
||||
EOF;
|
||||
}
|
||||
|
||||
private function createRecord(array $data)
|
||||
{
|
||||
Contact::create([
|
||||
'name' => $data['name'] ?? '?',
|
||||
'email' => $data['email'] ?? '?',
|
||||
'subject' => $data['subject'] ?? '?',
|
||||
'message' => $data['message'] ?? null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
abstract class Controller
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ImagesController extends Controller
|
||||
{
|
||||
public function show(Request $request, string $file)
|
||||
{
|
||||
try {
|
||||
return response()->file($this->imagePath($file));
|
||||
} catch (\Exception $e) {
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
|
||||
public function subDirectory(Request $request, string $directory, string $file)
|
||||
{
|
||||
try {
|
||||
return response()->file($this->imagePath("{$directory}/{$file}"));
|
||||
} catch (\Exception $e) {
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
|
||||
private function imagePath(string $file): string
|
||||
{
|
||||
return resource_path('images/'.$file);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\HasActive;
|
||||
use App\Traits\HasTableName;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Blog extends Model
|
||||
{
|
||||
use HasActive;
|
||||
use HasFactory;
|
||||
use HasTableName;
|
||||
|
||||
public function getRouteKeyName(): string
|
||||
{
|
||||
return 'slug';
|
||||
}
|
||||
|
||||
public function view(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => 'blog.'.$this->slug
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\HasTableName;
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Contact extends Model
|
||||
{
|
||||
use HasTableName;
|
||||
|
||||
protected $guarded = [
|
||||
'id',
|
||||
];
|
||||
|
||||
#[Scope]
|
||||
protected function unanswered(Builder $builder): void
|
||||
{
|
||||
$builder->where('answered', false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\HasActive;
|
||||
use App\Traits\HasTableName;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Faq extends Model
|
||||
{
|
||||
use HasActive;
|
||||
use HasFactory;
|
||||
use HasTableName;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\UserFactory> */
|
||||
use HasFactory, Notifiable;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'email',
|
||||
'password',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be hidden for serialization.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the attributes that should be cast.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Laravel\Telescope\IncomingEntry;
|
||||
use Laravel\Telescope\Telescope;
|
||||
use Laravel\Telescope\TelescopeApplicationServiceProvider;
|
||||
|
||||
class TelescopeServiceProvider extends TelescopeApplicationServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
$this->hideSensitiveRequestDetails();
|
||||
|
||||
$isLocal = $this->app->environment('local');
|
||||
$recordAll = config('telescope.record_all');
|
||||
|
||||
Telescope::filter(function (IncomingEntry $entry) use ($isLocal, $recordAll) {
|
||||
return $isLocal ||
|
||||
$recordAll ||
|
||||
$entry->isReportableException() ||
|
||||
$entry->isFailedRequest() ||
|
||||
$entry->isFailedJob() ||
|
||||
$entry->isScheduledTask() ||
|
||||
$entry->hasMonitoredTag();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent sensitive request details from being logged by Telescope.
|
||||
*/
|
||||
protected function hideSensitiveRequestDetails(): void
|
||||
{
|
||||
if ($this->app->environment('local')) {
|
||||
return;
|
||||
}
|
||||
|
||||
Telescope::hideRequestParameters(['_token']);
|
||||
|
||||
Telescope::hideRequestHeaders([
|
||||
'cookie',
|
||||
'x-csrf-token',
|
||||
'x-xsrf-token',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Telescope gate.
|
||||
*
|
||||
* This gate determines who can access Telescope in non-local environments.
|
||||
*/
|
||||
protected function gate(): void
|
||||
{
|
||||
Gate::define('viewTelescope', function ($user = null) {
|
||||
$allowed = explode(',', config('telescope.allowed_ips'));
|
||||
|
||||
return in_array(request()->ip(), $allowed);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
trait HasActive
|
||||
{
|
||||
public function scopeActive(Builder $query): Builder
|
||||
{
|
||||
return $query->where('active', true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
trait HasTableName
|
||||
{
|
||||
public static function tableName(): string
|
||||
{
|
||||
return (new static)->getTable();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class Footer extends Component
|
||||
{
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.footer');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class Header extends Component
|
||||
{
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.header');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class Meta extends Component
|
||||
{
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.meta');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user