feat(core): add config loader and request context
This commit is contained in:
1 parent
787e5fa3e2
commit
bcd3572890
3 files changed
+157
No files matched your search
@@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bazaar\Core;
|
||||||
|
|
||||||
|
final class Config
|
||||||
|
{
|
||||||
|
private static array $values = [];
|
||||||
|
private static bool $loaded = false;
|
||||||
|
|
||||||
|
public static function load(string $envFile): void
|
||||||
|
{
|
||||||
|
self::$loaded = true;
|
||||||
|
if (!is_file($envFile)) {
|
||||||
|
self::hydrateDefaults();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
|
||||||
|
$line = trim($line);
|
||||||
|
if ($line === '' || $line[0] === '#') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
[$name, $value] = array_pad(explode('=', $line, 2), 2, '');
|
||||||
|
$name = trim($name);
|
||||||
|
$value = trim($value);
|
||||||
|
if (strlen($value) >= 2 && ($value[0] === '"' || $value[0] === "'")) {
|
||||||
|
$value = substr($value, 1, -1);
|
||||||
|
}
|
||||||
|
self::$values[$name] = $value;
|
||||||
|
}
|
||||||
|
self::hydrateDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function hydrateDefaults(): void
|
||||||
|
{
|
||||||
|
self::$values += [
|
||||||
|
'APP_ENV' => 'production',
|
||||||
|
'APP_DEBUG' => 'false',
|
||||||
|
'APP_URL' => 'http://127.0.0.1:8000',
|
||||||
|
'DB_DRIVER' => 'sqlite',
|
||||||
|
'DB_DATABASE' => basePath('database/bazaar.sqlite'),
|
||||||
|
'DB_HOST' => '127.0.0.1',
|
||||||
|
'DB_PORT' => '3306',
|
||||||
|
'DB_USERNAME' => 'root',
|
||||||
|
'DB_PASSWORD' => '',
|
||||||
|
'STRIPE_SECRET_KEY' => 'sk_test_placeholder',
|
||||||
|
'STRIPE_PUBLISHABLE_KEY' => 'pk_test_placeholder',
|
||||||
|
'STRIPE_WEBHOOK_SECRET' => 'whsec_placeholder',
|
||||||
|
'CURRENCY' => 'usd',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get(string $key, mixed $default = null): mixed
|
||||||
|
{
|
||||||
|
if (!self::$loaded) {
|
||||||
|
self::hydrateDefaults();
|
||||||
|
self::$loaded = true;
|
||||||
|
}
|
||||||
|
return self::$values[$key] ?? $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function set(string $key, mixed $value): void
|
||||||
|
{
|
||||||
|
self::$values[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function stripeConfigured(): bool
|
||||||
|
{
|
||||||
|
$key = (string) self::get('STRIPE_SECRET_KEY');
|
||||||
|
return str_starts_with($key, 'sk_') && !str_contains($key, 'placeholder');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bazaar\Core;
|
||||||
|
|
||||||
|
use Bazaar\Repositories\AttributeRepository;
|
||||||
|
use Bazaar\Repositories\CategoryRepository;
|
||||||
|
use Bazaar\Repositories\CouponRepository;
|
||||||
|
use Bazaar\Repositories\OrderRepository;
|
||||||
|
use Bazaar\Repositories\ProductRepository;
|
||||||
|
use Bazaar\Repositories\ReviewRepository;
|
||||||
|
use Bazaar\Repositories\UserRepository;
|
||||||
|
use Bazaar\Repositories\VariantRepository;
|
||||||
|
use Bazaar\Repositories\WishlistRepository;
|
||||||
|
use Bazaar\Services\Analytics;
|
||||||
|
use Bazaar\Services\Auth;
|
||||||
|
use Bazaar\Services\Cart;
|
||||||
|
use Bazaar\Services\CouponService;
|
||||||
|
use Bazaar\Services\OrderService;
|
||||||
|
use Bazaar\Services\ProductSearch;
|
||||||
|
use Bazaar\Services\ReviewService;
|
||||||
|
use Bazaar\Support\Translator;
|
||||||
|
|
||||||
|
final class Context
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public readonly Request $request,
|
||||||
|
public readonly Session $session,
|
||||||
|
public readonly Csrf $csrf,
|
||||||
|
public readonly View $view,
|
||||||
|
public readonly Auth $auth,
|
||||||
|
public readonly Cart $cart,
|
||||||
|
public readonly OrderService $orderService,
|
||||||
|
public readonly UserRepository $users,
|
||||||
|
public readonly CategoryRepository $categories,
|
||||||
|
public readonly ProductRepository $products,
|
||||||
|
public readonly OrderRepository $orders,
|
||||||
|
public readonly AttributeRepository $attributes,
|
||||||
|
public readonly VariantRepository $variants,
|
||||||
|
public readonly CouponRepository $coupons,
|
||||||
|
public readonly ReviewRepository $reviews,
|
||||||
|
public readonly WishlistRepository $wishlist,
|
||||||
|
public readonly CouponService $couponService,
|
||||||
|
public readonly ReviewService $reviewService,
|
||||||
|
public readonly ProductSearch $productSearch,
|
||||||
|
public readonly Analytics $analytics,
|
||||||
|
public readonly Translator $translator
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bazaar\Core;
|
||||||
|
|
||||||
|
final class Csrf
|
||||||
|
{
|
||||||
|
private const KEY = 'csrfToken';
|
||||||
|
|
||||||
|
public function __construct(private readonly Session $session)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function token(): string
|
||||||
|
{
|
||||||
|
$token = $this->session->get(self::KEY);
|
||||||
|
if (!is_string($token) || $token === '') {
|
||||||
|
$token = bin2hex(random_bytes(32));
|
||||||
|
$this->session->put(self::KEY, $token);
|
||||||
|
}
|
||||||
|
return $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function verify(?string $candidate): bool
|
||||||
|
{
|
||||||
|
$token = $this->session->get(self::KEY);
|
||||||
|
if (!is_string($token) || !is_string($candidate) || $candidate === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return hash_equals($token, $candidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function field(): string
|
||||||
|
{
|
||||||
|
return '<input type="hidden" name="csrfToken" value="' . e($this->token()) . '">';
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user